@azure-tools/typespec-powershell
Version:
An experimental TypeSpec emitter for PowerShell codegen
78 lines (71 loc) • 3.33 kB
text/typescript
import { Program, EmitContext, listServices, emitFile, resolvePath } from "@typespec/compiler";
import { serialize, deserialize } from '@azure-tools/codegen';
import { createSdkContext } from "@azure-tools/typespec-client-generator-core";
// Following files finally should be imported from @autorest/powershell
// import { ModelState } from "./powershell/utils/model-state.js";
// import { PwshModel } from "./powershell/utils/PwshModel.js";
import { getClients } from "./utils/clientUtils.js";
import { transformPwshModel } from "./convertor/convertor.js";
import { PSOptions } from "./types/interfaces.js";
import { generatePwshModule } from "@autorest/powershell";
import { readFileSync } from "fs";
import path from "path";
import { fileURLToPath } from "url";
// Function to recursively interpolate placeholders in an object
function interpolatePlaceholders(obj: any, values: any) {
for (const key in obj) {
if (typeof obj[key] === 'string') {
obj[key] = obj[key].replace(/{([^}]+)}/g, (match: string, placeholder: string) => values[placeholder]);
} else if (typeof obj[key] === 'object') {
interpolatePlaceholders(obj[key], values);
}
}
}
//load configuration from configuration.md
function loadConfiguration(emitterOptions: Record<string, any>): Record<string, any> {
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const configPath = path.join(__dirname, '../../configuration.yaml');
const configuration = deserialize<Record<string, any>>(readFileSync(configPath, 'utf8'), configPath);
// Define the values for interpolation
const interpolationValues = {
'module-name': emitterOptions['module-name'],
'service-name': emitterOptions['service-name']
};
interpolatePlaceholders(configuration, interpolationValues);
// If there is overlap between the configuration and the emitter options, the emitter options will take precedence
return { ...configuration, ...emitterOptions };
}
export async function $onEmit(context: EmitContext) {
const program: Program = context.program;
// Emitter options from tspconfig.json
// ToDo: need to implement a configuration class for AzPS
const emitterOptions: PSOptions = context.options;
const PsContext = await createSdkContext(
context,
"@azure-tools/typespec-powershell",
);
// const pwshModel = new PwshModel("");
// const services = listServices(program);
// if (!context.program.compilerOptions.noEmit) {
// await emitFile(context.program, {
// path: resolvePath(context.emitterOutputDir, "output.txt"),
// content: "Hello world\n" + serialize(program.stateMap(Symbol("typescript-models-" + services[0].type.name + "Client"))),
// });
// }
await generatePwshModel();
async function generatePwshModel() {
const clients = getClients(PsContext);
for (const client of clients) {
const configurations = loadConfiguration(emitterOptions);
const model = await transformPwshModel(client, PsContext, configurations);
if (configurations['emit-modeler-output']) {
await emitFile(context.program, {
path: resolvePath(context.emitterOutputDir, `${client.name}.yaml`),
content: serialize(model),
});
}
await generatePwshModule(model, configurations);
}
}
}