Skip to content

Commit

Permalink
[IDP-1766] Improve configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
tjosepo committed Jul 3, 2024
1 parent 8f5c0cf commit 5ad1bac
Show file tree
Hide file tree
Showing 9 changed files with 443 additions and 97 deletions.
13 changes: 10 additions & 3 deletions packages/create-schemas/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@
},
"type": "module",
"bin": "./dist/bin.js",
"exports": {
".": {
"import": "./dist/index.js",
"types": "./dist/index.d.ts"
}
},
"scripts": {
"dev": "pnpm run build && pnpm run dev:link && pnpm run dev:tsup",
"dev:link": "pnpm link --global",
Expand All @@ -35,9 +41,10 @@
"node": ">=18.0.0"
},
"dependencies": {
"@types/yargs-parser": "21.0.3",
"c12": "1.11.1",
"commander": "12.1.0",
"openapi-typescript": "7.0.0-rc.0",
"typescript": "5.4.5",
"yargs-parser": "21.1.1"
"zod": "3.23.8"
}
}
}
52 changes: 0 additions & 52 deletions packages/create-schemas/src/argsHelper.ts

This file was deleted.

50 changes: 25 additions & 25 deletions packages/create-schemas/src/bin.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
import fs from "node:fs";
import path from "path";
import { getOpenApiTsOptionForArgs, getOutputPath } from "./argsHelper.ts";
import { ZodError } from "zod";
import { parseArgs, resolveConfig } from "./config.ts";
import { generateSchemas } from "./openapiTypescriptHelper.ts";

console.log("Received command: ", process.argv);

// Access command-line arguments
const args = process.argv.slice(2);

const openApiTsOptions = getOpenApiTsOptionForArgs(args);

const openApiPath = args[0];
const outputPath = getOutputPath(args);

if (!openApiPath || !outputPath) {
throw new Error("Both openApiPath and outputPath must be provided");
import { mkdirSync, writeFileSync } from "node:fs";
import { dirname } from "node:path";

try {
// Access command-line arguments
const config = await resolveConfig(parseArgs());

const contents = await generateSchemas(config);

// Write the content to a file
mkdirSync(dirname(config.output), { recursive: true });
writeFileSync(config.output, contents);
} catch (error) {
if (error instanceof ZodError) {
printConfigurationErrors(error);
}
}

console.log("Starting OpenAPI TypeScript types generation...");
console.log(`\t-openApiPath: ${openApiPath}`);
console.log(`\t-outputPath: ${outputPath}`);

const contents = await generateSchemas(openApiPath, outputPath, openApiTsOptions);

// Write the content to a file
fs.mkdirSync(path.dirname(outputPath), { recursive: true });
fs.writeFileSync(outputPath, contents);
function printConfigurationErrors(error: ZodError) {
console.log("Invalid configuration:");
error.errors.forEach(issue => {
console.log(` - ${issue.path.join(".")}: ${issue.message}`);
});
console.log("Use --help to see available options.");
}
81 changes: 81 additions & 0 deletions packages/create-schemas/src/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { Command } from "commander";
import { loadConfig } from "c12";
import * as z from "zod";
import packageJson from "../package.json" with { type: "json" };
import type { OpenAPITSOptions as OriginalOpenAPITSOptions } from "openapi-typescript";

const CONFIG_FILE_DEFAULT = "create-schemas.config";
const OUTPUT_FILE_DEFAULT = "openapi-types.ts";
const ROOT_DEFAULT = ".";

type OpenApiTsOptions = Omit<OriginalOpenAPITSOptions, "cwd" | "transform" | "postTransform" | "silent" | "version">;

export interface UserConfig {
root?: string;
input?: string;
output?: string;
openApiTsOptions?: OpenApiTsOptions;
}

export interface InlineConfig extends UserConfig {
configFile?: string;
}

const resolvedConfigSchema = z.object({
configFile: z.string(),
root: z.string(),
input: z.string(),
output: z.string(),
openApiTsOptions: z.custom<OpenApiTsOptions>().optional().default({})
});

export type ResolvedConfig = z.infer<typeof resolvedConfigSchema>;

export function parseArgs(argv?: string[]): InlineConfig {
const program = new Command();

program
.name("create-schemas")
.version(packageJson.version, "-v, --version", "display version number")
.argument("[input]")
.option("-c, --config <file>", "use specified config file", CONFIG_FILE_DEFAULT)
.option("-i, --input <path>", "path to the OpenAPI schema file")
.option("-o, --output <path>", "output file path", OUTPUT_FILE_DEFAULT)
.option("--cwd <path>", "path to working directory", ROOT_DEFAULT)
.helpOption("-h, --help", "display available CLI options")
.parse(argv);

const opts = program.opts();
const args = program.args;

return {
configFile: opts.config,
root: opts.cwd,
input: opts.input || args[0],
output: opts.output
};
}

export async function resolveConfig(inlineConfig: InlineConfig = {}): Promise<ResolvedConfig> {
const { configFile = CONFIG_FILE_DEFAULT, root = ROOT_DEFAULT } = inlineConfig;

const { config } = await loadConfig<InlineConfig>({
configFile,
cwd: root,
omit$Keys: true,
defaultConfig: {
configFile: CONFIG_FILE_DEFAULT,
root: ROOT_DEFAULT,
output: OUTPUT_FILE_DEFAULT
},
overrides: inlineConfig
});

const resolvedConfig = resolvedConfigSchema.parse(config);

return resolvedConfig;
}

export function defineConfig(config: UserConfig): UserConfig {
return config;
}
7 changes: 7 additions & 0 deletions packages/create-schemas/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export {
defineConfig,
resolveConfig,
type UserConfig,
type InlineConfig,
type ResolvedConfig
} from "./config.ts";
30 changes: 22 additions & 8 deletions packages/create-schemas/src/openapiTypescriptHelper.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
import openapiTS, { astToString, type OpenAPITSOptions } from "openapi-typescript";
import { generateExportEndpointsTypeDeclaration, generateExportSchemaTypeDeclaration, getSchemaNames } from "./astHelper.ts";

export async function generateSchemas(openApiPath: string, outputPath: string, openApiTsOptions: OpenAPITSOptions): Promise<string> {
const CWD = new URL(`file://${process.cwd()}/`);
import openapiTS, { astToString } from "openapi-typescript";
import {
generateExportEndpointsTypeDeclaration,
generateExportSchemaTypeDeclaration,
getSchemaNames
} from "./astHelper.ts";
import type { ResolvedConfig } from "./config.ts";
import { pathToFileURL } from "url";

export async function generateSchemas(config: ResolvedConfig): Promise<string> {
const base = pathToFileURL(config.root);

// Create a TypeScript AST from the OpenAPI schema
const ast = await openapiTS(new URL(openApiPath, CWD), openApiTsOptions);
const ast = await openapiTS(new URL(config.input, base), {
...config.openApiTsOptions,
silent: true,
cwd: config.root
});

// Find the node where all the DTOs are defined, and extract their names
const schemaNames = getSchemaNames(ast);
Expand All @@ -24,9 +34,13 @@ export async function generateSchemas(openApiPath: string, outputPath: string, o
contents += `\n${generateExportEndpointsTypeDeclaration()}\n`;

if (schemaNames.length === 0) {
console.warn(`⚠️ Suspiciously no schemas where found in the OpenAPI document at ${openApiPath}. It might due to a flag converting interface to type which is not supported at the moment. ⚠️`);
console.warn(
`⚠️ Suspiciously no schemas where found in the OpenAPI document at ${config.input}. It might due to a flag converting interface to type which is not supported at the moment. ⚠️`
);
} else {
console.log(`OpenAPI TypeScript types have been generated successfully at ${outputPath}! 🎉`);
console.log(
`OpenAPI TypeScript types have been generated successfully at ${config.output}! 🎉`
);
}

return contents;
Expand Down
2 changes: 1 addition & 1 deletion packages/create-schemas/tsup.build.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { defineBuildConfig } from "@workleap/tsup-configs";

export default defineBuildConfig({
entry: ["src/bin.ts"],
entry: ["src/bin.ts", "src/index.ts"],
platform: "node"
});
2 changes: 1 addition & 1 deletion packages/create-schemas/tsup.dev.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { defineDevConfig } from "@workleap/tsup-configs";

export default defineDevConfig({
entry: ["src/bin.ts"],
entry: ["src/bin.ts", "src/index.ts"],
platform: "node"
});
Loading

0 comments on commit 5ad1bac

Please sign in to comment.