Files
openstapps/packages/json-schema-generator/src/index.ts

79 lines
2.4 KiB
TypeScript

import {compileSchema} from './generator/compile-schema.js';
import {generateFiles, Plugin, PluginContext} from '@openstapps/tsup-plugin';
import {JSONSchema7} from 'json-schema';
import {Plugin as EsbuildPlugin} from 'esbuild';
import {createGenerator} from 'ts-json-schema-generator';
export type SchemaConsumer = (this: PluginContext, schema: JSONSchema7) => Record<string, string | Buffer>;
export const jsonSchema: EsbuildPlugin = {
name: 'json-schema',
setup(build) {
const fileRegex = /^schema:/;
const namespace = 'json-schema-ns';
const schemas = new Map<string, string>();
build.onResolve({filter: fileRegex}, ({path, importer}) => {
const [from, name] = path.replace(fileRegex, '').split('#', 1);
return {
path: `${from === 'file' ? importer : from}#${name}`,
namespace,
};
});
build.onLoad({filter: /.*/, namespace}, ({path}) => {
if (!schemas.has(path)) {
const [sourcePath, schemaName] = path.split('#', 1);
const generator = createGenerator({
path: sourcePath,
extraTags: ['elasticsearch'],
skipTypeCheck: true,
});
schemas.set(path, JSON.stringify(generator.createSchema(schemaName)));
}
return {
contents: schemas.get(path),
loader: 'json',
};
});
},
};
/**
* TSUp plugin for generating JSONSchema files
* @param schemaName the name of the generated schema
* @param schemaConsumers any consumers that can directly use the schema
*/
export function jsonSchemaPlugin(
schemaName: string,
...schemaConsumers: Array<[string, SchemaConsumer]>
): Plugin {
return {
name: 'json-schema-generator',
async buildEnd() {
let schema: JSONSchema7;
await generateFiles('JSON-Schema', async function () {
const [jsonSchema, types] = compileSchema(
(this.options.entry as string[])[0],
this.options.tsconfig!,
);
schema = jsonSchema;
return {
[schemaName]: JSON.stringify(jsonSchema),
[`${schemaName.replace(/\.json$/, '')}.d.ts`]: types,
};
}).call(this);
for (const [name, consumer] of schemaConsumers) {
await generateFiles(name, async function () {
return consumer.call(this, schema);
}).call(this);
}
},
};
}
export {compileSchema} from './generator/compile-schema.js';