@twin.org/ts-to-schema 0.0.1-next.2 → 0.0.1-next.21
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.
- package/dist/cjs/index.cjs +259 -0
- package/dist/esm/index.mjs +253 -0
- package/dist/locales/en.json +265 -0
- package/dist/types/cli.d.ts +5 -1
- package/docs/changelog.md +55 -1
- package/docs/reference/classes/CLI.md +23 -7
- package/docs/reference/functions/actionCommandTsToSchema.md +9 -3
- package/docs/reference/functions/buildCommandTsToSchema.md +3 -1
- package/docs/reference/functions/tsToSchema.md +9 -3
- package/docs/reference/interfaces/ITsToSchemaConfig.md +2 -2
- package/package.json +9 -38
- /package/docs/reference/{globals.md → index.md} +0 -0
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var path = require('node:path');
|
|
4
|
+
var node_url = require('node:url');
|
|
5
|
+
var cliCore = require('@twin.org/cli-core');
|
|
6
|
+
var promises = require('node:fs/promises');
|
|
7
|
+
var core = require('@twin.org/core');
|
|
8
|
+
var tsJsonSchemaGenerator = require('ts-json-schema-generator');
|
|
9
|
+
|
|
10
|
+
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
11
|
+
// Copyright 2024 IOTA Stiftung.
|
|
12
|
+
// SPDX-License-Identifier: Apache-2.0.
|
|
13
|
+
/**
|
|
14
|
+
* Build the root command to be consumed by the CLI.
|
|
15
|
+
* @param program The command to build on.
|
|
16
|
+
*/
|
|
17
|
+
function buildCommandTsToSchema(program) {
|
|
18
|
+
program
|
|
19
|
+
.argument(core.I18n.formatMessage("commands.ts-to-schema.options.config.param"), core.I18n.formatMessage("commands.ts-to-schema.options.config.description"))
|
|
20
|
+
.argument(core.I18n.formatMessage("commands.ts-to-schema.options.output-folder.param"), core.I18n.formatMessage("commands.ts-to-schema.options.output-folder.description"))
|
|
21
|
+
.action(async (config, outputFolder, opts) => {
|
|
22
|
+
await actionCommandTsToSchema(config, outputFolder);
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Action the root command.
|
|
27
|
+
* @param configFile The optional configuration file.
|
|
28
|
+
* @param outputFolder The output folder for the schemas.
|
|
29
|
+
* @param opts The options for the command.
|
|
30
|
+
*/
|
|
31
|
+
async function actionCommandTsToSchema(configFile, outputFolder, opts) {
|
|
32
|
+
let outputWorkingDir;
|
|
33
|
+
try {
|
|
34
|
+
let config;
|
|
35
|
+
const fullConfigFile = path.resolve(configFile);
|
|
36
|
+
const fullOutputFolder = path.resolve(outputFolder);
|
|
37
|
+
outputWorkingDir = path.join(fullOutputFolder, "working");
|
|
38
|
+
cliCore.CLIDisplay.value(core.I18n.formatMessage("commands.ts-to-schema.labels.configJson"), fullConfigFile);
|
|
39
|
+
cliCore.CLIDisplay.value(core.I18n.formatMessage("commands.ts-to-schema.labels.outputFolder"), fullOutputFolder);
|
|
40
|
+
cliCore.CLIDisplay.value(core.I18n.formatMessage("commands.ts-to-schema.labels.outputWorkingDir"), outputWorkingDir);
|
|
41
|
+
cliCore.CLIDisplay.break();
|
|
42
|
+
try {
|
|
43
|
+
cliCore.CLIDisplay.task(core.I18n.formatMessage("commands.ts-to-schema.progress.loadingConfigJson"));
|
|
44
|
+
cliCore.CLIDisplay.break();
|
|
45
|
+
config = await cliCore.CLIUtils.readJsonFile(fullConfigFile);
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
throw new core.GeneralError("commands", "commands.ts-to-schema.configFailed", undefined, err);
|
|
49
|
+
}
|
|
50
|
+
if (core.Is.empty(config)) {
|
|
51
|
+
throw new core.GeneralError("commands", "commands.ts-to-schema.configFailed");
|
|
52
|
+
}
|
|
53
|
+
cliCore.CLIDisplay.task(core.I18n.formatMessage("commands.ts-to-schema.progress.creatingWorkingDir"));
|
|
54
|
+
await promises.mkdir(outputWorkingDir, { recursive: true });
|
|
55
|
+
cliCore.CLIDisplay.break();
|
|
56
|
+
await tsToSchema(config ?? {}, fullOutputFolder, outputWorkingDir);
|
|
57
|
+
cliCore.CLIDisplay.break();
|
|
58
|
+
cliCore.CLIDisplay.done();
|
|
59
|
+
}
|
|
60
|
+
finally {
|
|
61
|
+
try {
|
|
62
|
+
if (outputWorkingDir) {
|
|
63
|
+
await promises.rm(outputWorkingDir, { recursive: true });
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
catch { }
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Convert the TypeScript definitions to JSON Schemas.
|
|
71
|
+
* @param config The configuration for the app.
|
|
72
|
+
* @param outputFolder The location of the folder to output the JSON schemas.
|
|
73
|
+
* @param workingDirectory The folder the app was run from.
|
|
74
|
+
*/
|
|
75
|
+
async function tsToSchema(config, outputFolder, workingDirectory) {
|
|
76
|
+
await promises.writeFile(path.join(workingDirectory, "tsconfig.json"), JSON.stringify({
|
|
77
|
+
compilerOptions: {}
|
|
78
|
+
}, undefined, "\t"));
|
|
79
|
+
cliCore.CLIDisplay.task(core.I18n.formatMessage("commands.ts-to-schema.progress.generatingSchemas"));
|
|
80
|
+
const schemas = await generateSchemas(config.sources, config.types, workingDirectory);
|
|
81
|
+
cliCore.CLIDisplay.break();
|
|
82
|
+
cliCore.CLIDisplay.task(core.I18n.formatMessage("commands.ts-to-schema.progress.writingSchemas"));
|
|
83
|
+
for (const type of config.types) {
|
|
84
|
+
if (core.Is.empty(schemas[type])) {
|
|
85
|
+
throw new core.GeneralError("commands", "commands.ts-to-schema.schemaNotFound", { type });
|
|
86
|
+
}
|
|
87
|
+
let content = JSON.stringify(schemas[type], undefined, "\t");
|
|
88
|
+
if (core.Is.objectValue(config.externalReferences)) {
|
|
89
|
+
for (const external in config.externalReferences) {
|
|
90
|
+
content = content.replace(new RegExp(`#/definitions/${external}`, "g"), config.externalReferences[external]);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// First replace all types that start with II to a single I with the new base url
|
|
94
|
+
content = content.replace(/#\/definitions\/II(.*)/g, `${config.baseUrl}I$1`);
|
|
95
|
+
// Then other types starting with capitals (optionally interfaces starting with I)
|
|
96
|
+
content = content.replace(/#\/definitions\/I?([A-Z].*)/g, `${config.baseUrl}$1`);
|
|
97
|
+
const filename = path.join(outputFolder, `${core.StringHelper.stripPrefix(type)}.json`);
|
|
98
|
+
cliCore.CLIDisplay.value(core.I18n.formatMessage("commands.ts-to-schema.progress.writingSchema"), filename, 1);
|
|
99
|
+
await promises.writeFile(filename, `${content}\n`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Generate schemas for the models.
|
|
104
|
+
* @param modelDirWildcards The filenames for all the models.
|
|
105
|
+
* @param types The types of the schema objects.
|
|
106
|
+
* @param outputWorkingDir The working directory.
|
|
107
|
+
* @returns Nothing.
|
|
108
|
+
* @internal
|
|
109
|
+
*/
|
|
110
|
+
async function generateSchemas(modelDirWildcards, types, outputWorkingDir) {
|
|
111
|
+
const allSchemas = {};
|
|
112
|
+
const arraySingularTypes = [];
|
|
113
|
+
for (const type of types) {
|
|
114
|
+
if (type.endsWith("[]")) {
|
|
115
|
+
const singularType = type.slice(0, -2);
|
|
116
|
+
arraySingularTypes.push(singularType);
|
|
117
|
+
if (!types.includes(singularType)) {
|
|
118
|
+
types.push(singularType);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
for (const files of modelDirWildcards) {
|
|
123
|
+
cliCore.CLIDisplay.value(core.I18n.formatMessage("commands.ts-to-schema.progress.models"), files.replace(/\\/g, "/"), 1);
|
|
124
|
+
const generator = tsJsonSchemaGenerator.createGenerator({
|
|
125
|
+
path: files.replace(/\\/g, "/"),
|
|
126
|
+
type: "*",
|
|
127
|
+
tsconfig: path.join(outputWorkingDir, "tsconfig.json"),
|
|
128
|
+
skipTypeCheck: true,
|
|
129
|
+
expose: "all"
|
|
130
|
+
});
|
|
131
|
+
const schema = generator.createSchema("*");
|
|
132
|
+
if (schema.definitions) {
|
|
133
|
+
for (const def in schema.definitions) {
|
|
134
|
+
// Remove the partial markers
|
|
135
|
+
let defSub = def.replace(/^Partial<(.*?)>/g, "$1");
|
|
136
|
+
// Cleanup the generic markers
|
|
137
|
+
defSub = defSub.replace(/</g, "%3C").replace(/>/g, "%3E");
|
|
138
|
+
allSchemas[defSub] = schema.definitions[def];
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
const referencedSchemas = {};
|
|
143
|
+
extractTypes(allSchemas, types, referencedSchemas);
|
|
144
|
+
for (const arraySingularType of arraySingularTypes) {
|
|
145
|
+
referencedSchemas[`${arraySingularType}[]`] = {
|
|
146
|
+
type: "array",
|
|
147
|
+
items: {
|
|
148
|
+
$ref: `#/components/schemas/${arraySingularType}`
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
return referencedSchemas;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Extract the required types from all the known schemas.
|
|
156
|
+
* @param allSchemas All the known schemas.
|
|
157
|
+
* @param requiredTypes The required types.
|
|
158
|
+
* @param referencedSchemas The references schemas.
|
|
159
|
+
* @internal
|
|
160
|
+
*/
|
|
161
|
+
function extractTypes(allSchemas, requiredTypes, referencedSchemas) {
|
|
162
|
+
for (const type of requiredTypes) {
|
|
163
|
+
if (allSchemas[type] && !referencedSchemas[type]) {
|
|
164
|
+
referencedSchemas[type] = allSchemas[type];
|
|
165
|
+
extractTypesFromSchema(allSchemas, allSchemas[type], referencedSchemas);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Extract type from properties definition.
|
|
171
|
+
* @param allTypes All the known types.
|
|
172
|
+
* @param schema The schema to extract from.
|
|
173
|
+
* @param output The output types.
|
|
174
|
+
* @internal
|
|
175
|
+
*/
|
|
176
|
+
function extractTypesFromSchema(allTypes, schema, output) {
|
|
177
|
+
const additionalTypes = [];
|
|
178
|
+
if (core.Is.stringValue(schema.$ref)) {
|
|
179
|
+
additionalTypes.push(schema.$ref.replace("#/definitions/", "").replace(/^Partial%3C(.*?)%3E/g, "$1"));
|
|
180
|
+
}
|
|
181
|
+
else if (core.Is.object(schema.items)) {
|
|
182
|
+
if (core.Is.arrayValue(schema.items)) {
|
|
183
|
+
for (const itemSchema of schema.items) {
|
|
184
|
+
extractTypesFromSchema(allTypes, itemSchema, output);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
extractTypesFromSchema(allTypes, schema.items, output);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
else if (core.Is.object(schema.properties) || core.Is.object(schema.additionalProperties)) {
|
|
192
|
+
if (core.Is.object(schema.properties)) {
|
|
193
|
+
for (const prop in schema.properties) {
|
|
194
|
+
const p = schema.properties[prop];
|
|
195
|
+
if (core.Is.object(p)) {
|
|
196
|
+
extractTypesFromSchema(allTypes, p, output);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
if (core.Is.object(schema.additionalProperties)) {
|
|
201
|
+
extractTypesFromSchema(allTypes, schema.additionalProperties, output);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
else if (core.Is.arrayValue(schema.anyOf)) {
|
|
205
|
+
for (const prop of schema.anyOf) {
|
|
206
|
+
if (core.Is.object(prop)) {
|
|
207
|
+
extractTypesFromSchema(allTypes, prop, output);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
else if (core.Is.arrayValue(schema.oneOf)) {
|
|
212
|
+
for (const prop of schema.oneOf) {
|
|
213
|
+
if (core.Is.object(prop)) {
|
|
214
|
+
extractTypesFromSchema(allTypes, prop, output);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
if (additionalTypes.length > 0) {
|
|
219
|
+
extractTypes(allTypes, additionalTypes, output);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Copyright 2024 IOTA Stiftung.
|
|
224
|
+
// SPDX-License-Identifier: Apache-2.0.
|
|
225
|
+
/**
|
|
226
|
+
* The main entry point for the CLI.
|
|
227
|
+
*/
|
|
228
|
+
class CLI extends cliCore.CLIBase {
|
|
229
|
+
/**
|
|
230
|
+
* Run the app.
|
|
231
|
+
* @param argv The process arguments.
|
|
232
|
+
* @param localesDirectory The directory for the locales, default to relative to the script.
|
|
233
|
+
* @param options Additional options.
|
|
234
|
+
* @param options.overrideOutputWidth Override the output width.
|
|
235
|
+
* @returns The exit code.
|
|
236
|
+
*/
|
|
237
|
+
async run(argv, localesDirectory, options) {
|
|
238
|
+
return this.execute({
|
|
239
|
+
title: "TWIN TypeScript To Schema",
|
|
240
|
+
appName: "ts-to-schema",
|
|
241
|
+
version: "0.0.1-next.21", // x-release-please-version
|
|
242
|
+
icon: "⚙️ ",
|
|
243
|
+
supportsEnvFiles: false,
|
|
244
|
+
overrideOutputWidth: options?.overrideOutputWidth
|
|
245
|
+
}, localesDirectory ?? path.join(path.dirname(node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)))), "../locales"), argv);
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Configure any options or actions at the root program level.
|
|
249
|
+
* @param program The root program command.
|
|
250
|
+
*/
|
|
251
|
+
configureRoot(program) {
|
|
252
|
+
buildCommandTsToSchema(program);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
exports.CLI = CLI;
|
|
257
|
+
exports.actionCommandTsToSchema = actionCommandTsToSchema;
|
|
258
|
+
exports.buildCommandTsToSchema = buildCommandTsToSchema;
|
|
259
|
+
exports.tsToSchema = tsToSchema;
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
import { CLIDisplay, CLIUtils, CLIBase } from '@twin.org/cli-core';
|
|
4
|
+
import { mkdir, rm, writeFile } from 'node:fs/promises';
|
|
5
|
+
import { I18n, GeneralError, Is, StringHelper } from '@twin.org/core';
|
|
6
|
+
import { createGenerator } from 'ts-json-schema-generator';
|
|
7
|
+
|
|
8
|
+
// Copyright 2024 IOTA Stiftung.
|
|
9
|
+
// SPDX-License-Identifier: Apache-2.0.
|
|
10
|
+
/**
|
|
11
|
+
* Build the root command to be consumed by the CLI.
|
|
12
|
+
* @param program The command to build on.
|
|
13
|
+
*/
|
|
14
|
+
function buildCommandTsToSchema(program) {
|
|
15
|
+
program
|
|
16
|
+
.argument(I18n.formatMessage("commands.ts-to-schema.options.config.param"), I18n.formatMessage("commands.ts-to-schema.options.config.description"))
|
|
17
|
+
.argument(I18n.formatMessage("commands.ts-to-schema.options.output-folder.param"), I18n.formatMessage("commands.ts-to-schema.options.output-folder.description"))
|
|
18
|
+
.action(async (config, outputFolder, opts) => {
|
|
19
|
+
await actionCommandTsToSchema(config, outputFolder);
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Action the root command.
|
|
24
|
+
* @param configFile The optional configuration file.
|
|
25
|
+
* @param outputFolder The output folder for the schemas.
|
|
26
|
+
* @param opts The options for the command.
|
|
27
|
+
*/
|
|
28
|
+
async function actionCommandTsToSchema(configFile, outputFolder, opts) {
|
|
29
|
+
let outputWorkingDir;
|
|
30
|
+
try {
|
|
31
|
+
let config;
|
|
32
|
+
const fullConfigFile = path.resolve(configFile);
|
|
33
|
+
const fullOutputFolder = path.resolve(outputFolder);
|
|
34
|
+
outputWorkingDir = path.join(fullOutputFolder, "working");
|
|
35
|
+
CLIDisplay.value(I18n.formatMessage("commands.ts-to-schema.labels.configJson"), fullConfigFile);
|
|
36
|
+
CLIDisplay.value(I18n.formatMessage("commands.ts-to-schema.labels.outputFolder"), fullOutputFolder);
|
|
37
|
+
CLIDisplay.value(I18n.formatMessage("commands.ts-to-schema.labels.outputWorkingDir"), outputWorkingDir);
|
|
38
|
+
CLIDisplay.break();
|
|
39
|
+
try {
|
|
40
|
+
CLIDisplay.task(I18n.formatMessage("commands.ts-to-schema.progress.loadingConfigJson"));
|
|
41
|
+
CLIDisplay.break();
|
|
42
|
+
config = await CLIUtils.readJsonFile(fullConfigFile);
|
|
43
|
+
}
|
|
44
|
+
catch (err) {
|
|
45
|
+
throw new GeneralError("commands", "commands.ts-to-schema.configFailed", undefined, err);
|
|
46
|
+
}
|
|
47
|
+
if (Is.empty(config)) {
|
|
48
|
+
throw new GeneralError("commands", "commands.ts-to-schema.configFailed");
|
|
49
|
+
}
|
|
50
|
+
CLIDisplay.task(I18n.formatMessage("commands.ts-to-schema.progress.creatingWorkingDir"));
|
|
51
|
+
await mkdir(outputWorkingDir, { recursive: true });
|
|
52
|
+
CLIDisplay.break();
|
|
53
|
+
await tsToSchema(config ?? {}, fullOutputFolder, outputWorkingDir);
|
|
54
|
+
CLIDisplay.break();
|
|
55
|
+
CLIDisplay.done();
|
|
56
|
+
}
|
|
57
|
+
finally {
|
|
58
|
+
try {
|
|
59
|
+
if (outputWorkingDir) {
|
|
60
|
+
await rm(outputWorkingDir, { recursive: true });
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
catch { }
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Convert the TypeScript definitions to JSON Schemas.
|
|
68
|
+
* @param config The configuration for the app.
|
|
69
|
+
* @param outputFolder The location of the folder to output the JSON schemas.
|
|
70
|
+
* @param workingDirectory The folder the app was run from.
|
|
71
|
+
*/
|
|
72
|
+
async function tsToSchema(config, outputFolder, workingDirectory) {
|
|
73
|
+
await writeFile(path.join(workingDirectory, "tsconfig.json"), JSON.stringify({
|
|
74
|
+
compilerOptions: {}
|
|
75
|
+
}, undefined, "\t"));
|
|
76
|
+
CLIDisplay.task(I18n.formatMessage("commands.ts-to-schema.progress.generatingSchemas"));
|
|
77
|
+
const schemas = await generateSchemas(config.sources, config.types, workingDirectory);
|
|
78
|
+
CLIDisplay.break();
|
|
79
|
+
CLIDisplay.task(I18n.formatMessage("commands.ts-to-schema.progress.writingSchemas"));
|
|
80
|
+
for (const type of config.types) {
|
|
81
|
+
if (Is.empty(schemas[type])) {
|
|
82
|
+
throw new GeneralError("commands", "commands.ts-to-schema.schemaNotFound", { type });
|
|
83
|
+
}
|
|
84
|
+
let content = JSON.stringify(schemas[type], undefined, "\t");
|
|
85
|
+
if (Is.objectValue(config.externalReferences)) {
|
|
86
|
+
for (const external in config.externalReferences) {
|
|
87
|
+
content = content.replace(new RegExp(`#/definitions/${external}`, "g"), config.externalReferences[external]);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
// First replace all types that start with II to a single I with the new base url
|
|
91
|
+
content = content.replace(/#\/definitions\/II(.*)/g, `${config.baseUrl}I$1`);
|
|
92
|
+
// Then other types starting with capitals (optionally interfaces starting with I)
|
|
93
|
+
content = content.replace(/#\/definitions\/I?([A-Z].*)/g, `${config.baseUrl}$1`);
|
|
94
|
+
const filename = path.join(outputFolder, `${StringHelper.stripPrefix(type)}.json`);
|
|
95
|
+
CLIDisplay.value(I18n.formatMessage("commands.ts-to-schema.progress.writingSchema"), filename, 1);
|
|
96
|
+
await writeFile(filename, `${content}\n`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Generate schemas for the models.
|
|
101
|
+
* @param modelDirWildcards The filenames for all the models.
|
|
102
|
+
* @param types The types of the schema objects.
|
|
103
|
+
* @param outputWorkingDir The working directory.
|
|
104
|
+
* @returns Nothing.
|
|
105
|
+
* @internal
|
|
106
|
+
*/
|
|
107
|
+
async function generateSchemas(modelDirWildcards, types, outputWorkingDir) {
|
|
108
|
+
const allSchemas = {};
|
|
109
|
+
const arraySingularTypes = [];
|
|
110
|
+
for (const type of types) {
|
|
111
|
+
if (type.endsWith("[]")) {
|
|
112
|
+
const singularType = type.slice(0, -2);
|
|
113
|
+
arraySingularTypes.push(singularType);
|
|
114
|
+
if (!types.includes(singularType)) {
|
|
115
|
+
types.push(singularType);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
for (const files of modelDirWildcards) {
|
|
120
|
+
CLIDisplay.value(I18n.formatMessage("commands.ts-to-schema.progress.models"), files.replace(/\\/g, "/"), 1);
|
|
121
|
+
const generator = createGenerator({
|
|
122
|
+
path: files.replace(/\\/g, "/"),
|
|
123
|
+
type: "*",
|
|
124
|
+
tsconfig: path.join(outputWorkingDir, "tsconfig.json"),
|
|
125
|
+
skipTypeCheck: true,
|
|
126
|
+
expose: "all"
|
|
127
|
+
});
|
|
128
|
+
const schema = generator.createSchema("*");
|
|
129
|
+
if (schema.definitions) {
|
|
130
|
+
for (const def in schema.definitions) {
|
|
131
|
+
// Remove the partial markers
|
|
132
|
+
let defSub = def.replace(/^Partial<(.*?)>/g, "$1");
|
|
133
|
+
// Cleanup the generic markers
|
|
134
|
+
defSub = defSub.replace(/</g, "%3C").replace(/>/g, "%3E");
|
|
135
|
+
allSchemas[defSub] = schema.definitions[def];
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
const referencedSchemas = {};
|
|
140
|
+
extractTypes(allSchemas, types, referencedSchemas);
|
|
141
|
+
for (const arraySingularType of arraySingularTypes) {
|
|
142
|
+
referencedSchemas[`${arraySingularType}[]`] = {
|
|
143
|
+
type: "array",
|
|
144
|
+
items: {
|
|
145
|
+
$ref: `#/components/schemas/${arraySingularType}`
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
return referencedSchemas;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Extract the required types from all the known schemas.
|
|
153
|
+
* @param allSchemas All the known schemas.
|
|
154
|
+
* @param requiredTypes The required types.
|
|
155
|
+
* @param referencedSchemas The references schemas.
|
|
156
|
+
* @internal
|
|
157
|
+
*/
|
|
158
|
+
function extractTypes(allSchemas, requiredTypes, referencedSchemas) {
|
|
159
|
+
for (const type of requiredTypes) {
|
|
160
|
+
if (allSchemas[type] && !referencedSchemas[type]) {
|
|
161
|
+
referencedSchemas[type] = allSchemas[type];
|
|
162
|
+
extractTypesFromSchema(allSchemas, allSchemas[type], referencedSchemas);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Extract type from properties definition.
|
|
168
|
+
* @param allTypes All the known types.
|
|
169
|
+
* @param schema The schema to extract from.
|
|
170
|
+
* @param output The output types.
|
|
171
|
+
* @internal
|
|
172
|
+
*/
|
|
173
|
+
function extractTypesFromSchema(allTypes, schema, output) {
|
|
174
|
+
const additionalTypes = [];
|
|
175
|
+
if (Is.stringValue(schema.$ref)) {
|
|
176
|
+
additionalTypes.push(schema.$ref.replace("#/definitions/", "").replace(/^Partial%3C(.*?)%3E/g, "$1"));
|
|
177
|
+
}
|
|
178
|
+
else if (Is.object(schema.items)) {
|
|
179
|
+
if (Is.arrayValue(schema.items)) {
|
|
180
|
+
for (const itemSchema of schema.items) {
|
|
181
|
+
extractTypesFromSchema(allTypes, itemSchema, output);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
extractTypesFromSchema(allTypes, schema.items, output);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
else if (Is.object(schema.properties) || Is.object(schema.additionalProperties)) {
|
|
189
|
+
if (Is.object(schema.properties)) {
|
|
190
|
+
for (const prop in schema.properties) {
|
|
191
|
+
const p = schema.properties[prop];
|
|
192
|
+
if (Is.object(p)) {
|
|
193
|
+
extractTypesFromSchema(allTypes, p, output);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
if (Is.object(schema.additionalProperties)) {
|
|
198
|
+
extractTypesFromSchema(allTypes, schema.additionalProperties, output);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
else if (Is.arrayValue(schema.anyOf)) {
|
|
202
|
+
for (const prop of schema.anyOf) {
|
|
203
|
+
if (Is.object(prop)) {
|
|
204
|
+
extractTypesFromSchema(allTypes, prop, output);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
else if (Is.arrayValue(schema.oneOf)) {
|
|
209
|
+
for (const prop of schema.oneOf) {
|
|
210
|
+
if (Is.object(prop)) {
|
|
211
|
+
extractTypesFromSchema(allTypes, prop, output);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
if (additionalTypes.length > 0) {
|
|
216
|
+
extractTypes(allTypes, additionalTypes, output);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Copyright 2024 IOTA Stiftung.
|
|
221
|
+
// SPDX-License-Identifier: Apache-2.0.
|
|
222
|
+
/**
|
|
223
|
+
* The main entry point for the CLI.
|
|
224
|
+
*/
|
|
225
|
+
class CLI extends CLIBase {
|
|
226
|
+
/**
|
|
227
|
+
* Run the app.
|
|
228
|
+
* @param argv The process arguments.
|
|
229
|
+
* @param localesDirectory The directory for the locales, default to relative to the script.
|
|
230
|
+
* @param options Additional options.
|
|
231
|
+
* @param options.overrideOutputWidth Override the output width.
|
|
232
|
+
* @returns The exit code.
|
|
233
|
+
*/
|
|
234
|
+
async run(argv, localesDirectory, options) {
|
|
235
|
+
return this.execute({
|
|
236
|
+
title: "TWIN TypeScript To Schema",
|
|
237
|
+
appName: "ts-to-schema",
|
|
238
|
+
version: "0.0.1-next.21", // x-release-please-version
|
|
239
|
+
icon: "⚙️ ",
|
|
240
|
+
supportsEnvFiles: false,
|
|
241
|
+
overrideOutputWidth: options?.overrideOutputWidth
|
|
242
|
+
}, localesDirectory ?? path.join(path.dirname(fileURLToPath(import.meta.url)), "../locales"), argv);
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Configure any options or actions at the root program level.
|
|
246
|
+
* @param program The root program command.
|
|
247
|
+
*/
|
|
248
|
+
configureRoot(program) {
|
|
249
|
+
buildCommandTsToSchema(program);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
export { CLI, actionCommandTsToSchema, buildCommandTsToSchema, tsToSchema };
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
{
|
|
2
|
+
"error": {
|
|
3
|
+
"commands": {
|
|
4
|
+
"common": {
|
|
5
|
+
"missingEnv": "The \"{option}\" option is configured as an environment variable, but there is no environment variable with the name \"{value}\" set.",
|
|
6
|
+
"optionInvalidHex": "The \"{option}\" does not appear to be hex. \"{value}\"",
|
|
7
|
+
"optionInvalidBase64": "The \"{option}\" does not appear to be base64. \"{value}\"",
|
|
8
|
+
"optionInvalidHexBase64": "The \"{option}\" does not appear to be hex or base64. \"{value}\"",
|
|
9
|
+
"optionInvalidBech32": "The \"{option}\" does not appear to be bech32. \"{value}\"",
|
|
10
|
+
"optionMinValue": "The \"{option}\" option must be greater than or equal to {minValue}, it is {value}.",
|
|
11
|
+
"optionMaxValue": "The \"{option}\" option must be less than or equal to {maxValue}, it is {value}."
|
|
12
|
+
},
|
|
13
|
+
"ts-to-schema": {
|
|
14
|
+
"configFailed": "Configuration failed to load.",
|
|
15
|
+
"schemaNotFound": "Could not find the requested schema in the generated types \"{type}\"."
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"validation": {
|
|
19
|
+
"beEmpty": "{fieldName} must be empty",
|
|
20
|
+
"beNotEmpty": "{fieldName} must not be empty",
|
|
21
|
+
"beText": "{fieldName} must be text",
|
|
22
|
+
"beTextValue": "{fieldName} must contain some text",
|
|
23
|
+
"beTextMinMax": "{fieldName} must be longer than {minLength} and shorter than {maxLength} characters",
|
|
24
|
+
"beTextMin": "{fieldName} must be longer than {minLength} characters",
|
|
25
|
+
"beTextMax": "{fieldName} must be shorter than {maxLength} characters",
|
|
26
|
+
"beTextBase58": "{fieldName} must be text formatted using Base58 characters",
|
|
27
|
+
"beTextBase64": "{fieldName} must be text formatted using Base64 characters",
|
|
28
|
+
"beTextHex": "{fieldName} must be text formatted using Hex characters",
|
|
29
|
+
"beTextRegExp": "{fieldName} must be text formatted using the matching pattern {format}",
|
|
30
|
+
"beNumber": "{fieldName} must be a number",
|
|
31
|
+
"beNumberMinMax": "{fieldName} must be >= {minValue} and <= {maxValue}",
|
|
32
|
+
"beNumberMin": "{fieldName} must be >= {minValue}",
|
|
33
|
+
"beNumberMax": "{fieldName} must be <= {maxValue}",
|
|
34
|
+
"beWholeNumber": "{fieldName} must be a whole number",
|
|
35
|
+
"beWholeNumberMinMax": "{fieldName} must be a whole number >= {minValue} and <= {maxValue}",
|
|
36
|
+
"beWholeNumberMin": "{fieldName} must be a whole number >= {minValue}",
|
|
37
|
+
"beWholeNumberMax": "{fieldName} must be a whole number <= {maxValue}",
|
|
38
|
+
"beBigInteger": "{fieldName} must be a bigint",
|
|
39
|
+
"beBigIntegerMinMax": "{fieldName} must be a bigint >= {minValue} and <= {maxValue}",
|
|
40
|
+
"beBigIntegerMin": "{fieldName} must be a bigint >= {minValue}",
|
|
41
|
+
"beBigIntegerMax": "{fieldName} must be a bigint <= {maxValue}",
|
|
42
|
+
"beBoolean": "{fieldName} must be true or false",
|
|
43
|
+
"beDate": "{fieldName} must be a date",
|
|
44
|
+
"beDateTime": "{fieldName} must be a date/time",
|
|
45
|
+
"beTime": "{fieldName} must be a time",
|
|
46
|
+
"beTimestampMilliseconds": "{fieldName} must be a timestamp in milliseconds",
|
|
47
|
+
"beTimestampSeconds": "{fieldName} must be a timestamp in seconds",
|
|
48
|
+
"beObject": "{fieldName} must be an object",
|
|
49
|
+
"beArray": "{fieldName} must be an array",
|
|
50
|
+
"beArrayValue": "{fieldName} must be an array with at least one item",
|
|
51
|
+
"beIncluded": "{fieldName} is unrecognised",
|
|
52
|
+
"beByteArray": "{fieldName} must be a byte array",
|
|
53
|
+
"beUrn": "{fieldName} must be a correctly formatted urn",
|
|
54
|
+
"beUrl": "{fieldName} must be a correctly formatted url",
|
|
55
|
+
"beJSON": "{fieldName} must be correctly formatted JSON",
|
|
56
|
+
"beEmail": "{fieldName} must be a correctly formatted e-mail address",
|
|
57
|
+
"failed": "Validation failed",
|
|
58
|
+
"failedObject": "Validation of \"{objectName}\" failed"
|
|
59
|
+
},
|
|
60
|
+
"guard": {
|
|
61
|
+
"undefined": "Property \"{property}\" must be defined, it is \"{value}\"",
|
|
62
|
+
"string": "Property \"{property}\" must be a string, it is \"{value}\"",
|
|
63
|
+
"stringEmpty": "Property \"{property}\" must have a value, it is empty",
|
|
64
|
+
"stringBase64": "Property \"{property}\" must be a base64 encoded string, it is \"{value}\"",
|
|
65
|
+
"stringBase64Url": "Property \"{property}\" must be a base64 url encoded string, it is \"{value}\"",
|
|
66
|
+
"stringBase58": "Property \"{property}\" must be a base58 encoded string, it is \"{value}\"",
|
|
67
|
+
"stringHex": "Property \"{property}\" must be a hex string, it is \"{value}\"",
|
|
68
|
+
"stringHexLength": "Property \"{property}\" must be a hex string of length \"{options}\", it is \"{value}\"",
|
|
69
|
+
"stringJson": "Property \"{property}\" must be a JSON string",
|
|
70
|
+
"number": "Property \"{property}\" must be a number, it is \"{value}\"",
|
|
71
|
+
"integer": "Property \"{property}\" must be an integer, it is \"{value}\"",
|
|
72
|
+
"bigint": "Property \"{property}\" must be a bigint, it is \"{value}\"",
|
|
73
|
+
"boolean": "Property \"{property}\" must be a boolean, it is \"{value}\"",
|
|
74
|
+
"date": "Property \"{property}\" must be a date, it is \"{value}\"",
|
|
75
|
+
"timestampMilliseconds": "Property \"{property}\" must be a timestamp in milliseconds, it is \"{value}\"",
|
|
76
|
+
"timestampSeconds": "Property \"{property}\" must be a timestamp in seconds, it is \"{value}\"",
|
|
77
|
+
"objectUndefined": "Property \"{property}\" must be an object, it is \"undefined\"",
|
|
78
|
+
"object": "Property \"{property}\" must be an object, it is \"{value}\"",
|
|
79
|
+
"objectValue": "Property \"{property}\" must be an object, with at least one property, it is \"{value}\"",
|
|
80
|
+
"array": "Property \"{property}\" must be an array, it is \"{value}\"",
|
|
81
|
+
"arrayValue": "Property \"{property}\" must be an array with at least one item",
|
|
82
|
+
"arrayOneOf": "Property \"{property}\" must be one of [{options}], it is \"{value}\"",
|
|
83
|
+
"uint8Array": "Property \"{property}\" must be a Uint8Array, it is \"{value}\"",
|
|
84
|
+
"function": "Property \"{property}\" must be a function, it is \"{value}\"",
|
|
85
|
+
"urn": "Property \"{property}\" must be a Urn formatted string, it is \"{value}\"",
|
|
86
|
+
"url": "Property \"{property}\" must be a Url formatted string, it is \"{value}\"",
|
|
87
|
+
"email": "Property \"{property}\" must be string in e-mail format, it is \"{value}\"",
|
|
88
|
+
"length32Multiple": "Property \"{property}\" should be a multiple of 32, it is {value}",
|
|
89
|
+
"lengthEntropy": "Property \"{property}\" should be a multiple of 4, >=16 and <= 32, it is {value}",
|
|
90
|
+
"length3Multiple": "Property \"{property}\" should be a multiple of 3, it is {value}",
|
|
91
|
+
"greaterThan0": "Property \"{property}\" must be greater than zero, it is {value}"
|
|
92
|
+
},
|
|
93
|
+
"objectHelper": {
|
|
94
|
+
"failedBytesToJSON": "Failed converting bytes to JSON",
|
|
95
|
+
"cannotSetArrayIndex": "Cannot set property \"{property}\" using index \"{index}\" as it is not an array",
|
|
96
|
+
"cannotSetProperty": "Cannot set property \"{property}\" when the target is not an object"
|
|
97
|
+
},
|
|
98
|
+
"common": {
|
|
99
|
+
"notImplementedMethod": "The method \"{method}\" has not been implemented",
|
|
100
|
+
"validation": "Validation failed"
|
|
101
|
+
},
|
|
102
|
+
"factory": {
|
|
103
|
+
"noUnregister": "There is no {typeName} registered with the name \"{name}\"",
|
|
104
|
+
"noGet": "The requested {typeName} \"{name}\" does not exist in the factory"
|
|
105
|
+
},
|
|
106
|
+
"bitString": {
|
|
107
|
+
"outOfRange": "The index should be >= 0 and less than the length of the bit string"
|
|
108
|
+
},
|
|
109
|
+
"base32": {
|
|
110
|
+
"invalidCharacter": "Data contains a character \"{invalidCharacter}\" which is not in the charset"
|
|
111
|
+
},
|
|
112
|
+
"base64": {
|
|
113
|
+
"length4Multiple": "Invalid length should be a multiple of 4, it is \"{value}\""
|
|
114
|
+
},
|
|
115
|
+
"base58": {
|
|
116
|
+
"invalidCharacter": "Data contains a character \"{invalidCharacter}\" which is not in the charset"
|
|
117
|
+
},
|
|
118
|
+
"jsonHelper": {
|
|
119
|
+
"failedPatch": "Failed to patch the JSON object, patch index \"{index}\" failed"
|
|
120
|
+
},
|
|
121
|
+
"bip39": {
|
|
122
|
+
"missingMnemonicWord": "The mnemonic contains a word not in the wordlist, \"{value}\"",
|
|
123
|
+
"checksumMismatch": "The checksum does not match \"{newChecksum}\" != \"{checksumBits}\""
|
|
124
|
+
},
|
|
125
|
+
"ed25519": {
|
|
126
|
+
"privateKeyLength": "The private key length is incorrect, it should be \"{requiredSize}\" but is \"{actualSize}\"",
|
|
127
|
+
"publicKeyLength": "The public key length is incorrect, it should be \"{requiredSize}\" but is \"{actualSize}\""
|
|
128
|
+
},
|
|
129
|
+
"secp256k1": {
|
|
130
|
+
"privateKeyLength": "The private key length is incorrect, it should be \"{requiredSize}\" but is \"{actualSize}\"",
|
|
131
|
+
"publicKeyLength": "The public key length is incorrect, it should be \"{requiredSize}\" but is \"{actualSize}\""
|
|
132
|
+
},
|
|
133
|
+
"x25519": {
|
|
134
|
+
"invalidPublicKey": "Invalid Ed25519 Public Key"
|
|
135
|
+
},
|
|
136
|
+
"blake2b": {
|
|
137
|
+
"outputLength64": "The output length should be between 1 and 64, it is \"{outputLength}\"",
|
|
138
|
+
"keyLength64": "The key length should be between 1 and 64, it is \"{keyLength}\""
|
|
139
|
+
},
|
|
140
|
+
"sha512": {
|
|
141
|
+
"bitSize": "Only 224, 256, 384 or 512 bits are supported, it is \"{bitSize}\""
|
|
142
|
+
},
|
|
143
|
+
"sha256": {
|
|
144
|
+
"bitSize": "Only 224 or 256 bits are supported, it is \"{bitSize}\""
|
|
145
|
+
},
|
|
146
|
+
"sha3": {
|
|
147
|
+
"bitSize": "Only 224, 256, 384 or 512 bits are supported, it is \"{bitSize}\""
|
|
148
|
+
},
|
|
149
|
+
"hmacSha256": {
|
|
150
|
+
"bitSize": "Only 224 or 256 bits are supported, it is \"{bitSize}\""
|
|
151
|
+
},
|
|
152
|
+
"hmacSha512": {
|
|
153
|
+
"bitSize": "Only 224, 256, 384 or 512 bits are supported, it is \"{bitSize}\""
|
|
154
|
+
},
|
|
155
|
+
"bech32": {
|
|
156
|
+
"decodeFailed": "The address contains decoding failed for address \"{bech32}\"",
|
|
157
|
+
"invalidChecksum": "The address contains an invalid checksum in address, \"{bech32}\"",
|
|
158
|
+
"separatorMisused": "The separator character '1' should only be used between hrp and data, \"{bech32}\"",
|
|
159
|
+
"lowerUpper": "The address my use either lowercase or uppercase, \"{bech32}\"",
|
|
160
|
+
"dataTooShort": "The address does not contain enough data to decode, \"{bech32}\""
|
|
161
|
+
},
|
|
162
|
+
"pbkdf2": {
|
|
163
|
+
"keyTooLong": "The requested key length \"{keyLength}\" is too long, based on the \"{macLength}\""
|
|
164
|
+
},
|
|
165
|
+
"chaCha20Poly1305": {
|
|
166
|
+
"noAadWithData": "You can not set the aad when there is already data",
|
|
167
|
+
"noAuthTag": "Can not finalise when the auth tag is not set",
|
|
168
|
+
"authenticationFailed": "The data could not be authenticated",
|
|
169
|
+
"authTagDecrypting": "Can not get the auth tag when decrypting",
|
|
170
|
+
"authTagEncrypting": "Can not set the auth tag when encrypting",
|
|
171
|
+
"noAuthTagSet": "The auth tag has not been set"
|
|
172
|
+
},
|
|
173
|
+
"bip44": {
|
|
174
|
+
"unsupportedKeyType": "The key type \"{keyType}\" is not supported"
|
|
175
|
+
},
|
|
176
|
+
"slip0010": {
|
|
177
|
+
"invalidSeed": "The seed is invalid \"{seed}\""
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
"cli": {
|
|
181
|
+
"progress": {
|
|
182
|
+
"done": "Done.",
|
|
183
|
+
"error": "Error",
|
|
184
|
+
"loadingEnvFiles": "Loading env files",
|
|
185
|
+
"pleaseWait": "Please wait...",
|
|
186
|
+
"writingJsonFile": "Writing JSON file",
|
|
187
|
+
"writingEnvFile": "Writing env file",
|
|
188
|
+
"readingJsonFile": "Reading JSON file",
|
|
189
|
+
"readingEnvFile": "Reading env file"
|
|
190
|
+
},
|
|
191
|
+
"options": {
|
|
192
|
+
"lang": {
|
|
193
|
+
"param": "--lang '<'lang'>'",
|
|
194
|
+
"description": "The language to display the output in."
|
|
195
|
+
},
|
|
196
|
+
"load-env": {
|
|
197
|
+
"param": "--load-env [env...]",
|
|
198
|
+
"description": "Load the env files to initialise any environment variables."
|
|
199
|
+
},
|
|
200
|
+
"no-console": {
|
|
201
|
+
"param": "--no-console",
|
|
202
|
+
"description": "Hides the output in the console."
|
|
203
|
+
},
|
|
204
|
+
"json": {
|
|
205
|
+
"param": "--json '<'filename'>'",
|
|
206
|
+
"description": "Creates a JSON file containing the output."
|
|
207
|
+
},
|
|
208
|
+
"env": {
|
|
209
|
+
"param": "--env '<'filename'>'",
|
|
210
|
+
"description": "Creates an env file containing the output."
|
|
211
|
+
},
|
|
212
|
+
"merge-json": {
|
|
213
|
+
"param": "--merge-json",
|
|
214
|
+
"description": "If the JSON file already exists merge the data instead of overwriting."
|
|
215
|
+
},
|
|
216
|
+
"merge-env": {
|
|
217
|
+
"param": "--merge-env",
|
|
218
|
+
"description": "If the env file already exists merge the data instead of overwriting."
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
},
|
|
222
|
+
"errorNames": {
|
|
223
|
+
"error": "Error",
|
|
224
|
+
"generalError": "General",
|
|
225
|
+
"guardError": "Guard",
|
|
226
|
+
"conflictError": "Conflict",
|
|
227
|
+
"notFoundError": "Not Found",
|
|
228
|
+
"notSupportedError": "Not Supported",
|
|
229
|
+
"alreadyExistsError": "Already Exists",
|
|
230
|
+
"notImplementedError": "Not Implemented",
|
|
231
|
+
"validationError": "Validation",
|
|
232
|
+
"unprocessableError": "Unprocessable"
|
|
233
|
+
},
|
|
234
|
+
"validation": {
|
|
235
|
+
"defaultFieldName": "The field"
|
|
236
|
+
},
|
|
237
|
+
"commands": {
|
|
238
|
+
"ts-to-schema": {
|
|
239
|
+
"options": {
|
|
240
|
+
"config": {
|
|
241
|
+
"param": "'<'config'>'",
|
|
242
|
+
"description": "Path to the JSON configuration file."
|
|
243
|
+
},
|
|
244
|
+
"output-folder": {
|
|
245
|
+
"param": "'<'output-folder'>'",
|
|
246
|
+
"description": "The folder to write the schema files."
|
|
247
|
+
}
|
|
248
|
+
},
|
|
249
|
+
"progress": {
|
|
250
|
+
"loadingConfigJson": "Loading Config JSON",
|
|
251
|
+
"creatingWorkingDir": "Creating Working Directory",
|
|
252
|
+
"generatingSchemas": "Generating Schemas",
|
|
253
|
+
"finalisingSchemas": "Finalising Schemas",
|
|
254
|
+
"writingSchemas": "Writing Schemas",
|
|
255
|
+
"writingSchema": "Writing Schema",
|
|
256
|
+
"models": "Models"
|
|
257
|
+
},
|
|
258
|
+
"labels": {
|
|
259
|
+
"configJson": "Config JSON",
|
|
260
|
+
"outputFolder": "Output Folder",
|
|
261
|
+
"outputWorkingDir": "Output Working Directory"
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
package/dist/types/cli.d.ts
CHANGED
|
@@ -8,9 +8,13 @@ export declare class CLI extends CLIBase {
|
|
|
8
8
|
* Run the app.
|
|
9
9
|
* @param argv The process arguments.
|
|
10
10
|
* @param localesDirectory The directory for the locales, default to relative to the script.
|
|
11
|
+
* @param options Additional options.
|
|
12
|
+
* @param options.overrideOutputWidth Override the output width.
|
|
11
13
|
* @returns The exit code.
|
|
12
14
|
*/
|
|
13
|
-
run(argv: string[], localesDirectory?: string
|
|
15
|
+
run(argv: string[], localesDirectory?: string, options?: {
|
|
16
|
+
overrideOutputWidth?: number;
|
|
17
|
+
}): Promise<number>;
|
|
14
18
|
/**
|
|
15
19
|
* Configure any options or actions at the root program level.
|
|
16
20
|
* @param program The root program command.
|
package/docs/changelog.md
CHANGED
|
@@ -1,5 +1,59 @@
|
|
|
1
1
|
# @twin.org/ts-to-schema - Changelog
|
|
2
2
|
|
|
3
|
-
## v0.0.1-next.
|
|
3
|
+
## [0.0.1-next.21](https://github.com/twinfoundation/tools/compare/ts-to-schema-v0.0.1-next.20...ts-to-schema-v0.0.1-next.21) (2025-04-17)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* use shared store mechanism ([#31](https://github.com/twinfoundation/tools/issues/31)) ([d9fe68b](https://github.com/twinfoundation/tools/commit/d9fe68b903d1268c7cb3c64772df5cb78fd63667))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Dependencies
|
|
12
|
+
|
|
13
|
+
* The following workspace dependencies were updated
|
|
14
|
+
* dependencies
|
|
15
|
+
* @twin.org/nameof bumped from 0.0.1-next.20 to 0.0.1-next.21
|
|
16
|
+
* devDependencies
|
|
17
|
+
* @twin.org/merge-locales bumped from 0.0.1-next.20 to 0.0.1-next.21
|
|
18
|
+
* @twin.org/nameof-transformer bumped from 0.0.1-next.20 to 0.0.1-next.21
|
|
19
|
+
* @twin.org/nameof-vitest-plugin bumped from 0.0.1-next.20 to 0.0.1-next.21
|
|
20
|
+
|
|
21
|
+
## [0.0.1-next.20](https://github.com/twinfoundation/tools/compare/ts-to-schema-v0.0.1-next.19...ts-to-schema-v0.0.1-next.20) (2025-03-28)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
### Miscellaneous Chores
|
|
25
|
+
|
|
26
|
+
* **ts-to-schema:** Synchronize repo versions
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
### Dependencies
|
|
30
|
+
|
|
31
|
+
* The following workspace dependencies were updated
|
|
32
|
+
* dependencies
|
|
33
|
+
* @twin.org/nameof bumped from 0.0.1-next.19 to 0.0.1-next.20
|
|
34
|
+
* devDependencies
|
|
35
|
+
* @twin.org/merge-locales bumped from 0.0.1-next.19 to 0.0.1-next.20
|
|
36
|
+
* @twin.org/nameof-transformer bumped from 0.0.1-next.19 to 0.0.1-next.20
|
|
37
|
+
* @twin.org/nameof-vitest-plugin bumped from 0.0.1-next.19 to 0.0.1-next.20
|
|
38
|
+
|
|
39
|
+
## [0.0.1-next.19](https://github.com/twinfoundation/tools/compare/ts-to-schema-v0.0.1-next.18...ts-to-schema-v0.0.1-next.19) (2025-03-26)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
### Miscellaneous Chores
|
|
43
|
+
|
|
44
|
+
* **ts-to-schema:** Synchronize repo versions
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
### Dependencies
|
|
48
|
+
|
|
49
|
+
* The following workspace dependencies were updated
|
|
50
|
+
* dependencies
|
|
51
|
+
* @twin.org/nameof bumped from 0.0.1-next.18 to 0.0.1-next.19
|
|
52
|
+
* devDependencies
|
|
53
|
+
* @twin.org/merge-locales bumped from 0.0.1-next.18 to 0.0.1-next.19
|
|
54
|
+
* @twin.org/nameof-transformer bumped from 0.0.1-next.18 to 0.0.1-next.19
|
|
55
|
+
* @twin.org/nameof-vitest-plugin bumped from 0.0.1-next.18 to 0.0.1-next.19
|
|
56
|
+
|
|
57
|
+
## v0.0.1-next.18
|
|
4
58
|
|
|
5
59
|
- Initial Release
|
|
@@ -8,13 +8,13 @@ The main entry point for the CLI.
|
|
|
8
8
|
|
|
9
9
|
## Constructors
|
|
10
10
|
|
|
11
|
-
###
|
|
11
|
+
### Constructor
|
|
12
12
|
|
|
13
|
-
> **new CLI**():
|
|
13
|
+
> **new CLI**(): `CLI`
|
|
14
14
|
|
|
15
15
|
#### Returns
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
`CLI`
|
|
18
18
|
|
|
19
19
|
#### Inherited from
|
|
20
20
|
|
|
@@ -24,20 +24,34 @@ The main entry point for the CLI.
|
|
|
24
24
|
|
|
25
25
|
### run()
|
|
26
26
|
|
|
27
|
-
> **run**(`argv`, `localesDirectory
|
|
27
|
+
> **run**(`argv`, `localesDirectory?`, `options?`): `Promise`\<`number`\>
|
|
28
28
|
|
|
29
29
|
Run the app.
|
|
30
30
|
|
|
31
31
|
#### Parameters
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
##### argv
|
|
34
|
+
|
|
35
|
+
`string`[]
|
|
34
36
|
|
|
35
37
|
The process arguments.
|
|
36
38
|
|
|
37
|
-
|
|
39
|
+
##### localesDirectory?
|
|
40
|
+
|
|
41
|
+
`string`
|
|
38
42
|
|
|
39
43
|
The directory for the locales, default to relative to the script.
|
|
40
44
|
|
|
45
|
+
##### options?
|
|
46
|
+
|
|
47
|
+
Additional options.
|
|
48
|
+
|
|
49
|
+
###### overrideOutputWidth?
|
|
50
|
+
|
|
51
|
+
`number`
|
|
52
|
+
|
|
53
|
+
Override the output width.
|
|
54
|
+
|
|
41
55
|
#### Returns
|
|
42
56
|
|
|
43
57
|
`Promise`\<`number`\>
|
|
@@ -54,7 +68,9 @@ Configure any options or actions at the root program level.
|
|
|
54
68
|
|
|
55
69
|
#### Parameters
|
|
56
70
|
|
|
57
|
-
|
|
71
|
+
##### program
|
|
72
|
+
|
|
73
|
+
`Command`
|
|
58
74
|
|
|
59
75
|
The root program command.
|
|
60
76
|
|
|
@@ -6,15 +6,21 @@ Action the root command.
|
|
|
6
6
|
|
|
7
7
|
## Parameters
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
### configFile
|
|
10
|
+
|
|
11
|
+
`string`
|
|
10
12
|
|
|
11
13
|
The optional configuration file.
|
|
12
14
|
|
|
13
|
-
|
|
15
|
+
### outputFolder
|
|
16
|
+
|
|
17
|
+
`string`
|
|
14
18
|
|
|
15
19
|
The output folder for the schemas.
|
|
16
20
|
|
|
17
|
-
|
|
21
|
+
### opts
|
|
22
|
+
|
|
23
|
+
`unknown`
|
|
18
24
|
|
|
19
25
|
The options for the command.
|
|
20
26
|
|
|
@@ -6,15 +6,21 @@ Convert the TypeScript definitions to JSON Schemas.
|
|
|
6
6
|
|
|
7
7
|
## Parameters
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
### config
|
|
10
|
+
|
|
11
|
+
[`ITsToSchemaConfig`](../interfaces/ITsToSchemaConfig.md)
|
|
10
12
|
|
|
11
13
|
The configuration for the app.
|
|
12
14
|
|
|
13
|
-
|
|
15
|
+
### outputFolder
|
|
16
|
+
|
|
17
|
+
`string`
|
|
14
18
|
|
|
15
19
|
The location of the folder to output the JSON schemas.
|
|
16
20
|
|
|
17
|
-
|
|
21
|
+
### workingDirectory
|
|
22
|
+
|
|
23
|
+
`string`
|
|
18
24
|
|
|
19
25
|
The folder the app was run from.
|
|
20
26
|
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@twin.org/ts-to-schema",
|
|
3
|
-
"version": "0.0.1-next.
|
|
3
|
+
"version": "0.0.1-next.21",
|
|
4
4
|
"description": "Tool to convert TypeScript definitions to JSON schemas",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "git+https://github.com/twinfoundation/tools.git",
|
|
8
|
-
"directory": "
|
|
8
|
+
"directory": "apps/ts-to-schema"
|
|
9
9
|
},
|
|
10
10
|
"author": "martyn.janes@iota.org",
|
|
11
11
|
"license": "Apache-2.0",
|
|
@@ -13,52 +13,23 @@
|
|
|
13
13
|
"engines": {
|
|
14
14
|
"node": ">=20.0.0"
|
|
15
15
|
},
|
|
16
|
-
"scripts": {
|
|
17
|
-
"clean": "rimraf dist coverage",
|
|
18
|
-
"build": "tspc",
|
|
19
|
-
"merge-locales": "merge-locales",
|
|
20
|
-
"test": "vitest --run --config ./vitest.config.ts --no-cache",
|
|
21
|
-
"coverage": "vitest --run --coverage --config ./vitest.config.ts --no-cache",
|
|
22
|
-
"bundle:esm": "rollup --config rollup.config.mjs --environment MODULE:esm",
|
|
23
|
-
"bundle:cjs": "rollup --config rollup.config.mjs --environment MODULE:cjs",
|
|
24
|
-
"bundle": "npm run bundle:esm && npm run bundle:cjs",
|
|
25
|
-
"docs:clean": "rimraf docs/reference",
|
|
26
|
-
"docs:generate": "typedoc",
|
|
27
|
-
"docs": "npm run docs:clean && npm run docs:generate",
|
|
28
|
-
"dist": "npm run clean && npm run build && npm run merge-locales && npm run test && npm run bundle && npm run docs"
|
|
29
|
-
},
|
|
30
16
|
"dependencies": {
|
|
31
17
|
"@twin.org/cli-core": "next",
|
|
32
18
|
"@twin.org/core": "next",
|
|
33
|
-
"@twin.org/nameof": "0.0.1-next.
|
|
34
|
-
"commander": "
|
|
35
|
-
"glob": "11.0.
|
|
36
|
-
"jsonschema": "1.
|
|
37
|
-
"ts-json-schema-generator": "2.4.0
|
|
38
|
-
},
|
|
39
|
-
"devDependencies": {
|
|
40
|
-
"@twin.org/merge-locales": "0.0.1-next.2",
|
|
41
|
-
"@twin.org/nameof-transformer": "0.0.1-next.2",
|
|
42
|
-
"@types/node": "22.5.5",
|
|
43
|
-
"@vitest/coverage-v8": "2.1.1",
|
|
44
|
-
"copyfiles": "2.4.1",
|
|
45
|
-
"rimraf": "6.0.1",
|
|
46
|
-
"rollup": "4.21.3",
|
|
47
|
-
"rollup-plugin-typescript2": "0.36.0",
|
|
48
|
-
"ts-patch": "3.2.1",
|
|
49
|
-
"typedoc": "0.26.7",
|
|
50
|
-
"typedoc-plugin-markdown": "4.2.7",
|
|
51
|
-
"typescript": "5.6.2",
|
|
52
|
-
"vitest": "2.1.1"
|
|
19
|
+
"@twin.org/nameof": "0.0.1-next.21",
|
|
20
|
+
"commander": "13.1.0",
|
|
21
|
+
"glob": "11.0.1",
|
|
22
|
+
"jsonschema": "1.5.0",
|
|
23
|
+
"ts-json-schema-generator": "2.4.0"
|
|
53
24
|
},
|
|
54
25
|
"main": "./dist/cjs/index.cjs",
|
|
55
26
|
"module": "./dist/esm/index.mjs",
|
|
56
27
|
"types": "./dist/types/index.d.ts",
|
|
57
28
|
"exports": {
|
|
58
29
|
".": {
|
|
30
|
+
"types": "./dist/types/index.d.ts",
|
|
59
31
|
"require": "./dist/cjs/index.cjs",
|
|
60
|
-
"import": "./dist/esm/index.mjs"
|
|
61
|
-
"types": "./dist/types/index.d.ts"
|
|
32
|
+
"import": "./dist/esm/index.mjs"
|
|
62
33
|
}
|
|
63
34
|
},
|
|
64
35
|
"files": [
|
|
File without changes
|