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; export const jsonSchema: EsbuildPlugin = { name: 'json-schema', setup(build) { const fileRegex = /^schema:/; const namespace = 'json-schema-ns'; const schemas = new Map(); 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';