@tsofist/schema-forge 2.4.3 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -2,6 +2,7 @@ import '../util/patch.extended-annotations-reader';
|
|
|
2
2
|
import { SchemaObject } from 'ajv';
|
|
3
3
|
import { ChainNodeParser, CompletedConfig, Context, SubNodeParser, TupleType } from 'ts-json-schema-generator';
|
|
4
4
|
import { Node, TupleTypeNode } from 'typescript';
|
|
5
|
+
import { SchemaForgeOptions } from '../types';
|
|
5
6
|
import { TypeExposeKind } from './types';
|
|
6
7
|
interface Options {
|
|
7
8
|
tsconfig: string;
|
|
@@ -14,6 +15,7 @@ interface Options {
|
|
|
14
15
|
openapiCompatible?: boolean;
|
|
15
16
|
sortObjectProperties?: boolean;
|
|
16
17
|
allowUseFallbackDescription?: boolean;
|
|
18
|
+
shrinkDefinitionNames: SchemaForgeOptions['shrinkDefinitionNames'];
|
|
17
19
|
}
|
|
18
20
|
export declare function generateSchemaByDraftTypes(options: Options): Promise<SchemaObject>;
|
|
19
21
|
export declare class TupleTypeParser implements SubNodeParser {
|
|
@@ -5,6 +5,7 @@ exports.generateSchemaByDraftTypes = generateSchemaByDraftTypes;
|
|
|
5
5
|
require("../util/patch.extended-annotations-reader");
|
|
6
6
|
const error_1 = require("@tsofist/stem/lib/error");
|
|
7
7
|
const ajv_1 = require("ajv");
|
|
8
|
+
const jsonpath_plus_1 = require("jsonpath-plus");
|
|
8
9
|
const ts_json_schema_generator_1 = require("ts-json-schema-generator");
|
|
9
10
|
const typescript_1 = require("typescript");
|
|
10
11
|
const sort_properties_1 = require("../util/sort-properties");
|
|
@@ -54,12 +55,43 @@ async function generateSchemaByDraftTypes(options) {
|
|
|
54
55
|
const schema = generator.createSchema(definitionName);
|
|
55
56
|
Object.assign(result.definitions, schema.definitions);
|
|
56
57
|
}
|
|
58
|
+
if (options.shrinkDefinitionNames) {
|
|
59
|
+
const replacement = new Set();
|
|
60
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
61
|
+
for (const name of Object.keys(result.definitions)) {
|
|
62
|
+
console.log('DEF::::', name);
|
|
63
|
+
const r = options.shrinkDefinitionNames(name);
|
|
64
|
+
if (r) {
|
|
65
|
+
if (replacement.has(r) || r in result.definitions) {
|
|
66
|
+
(0, error_1.raise)(`Duplicate replacement definition name: ${r}`);
|
|
67
|
+
}
|
|
68
|
+
// rename property
|
|
69
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
70
|
+
result.definitions[r] = result.definitions[name];
|
|
71
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
72
|
+
delete result.definitions[name];
|
|
73
|
+
// rename references
|
|
74
|
+
const targets = (0, jsonpath_plus_1.JSONPath)({
|
|
75
|
+
path: `$..[?(@ && @.$ref == "#/definitions/${name}")]`,
|
|
76
|
+
json: result,
|
|
77
|
+
eval: 'safe',
|
|
78
|
+
});
|
|
79
|
+
targets.forEach((item) => {
|
|
80
|
+
item.$ref = item.$ref.replace(`#/definitions/${name}`, `#/definitions/${r}`);
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
57
85
|
result.definitions = Object.fromEntries(Object.entries((result.definitions || {})).sort());
|
|
58
86
|
if (options.sortObjectProperties)
|
|
59
87
|
(0, sort_properties_1.sortProperties)(result.definitions);
|
|
60
88
|
await new ajv_1.default({
|
|
61
89
|
strict: true,
|
|
62
90
|
allErrors: true,
|
|
91
|
+
strictSchema: true,
|
|
92
|
+
strictTypes: false,
|
|
93
|
+
strictTuples: false,
|
|
94
|
+
allowUnionTypes: true,
|
|
63
95
|
}).validateSchema(result, true);
|
|
64
96
|
return result;
|
|
65
97
|
}
|
package/lib/generator.js
CHANGED
|
@@ -3,10 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.forgeSchema = forgeSchema;
|
|
4
4
|
exports.loadJSONSchema = loadJSONSchema;
|
|
5
5
|
exports.loadJSONSchemaSync = loadJSONSchemaSync;
|
|
6
|
-
const fs_1 = require("fs");
|
|
7
|
-
const promises_1 = require("fs/promises");
|
|
8
6
|
const node_crypto_1 = require("node:crypto");
|
|
9
|
-
const
|
|
7
|
+
const node_fs_1 = require("node:fs");
|
|
8
|
+
const promises_1 = require("node:fs/promises");
|
|
10
9
|
const as_array_1 = require("@tsofist/stem/lib/as-array");
|
|
11
10
|
const error_1 = require("@tsofist/stem/lib/error");
|
|
12
11
|
const noop_1 = require("@tsofist/stem/lib/noop");
|
|
@@ -53,6 +52,7 @@ async function forgeSchema(options) {
|
|
|
53
52
|
openapiCompatible: options.openapiCompatible,
|
|
54
53
|
sortObjectProperties: options.sortObjectProperties,
|
|
55
54
|
allowUseFallbackDescription: options.allowUseFallbackDescription,
|
|
55
|
+
shrinkDefinitionNames: options.shrinkDefinitionNames,
|
|
56
56
|
})),
|
|
57
57
|
...(options.schemaMetadata || {}),
|
|
58
58
|
};
|
|
@@ -106,7 +106,7 @@ async function forgeSchema(options) {
|
|
|
106
106
|
}
|
|
107
107
|
finally {
|
|
108
108
|
if (!KEEP_ARTEFACTS) {
|
|
109
|
-
await Promise.all(files.map((fileName) => (0,
|
|
109
|
+
await Promise.all(files.map((fileName) => (0, promises_1.unlink)(fileName).catch(noop_1.noop)));
|
|
110
110
|
}
|
|
111
111
|
}
|
|
112
112
|
return {
|
|
@@ -118,7 +118,7 @@ async function forgeSchema(options) {
|
|
|
118
118
|
}
|
|
119
119
|
finally {
|
|
120
120
|
if (tsconfig && tsconfigGenerated) {
|
|
121
|
-
await (0,
|
|
121
|
+
await (0, promises_1.unlink)(tsconfig).catch(noop_1.noop);
|
|
122
122
|
}
|
|
123
123
|
}
|
|
124
124
|
}
|
|
@@ -127,7 +127,7 @@ async function loadJSONSchema(files) {
|
|
|
127
127
|
}
|
|
128
128
|
function loadJSONSchemaSync(files) {
|
|
129
129
|
return files.map((fn) => {
|
|
130
|
-
const content = (0,
|
|
130
|
+
const content = (0, node_fs_1.readFileSync)(fn, { encoding: 'utf8' });
|
|
131
131
|
return JSON.parse(content);
|
|
132
132
|
});
|
|
133
133
|
}
|
package/lib/generator.spec.js
CHANGED
|
@@ -176,6 +176,11 @@ describe('generator for a5', () => {
|
|
|
176
176
|
outputSchemaMetadataFile,
|
|
177
177
|
expose: 'all',
|
|
178
178
|
explicitPublic: true,
|
|
179
|
+
shrinkDefinitionNames: (definitionName) => {
|
|
180
|
+
if (definitionName === 'NamesType')
|
|
181
|
+
return 'NT';
|
|
182
|
+
return undefined;
|
|
183
|
+
},
|
|
179
184
|
});
|
|
180
185
|
validator = (0, validator_1.createSchemaForgeValidator)({}, true);
|
|
181
186
|
const schema = await (0, generator_1.loadJSONSchema)([outputSchemaFile]);
|
|
@@ -195,7 +200,7 @@ describe('generator for a5', () => {
|
|
|
195
200
|
'DomainNum',
|
|
196
201
|
'DomainValue',
|
|
197
202
|
'DomainValuesType',
|
|
198
|
-
'NamesType',
|
|
203
|
+
'NT', // 'NamesType',
|
|
199
204
|
'NamesTypeAbnormal',
|
|
200
205
|
'NumN',
|
|
201
206
|
'Nums',
|
|
@@ -205,7 +210,7 @@ describe('generator for a5', () => {
|
|
|
205
210
|
'VariadicList',
|
|
206
211
|
'VariadicList1',
|
|
207
212
|
]);
|
|
208
|
-
expect(validator.getValidator('test#/definitions/
|
|
213
|
+
expect(validator.getValidator('test#/definitions/NT').schema).toStrictEqual({
|
|
209
214
|
type: 'string',
|
|
210
215
|
enum: ['v:name1', 'v:name2'],
|
|
211
216
|
});
|
|
@@ -217,7 +222,7 @@ describe('generator for a5', () => {
|
|
|
217
222
|
$ref: '#/definitions/DomainValuesType',
|
|
218
223
|
},
|
|
219
224
|
name0: {
|
|
220
|
-
$ref: '#/definitions/
|
|
225
|
+
$ref: '#/definitions/NT',
|
|
221
226
|
},
|
|
222
227
|
name1: {
|
|
223
228
|
type: 'string',
|
package/lib/types/db.types.d.ts
CHANGED
package/lib/types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Nullable, PRec } from '@tsofist/stem';
|
|
1
|
+
import { NonEmptyString, Nullable, PRec } from '@tsofist/stem';
|
|
2
2
|
import { ErrorCode } from '@tsofist/stem/lib/error';
|
|
3
3
|
import { ErrorObject, ErrorsTextOptions, SchemaObject, ValidateFunction } from 'ajv';
|
|
4
4
|
import { SchemaForgeBaseOptions } from './generator/types';
|
|
@@ -73,6 +73,12 @@ export interface SchemaForgeOptions extends SchemaForgeBaseOptions {
|
|
|
73
73
|
* @default false
|
|
74
74
|
*/
|
|
75
75
|
readonly sortObjectProperties?: boolean;
|
|
76
|
+
/**
|
|
77
|
+
* If you want to shrink the schema definition names, you have to provide a replacement function.
|
|
78
|
+
*
|
|
79
|
+
* WARN: this functionality is not compatible (yet) with `encodeRefs=true` option.
|
|
80
|
+
*/
|
|
81
|
+
readonly shrinkDefinitionNames?: (definitionName: string) => undefined | NonEmptyString;
|
|
76
82
|
}
|
|
77
83
|
export interface SchemaForgeMetadata {
|
|
78
84
|
$id: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tsofist/schema-forge",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.0",
|
|
4
4
|
"description": "Generate JSON schema from TypeScript types",
|
|
5
5
|
"author": "Andrew Berdnikov <tsofistgudmen@gmail.com>",
|
|
6
6
|
"license": "LGPL-3.0",
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"ajv": "^8.17.1",
|
|
26
26
|
"ajv-formats": "^3.0.1",
|
|
27
27
|
"json-schema-faker": "^0.5.8",
|
|
28
|
+
"jsonpath-plus": "^10.3.0",
|
|
28
29
|
"ts-json-schema-generator": "~2.3.0",
|
|
29
30
|
"tslib": "^2.8.1"
|
|
30
31
|
},
|