diff --git a/backend/backend/config/f-u/about-pages/index.js b/backend/backend/config/f-u/about-pages/index.js index 311a70a3..a627f877 100644 --- a/backend/backend/config/f-u/about-pages/index.js +++ b/backend/backend/config/f-u/about-pages/index.js @@ -3,7 +3,7 @@ import about from './about.js'; import imprint from './imprint.js'; import privacy from './privacy.js'; -/** @type {import('@openstapps/core').SCMap} */ +/** @type {Record} */ const aboutPages = { 'about': about, 'about/imprint': imprint, diff --git a/backend/backend/package.json b/backend/backend/package.json index 4b09a05f..e50b82da 100644 --- a/backend/backend/package.json +++ b/backend/backend/package.json @@ -45,6 +45,7 @@ "dependencies": { "@elastic/elasticsearch": "8.10.0", "@openstapps/core": "workspace:*", + "@openstapps/core-validator": "workspace:*", "@openstapps/logger": "workspace:*", "@types/body-parser": "1.19.2", "@types/cors": "2.8.13", diff --git a/backend/backend/src/app.ts b/backend/backend/src/app.ts index ce707d03..128b0ffb 100644 --- a/backend/backend/src/app.ts +++ b/backend/backend/src/app.ts @@ -14,7 +14,6 @@ * along with this program. If not, see . */ import { - SCConfigFile, SCNotFoundErrorResponse, SCRequestBodyTooLargeErrorResponse, SCSyntaxErrorResponse, @@ -39,7 +38,7 @@ import {virtualPluginRoute} from './routes/virtual-plugin-route.js'; import {BulkStorage} from './storage/bulk-storage.js'; import {DatabaseConstructor} from './storage/database.js'; import {backendConfig} from './config.js'; -import {createValidator} from './validator.js'; +import {validator} from './validator.js'; /** * Configure the backend @@ -143,11 +142,8 @@ export async function configureApp(app: Express, databases: {[name: string]: Dat request.on('data', chunkGatherer).on('end', endCallback); }); - const configFileValid = createValidator('SCConfigFile'); - if (!configFileValid(backendConfig)) { - throw new Error( - `Validation of config file failed. Errors were: ${JSON.stringify(configFileValid.errors)}`, - ); + if (!validator.validate(backendConfig, 'SCConfigFile')) { + throw new Error(`Validation of config file failed. Errors were: ${JSON.stringify(validator.errors)}`); } // check if a database name was given diff --git a/backend/backend/src/routes/route.ts b/backend/backend/src/routes/route.ts index fca535d8..94664e10 100644 --- a/backend/backend/src/routes/route.ts +++ b/backend/backend/src/routes/route.ts @@ -24,7 +24,7 @@ import {Application, Router} from 'express'; import PromiseRouter from 'express-promise-router'; import {isTestEnvironment} from '../common.js'; import {isHttpMethod} from './http-types.js'; -import {createValidator} from '../validator.js'; +import {validator} from '../validator.js'; /** * Creates a router from a route class and a handler function which implements the logic @@ -44,8 +44,6 @@ export function createRoute( ): Router { // create router const router = PromiseRouter({mergeParams: true}); - const requestValidator = createValidator(routeClass.requestBodyName); - const responseValidator = createValidator(routeClass.responseBodyName); // create route // the given type has no index signature so we have to cast to get the IRouteHandler when a HTTP method is given @@ -58,8 +56,8 @@ export function createRoute( // create a route handler for the given HTTP method route[verb](async (request, response) => { try { - if (!requestValidator(request.body)) { - const error = new SCValidationErrorResponse(requestValidator.errors as any, isTestEnvironment); + if (!validator.validate(request.body, routeClass.requestBodyName as never)) { + const error = new SCValidationErrorResponse(validator.errors, isTestEnvironment); response.status(error.statusCode); response.json(error); await Logger.error(error); @@ -67,13 +65,10 @@ export function createRoute( return; } - const handlerResponse = await handler(request.body, request.app, request.params); + const handlerResponse = await handler(request.body as REQUESTTYPE, request.app, request.params); - if (!responseValidator(handlerResponse)) { - const validationError = new SCValidationErrorResponse( - responseValidator.errors as any, - isTestEnvironment, - ); + if (!validator.validate(handlerResponse, routeClass.responseBodyName)) { + const validationError = new SCValidationErrorResponse(validator.errors, isTestEnvironment); // The validation error is not caused by faulty user input, but through an error that originates somewhere in // the backend, therefore we use this "stacked" error. const internalServerError = new SCInternalServerErrorResponse(validationError, isTestEnvironment); diff --git a/backend/backend/src/routes/virtual-plugin-route.ts b/backend/backend/src/routes/virtual-plugin-route.ts index babc2434..741cd71b 100644 --- a/backend/backend/src/routes/virtual-plugin-route.ts +++ b/backend/backend/src/routes/virtual-plugin-route.ts @@ -13,7 +13,6 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ - import {SCInternalServerErrorResponse, SCPluginMetaData, SCValidationErrorResponse} from '@openstapps/core'; import {Request} from 'express'; import got from 'got'; @@ -31,7 +30,7 @@ export async function virtualPluginRoute(request: Request, plugin: SCPluginMetaD try { if (!validator.validate(request.body, plugin.requestSchema)) { // noinspection ExceptionCaughtLocallyJS - throw new SCValidationErrorResponse(validator.errors as any, isTestEnvironment); + throw new SCValidationErrorResponse(validator.errors, isTestEnvironment); } // send the request to the plugin (forward the body) and save the response const response = await got.post(plugin.route.replaceAll(/^\//gi, ''), { @@ -45,7 +44,7 @@ export async function virtualPluginRoute(request: Request, plugin: SCPluginMetaD const responseBody = response.body; if (!validator.validate(responseBody, plugin.responseSchema)) { // noinspection ExceptionCaughtLocallyJS - throw new SCValidationErrorResponse(validator.errors as any, isTestEnvironment); + throw new SCValidationErrorResponse(validator.errors, isTestEnvironment); } return responseBody as object; } catch (error) { diff --git a/backend/backend/src/storage/elasticsearch/elasticsearch.ts b/backend/backend/src/storage/elasticsearch/elasticsearch.ts index 2a9b8181..d308023e 100644 --- a/backend/backend/src/storage/elasticsearch/elasticsearch.ts +++ b/backend/backend/src/storage/elasticsearch/elasticsearch.ts @@ -31,7 +31,7 @@ import {parseAggregations} from './aggregations.js'; import * as Monitoring from './monitoring.js'; import {buildQuery} from './query/query.js'; import {buildSort} from './query/sort.js'; -import {aggregations, putTemplate} from './templating.js'; +import {putTemplate} from './templating.js'; import { ElasticsearchConfig, ElasticsearchQueryDisMaxConfig, @@ -46,6 +46,7 @@ import { } from './util/index.js'; import {noUndefined} from './util/no-undefined.js'; import {retryCatch, RetryOptions} from './util/retry.js'; +import config from '@openstapps/core/elasticsearch-mappings.json'; /** * A database interface for elasticsearch @@ -370,7 +371,7 @@ export class Elasticsearch implements Database { }; const response: SearchResponse = await this.client.search({ - aggs: aggregations, + aggs: config.default.search.aggs, query: buildQuery(parameters, this.config, esConfig), from: parameters.from, index: ACTIVE_INDICES_ALIAS, diff --git a/backend/backend/src/storage/elasticsearch/templating.ts b/backend/backend/src/storage/elasticsearch/templating.ts index d807cd3a..87e72752 100644 --- a/backend/backend/src/storage/elasticsearch/templating.ts +++ b/backend/backend/src/storage/elasticsearch/templating.ts @@ -15,19 +15,7 @@ */ import {Client} from '@elastic/elasticsearch'; import {SCThingType} from '@openstapps/core'; -import type {AggregationSchema} from '@openstapps/core/lib/mappings/aggregations.json.js'; -import type {ElasticsearchTemplateCollection} from '@openstapps/core/lib/mappings/mappings.json.js'; -import {readFileSync} from 'fs'; -import path from 'path'; - -const mappingsPath = path.resolve('node_modules', '@openstapps', 'core', 'lib', 'mappings'); - -export const mappings = JSON.parse( - readFileSync(path.resolve(mappingsPath, 'mappings.json'), 'utf8'), -) as ElasticsearchTemplateCollection; -export const aggregations = JSON.parse( - readFileSync(path.resolve(mappingsPath, 'aggregations.json'), 'utf8'), -) as AggregationSchema; +import config from '@openstapps/core/elasticsearch-mappings.json'; /** * Prepares all indices @@ -40,7 +28,7 @@ export async function putTemplate(client: Client, type: SCThingType) { const sanitizedType = `template_${type.replaceAll(/\s/g, '_')}`; return client.indices.putTemplate({ - body: mappings[sanitizedType], + body: config.default.mappings[sanitizedType], name: sanitizedType, }); } diff --git a/backend/backend/src/validator.ts b/backend/backend/src/validator.ts index 38366c8e..fda33b59 100644 --- a/backend/backend/src/validator.ts +++ b/backend/backend/src/validator.ts @@ -1,25 +1,3 @@ -import Ajv from 'ajv'; -import addFormats from 'ajv-formats'; -import schema from '@openstapps/core?json-schema'; +import {Validator} from '@openstapps/core-validator'; -export const validator = new Ajv.default({ - schemas: [schema], - verbose: true, - allowUnionTypes: true, -}); -addFormats.default(validator, { - formats: ['date-time', 'time', 'uuid', 'duration'], - mode: 'fast', -}); - -/** - * Create a validator function - * @example - * import schema from '@openstapps/core#schema:SCThings' - * createValidator(schema) - */ -export function createValidator(schemaName: string): Ajv.ValidateFunction { - return validator.compile({ - $ref: `#/definitions/${schemaName}`, - }); -} +export const validator = new Validator(); diff --git a/backend/backend/test/routes/route.spec.ts b/backend/backend/test/routes/route.spec.ts index 35673d3f..3e85c9a3 100644 --- a/backend/backend/test/routes/route.spec.ts +++ b/backend/backend/test/routes/route.spec.ts @@ -78,7 +78,6 @@ describe('Create route', async function () { it('should complain (throw an error) if used method is other than defined in the route creation', async function () { const methodNotAllowedError = new SCMethodNotAllowedErrorResponse(); - // @ts-expect-error not assignable sandbox.stub(validator, 'validate').returns({errors: []}); let error: any = {}; sandbox.stub(Logger, 'warn').callsFake(error_ => { @@ -97,7 +96,6 @@ describe('Create route', async function () { }); it('should provide a route which returns handler response and success code', async function () { - // @ts-expect-error not assignable sandbox.stub(validator, 'validate').returns({errors: []}); const router = createRoute(routeClass, handler); app.use(router); @@ -115,7 +113,6 @@ describe('Create route', async function () { app.use(router); const startApp = supertest(app); const validatorStub = sandbox.stub(validator, 'validate'); - // @ts-expect-error not assignable validatorStub.withArgs(body, routeClass.requestBodyName).returns({errors: [new Error('Foo Error')]}); const response = await startApp @@ -131,11 +128,9 @@ describe('Create route', async function () { const router = createRoute(routeClass, handler); await app.use(router); const startApp = supertest(app); - // @ts-expect-error not assignable const validatorStub = sandbox.stub(validator, 'validate').returns({errors: []}); validatorStub .withArgs(bodySuccess, routeClass.responseBodyName) - // @ts-expect-error not assignable .returns({errors: [new Error('Foo Error')]}); const response = await startApp.post(routeClass.urlPath).send(); @@ -177,7 +172,6 @@ describe('Create route', async function () { await app.use(router); const startApp = supertest(app); - // @ts-expect-error not assignable sandbox.stub(validator, 'validate').returns({errors: []}); const response = await startApp.post(routeClass.urlPath).send(); @@ -213,7 +207,6 @@ describe('Create route', async function () { await app.use(router); const startApp = supertest(app); - // @ts-expect-error not assignable sandbox.stub(validator, 'validate').returns({errors: []}); const response = await startApp.post(routeClass.urlPath).send(); diff --git a/backend/backend/test/routes/virtual-plugin-route.spec.ts b/backend/backend/test/routes/virtual-plugin-route.spec.ts index 02ecfb44..ce39bc41 100644 --- a/backend/backend/test/routes/virtual-plugin-route.spec.ts +++ b/backend/backend/test/routes/virtual-plugin-route.spec.ts @@ -22,11 +22,12 @@ import got, {Options} from 'got'; import nock from 'nock'; import sinon from 'sinon'; import {mockReq} from 'sinon-express-mock'; -import {plugins, validator} from '../../src/common.js'; +import {plugins} from '../../src/common.js'; import {virtualPluginRoute} from '../../src/routes/virtual-plugin-route.js'; import {DEFAULT_TEST_TIMEOUT, FooError} from '../common.js'; import {registerAddRequest} from './plugin-register-route.spec.js'; import {testApp} from '../tests-setup.js'; +import {validator} from '../../src/validator.js'; use(chaiAsPromised); @@ -71,7 +72,6 @@ describe('Virtual plugin routes', async function () { // spy the post method of got // @ts-expect-error not assignable const gotStub = sandbox.stub(got, 'post').returns({body: {}}); - // @ts-expect-error not assignable sandbox.stub(validator, 'validate').returns({errors: []}); const request_ = mockReq(request); diff --git a/backend/backend/tsup.config.ts b/backend/backend/tsup.config.ts index bdd265c7..66ceb5b1 100644 --- a/backend/backend/tsup.config.ts +++ b/backend/backend/tsup.config.ts @@ -7,4 +7,5 @@ export default defineConfig({ target: 'es2022', format: 'esm', outDir: 'lib', + noExternal: [/\.json$/], }); diff --git a/packages/core-validator/src/index.ts b/packages/core-validator/src/index.ts index 01d92c7c..357611ee 100644 --- a/packages/core-validator/src/index.ts +++ b/packages/core-validator/src/index.ts @@ -24,6 +24,10 @@ type NameOf = keyof IncludeProperty(instance: unknown, schema: NameOf): instance is T { - return this.ajv.validate(schema as string, instance); + public validate(instance: unknown, schema: NameOf): instance is T; + public validate(instance: unknown, schema: Ajv.Schema): boolean; + public validate(instance: unknown, schema: Ajv.Schema | string): boolean { + return this.ajv.validate(schema, instance); } } diff --git a/packages/core/package.json b/packages/core/package.json index 649cc6b1..92f609c2 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -32,7 +32,11 @@ }, "./schema.json": { "import": "./lib/schema.json", - "types": "./lib/schema.d.ts" + "types": "./lib/schema.json.d.ts" + }, + "./elasticsearch-mappings.json": { + "import": "./lib/elasticsearch.json", + "types": "./lib/elasticsearch.json.d.ts" } }, "files": [ diff --git a/packages/es-mapping-generator/package.json b/packages/es-mapping-generator/package.json index b49d3e8b..0d611fc2 100644 --- a/packages/es-mapping-generator/package.json +++ b/packages/es-mapping-generator/package.json @@ -24,6 +24,8 @@ "test": "c8 mocha" }, "dependencies": { + "ajv": "8.12.0", + "ajv-formats": "2.1.1", "@elastic/elasticsearch": "8.10.0", "@openstapps/json-schema-generator": "workspace:*", "@openstapps/tsup-plugin": "workspace:*", diff --git a/packages/es-mapping-generator/schema/aggregations.d.ts b/packages/es-mapping-generator/schema/aggregations.d.ts deleted file mode 100644 index a4e96903..00000000 --- a/packages/es-mapping-generator/schema/aggregations.d.ts +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2019-2021 StApps - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - */ -declare module 'aggregations.json' { - const value: AggregationSchema; - export default value; -} - -/** - * An elasticsearch bucket aggregation - * @see https://www.elastic.co/guide/en/elasticsearch/reference/5.6/search-aggregations-bucket.html - */ -export interface AggregationSchema { - [aggregationName: string]: ESTermsFilter | ESNestedAggregation; -} - -/** - * An elasticsearch terms filter - */ -export interface ESTermsFilter { - /** - * Terms filter definition - */ - terms: { - /** - * Field to apply filter to - */ - field: string; - - /** - * Number of results - */ - size?: number; - }; -} - -/** - * Filter that filters by name of the the field type - */ -export interface ESAggTypeFilter { - /** - * The type of the object to find - */ - term: { - /** - * The name of the type - */ - type: string; - }; -} - -/** - * Filter that matches everything - */ -export interface ESAggMatchAllFilter { - /** - * Filter that matches everything - */ - match_all: object; -} - -/** - * For nested aggregations - */ -export interface ESNestedAggregation { - /** - * Possible nested Aggregations - */ - aggs: AggregationSchema; - /** - * Possible filter for types - */ - filter: ESAggTypeFilter | ESAggMatchAllFilter; -} diff --git a/packages/es-mapping-generator/schema/mappings.d.ts b/packages/es-mapping-generator/schema/mappings.d.ts index a0974f82..342f0240 100644 --- a/packages/es-mapping-generator/schema/mappings.d.ts +++ b/packages/es-mapping-generator/schema/mappings.d.ts @@ -1,124 +1,9 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -import {IndicesPutTemplateRequest, MappingProperty} from '@elastic/elasticsearch/lib/api/types'; -/* - * Copyright (C) 2019-2021 StApps - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - */ -import {AggregationSchema} from './aggregations'; +import {IndicesPutTemplateRequest, SearchRequest} from '@elastic/elasticsearch/lib/api/types.js'; -declare module 'mappings.json' { - const value: ElasticsearchTemplateCollection; - export default value; +export interface ElasticsearchConfig { + mappings: Record; + search: Partial; } -/** - * Template output of the mapping generation - */ -export interface MappingGenTemplate { - /** - * All generated aggregations - */ - aggregations: AggregationSchema; - - /** - * All errors that occurred - */ - errors: string[]; - - /** - * All mappings that were generated - */ - mappings: ElasticsearchTemplateCollection; -} - -export type SimpleType = MappingProperty['type'] & - ('keyword' | 'float' | 'boolean' | 'date' | 'integer' | 'text'); - -/** - * The Typemap is used to get the corresponding ElasticsearchDataType for a name provided by the ProjectReflection - */ -export interface ElasticsearchTypemap { - /** - * The `stringLiteral` type must always be provided - */ - stringLiteral: { - /** - * The default can be chosen freely, but must be provided - */ - default: SimpleType; - }; - - /** - * The name of the JS type, so for `number` it would be number - */ - [name: string]: { - /** - * The default ElasticsearchDataType that should be used, if no tag or only not implemented tags are found - */ - default: SimpleType; - - /** - * The name of the tag, so for `@integer` it would be `integer` - */ - [name: string]: SimpleType; - }; -} - -/** - * The Fieldmap contains all tag names for fields and the corresponding fields - * - * The Fieldmap works in a similar fashion to the Typemap - */ -export interface ElasticsearchFieldmap { - /** - * The name of the tag, so for `@sortable` it would be `sortable` - */ - [name: string]: { - /** - * The default value if no parameter is provided - */ - default: { - /** - * To allow the usage of `prev.fields = {...prev.fields, ...fieldmap[tag.tagName].default}` - * - * We could also have used `default: any`, but this adds slightly more improved type-safety. - */ - [name: string]: any; - }; - - /** - * The tag parameters that will be ignored - * - * Some tag parameters might not be important for your implementation, so you can add their names here to not get - * any errors. The `default` will be used in that case. - */ - ignore: string[]; - - /** - * The parameters of the tag, so for `@sortable ducet` it would be `ducet` - */ - [name: string]: { - /** - * To allow the usage of `prev.fields = {...prev.fields, ...fieldmap[tag.tagName][tag.text.trim()]}` - * - * We could also have used `default: any`, but this adds slightly more improved type-safety. - */ - [name: string]: any; - }; - }; -} - -/** - * A collection of Elasticsearch Templates - */ -export type ElasticsearchTemplateCollection = Record>; +declare const elasticsearchConfig: ElasticsearchConfig; +export default elasticsearchConfig; diff --git a/packages/es-mapping-generator/src/generator/context.ts b/packages/es-mapping-generator/src/generator/context.ts index 385210b7..411a174a 100644 --- a/packages/es-mapping-generator/src/generator/context.ts +++ b/packages/es-mapping-generator/src/generator/context.ts @@ -58,7 +58,7 @@ export class Context { this.propertyPath, new Map(), ); - const result = transformDefinition(derivedContext, definition); + const result = transformDefinition(derivedContext, definition!); referenceName ??= crypto.createHash('md5').update(JSON.stringify(result)).digest('hex'); this.generator.cache.set(referenceName, {mapping: result, dependencies: derivedContext.dependencies}); diff --git a/packages/es-mapping-generator/src/generator/index.ts b/packages/es-mapping-generator/src/generator/index.ts index ecfd5cb6..bbf25848 100644 --- a/packages/es-mapping-generator/src/generator/index.ts +++ b/packages/es-mapping-generator/src/generator/index.ts @@ -3,6 +3,7 @@ import {ElasticsearchOptionsDSL} from '../dsl/schema.js'; import {IndicesPutTemplateRequest, MappingProperty} from '@elastic/elasticsearch/lib/api/types.js'; import {MappingGenerator} from './mapping-generator.js'; import {getTags, INDEXABLE_TAG_NAME} from './tags.js'; +import {ElasticsearchConfig} from '../../schema/mappings.js'; export interface GeneratorOptions { /** @@ -24,15 +25,16 @@ export interface GeneratorOptions { /** * Fully transform a project */ -export function transformProject(project: JSONSchema7) { +export function transformProject(project: JSONSchema7): ElasticsearchConfig { const context = new MappingGenerator(project, OPTIONS); - const results = []; + const results: Record = {}; for (const name in project.definitions) { const definition = project.definitions[name]; if (typeof definition !== 'object' || !getTags(definition).has(INDEXABLE_TAG_NAME)) continue; - results.push(context.buildTemplate(name)); + const [type, template] = context.buildTemplate(name); + results[type] = template; } return { mappings: results, diff --git a/packages/es-mapping-generator/src/generator/mapping-generator.ts b/packages/es-mapping-generator/src/generator/mapping-generator.ts index 379f736a..4ec3dfec 100644 --- a/packages/es-mapping-generator/src/generator/mapping-generator.ts +++ b/packages/es-mapping-generator/src/generator/mapping-generator.ts @@ -41,7 +41,7 @@ export class MappingGenerator { ); } - buildTemplate(name: string): IndicesPutTemplateRequest { + buildTemplate(name: string): [string, IndicesPutTemplateRequest] { const thingType = ((this.project.definitions![name] as JSONSchema7).properties!.type as JSONSchema7) .const; if (typeof thingType !== 'string') { @@ -71,6 +71,6 @@ export class MappingGenerator { } } - return request; + return [thingType, request]; } } diff --git a/packages/es-mapping-generator/src/index.ts b/packages/es-mapping-generator/src/index.ts index 337238fa..35f51f97 100644 --- a/packages/es-mapping-generator/src/index.ts +++ b/packages/es-mapping-generator/src/index.ts @@ -1,5 +1,13 @@ import {transformProject} from './generator/index.js'; import {SchemaConsumer} from '@openstapps/json-schema-generator'; +import {readFile} from 'fs/promises'; +import path from 'path'; +import {fileURLToPath} from 'url'; + +const mappingTypes = await readFile( + path.join(path.dirname(fileURLToPath(import.meta.url)), '..', 'schema', 'mappings.d.ts'), + 'utf8', +); /** * JSON Schema Generator plugin for Elasticsearch Mappings @@ -10,6 +18,7 @@ export function elasticsearchMappingGenerator(fileName: string): [string, Schema function (schema) { return { [fileName]: JSON.stringify(transformProject(schema)), + [`${fileName}.d.ts`]: mappingTypes, }; }, ]; diff --git a/packages/json-schema-generator/src/generator/compile-schema.ts b/packages/json-schema-generator/src/generator/compile-schema.ts index 8efebca2..e89bfb66 100644 --- a/packages/json-schema-generator/src/generator/compile-schema.ts +++ b/packages/json-schema-generator/src/generator/compile-schema.ts @@ -24,10 +24,10 @@ export function compileSchema(path: string, tsconfig: string): [schma: JSONSchem Object.assign(fullSchema.definitions, generator.createSchema(schema).definitions); } - const schemaTypes = `import {JSONSchema7} from 'json-schema';\n\nexport interface SchemaMap {\n${[ + const schemaTypes = `import {JSONSchema7} from 'json-schema';\nimport * as index from './index.js';\n\nexport interface SchemaMap {\n${[ ...schemaNames, ] - .map(schemaName => ` '${schemaName}': core.${schemaName};`) + .map(schemaName => ` '${schemaName}': index.${schemaName};`) .join('\n')}\n}\n\nconst schema: JSONSchema7;\nexport default schema;`; return [fullSchema, schemaTypes]; diff --git a/packages/json-schema-generator/src/index.ts b/packages/json-schema-generator/src/index.ts index 879af22c..83940929 100644 --- a/packages/json-schema-generator/src/index.ts +++ b/packages/json-schema-generator/src/index.ts @@ -76,7 +76,7 @@ export function jsonSchemaPlugin( return { [schemaName]: JSON.stringify(jsonSchema), - [`${schemaName.replace(/\.json$/, '')}.d.ts`]: types, + [`${schemaName}.d.ts`]: types, }; }).call(this); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a369007f..c399817e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -58,6 +58,9 @@ importers: '@openstapps/core': specifier: workspace:* version: link:../../packages/core + '@openstapps/core-validator': + specifier: workspace:* + version: link:../../packages/core-validator '@openstapps/logger': specifier: workspace:* version: link:../../packages/logger @@ -1834,6 +1837,12 @@ importers: '@types/json-schema': specifier: 7.0.14 version: 7.0.14 + ajv: + specifier: 8.12.0 + version: 8.12.0 + ajv-formats: + specifier: 2.1.1 + version: 2.1.1(ajv@8.12.0) devDependencies: '@openstapps/eslint-config': specifier: workspace:*