Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,304 changes: 681 additions & 623 deletions package-lock.json

Large diffs are not rendered by default.

25 changes: 12 additions & 13 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"prepare": "npm run build",
"prepublishOnly": "rm -rf dist && npm run build",
"postpublish": "git push && git push --tags",
"test": "(cd tests && npm test)"
"test": "npm test --prefix ./tests"
},
"keywords": [
"openapi",
Expand All @@ -34,22 +34,21 @@
},
"homepage": "https://github.com/Q42/openapi-typescript-validator",
"peerDependencies": {
"ajv": "^8.0.0",
"ajv-formats": "^2.0.0"
"ajv": "^8.17.1"
},
"dependencies": {
"@openapi-contrib/openapi-schema-to-json-schema": "^3.0.4",
"ajv": "^8.0.0",
"ajv-formats": "^2.0.0",
"js-yaml": "^4.0.0",
"json-schema-to-typescript": "^11.0.2",
"@openapi-contrib/openapi-schema-to-json-schema": "^5.1.0",
"ajv": "^8.17.1",
"ajv-formats": "^3.0.1",
"js-yaml": "^4.1.0",
"json-schema-to-typescript": "^15.0.4",
"lodash.keyby": "^4.6.0"
},
"devDependencies": {
"@types/js-yaml": "^4.0.0",
"@types/lodash.keyby": "^4.6.6",
"@types/object-hash": "^1.3.4",
"prettier": "^2.2.1",
"typescript": "^4.2.2"
"@types/js-yaml": "^4.0.9",
"@types/lodash.keyby": "^4.6.9",
"@types/object-hash": "^3.0.6",
"prettier": "^3.7.0",
"typescript": "^5.9.3"
}
}
4 changes: 2 additions & 2 deletions src/GenerateOptions.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { FormatsPluginOptions } from 'ajv-formats';
import { FormatsPluginOptions } from "ajv-formats";
import { Options } from "prettier";
import { SchemaType } from "./parse-schema";

Expand Down Expand Up @@ -30,7 +30,7 @@ export interface GenerateOptions {
/**
* adds the "ajv-formats" packages
* @default false
*/
*/
addFormats?: boolean;

/**
Expand Down
31 changes: 15 additions & 16 deletions src/builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,7 @@ type PropertyBaseOptions = Pick<
"title" | "description" | "default"
>;

type ObjectBaseOptions = Pick<
JSONSchema,
"title" | "description" | "default"
>;
type ObjectBaseOptions = Pick<JSONSchema, "title" | "description" | "default">;

type ArrayOptions = PropertyBaseOptions;

Expand Down Expand Up @@ -64,24 +61,23 @@ export const boolean = (options: BooleanOptions = {}): PropertyValue => ({
});

export const any = (options: JSONSchema = {}): PropertyValue => ({
...options
})
...options,
});

export const anonymousData = (options: JSONSchema): PropertyValue => ({
additionalProperties: { type: "string" },
...options,
});


const stringFormat = (format: FormatName) => (
options: FormatOptions = {}
): PropertyValue => {
return {
type: "string",
format,
...(options ?? {}),
const stringFormat =
(format: FormatName) =>
(options: FormatOptions = {}): PropertyValue => {
return {
type: "string",
format,
...(options ?? {}),
};
};
};

export const date = stringFormat("date");
export const time = stringFormat("time");
Expand Down Expand Up @@ -133,7 +129,10 @@ export const ref = (refName: string): SchemaObject => ({
const autoRef = (type: SchemaObjectOrRef): SchemaObject =>
typeof type === "string" ? ref(type) : type;

export const array = (itemType: SchemaObjectOrRef, options: ArrayOptions = {}): SchemaObject => ({
export const array = (
itemType: SchemaObjectOrRef,
options: ArrayOptions = {},
): SchemaObject => ({
type: "array",
items: autoRef(itemType),
...options,
Expand Down
29 changes: 17 additions & 12 deletions src/generate.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import keyby from "lodash.keyby";
import { parseSchema } from "./parse-schema";
import { GenerateOptions } from "./GenerateOptions";
import type { GenerateOptions } from "./GenerateOptions";
import { generateMetaFile } from "./generate/generate-meta";
import { generateCompileBasedDecoders } from "./generate/generate-compile-decoders";
import {
Expand All @@ -21,7 +21,7 @@ export async function generate(options: GenerateOptions) {
: options.directory;

console.info(
`Start generating files for ${schemaType} schema: ${schemaFile}`
`Start generating files for ${schemaType} schema: ${schemaFile}`,
);

const schema = await parseSchema(schemaFile, schemaType);
Expand All @@ -39,37 +39,37 @@ export async function generate(options: GenerateOptions) {
});

if (options.skipDecoders !== true && definitionNames.length > 0) {
generateAjvValidator(prettierOptions, directories);
await generateAjvValidator(prettierOptions, directories);

if (!options.standalone) {
generateCompileBasedDecoders(
await generateCompileBasedDecoders(
definitionNames,
options.addFormats ?? false,
options.formatOptions,
directories,
prettierOptions
prettierOptions,
);
} else if (options.standalone.mergeDecoders === true) {
generateStandaloneMergedDecoders(
await generateStandaloneMergedDecoders(
definitionNames,
schema,
options.addFormats ?? false,
options.formatOptions,
options.esm ? "module" : options.standalone.validatorOutput,
options.esm ?? false,
directories,
prettierOptions
prettierOptions,
);
} else {
generateStandaloneDecoders(
await generateStandaloneDecoders(
definitionNames,
schema,
options.addFormats ?? false,
options.formatOptions,
options.esm ? "module" : options.standalone.validatorOutput,
options.esm ?? false,
directories,
prettierOptions
prettierOptions,
);
}
}
Expand All @@ -78,12 +78,17 @@ export async function generate(options: GenerateOptions) {
schema,
{ skipSchemaFile: options.skipSchemaFile },
prettierOptions,
directories
directories,
);
generateHelpers(prettierOptions, directories);
await generateHelpers(prettierOptions, directories);

if (options.skipMetaFile !== true) {
generateMetaFile(allDefinitions, directories, prettierOptions, options.esm ?? false);
await generateMetaFile(
allDefinitions,
directories,
prettierOptions,
options.esm ?? false,
);
}

console.info(`Successfully generated files for ${schemaFile}`);
Expand Down
8 changes: 4 additions & 4 deletions src/generate/generate-ajv-validator.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { format, Options } from "prettier";
import { format, type Options } from "prettier";
import { writeFileSync, mkdirSync } from "fs";
import path from "path";

export function generateAjvValidator(
export async function generateAjvValidator(
prettierOptions: Options,
outDirs: string[]
outDirs: string[],
) {
const helpers = format(helpersTemplate, prettierOptions);
const helpers = await format(helpersTemplate, prettierOptions);

outDirs.forEach((outDir) => {
mkdirSync(outDir, { recursive: true });
Expand Down
14 changes: 7 additions & 7 deletions src/generate/generate-compile-decoders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,39 +4,39 @@ import path from "path";
import { createDecoderName } from "./generation-utils";
import { FormatsPluginOptions } from "ajv-formats";

export function generateCompileBasedDecoders(
export async function generateCompileBasedDecoders(
definitionNames: string[],
addFormats: boolean,
formatOptions: FormatsPluginOptions | undefined,
outDirs: string[],
prettierOptions: Options
): void {
prettierOptions: Options,
): Promise<void> {
const decoders = definitionNames
.map((definitionName) =>
decoderTemplate
.replace(/\$DecoderName/g, createDecoderName(definitionName))
.replace(/\$Class/g, definitionName)
.trim()
.trim(),
)
.join("\n");

const rawDecoderOutput = decodersFileTemplate
.replace(
/\$Imports/g,
addFormats ? 'import addFormats from "ajv-formats"' : ""
addFormats ? 'import addFormats from "ajv-formats"' : "",
)
.replace(
/\$Formats/g,
addFormats
? `addFormats(ajv, ${
formatOptions ? JSON.stringify(formatOptions) : "undefined"
});`
: ""
: "",
)
.replace(/\$ModelImports/g, definitionNames.join(", "))
.replace(/\$Decoders/g, decoders);

const decoderOutput = format(rawDecoderOutput, prettierOptions);
const decoderOutput = await format(rawDecoderOutput, prettierOptions);

outDirs.forEach((outDir) => {
mkdirSync(outDir, { recursive: true });
Expand Down
8 changes: 4 additions & 4 deletions src/generate/generate-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import { format, Options } from "prettier";
import { writeFileSync, mkdirSync } from "fs";
import path from "path";

export function generateHelpers(
export async function generateHelpers(
prettierOptions: Options,
outDirs: string[]
) {
const helpers = format(helpersTemplate, prettierOptions);
outDirs: string[],
): Promise<void> {
const helpers = await format(helpersTemplate, prettierOptions);

outDirs.forEach((outDir) => {
mkdirSync(outDir, { recursive: true });
Expand Down
14 changes: 7 additions & 7 deletions src/generate/generate-meta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import { mkdirSync, writeFileSync } from "fs";
import path from "path";
import { ValidatorOutput } from "../GenerateOptions";

export function generateMetaFile(
export async function generateMetaFile(
definitionNames: string[],
outDirs: string[],
prettierOptions: Options,
esm: boolean
): void {
esm: boolean,
): Promise<void> {
const metas = definitionNames
.map((definitionName) => {
return `${definitionName}: info<${definitionName}>('${definitionName}', '#/definitions/${definitionName}'),`;
Expand All @@ -17,9 +17,9 @@ export function generateMetaFile(

const rawOutput = metaTemplate(esm)
.replace(/\$Definitions/g, metas)
.replace(/\$ModelImports/g, definitionNames.join(", "))
.replace(/\$ModelImports/g, definitionNames.join(", "));

const output = format(rawOutput, prettierOptions);
const output = await format(rawOutput, prettierOptions);

outDirs.forEach((outDir) => {
mkdirSync(outDir, { recursive: true });
Expand All @@ -45,5 +45,5 @@ export interface SchemaInfo<T> {
function info<T>(definitionName: string, schemaRef: string): SchemaInfo<T> {
return { definitionName, schemaRef };
}
`
}
`;
};
18 changes: 9 additions & 9 deletions src/generate/generate-models.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
import { mkdirSync, writeFileSync } from "fs";
import path from 'path';
import { compile } from 'json-schema-to-typescript';
import { format, Options } from 'prettier';
import { ParsedSchema } from '../parse-schema';
import { GenerateOptions } from '../GenerateOptions';
import path from "path";
import { compile } from "json-schema-to-typescript";
import { format, Options } from "prettier";
import { ParsedSchema } from "../parse-schema";
import { GenerateOptions } from "../GenerateOptions";

export async function generateModels(
schema: ParsedSchema,
options: Pick<GenerateOptions, 'skipSchemaFile'>,
options: Pick<GenerateOptions, "skipSchemaFile">,
prettierOptions: Options,
outDirs: string[]
outDirs: string[],
): Promise<void> {
const compiledTypescriptModels = await compile(
JSON.parse(schema.json),
"Schema"
"Schema",
);
const rawTypescriptModels = modelsFileTemplate
.replace(/\$Models/g, compiledTypescriptModels)
.replace(/\s*\[k: string\]: unknown;/g, "") // Allow additional properties in schema but not in typescript
.replace(/export interface Schema \{[^]*?\n\}/, "");

const typescriptModels = format(rawTypescriptModels, prettierOptions);
const typescriptModels = await format(rawTypescriptModels, prettierOptions);

outDirs.forEach((outDir) => {
mkdirSync(outDir, { recursive: true });
Expand Down
Loading
Loading