Skip to content

Commit

Permalink
refactor: prepare for hooking
Browse files Browse the repository at this point in the history
  • Loading branch information
Xiphe committed Mar 10, 2024
1 parent 85fdc27 commit 3a0a23a
Show file tree
Hide file tree
Showing 11 changed files with 541 additions and 367 deletions.
129 changes: 98 additions & 31 deletions packages/codegen/src/__future__/generate/generateApi.ts
Expand Up @@ -4,50 +4,117 @@ import { OazapftsContext } from "../../context";
import generateServers, { defaultBaseUrl } from "../../generateServers";
import * as cg from "../../tscodegen";
import * as h from "../helpers";
import { generateMethods } from "./generateMethods";
import { generateClientMethod } from "./generateClientMethod";
import { setDefaultBaseUrl } from "./setDefaultBaseUrl";
import * as OpenAPI from "../../openApi3-x";

export function generateApi(ctx: OazapftsContext) {
// TODO-HOOK(prepare): context is complete but we haven't started generating anything
prepare(ctx);

// TODO-HOOK(createSourceFile): create the base file that we'll be adding everything to
const sourceTemplateFile = createSourceFile(
__API_STUB_PLACEHOLDER__, // replaced with template/ApiStub.ts during build
ctx,
);

const sourceFile = cg.transform(sourceTemplateFile, (node) => {
if (ts.isVariableDeclaration(node) && ts.isIdentifier(node.name)) {
if (node.name.text === "servers") {
// TODO-HOOK(modifyServers): modify the servers variable
return modifyServers(node, sourceTemplateFile, ctx);
}

if (node.name.text === "defaults") {
// TODO-HOOK(getDefaultBaseUrl): get the default base url
const defaultBaseUrl = getDefaultBaseUrl(ctx, sourceTemplateFile);

const defaultsWithBaseUrl = setDefaultBaseUrl(node, defaultBaseUrl);

// TODO-HOOK(modifyDefaults): modify the defaults variable
return (
modifyDefaults(defaultsWithBaseUrl, sourceTemplateFile, ctx) ||
defaultsWithBaseUrl
);
}
}
});

const methods = Object.entries(ctx.spec.paths || {}).flatMap(
([path, pathItem]) => {
if (!pathItem) return [];

return Object.entries(pathItem).flatMap(([verb, operation]) => {
if (!operation) return [];
const method = verb.toUpperCase();
if (!h.isHttpMethod(method)) return [];

// TODO-HOOK(generateMethod): generate the methods
return generateMethod(
method,
path,
operation as OpenAPI.OperationObject,
pathItem,
ctx,
sourceFile,
);
});
},
);

const apiSourceFile = ts.factory.updateSourceFile(sourceFile, [
...sourceFile.statements,
...[...ctx.aliases, ...h.dedupeMethodNames(methods)],
...ctx.enumAliases,
]);

return apiSourceFile;
}

function prepare(ctx: OazapftsContext) {
h.preprocessComponents(ctx);
}

function createSourceFile(sourceText: string, _: OazapftsContext) {
// Parse ApiStub.ts so that we don't have to generate everything manually
const stub = ts.createSourceFile(
return ts.createSourceFile(
"ApiStub.ts",
__API_STUB_PLACEHOLDER__, // replaced with ApiStub.ts during build
sourceText,
ts.ScriptTarget.Latest,
/*setParentNodes*/ false,
/* setParentNodes */ false,
ts.ScriptKind.TS,
);
}

// ApiStub contains `const servers = {}`, find it ...
const servers = cg.findFirstVariableDeclaration(stub.statements, "servers");
// servers.initializer is readonly, this might break in a future TS version, but works fine for now.
Object.assign(servers, {
function modifyServers(
servers: ts.VariableDeclaration,
_: ts.SourceFile,
ctx: OazapftsContext,
) {
return cg.updateVariableDeclaration(servers, {
initializer: generateServers(ctx.spec.servers || []),
});
}

const { initializer } = cg.findFirstVariableDeclaration(
stub.statements,
"defaults",
);
if (!initializer || !ts.isObjectLiteralExpression(initializer)) {
throw new Error("No object literal: defaults");
}

cg.changePropertyValue(
initializer,
"baseUrl",
defaultBaseUrl(ctx.spec.servers || []),
);

const methods = generateMethods(ctx);
function modifyDefaults(
_: ts.VariableDeclaration,
__: ts.SourceFile,
___: OazapftsContext,
): ts.VariableDeclaration | undefined {
return;
}

Object.assign(stub, {
statements: cg.appendNodes(
stub.statements,
...[...ctx.aliases, ...methods],
...ctx.enumAliases,
),
});
function getDefaultBaseUrl(ctx: OazapftsContext, _: ts.SourceFile) {
return defaultBaseUrl(ctx.spec.servers || []);
}

return stub;
function generateMethod(
method: h.HttpMethod,
path: string,
operation: OpenAPI.OperationObject,
pathItem: OpenAPI.PathItemObject,
ctx: OazapftsContext,
_: ts.SourceFile,
) {
return generateClientMethod(method, path, operation, pathItem, ctx);
}

0 comments on commit 3a0a23a

Please sign in to comment.