Skip to content

Commit 8f4baa2

Browse files
committed
update
1 parent e39f00d commit 8f4baa2

File tree

11 files changed

+96
-63
lines changed

11 files changed

+96
-63
lines changed

src/core/app.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import fs from "node:fs";
2+
import path from "node:path";
3+
4+
export default function getAppName(): string {
5+
try {
6+
const filePath = path.resolve(process.cwd(), "package.json");
7+
const content = fs.readFileSync(filePath, "utf-8");
8+
const data = JSON.parse(content);
9+
return data.name;
10+
} catch (error) {
11+
return "unknown-service";
12+
}
13+
}

src/core/arguments.ts

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
11
import yargs from "yargs";
22

3-
const argv = yargs.option("output", {
4-
alias: "o",
5-
describe: "Specify the output directory",
6-
type: "string",
7-
demandOption: false,
8-
}).argv;
3+
const argv = yargs
4+
.option("source", {
5+
alias: "s",
6+
describe: "Specify the source directory",
7+
type: "string",
8+
demandOption: false,
9+
})
10+
.option("output", {
11+
alias: "o",
12+
describe: "Specify the output directory",
13+
type: "string",
14+
demandOption: false,
15+
})
16+
.argv;
917

1018
export default async function getArgument(name: string) {
1119
const a = argv instanceof Promise ? await argv : argv;

src/core/renderers/interface.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,16 @@
1-
import Handlebars from "handlebars";
21
import type { OperationTemplate } from "~/core/resolvers/operation";
2+
import getTemplate from "~/core/template";
33
import interfaceTemplate from "~/templates/interface.hbs";
44

55
type InterfaceTemplate = {
6-
baseUrl: string,
7-
schemas: string[],
6+
envName: string,
87
operations: OperationTemplate[],
98
};
109

11-
export default function generateInterface(baseUrl: string, schemas: string[], operations: OperationTemplate[]) {
12-
const template = Handlebars.compile<InterfaceTemplate>(interfaceTemplate);
10+
export default function generateInterface(envName: string, operations: OperationTemplate[]) {
11+
const template = getTemplate<InterfaceTemplate>(interfaceTemplate);
1312
return template({
14-
baseUrl,
15-
schemas,
13+
envName,
1614
operations,
1715
});
1816
}

src/core/resolvers/operation.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export default function resolveOperations(paths: OpenAPI["paths"]) {
2727
name: operation.operationId,
2828
method: method.toUpperCase(),
2929
path: quotePathName(path, operation.parameters ?? []),
30-
parameters: resolveOperationParams(operation, true).join(", "),
30+
parameters: resolveOperationParams(operation, false).join(", "),
3131
searchParams: getSearchParams(operation.parameters ?? []),
3232
responses: resolveResponses(operation.responses),
3333
}));

src/core/resolvers/response.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,6 @@ function handleResponse(statusCode: string, response: Operation["responses"]["20
2121

2222
export function resolveResponses(responses: Operation["responses"]) {
2323
return Object.entries(responses).map(([statusCode, response]) => (
24-
`case ${statusCode}: ${handleResponse(statusCode, response, true)};`
24+
`case ${statusCode}: ${handleResponse(statusCode, response, false)};`
2525
));
2626
}

src/core/source.ts

Lines changed: 0 additions & 18 deletions
This file was deleted.

src/core/swagger.ts

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,21 @@
1+
import path from "node:path";
2+
import swaggerJsdoc from "swagger-jsdoc";
3+
import getAppVersion from "./version";
14
import type { OpenAPI } from "./openapi";
25

3-
export default async function getSwaggerJSON(base: string, specs?: string) {
4-
const url = new URL(specs ?? "/swagger", base);
5-
const response = await fetch(url);
6-
const data = await response.json();
7-
return data as OpenAPI;
6+
export default function generateSwaggerJson(sourcePath: string,) {
7+
const spec = swaggerJsdoc({
8+
apis: [
9+
path.resolve(sourcePath, "**", "*.ts"),
10+
path.resolve(sourcePath, "**", "*.js"),
11+
],
12+
definition: {
13+
openapi: "3.0.0",
14+
info: {
15+
title: "Next.js API",
16+
version: getAppVersion(),
17+
},
18+
},
19+
});
20+
return spec as OpenAPI;
821
}

src/core/version.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import fs from "node:fs";
2+
import path from "node:path";
3+
4+
export default function getAppVersion(): string {
5+
try {
6+
const filePath = path.resolve(process.cwd(), "package.json");
7+
const content = fs.readFileSync(filePath, "utf-8");
8+
const data = JSON.parse(content);
9+
return data.version;
10+
} catch (error) {
11+
return "?.?.?";
12+
}
13+
}

src/index.ts

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,40 @@
11
import "~/core/renderers/operation";
22
import "~/core/renderers/parameter";
33
import path from "node:path";
4+
import getAppName from "./core/app";
45
import getArgument from "./core/arguments";
56
import createFile from "./core/file";
67
import generateInterface from "./core/renderers/interface";
78
import generateSchema from "./core/renderers/schema";
89
import { resolveSchemas, resolveSchemasFromProps } from "./core/resolvers/imported-schema";
910
import resolveOperations from "./core/resolvers/operation";
1011
import resolveProperties from "./core/resolvers/property";
11-
import readSource from "./core/source";
12-
import getSwaggerJSON from "./core/swagger";
12+
import generateSwaggerJson from "./core/swagger";
1313

1414
(async () => {
15-
const outputFolder = await getArgument("output") ?? "src";
15+
const sourceFolder = await getArgument("source") ?? "src";
16+
const sourceDir = path.resolve(process.cwd(), sourceFolder);
17+
18+
const outputFolder = await getArgument("output") ?? "dist";
1619
const outputDir = path.resolve(process.cwd(), outputFolder);
1720

18-
const source = await readSource();
19-
for (const service of source.services) {
20-
const data = await getSwaggerJSON(service.url, service.specs);
21-
for (const [schemaName, schema] of Object.entries(data.components.schemas)) {
22-
if (schema.type === "object") {
23-
const properties = resolveProperties(schema.properties, schema.required ?? []);
24-
const importedSchemas = resolveSchemasFromProps(schema.properties);
25-
const content = generateSchema(schemaName, properties, importedSchemas);
26-
await createFile(content, `${schemaName}.ts`, outputDir, "schemas");
27-
}
21+
const data = generateSwaggerJson(sourceDir);
22+
for (const [schemaName, schema] of Object.entries(data.components.schemas)) {
23+
if (schema.type === "object") {
24+
const properties = resolveProperties(schema.properties, schema.required ?? []);
25+
const importedSchemas = resolveSchemasFromProps(schema.properties);
26+
const content = generateSchema(schemaName, properties, importedSchemas);
27+
await createFile(content, `${schemaName}.ts`, outputDir, "schemas");
2828
}
29-
const schemas = resolveSchemas(data.paths);
30-
const paths = resolveOperations(data.paths);
31-
const content = generateInterface(service.url, schemas, paths);
32-
await createFile(content, `${service.name}.ts`, outputDir);
3329
}
30+
31+
const packageName = getAppName();
32+
const appName = packageName.split("/").pop() ?? "unknown-service";
33+
const envName = `${appName.replace(/-/g, "_").toUpperCase()}_BASE_URL`;
34+
35+
const schemas = resolveSchemas(data.paths);
36+
const resolvedPaths = resolveOperations(data.paths);
37+
38+
const content = generateInterface(envName, resolvedPaths);
39+
await createFile(content, "index.js", outputDir);
3440
})();

src/templates/interface.hbs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
{{#each schemas}}
2-
import type {{this}} from "./schemas/{{this}}";
3-
{{/each}}
4-
5-
const BASE_URL = "{{baseUrl}}";
6-
1+
function createURL(endPoint) {
2+
if (!process.env.{{envName}}) {
3+
throw new Error("Base URL is not defined for this service! Please add {{envName}} to the environment variables.");
4+
}
5+
return new URL(endPoint, process.env.{{envName}});
6+
}
77
{{#each operations}}
8-
{{> operation }}
98

9+
{{> operation }}
1010
{{/each}}

0 commit comments

Comments
 (0)