@opra/cli 0.33.13 → 1.0.0-alpha.7
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/bin/bin/oprimp.mjs +1 -1
- package/bin/oprimp.mjs +1 -1
- package/cjs/code-block.js +17 -0
- package/cjs/index.js +1 -1
- package/cjs/oprimp-cli.js +9 -9
- package/cjs/ts-generator/http-controller-node.js +21 -0
- package/cjs/ts-generator/index.js +4 -0
- package/cjs/ts-generator/processors/clean-directory.js +35 -0
- package/cjs/ts-generator/processors/process-data-types.js +252 -0
- package/cjs/ts-generator/processors/process-document.js +60 -0
- package/cjs/ts-generator/processors/process-http-api.js +45 -0
- package/cjs/ts-generator/processors/process-http-controller.js +189 -0
- package/cjs/ts-generator/ts-file.js +101 -0
- package/cjs/ts-generator/ts-generator.js +108 -0
- package/cjs/ts-generator/utils/locate-named-type.js +16 -0
- package/cjs/{utils → ts-generator/utils}/string-utils.js +17 -16
- package/esm/code-block.js +13 -0
- package/esm/index.js +1 -1
- package/esm/oprimp-cli.js +9 -9
- package/esm/ts-generator/http-controller-node.js +18 -0
- package/esm/ts-generator/index.js +1 -0
- package/esm/ts-generator/processors/clean-directory.js +30 -0
- package/esm/ts-generator/processors/process-data-types.js +241 -0
- package/esm/ts-generator/processors/process-document.js +55 -0
- package/esm/ts-generator/processors/process-http-api.js +40 -0
- package/esm/ts-generator/processors/process-http-controller.js +184 -0
- package/esm/ts-generator/ts-file.js +96 -0
- package/esm/ts-generator/ts-generator.js +103 -0
- package/esm/ts-generator/utils/locate-named-type.js +12 -0
- package/esm/{utils → ts-generator/utils}/string-utils.js +17 -16
- package/package.json +8 -6
- package/types/code-block.d.ts +5 -0
- package/types/{api-exporter/file-writer.d.ts → file-writer.d.ts} +1 -1
- package/types/index.d.ts +1 -1
- package/types/ts-generator/http-controller-node.d.ts +1 -0
- package/types/ts-generator/index.d.ts +1 -0
- package/types/ts-generator/processors/clean-directory.d.ts +2 -0
- package/types/ts-generator/processors/process-data-types.d.ts +30 -0
- package/types/ts-generator/processors/process-document.d.ts +8 -0
- package/types/ts-generator/processors/process-http-api.d.ts +3 -0
- package/types/ts-generator/processors/process-http-controller.d.ts +3 -0
- package/types/{api-exporter → ts-generator}/ts-file.d.ts +4 -4
- package/types/ts-generator/ts-generator.d.ts +70 -0
- package/types/ts-generator/utils/locate-named-type.d.ts +2 -0
- package/cjs/api-exporter/api-exporter.js +0 -115
- package/cjs/api-exporter/process-resources.js +0 -131
- package/cjs/api-exporter/process-types.js +0 -261
- package/cjs/api-exporter/ts-file.js +0 -104
- package/cjs/utils/get-caller-file.util.js +0 -24
- package/esm/api-exporter/api-exporter.js +0 -110
- package/esm/api-exporter/process-resources.js +0 -126
- package/esm/api-exporter/process-types.js +0 -249
- package/esm/api-exporter/ts-file.js +0 -99
- package/esm/utils/get-caller-file.util.js +0 -20
- package/types/api-exporter/api-exporter.d.ts +0 -46
- package/types/api-exporter/process-resources.d.ts +0 -4
- package/types/api-exporter/process-types.d.ts +0 -62
- package/types/utils/get-caller-file.util.d.ts +0 -1
- /package/cjs/{api-exporter/file-writer.js → file-writer.js} +0 -0
- /package/esm/{api-exporter/file-writer.js → file-writer.js} +0 -0
- /package/types/{utils → ts-generator/utils}/string-utils.d.ts +0 -0
package/bin/bin/oprimp.mjs
CHANGED
package/bin/oprimp.mjs
CHANGED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CodeBlock = void 0;
|
|
4
|
+
class CodeBlock {
|
|
5
|
+
toString() {
|
|
6
|
+
// if (this.content) return this.content;
|
|
7
|
+
let out = '';
|
|
8
|
+
for (const x of Object.values(this)) {
|
|
9
|
+
out += String(x);
|
|
10
|
+
}
|
|
11
|
+
return out;
|
|
12
|
+
}
|
|
13
|
+
[Symbol.toStringTag]() {
|
|
14
|
+
return this.toString();
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
exports.CodeBlock = CodeBlock;
|
package/cjs/index.js
CHANGED
package/cjs/oprimp-cli.js
CHANGED
|
@@ -7,29 +7,29 @@ const console = tslib_1.__importStar(require("console"));
|
|
|
7
7
|
const fs = tslib_1.__importStar(require("fs"));
|
|
8
8
|
const path_1 = tslib_1.__importDefault(require("path"));
|
|
9
9
|
const process = tslib_1.__importStar(require("process"));
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
const dirname = path_1.default.dirname((0,
|
|
10
|
+
const common_1 = require("@opra/common");
|
|
11
|
+
const ts_generator_js_1 = require("./ts-generator/ts-generator.js");
|
|
12
|
+
const dirname = path_1.default.dirname((0, common_1.getStackFileName)());
|
|
13
13
|
const pkgJson = JSON.parse(fs.readFileSync(path_1.default.resolve(dirname, '../package.json'), 'utf-8'));
|
|
14
14
|
commander_1.program
|
|
15
15
|
.version(pkgJson.version)
|
|
16
16
|
.argument('<serviceUrl>', 'OPRA service url')
|
|
17
17
|
.argument('<outDir>', 'Output directory')
|
|
18
|
-
.option('--name <name>', 'Name of the service')
|
|
19
18
|
.option('--ext', 'Adds js extension to imports')
|
|
20
19
|
.option('--no-color', 'Disables colors in logs messages')
|
|
21
20
|
.action(async (serviceUrl, outDir, options) => {
|
|
22
21
|
if (!options.color)
|
|
23
22
|
chalk_1.default.level = 0;
|
|
24
|
-
|
|
23
|
+
const generator = new ts_generator_js_1.TsGenerator({
|
|
25
24
|
serviceUrl,
|
|
26
25
|
logger: console,
|
|
27
26
|
outDir,
|
|
28
|
-
name: options.name,
|
|
29
27
|
importExt: options.ext,
|
|
30
|
-
fileHeader:
|
|
31
|
-
|
|
32
|
-
|
|
28
|
+
fileHeader: `/* Generated by OPRA Code Generator, Version ${pkgJson.version} */`,
|
|
29
|
+
});
|
|
30
|
+
await generator
|
|
31
|
+
.generate()
|
|
32
|
+
.then(() => console.log(chalk_1.default.greenBright('Completed')))
|
|
33
33
|
.catch(e => console.error(e.message));
|
|
34
34
|
});
|
|
35
35
|
if (process.argv.length < 3)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.httpControllerNodeScript = void 0;
|
|
4
|
+
exports.httpControllerNodeScript = `import { kClient, OpraHttpClient } from '@opra/client';
|
|
5
|
+
|
|
6
|
+
const PARAM_PATTERN = /:\\w+/g;
|
|
7
|
+
|
|
8
|
+
export class HttpControllerNode {
|
|
9
|
+
readonly [kClient]: OpraHttpClient;
|
|
10
|
+
|
|
11
|
+
constructor(client: OpraHttpClient) {
|
|
12
|
+
this[kClient] = client;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
protected _prepareUrl(url: string, params: Record<string, any>): string {
|
|
16
|
+
return url.replace(PARAM_PATTERN, s => {
|
|
17
|
+
return params[s.substring(1)] || '';
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
`;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.cleanDirectory = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
6
|
+
const node_fs_1 = tslib_1.__importDefault(require("node:fs"));
|
|
7
|
+
const node_path_1 = tslib_1.__importDefault(require("node:path"));
|
|
8
|
+
function cleanDirectory(dirname) {
|
|
9
|
+
const rootDir = dirname;
|
|
10
|
+
const _cleanDirectory = (targetDir) => {
|
|
11
|
+
if (!node_fs_1.default.existsSync(targetDir))
|
|
12
|
+
return;
|
|
13
|
+
const files = node_fs_1.default.readdirSync(targetDir);
|
|
14
|
+
for (const f of files) {
|
|
15
|
+
const absolutePath = node_path_1.default.join(targetDir, f);
|
|
16
|
+
if (node_fs_1.default.statSync(absolutePath).isDirectory()) {
|
|
17
|
+
_cleanDirectory(absolutePath);
|
|
18
|
+
if (!node_fs_1.default.readdirSync(absolutePath).length) {
|
|
19
|
+
this.emit('verbose', chalk_1.default.cyan(`Removing directory ${node_path_1.default.relative(absolutePath, rootDir)}`));
|
|
20
|
+
node_fs_1.default.rmdirSync(absolutePath);
|
|
21
|
+
}
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
if (node_path_1.default.extname(f) === '.ts') {
|
|
25
|
+
const contents = node_fs_1.default.readFileSync(absolutePath, 'utf-8');
|
|
26
|
+
if (contents.includes('#!oprimp_auto_generated!#')) {
|
|
27
|
+
this.emit('verbose', chalk_1.default.cyan(`Removing file ${node_path_1.default.relative(absolutePath, rootDir)}`));
|
|
28
|
+
node_fs_1.default.unlinkSync(absolutePath);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
_cleanDirectory(dirname);
|
|
34
|
+
}
|
|
35
|
+
exports.cleanDirectory = cleanDirectory;
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveTypeNameOrDef = exports.generateMappedTypeDefinition = exports.generateMixinTypeDefinition = exports.generateSimpleTypeDefinition = exports.generateComplexTypeDefinition = exports.generateEnumTypeDefinition = exports.processDataType = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const path_1 = tslib_1.__importDefault(require("path"));
|
|
6
|
+
const common_1 = require("@opra/common");
|
|
7
|
+
const code_block_js_1 = require("../../code-block.js");
|
|
8
|
+
const string_utils_js_1 = require("../utils/string-utils.js");
|
|
9
|
+
const internalTypeNames = ['any', 'boolean', 'bigint', 'number', 'null', 'string', 'object'];
|
|
10
|
+
async function processDataType(dataType) {
|
|
11
|
+
const doc = dataType.node.getDocument();
|
|
12
|
+
if (doc.id !== this._document?.id) {
|
|
13
|
+
const { generator } = await this.processDocument(doc);
|
|
14
|
+
return await generator.processDataType(dataType);
|
|
15
|
+
}
|
|
16
|
+
const typeName = dataType.name;
|
|
17
|
+
if (typeName && internalTypeNames.includes(typeName))
|
|
18
|
+
return;
|
|
19
|
+
if (!typeName)
|
|
20
|
+
throw new TypeError(`DataType has no name`);
|
|
21
|
+
let file = this._filesMap.get(dataType);
|
|
22
|
+
if (file)
|
|
23
|
+
return file;
|
|
24
|
+
if (dataType instanceof common_1.SimpleType)
|
|
25
|
+
file = this.addFile(path_1.default.join(this._documentRoot, '/simple-types.ts'), true);
|
|
26
|
+
else {
|
|
27
|
+
if (dataType instanceof common_1.EnumType)
|
|
28
|
+
file = this.addFile(path_1.default.join(this._typesRoot, 'enums', typeName + '.ts'));
|
|
29
|
+
else
|
|
30
|
+
file = this.addFile(path_1.default.join(this._typesRoot, 'types', typeName + '.ts'));
|
|
31
|
+
}
|
|
32
|
+
this._filesMap.set(dataType, file);
|
|
33
|
+
file = this._filesMap.get(dataType);
|
|
34
|
+
if (file.exportTypes.includes(typeName))
|
|
35
|
+
return file;
|
|
36
|
+
file.exportTypes.push(typeName);
|
|
37
|
+
const typesIndexTs = this.addFile(path_1.default.join(this._typesRoot, 'index.ts'), true);
|
|
38
|
+
const indexTs = this.addFile('/index.ts', true);
|
|
39
|
+
indexTs.addExport(typesIndexTs.filename);
|
|
40
|
+
const codeBlock = (file.code['type_' + typeName] = new code_block_js_1.CodeBlock());
|
|
41
|
+
codeBlock.head = `/**\n * ${typeName}`;
|
|
42
|
+
if (dataType.description)
|
|
43
|
+
codeBlock.head += `\n * ${(0, string_utils_js_1.wrapJSDocString)(dataType.description || '')}`;
|
|
44
|
+
codeBlock.head += `
|
|
45
|
+
* @url ${path_1.default.posix.join(doc.url || this.serviceUrl, '$schema', '#types/' + typeName)}
|
|
46
|
+
*/
|
|
47
|
+
export `;
|
|
48
|
+
if (dataType instanceof common_1.EnumType)
|
|
49
|
+
codeBlock.typeDef = await this.generateEnumTypeDefinition(dataType, 'scope');
|
|
50
|
+
else if (dataType instanceof common_1.ComplexType)
|
|
51
|
+
codeBlock.typeDef = await this.generateComplexTypeDefinition(dataType, file, 'scope');
|
|
52
|
+
else if (dataType instanceof common_1.SimpleType)
|
|
53
|
+
codeBlock.typeDef = await this.generateSimpleTypeDefinition(dataType, 'scope');
|
|
54
|
+
else if (dataType instanceof common_1.MappedType)
|
|
55
|
+
codeBlock.typeDef = await this.generateMappedTypeDefinition(dataType, file, 'scope');
|
|
56
|
+
else if (dataType instanceof common_1.MixinType)
|
|
57
|
+
codeBlock.typeDef = await this.generateMixinTypeDefinition(dataType, file, 'scope');
|
|
58
|
+
else
|
|
59
|
+
throw new TypeError(`${dataType.kind} data type (${typeName}) can not be directly exported`);
|
|
60
|
+
typesIndexTs.addExport(file.filename);
|
|
61
|
+
return file;
|
|
62
|
+
}
|
|
63
|
+
exports.processDataType = processDataType;
|
|
64
|
+
/**
|
|
65
|
+
*
|
|
66
|
+
*/
|
|
67
|
+
async function generateEnumTypeDefinition(dataType, intent) {
|
|
68
|
+
if (intent === 'field')
|
|
69
|
+
return ('(' +
|
|
70
|
+
Object.keys(dataType.attributes)
|
|
71
|
+
.map(t => `'${t}'`)
|
|
72
|
+
.join(' | ') +
|
|
73
|
+
')');
|
|
74
|
+
if (intent !== 'scope')
|
|
75
|
+
throw new TypeError(`Can't generate EnumType for "${intent}" intent`);
|
|
76
|
+
if (!dataType.name)
|
|
77
|
+
throw new TypeError(`Name required to generate EnumType for "${intent}" intent`);
|
|
78
|
+
let out = `enum ${dataType.name} {\n\t`;
|
|
79
|
+
for (const [value, info] of Object.entries(dataType.attributes)) {
|
|
80
|
+
// Print JSDoc
|
|
81
|
+
let jsDoc = '';
|
|
82
|
+
if (dataType.attributes[value].description)
|
|
83
|
+
jsDoc += ` * ${dataType.attributes[value].description}\n`;
|
|
84
|
+
if (jsDoc)
|
|
85
|
+
out += `/**\n${jsDoc} */\n`;
|
|
86
|
+
out +=
|
|
87
|
+
`${info.alias || value} = ` + (typeof value === 'number' ? value : "'" + String(value).replace("'", "\\'") + "'");
|
|
88
|
+
out += ',\n\n';
|
|
89
|
+
}
|
|
90
|
+
return out + '\b}';
|
|
91
|
+
}
|
|
92
|
+
exports.generateEnumTypeDefinition = generateEnumTypeDefinition;
|
|
93
|
+
/**
|
|
94
|
+
*
|
|
95
|
+
*/
|
|
96
|
+
async function generateComplexTypeDefinition(dataType, file, intent) {
|
|
97
|
+
if (intent === 'scope' && !dataType.name)
|
|
98
|
+
throw new TypeError(`Name required to generate ComplexType for "${intent}" intent`);
|
|
99
|
+
let out = intent === 'scope' ? `interface ${dataType.name} ` : '';
|
|
100
|
+
const ownFields = [...dataType.fields.values()].filter(f => f.origin === dataType);
|
|
101
|
+
if (dataType.base) {
|
|
102
|
+
const base = await this.resolveTypeNameOrDef(dataType.base, file, 'extends');
|
|
103
|
+
const omitBaseFields = dataType.base ? ownFields.filter(f => dataType.base.fields.has(f.name)) : [];
|
|
104
|
+
const baseDef = omitBaseFields.length
|
|
105
|
+
? `Omit<${base}, ${omitBaseFields.map(x => "'" + x.name + "'").join(' | ')}>`
|
|
106
|
+
: `${base}`;
|
|
107
|
+
if (intent === 'scope')
|
|
108
|
+
out += `extends ${baseDef} `;
|
|
109
|
+
else {
|
|
110
|
+
out += baseDef;
|
|
111
|
+
if (!ownFields.length)
|
|
112
|
+
return out;
|
|
113
|
+
out += ' & ';
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
out += '{\n\t';
|
|
117
|
+
let i = 0;
|
|
118
|
+
for (const field of ownFields) {
|
|
119
|
+
if (i++)
|
|
120
|
+
out += '\n';
|
|
121
|
+
// Print JSDoc
|
|
122
|
+
out += `/**\n * ${field.description || ''}\n`;
|
|
123
|
+
if (field.default)
|
|
124
|
+
out += ` * @default ` + field.default + '\n';
|
|
125
|
+
// if (field.format)
|
|
126
|
+
// jsDoc += ` * @format ` + field.format + '\n';
|
|
127
|
+
if (field.exclusive)
|
|
128
|
+
out += ` * @exclusive\n`;
|
|
129
|
+
if (field.readonly)
|
|
130
|
+
out += ` * @readonly\n`;
|
|
131
|
+
if (field.writeonly)
|
|
132
|
+
out += ` * @writeonly\n`;
|
|
133
|
+
if (field.deprecated)
|
|
134
|
+
out += ` * @deprecated ` + (typeof field.deprecated === 'string' ? field.deprecated : '') + '\n';
|
|
135
|
+
out += ' */\n';
|
|
136
|
+
// Print field name
|
|
137
|
+
if (field.readonly)
|
|
138
|
+
out += 'readonly ';
|
|
139
|
+
out += `${field.name}${field.required ? '' : '?'}: `;
|
|
140
|
+
if (field.fixed) {
|
|
141
|
+
const t = typeof field.fixed;
|
|
142
|
+
out += `${t === 'number' || t === 'boolean' || t === 'bigint' ? field.fixed : "'" + field.fixed + "'"}\n`;
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
out += (await this.resolveTypeNameOrDef(field.type, file, 'field')) + `${field.isArray ? '[]' : ''};\n`;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
if (dataType.additionalFields)
|
|
149
|
+
out += '[key: string]: any;\n';
|
|
150
|
+
return out + '\b}';
|
|
151
|
+
}
|
|
152
|
+
exports.generateComplexTypeDefinition = generateComplexTypeDefinition;
|
|
153
|
+
/**
|
|
154
|
+
*
|
|
155
|
+
*/
|
|
156
|
+
async function generateSimpleTypeDefinition(dataType, intent) {
|
|
157
|
+
if (intent === 'scope' && !dataType.name)
|
|
158
|
+
throw new TypeError(`Name required to generate SimpleType for "${intent}" intent`);
|
|
159
|
+
let out = intent === 'scope' ? `type ${dataType.name} = ` : '';
|
|
160
|
+
out += dataType.nameMappings.js || 'any';
|
|
161
|
+
return intent === 'scope' ? out + ';' : out;
|
|
162
|
+
}
|
|
163
|
+
exports.generateSimpleTypeDefinition = generateSimpleTypeDefinition;
|
|
164
|
+
/**
|
|
165
|
+
*
|
|
166
|
+
*/
|
|
167
|
+
async function generateMixinTypeDefinition(dataType, file, intent) {
|
|
168
|
+
return (await Promise.all(dataType.types.map(t => this.resolveTypeNameOrDef(t, file, intent))))
|
|
169
|
+
.map(t => (t.includes('|') ? '(' + t + ')' : t))
|
|
170
|
+
.join(intent === 'extends' ? ', ' : ' & ');
|
|
171
|
+
}
|
|
172
|
+
exports.generateMixinTypeDefinition = generateMixinTypeDefinition;
|
|
173
|
+
/**
|
|
174
|
+
*
|
|
175
|
+
*/
|
|
176
|
+
async function generateMappedTypeDefinition(dataType, file, intent) {
|
|
177
|
+
const typeDef = await this.resolveTypeNameOrDef(dataType.base, file, intent);
|
|
178
|
+
const pick = dataType.pick?.length ? dataType.pick : undefined;
|
|
179
|
+
const omit = !pick && dataType.omit?.length ? dataType.omit : undefined;
|
|
180
|
+
const partial = dataType.partial === true || (Array.isArray(dataType.partial) && dataType.partial.length > 0)
|
|
181
|
+
? dataType.partial
|
|
182
|
+
: undefined;
|
|
183
|
+
const required = dataType.required === true || (Array.isArray(dataType.required) && dataType.required.length > 0)
|
|
184
|
+
? dataType.required
|
|
185
|
+
: undefined;
|
|
186
|
+
if (!(pick || omit || partial || required))
|
|
187
|
+
return typeDef;
|
|
188
|
+
let out = '';
|
|
189
|
+
if (partial === true)
|
|
190
|
+
out += 'Partial<';
|
|
191
|
+
else if (partial) {
|
|
192
|
+
out += 'PartialSome<';
|
|
193
|
+
file.addExport('ts-gems', ['PartialSome']);
|
|
194
|
+
}
|
|
195
|
+
if (required === true)
|
|
196
|
+
out += 'Partial<';
|
|
197
|
+
else if (required) {
|
|
198
|
+
out += 'RequiredSome<';
|
|
199
|
+
file.addExport('ts-gems', ['RequiredSome']);
|
|
200
|
+
}
|
|
201
|
+
if (pick)
|
|
202
|
+
out += 'Pick<';
|
|
203
|
+
else if (omit)
|
|
204
|
+
out += 'Omit<';
|
|
205
|
+
out += typeDef;
|
|
206
|
+
if (omit || pick)
|
|
207
|
+
out +=
|
|
208
|
+
', ' +
|
|
209
|
+
(omit || pick)
|
|
210
|
+
.filter(x => !!x)
|
|
211
|
+
.map(x => `'${x}'`)
|
|
212
|
+
.join(' | ') +
|
|
213
|
+
'>';
|
|
214
|
+
if (partial) {
|
|
215
|
+
if (Array.isArray(partial))
|
|
216
|
+
out +=
|
|
217
|
+
', ' +
|
|
218
|
+
partial
|
|
219
|
+
.filter(x => !!x)
|
|
220
|
+
.map(x => `'${x}'`)
|
|
221
|
+
.join(' | ');
|
|
222
|
+
out += '>';
|
|
223
|
+
}
|
|
224
|
+
return out;
|
|
225
|
+
}
|
|
226
|
+
exports.generateMappedTypeDefinition = generateMappedTypeDefinition;
|
|
227
|
+
/**
|
|
228
|
+
*
|
|
229
|
+
*/
|
|
230
|
+
async function resolveTypeNameOrDef(dataType, file, intent) {
|
|
231
|
+
if (dataType.name && !dataType.embedded) {
|
|
232
|
+
if (internalTypeNames.includes(dataType.name))
|
|
233
|
+
return dataType.name;
|
|
234
|
+
const f = await this.processDataType(dataType);
|
|
235
|
+
if (!f)
|
|
236
|
+
return '';
|
|
237
|
+
file.addImport(f.filename, [dataType.name], true);
|
|
238
|
+
return dataType.name;
|
|
239
|
+
}
|
|
240
|
+
if (dataType instanceof common_1.SimpleType)
|
|
241
|
+
return this.generateSimpleTypeDefinition(dataType, intent);
|
|
242
|
+
if (dataType instanceof common_1.EnumType)
|
|
243
|
+
return this.generateEnumTypeDefinition(dataType, intent);
|
|
244
|
+
if (dataType instanceof common_1.MixinType)
|
|
245
|
+
return this.generateMixinTypeDefinition(dataType, file, intent);
|
|
246
|
+
if (dataType instanceof common_1.MappedType)
|
|
247
|
+
return this.generateMappedTypeDefinition(dataType, file, intent);
|
|
248
|
+
if (dataType instanceof common_1.ComplexType)
|
|
249
|
+
return this.generateComplexTypeDefinition(dataType, file, intent);
|
|
250
|
+
return '';
|
|
251
|
+
}
|
|
252
|
+
exports.resolveTypeNameOrDef = resolveTypeNameOrDef;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.processDocument = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
6
|
+
const path_1 = tslib_1.__importDefault(require("path"));
|
|
7
|
+
const putil_varhelpers_1 = require("putil-varhelpers");
|
|
8
|
+
const client_1 = require("@opra/client");
|
|
9
|
+
const common_1 = require("@opra/common");
|
|
10
|
+
async function processDocument(document, options) {
|
|
11
|
+
if (!document || typeof document === 'string') {
|
|
12
|
+
if (document) {
|
|
13
|
+
const out = this._documentsMap.get(document);
|
|
14
|
+
if (out)
|
|
15
|
+
return out;
|
|
16
|
+
}
|
|
17
|
+
this.emit('log', chalk_1.default.cyan('Fetching document schema from ') + chalk_1.default.blueBright(this.serviceUrl));
|
|
18
|
+
const client = new client_1.OpraHttpClient(this.serviceUrl);
|
|
19
|
+
document = await client.fetchDocument({ documentId: document });
|
|
20
|
+
}
|
|
21
|
+
this._document = document;
|
|
22
|
+
let out = this._documentsMap.get(document.id);
|
|
23
|
+
if (out)
|
|
24
|
+
return out;
|
|
25
|
+
out = {
|
|
26
|
+
document,
|
|
27
|
+
generator: this,
|
|
28
|
+
};
|
|
29
|
+
this._documentsMap.set(document.id, out);
|
|
30
|
+
this.emit('log', chalk_1.default.white('[' + document.id + '] ') + chalk_1.default.cyan('Processing document ') + chalk_1.default.magenta(document.info.title));
|
|
31
|
+
if (document.references.size) {
|
|
32
|
+
this.emit('log', chalk_1.default.white('[' + document.id + '] ') + chalk_1.default.cyan(`Processing references`));
|
|
33
|
+
for (const ref of document.references.values()) {
|
|
34
|
+
const generator = this.extend();
|
|
35
|
+
generator._document = ref;
|
|
36
|
+
generator._documentRoot = '/references/' + (ref.info.title ? (0, putil_varhelpers_1.pascalCase)(ref.info.title) : ref.id);
|
|
37
|
+
generator._typesRoot = path_1.default.join(generator._documentRoot, 'models');
|
|
38
|
+
await generator.processDocument(ref, { typesOnly: true });
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
this._fileHeaderDocInfo = `/*
|
|
42
|
+
* ${document.info.title}
|
|
43
|
+
* Id: ${document.id}
|
|
44
|
+
* Version: ${document.info.version}
|
|
45
|
+
* ${this.serviceUrl}
|
|
46
|
+
*/`;
|
|
47
|
+
if (document.types.size) {
|
|
48
|
+
this.emit('log', chalk_1.default.white('[' + document.id + ']'), chalk_1.default.cyan(`Processing data types`));
|
|
49
|
+
for (const t of document.types.values()) {
|
|
50
|
+
await this.processDataType(t);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
if (options?.typesOnly)
|
|
54
|
+
return out;
|
|
55
|
+
if (document.api instanceof common_1.HttpApi) {
|
|
56
|
+
await this.processHttpApi(document.api);
|
|
57
|
+
}
|
|
58
|
+
return out;
|
|
59
|
+
}
|
|
60
|
+
exports.processDocument = processDocument;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.processHttpApi = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const node_path_1 = tslib_1.__importDefault(require("node:path"));
|
|
6
|
+
const putil_varhelpers_1 = require("putil-varhelpers");
|
|
7
|
+
const code_block_js_1 = require("../../code-block.js");
|
|
8
|
+
const http_controller_node_js_1 = require("../http-controller-node.js");
|
|
9
|
+
const string_utils_js_1 = require("../utils/string-utils.js");
|
|
10
|
+
async function processHttpApi(api) {
|
|
11
|
+
let file = this._filesMap.get(api);
|
|
12
|
+
if (file)
|
|
13
|
+
return file;
|
|
14
|
+
const className = api.name ? (0, putil_varhelpers_1.pascalCase)(api.name) : 'Api';
|
|
15
|
+
file = this.addFile(className + '.ts');
|
|
16
|
+
file.addImport('@opra/client', ['kClient', 'OpraHttpClient']);
|
|
17
|
+
const indexTs = this.addFile('/index.ts', true);
|
|
18
|
+
indexTs.addExport('.' + file.filename);
|
|
19
|
+
const httpApiNodeFile = this.addFile('./http-controller-node.ts');
|
|
20
|
+
httpApiNodeFile.code.content = http_controller_node_js_1.httpControllerNodeScript;
|
|
21
|
+
const classBlock = (file.code[className] = new code_block_js_1.CodeBlock());
|
|
22
|
+
classBlock.doc = `/**
|
|
23
|
+
* ${(0, string_utils_js_1.wrapJSDocString)(api.description || '')}
|
|
24
|
+
* @class ${className}
|
|
25
|
+
* @url ${node_path_1.default.posix.join(this.serviceUrl, '$schema')}
|
|
26
|
+
*/`;
|
|
27
|
+
classBlock.head = `\nexport class ${className} {\n\t`;
|
|
28
|
+
classBlock.properties = 'readonly [kClient]: OpraHttpClient;';
|
|
29
|
+
const classConstBlock = (classBlock.classConstBlock = new code_block_js_1.CodeBlock());
|
|
30
|
+
classConstBlock.head = `\n\nconstructor(client: OpraHttpClient) {`;
|
|
31
|
+
classConstBlock.body = `\n\tthis[kClient] = client;`;
|
|
32
|
+
classConstBlock.tail = `\b\n}\n`;
|
|
33
|
+
for (const controller of api.controllers.values()) {
|
|
34
|
+
const generator = this.extend();
|
|
35
|
+
const f = await generator.processHttpController(controller);
|
|
36
|
+
const childClassName = (0, putil_varhelpers_1.pascalCase)(controller.name) + 'Controller';
|
|
37
|
+
file.addImport('.' + f.filename, [childClassName]);
|
|
38
|
+
const property = '$' + controller.name.charAt(0).toLowerCase() + (0, putil_varhelpers_1.camelCase)(controller.name.substring(1));
|
|
39
|
+
classBlock.properties += `\nreadonly ${property}: ${childClassName};`;
|
|
40
|
+
classConstBlock.body += `\nthis.${property} = new ${childClassName}(client);`;
|
|
41
|
+
}
|
|
42
|
+
classBlock.tail = `\b}`;
|
|
43
|
+
return file;
|
|
44
|
+
}
|
|
45
|
+
exports.processHttpApi = processHttpApi;
|