@opra/cli 1.0.0-alpha.23 → 1.0.0-alpha.25
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/package.json +3 -3
- package/cjs/ts-generator/processors/clean-directory.js +0 -35
- package/cjs/ts-generator/processors/process-data-types.js +0 -258
- package/cjs/ts-generator/processors/process-document.js +0 -60
- package/cjs/ts-generator/processors/process-http-api.js +0 -45
- package/cjs/ts-generator/processors/process-http-controller.js +0 -198
- package/esm/ts-generator/processors/clean-directory.js +0 -30
- package/esm/ts-generator/processors/process-data-types.js +0 -247
- package/esm/ts-generator/processors/process-document.js +0 -55
- package/esm/ts-generator/processors/process-http-api.js +0 -40
- package/esm/ts-generator/processors/process-http-controller.js +0 -193
- package/types/ts-generator/processors/clean-directory.d.ts +0 -2
- package/types/ts-generator/processors/process-data-types.d.ts +0 -41
- package/types/ts-generator/processors/process-document.d.ts +0 -8
- package/types/ts-generator/processors/process-http-api.d.ts +0 -3
- package/types/ts-generator/processors/process-http-controller.d.ts +0 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opra/cli",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.25",
|
|
4
4
|
"description": "Opra CLI tools",
|
|
5
5
|
"author": "Panates",
|
|
6
6
|
"license": "MIT",
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"@browsery/type-is": "^1.6.18-r3",
|
|
35
|
-
"@opra/client": "^1.0.0-alpha.
|
|
36
|
-
"@opra/common": "^1.0.0-alpha.
|
|
35
|
+
"@opra/client": "^1.0.0-alpha.25",
|
|
36
|
+
"@opra/common": "^1.0.0-alpha.25",
|
|
37
37
|
"chalk": "^5.3.0",
|
|
38
38
|
"commander": "^12.0.0",
|
|
39
39
|
"js-string-escape": "^1.0.1",
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.cleanDirectory = void 0;
|
|
4
|
-
const tslib_1 = require("tslib");
|
|
5
|
-
const node_fs_1 = tslib_1.__importDefault(require("node:fs"));
|
|
6
|
-
const node_path_1 = tslib_1.__importDefault(require("node:path"));
|
|
7
|
-
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
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;
|
|
@@ -1,258 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.generateMappedTypeDefinition = exports.generateMixinTypeDefinition = exports.generateSimpleTypeDefinition = exports.generateComplexTypeDefinition = exports.generateEnumTypeDefinition = exports.generateTypeDefinition = exports.processDataType = void 0;
|
|
4
|
-
const tslib_1 = require("tslib");
|
|
5
|
-
const common_1 = require("@opra/common");
|
|
6
|
-
const path_1 = tslib_1.__importDefault(require("path"));
|
|
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, currentFile, intent) {
|
|
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, currentFile, intent);
|
|
15
|
-
}
|
|
16
|
-
const typeName = dataType.name;
|
|
17
|
-
if (typeName) {
|
|
18
|
-
if (internalTypeNames.includes(typeName))
|
|
19
|
-
return { kind: 'internal', typeName: dataType.name };
|
|
20
|
-
let file = this._filesMap.get(dataType);
|
|
21
|
-
if (file) {
|
|
22
|
-
if (currentFile)
|
|
23
|
-
currentFile.addImport(file.filename, [typeName]);
|
|
24
|
-
return { kind: 'named', file, typeName: dataType.name };
|
|
25
|
-
}
|
|
26
|
-
if (dataType instanceof common_1.SimpleType)
|
|
27
|
-
file = this.addFile(path_1.default.join(this._documentRoot, '/simple-types.ts'), true);
|
|
28
|
-
else if (dataType instanceof common_1.EnumType)
|
|
29
|
-
file = this.addFile(path_1.default.join(this._typesRoot, 'enums', typeName + '.ts'));
|
|
30
|
-
else
|
|
31
|
-
file = this.addFile(path_1.default.join(this._typesRoot, 'types', typeName + '.ts'));
|
|
32
|
-
this._filesMap.set(dataType, file);
|
|
33
|
-
if (file.exportTypes.includes(typeName)) {
|
|
34
|
-
if (currentFile)
|
|
35
|
-
currentFile.addImport(file.filename, [typeName]);
|
|
36
|
-
return { kind: 'named', file, typeName: dataType.name };
|
|
37
|
-
}
|
|
38
|
-
file.exportTypes.push(typeName);
|
|
39
|
-
const typesIndexTs = this.addFile(path_1.default.join(this._typesRoot, 'index.ts'), true);
|
|
40
|
-
const indexTs = this.addFile('/index.ts', true);
|
|
41
|
-
indexTs.addExport(typesIndexTs.filename);
|
|
42
|
-
const codeBlock = (file.code['type_' + typeName] = new code_block_js_1.CodeBlock());
|
|
43
|
-
codeBlock.head = `/**\n * ${(0, string_utils_js_1.wrapJSDocString)(dataType.description || '')}\n *`;
|
|
44
|
-
codeBlock.head += `
|
|
45
|
-
* @url ${path_1.default.posix.join(doc.url || this.serviceUrl, '$schema', '#types/' + typeName)}
|
|
46
|
-
*/
|
|
47
|
-
export `;
|
|
48
|
-
codeBlock.typeDef = (await this.generateTypeDefinition(file, dataType, 'root')) + '\n\n';
|
|
49
|
-
typesIndexTs.addExport(file.filename);
|
|
50
|
-
if (currentFile)
|
|
51
|
-
currentFile.addImport(file.filename, [typeName]);
|
|
52
|
-
return { kind: 'named', file, typeName };
|
|
53
|
-
}
|
|
54
|
-
if (!currentFile)
|
|
55
|
-
throw new TypeError(`You must provide currentFile to generate data type`);
|
|
56
|
-
const code = await this.generateTypeDefinition(currentFile, dataType, intent);
|
|
57
|
-
return { kind: 'embedded', code };
|
|
58
|
-
}
|
|
59
|
-
exports.processDataType = processDataType;
|
|
60
|
-
/**
|
|
61
|
-
*
|
|
62
|
-
*/
|
|
63
|
-
async function generateTypeDefinition(currentFile, dataType, intent) {
|
|
64
|
-
if (intent === 'root' && !dataType.name) {
|
|
65
|
-
throw new TypeError(`Name required to generate data type code to root intent`);
|
|
66
|
-
}
|
|
67
|
-
if (dataType instanceof common_1.EnumType) {
|
|
68
|
-
return await this.generateEnumTypeDefinition(currentFile, dataType, intent);
|
|
69
|
-
}
|
|
70
|
-
if (dataType instanceof common_1.ComplexType) {
|
|
71
|
-
return await this.generateComplexTypeDefinition(currentFile, dataType, intent);
|
|
72
|
-
}
|
|
73
|
-
if (dataType instanceof common_1.SimpleType) {
|
|
74
|
-
return await this.generateSimpleTypeDefinition(currentFile, dataType, intent);
|
|
75
|
-
}
|
|
76
|
-
if (dataType instanceof common_1.MappedType) {
|
|
77
|
-
return await this.generateMappedTypeDefinition(currentFile, dataType, intent);
|
|
78
|
-
}
|
|
79
|
-
if (dataType instanceof common_1.MixinType) {
|
|
80
|
-
return await this.generateMixinTypeDefinition(currentFile, dataType, intent);
|
|
81
|
-
}
|
|
82
|
-
/* istanbul ignore next */
|
|
83
|
-
throw new TypeError(`${dataType.kind} data types can not be directly exported`);
|
|
84
|
-
}
|
|
85
|
-
exports.generateTypeDefinition = generateTypeDefinition;
|
|
86
|
-
/**
|
|
87
|
-
*
|
|
88
|
-
*/
|
|
89
|
-
async function generateEnumTypeDefinition(currentFile, dataType, intent) {
|
|
90
|
-
if (intent === 'root') {
|
|
91
|
-
let out = `enum ${dataType.name} {\n\t`;
|
|
92
|
-
for (const [value, info] of Object.entries(dataType.attributes)) {
|
|
93
|
-
// Print JSDoc
|
|
94
|
-
let jsDoc = '';
|
|
95
|
-
if (dataType.attributes[value].description)
|
|
96
|
-
jsDoc += ` * ${dataType.attributes[value].description}\n`;
|
|
97
|
-
if (jsDoc)
|
|
98
|
-
out += `/**\n${jsDoc} */\n`;
|
|
99
|
-
out +=
|
|
100
|
-
`${info.alias || value} = ` +
|
|
101
|
-
(typeof value === 'number' ? value : "'" + String(value).replace("'", "\\'") + "'");
|
|
102
|
-
out += ',\n\n';
|
|
103
|
-
}
|
|
104
|
-
return out + '\b}';
|
|
105
|
-
}
|
|
106
|
-
return ('(' +
|
|
107
|
-
Object.keys(dataType.attributes)
|
|
108
|
-
.map(t => `'${t}'`)
|
|
109
|
-
.join(' | ') +
|
|
110
|
-
')');
|
|
111
|
-
}
|
|
112
|
-
exports.generateEnumTypeDefinition = generateEnumTypeDefinition;
|
|
113
|
-
/**
|
|
114
|
-
*
|
|
115
|
-
*/
|
|
116
|
-
async function generateComplexTypeDefinition(currentFile, dataType, intent) {
|
|
117
|
-
let out = intent === 'root' ? `interface ${dataType.name} ` : '';
|
|
118
|
-
const ownFields = [...dataType.fields.values()].filter(f => f.origin === dataType);
|
|
119
|
-
if (dataType.base) {
|
|
120
|
-
const base = await this.processDataType(dataType.base, currentFile, 'extends');
|
|
121
|
-
let baseDef = base.kind === 'embedded' ? base.code : base.typeName;
|
|
122
|
-
const omitBaseFields = ownFields.filter(f => dataType.base.fields.has(f.name));
|
|
123
|
-
if (omitBaseFields.length)
|
|
124
|
-
baseDef = `Omit<${baseDef}, ${omitBaseFields.map(x => "'" + x.name + "'").join(' | ')}>`;
|
|
125
|
-
if (intent === 'root')
|
|
126
|
-
out += `extends ${baseDef} `;
|
|
127
|
-
else {
|
|
128
|
-
out += baseDef;
|
|
129
|
-
if (!ownFields.length)
|
|
130
|
-
return out;
|
|
131
|
-
out += ' & ';
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
out += '{\n\t';
|
|
135
|
-
let i = 0;
|
|
136
|
-
for (const field of ownFields) {
|
|
137
|
-
if (i++)
|
|
138
|
-
out += '\n';
|
|
139
|
-
// Print JSDoc
|
|
140
|
-
out += `/**\n * ${field.description || ''}\n`;
|
|
141
|
-
if (field.default)
|
|
142
|
-
out += ` * @default ` + field.default + '\n';
|
|
143
|
-
// if (field.format)
|
|
144
|
-
// jsDoc += ` * @format ` + field.format + '\n';
|
|
145
|
-
if (field.exclusive)
|
|
146
|
-
out += ` * @exclusive\n`;
|
|
147
|
-
if (field.readonly)
|
|
148
|
-
out += ` * @readonly\n`;
|
|
149
|
-
if (field.writeonly)
|
|
150
|
-
out += ` * @writeonly\n`;
|
|
151
|
-
if (field.deprecated) {
|
|
152
|
-
out += ` * @deprecated ` + (typeof field.deprecated === 'string' ? field.deprecated : '') + '\n';
|
|
153
|
-
}
|
|
154
|
-
out += ' */\n';
|
|
155
|
-
// Print field name
|
|
156
|
-
if (field.readonly)
|
|
157
|
-
out += 'readonly ';
|
|
158
|
-
out += `${field.name}${field.required ? '' : '?'}: `;
|
|
159
|
-
if (field.fixed) {
|
|
160
|
-
const t = typeof field.fixed;
|
|
161
|
-
out += `${t === 'number' || t === 'boolean' || t === 'bigint' ? field.fixed : "'" + field.fixed + "'"}\n`;
|
|
162
|
-
}
|
|
163
|
-
else {
|
|
164
|
-
const x = await this.processDataType(field.type, currentFile);
|
|
165
|
-
out += (x.kind === 'embedded' ? x.code : x.typeName) + `${field.isArray ? '[]' : ''};\n`;
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
if (dataType.additionalFields)
|
|
169
|
-
out += '[key: string]: any;\n';
|
|
170
|
-
return out + '\b}';
|
|
171
|
-
}
|
|
172
|
-
exports.generateComplexTypeDefinition = generateComplexTypeDefinition;
|
|
173
|
-
/**
|
|
174
|
-
*
|
|
175
|
-
*/
|
|
176
|
-
async function generateSimpleTypeDefinition(currentFile, dataType, intent) {
|
|
177
|
-
let out = intent === 'root' ? `type ${dataType.name} = ` : '';
|
|
178
|
-
out += dataType.nameMappings.js || 'any';
|
|
179
|
-
return intent === 'root' ? out + ';' : out;
|
|
180
|
-
}
|
|
181
|
-
exports.generateSimpleTypeDefinition = generateSimpleTypeDefinition;
|
|
182
|
-
/**
|
|
183
|
-
*
|
|
184
|
-
*/
|
|
185
|
-
async function generateMixinTypeDefinition(currentFile, dataType, intent) {
|
|
186
|
-
const outArray = [];
|
|
187
|
-
for (const t of dataType.types) {
|
|
188
|
-
const x = await this.processDataType(t, currentFile);
|
|
189
|
-
if (x.kind === 'embedded') {
|
|
190
|
-
outArray.push(x.code.includes('|') ? '(' + x.code + ')' : x.code);
|
|
191
|
-
}
|
|
192
|
-
else
|
|
193
|
-
outArray.push(x.typeName);
|
|
194
|
-
}
|
|
195
|
-
if (intent === 'root')
|
|
196
|
-
return `type ${dataType.name} = ${outArray.join(' & ')}`;
|
|
197
|
-
if (intent === 'extends')
|
|
198
|
-
return outArray.join(', ');
|
|
199
|
-
return outArray.join(' & ');
|
|
200
|
-
}
|
|
201
|
-
exports.generateMixinTypeDefinition = generateMixinTypeDefinition;
|
|
202
|
-
/**
|
|
203
|
-
*
|
|
204
|
-
*/
|
|
205
|
-
async function generateMappedTypeDefinition(currentFile, dataType, intent) {
|
|
206
|
-
let out = intent === 'root' ? `type ${dataType.name} = ` : '';
|
|
207
|
-
const base = await this.processDataType(dataType.base, currentFile);
|
|
208
|
-
const typeDef = base.kind === 'embedded' ? base.code : base.typeName;
|
|
209
|
-
const pick = dataType.pick?.length ? dataType.pick : undefined;
|
|
210
|
-
const omit = !pick && dataType.omit?.length ? dataType.omit : undefined;
|
|
211
|
-
const partial = dataType.partial === true || (Array.isArray(dataType.partial) && dataType.partial.length > 0)
|
|
212
|
-
? dataType.partial
|
|
213
|
-
: undefined;
|
|
214
|
-
const required = dataType.required === true || (Array.isArray(dataType.required) && dataType.required.length > 0)
|
|
215
|
-
? dataType.required
|
|
216
|
-
: undefined;
|
|
217
|
-
if (!(pick || omit || partial || required))
|
|
218
|
-
return typeDef;
|
|
219
|
-
if (partial === true)
|
|
220
|
-
out += 'Partial<';
|
|
221
|
-
else if (partial) {
|
|
222
|
-
out += 'PartialSome<';
|
|
223
|
-
currentFile.addExport('ts-gems', ['PartialSome']);
|
|
224
|
-
}
|
|
225
|
-
if (required === true)
|
|
226
|
-
out += 'Partial<';
|
|
227
|
-
else if (required) {
|
|
228
|
-
out += 'RequiredSome<';
|
|
229
|
-
currentFile.addExport('ts-gems', ['RequiredSome']);
|
|
230
|
-
}
|
|
231
|
-
if (pick)
|
|
232
|
-
out += 'Pick<';
|
|
233
|
-
else if (omit)
|
|
234
|
-
out += 'Omit<';
|
|
235
|
-
out += typeDef;
|
|
236
|
-
if (omit || pick) {
|
|
237
|
-
out +=
|
|
238
|
-
', ' +
|
|
239
|
-
(omit || pick)
|
|
240
|
-
.filter(x => !!x)
|
|
241
|
-
.map(x => `'${x}'`)
|
|
242
|
-
.join(' | ') +
|
|
243
|
-
'>';
|
|
244
|
-
}
|
|
245
|
-
if (partial) {
|
|
246
|
-
if (Array.isArray(partial)) {
|
|
247
|
-
out +=
|
|
248
|
-
', ' +
|
|
249
|
-
partial
|
|
250
|
-
.filter(x => !!x)
|
|
251
|
-
.map(x => `'${x}'`)
|
|
252
|
-
.join(' | ');
|
|
253
|
-
}
|
|
254
|
-
out += '>';
|
|
255
|
-
}
|
|
256
|
-
return out;
|
|
257
|
-
}
|
|
258
|
-
exports.generateMappedTypeDefinition = generateMappedTypeDefinition;
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.processDocument = void 0;
|
|
4
|
-
const tslib_1 = require("tslib");
|
|
5
|
-
const client_1 = require("@opra/client");
|
|
6
|
-
const common_1 = require("@opra/common");
|
|
7
|
-
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
8
|
-
const path_1 = tslib_1.__importDefault(require("path"));
|
|
9
|
-
const putil_varhelpers_1 = require("putil-varhelpers");
|
|
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;
|
|
@@ -1,45 +0,0 @@
|
|
|
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;
|
|
@@ -1,198 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.processHttpController = 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 locate_named_type_js_1 = require("../utils/locate-named-type.js");
|
|
9
|
-
const string_utils_js_1 = require("../utils/string-utils.js");
|
|
10
|
-
async function processHttpController(controller) {
|
|
11
|
-
let file = this._filesMap.get(controller);
|
|
12
|
-
if (file)
|
|
13
|
-
return file;
|
|
14
|
-
const className = (0, putil_varhelpers_1.pascalCase)(controller.name) + 'Controller';
|
|
15
|
-
file = this.addFile(node_path_1.default.join(this._apiPath, className + '.ts'));
|
|
16
|
-
file.addImport('@opra/client', ['HttpRequestObservable', 'kClient', 'OpraHttpClient']);
|
|
17
|
-
file.addImport(node_path_1.default.relative(file.dirname, '/http-controller-node.ts'), ['HttpControllerNode']);
|
|
18
|
-
const classBlock = (file.code[className] = new code_block_js_1.CodeBlock());
|
|
19
|
-
classBlock.doc = `/**
|
|
20
|
-
* ${(0, string_utils_js_1.wrapJSDocString)(controller.description || '')}
|
|
21
|
-
* @class ${className}
|
|
22
|
-
* @url ${node_path_1.default.posix.join(this.serviceUrl, '$schema', '#resources/' + className)}
|
|
23
|
-
*/`;
|
|
24
|
-
classBlock.head = `\nexport class ${className} extends HttpControllerNode {\n\t`;
|
|
25
|
-
classBlock.properties = '';
|
|
26
|
-
const classConstBlock = (classBlock.classConstBlock = new code_block_js_1.CodeBlock());
|
|
27
|
-
classConstBlock.head = `\n\nconstructor(client: OpraHttpClient) {`;
|
|
28
|
-
classConstBlock.body = `\n\tsuper(client);`;
|
|
29
|
-
classConstBlock.tail = `\b\n}\n`;
|
|
30
|
-
if (controller.controllers.size) {
|
|
31
|
-
for (const child of controller.controllers.values()) {
|
|
32
|
-
const generator = this.extend();
|
|
33
|
-
generator._apiPath = node_path_1.default.join(this._apiPath, className);
|
|
34
|
-
const f = await generator.processHttpController(child);
|
|
35
|
-
const childClassName = (0, putil_varhelpers_1.pascalCase)(child.name) + 'Controller';
|
|
36
|
-
file.addImport(f.filename, [childClassName]);
|
|
37
|
-
const property = '$' + child.name.charAt(0).toLowerCase() + (0, putil_varhelpers_1.camelCase)(child.name.substring(1));
|
|
38
|
-
classBlock.properties += `\nreadonly ${property}: ${childClassName};`;
|
|
39
|
-
classConstBlock.body += `\nthis.${property} = new ${childClassName}(client);`;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
/** Process operations */
|
|
43
|
-
for (const operation of controller.operations.values()) {
|
|
44
|
-
const operationBlock = (classBlock['operation_' + operation.name] = new code_block_js_1.CodeBlock());
|
|
45
|
-
operationBlock.doc = `
|
|
46
|
-
/**
|
|
47
|
-
* ${(0, string_utils_js_1.wrapJSDocString)(operation.description || operation.name + ' operation')}`;
|
|
48
|
-
if (operation.parameters.length) {
|
|
49
|
-
const block = new code_block_js_1.CodeBlock();
|
|
50
|
-
block.doc = '\n *\n * RegExp parameters:';
|
|
51
|
-
let i = 0;
|
|
52
|
-
for (const prm of operation.parameters) {
|
|
53
|
-
if (!(prm.name instanceof RegExp))
|
|
54
|
-
continue;
|
|
55
|
-
i++;
|
|
56
|
-
block.doc +=
|
|
57
|
-
`\n * > ${String(prm.name)} - ${prm.description || ''}` +
|
|
58
|
-
`\n * - location: ${prm.location}` +
|
|
59
|
-
`\n * - type: ${(0, locate_named_type_js_1.locateNamedType)(prm.type)?.name || 'any'}${prm.isArray ? '[' + prm.arraySeparator + ']' : ''}` +
|
|
60
|
-
(prm.required ? `\n * required: ${prm.required}` : '') +
|
|
61
|
-
(prm.deprecated ? `\n * deprecated: ${prm.deprecated}` : '');
|
|
62
|
-
}
|
|
63
|
-
if (i)
|
|
64
|
-
operationBlock.doc += block;
|
|
65
|
-
}
|
|
66
|
-
operationBlock.doc += `\n */\n`;
|
|
67
|
-
operationBlock.head = `${operation.name}(`;
|
|
68
|
-
/** Process operation parameters */
|
|
69
|
-
const mergedParams = [...controller.parameters, ...operation.parameters];
|
|
70
|
-
const pathParams = [];
|
|
71
|
-
const queryParams = [];
|
|
72
|
-
const headerParams = [];
|
|
73
|
-
if (mergedParams.length) {
|
|
74
|
-
const pathParamsMap = {};
|
|
75
|
-
const queryParamsMap = {};
|
|
76
|
-
const headerParamsMap = {};
|
|
77
|
-
for (const prm of mergedParams) {
|
|
78
|
-
if (typeof prm.name !== 'string')
|
|
79
|
-
continue;
|
|
80
|
-
if (prm.location === 'path')
|
|
81
|
-
pathParamsMap[prm.name] = prm;
|
|
82
|
-
if (prm.location === 'query')
|
|
83
|
-
queryParamsMap[prm.name] = prm;
|
|
84
|
-
if (prm.location === 'header')
|
|
85
|
-
headerParamsMap[prm.name] = prm;
|
|
86
|
-
}
|
|
87
|
-
pathParams.push(...Object.values(pathParamsMap));
|
|
88
|
-
queryParams.push(...Object.values(queryParamsMap));
|
|
89
|
-
headerParams.push(...Object.values(headerParamsMap));
|
|
90
|
-
}
|
|
91
|
-
let argIndex = 0;
|
|
92
|
-
for (const prm of pathParams) {
|
|
93
|
-
let typeName;
|
|
94
|
-
if (prm.type) {
|
|
95
|
-
const xt = await this.processDataType(prm.type, file);
|
|
96
|
-
typeName = xt.kind === 'embedded' ? xt.code : xt.typeName;
|
|
97
|
-
}
|
|
98
|
-
else
|
|
99
|
-
typeName = `any`;
|
|
100
|
-
if (argIndex++ > 0)
|
|
101
|
-
operationBlock.head += ', ';
|
|
102
|
-
operationBlock.head += `${prm.name}: ${typeName}`;
|
|
103
|
-
}
|
|
104
|
-
let hasBody = false;
|
|
105
|
-
if (operation.requestBody?.content.length) {
|
|
106
|
-
if (argIndex++ > 0)
|
|
107
|
-
operationBlock.head += ', ';
|
|
108
|
-
let typeArr = [];
|
|
109
|
-
for (const content of operation.requestBody.content) {
|
|
110
|
-
if (content.type) {
|
|
111
|
-
const xt = await this.processDataType(content.type, file);
|
|
112
|
-
const typeName = xt.kind === 'embedded' ? xt.code : xt.typeName;
|
|
113
|
-
typeArr.push(typeName);
|
|
114
|
-
continue;
|
|
115
|
-
}
|
|
116
|
-
typeArr = [];
|
|
117
|
-
break;
|
|
118
|
-
}
|
|
119
|
-
if (typeArr.length) {
|
|
120
|
-
if (operation.requestBody.partial) {
|
|
121
|
-
file.addImport('ts-gems', ['PartialDTO']);
|
|
122
|
-
operationBlock.head += `$body: PartialDTO<${typeArr.join(' | ')}>`;
|
|
123
|
-
}
|
|
124
|
-
else {
|
|
125
|
-
file.addImport('ts-gems', ['DTO']);
|
|
126
|
-
operationBlock.head += `$body: DTO<${typeArr.join(' | ')}>`;
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
else
|
|
130
|
-
operationBlock.head += `$body: any`;
|
|
131
|
-
hasBody = true;
|
|
132
|
-
}
|
|
133
|
-
/** process query params */
|
|
134
|
-
const isQueryRequired = queryParams.find(p => p.required);
|
|
135
|
-
const isHeadersRequired = queryParams.find(p => p.required);
|
|
136
|
-
if (queryParams.length) {
|
|
137
|
-
if (argIndex++ > 0)
|
|
138
|
-
operationBlock.head += ', ';
|
|
139
|
-
operationBlock.head += '\n\t$params' + (isHeadersRequired || isQueryRequired ? '' : '?') + ': {\n\t';
|
|
140
|
-
for (const prm of queryParams) {
|
|
141
|
-
operationBlock.head += `/**\n * ${prm.description || ''}\n */\n`;
|
|
142
|
-
operationBlock.head += `${prm.name}${prm.required ? '' : '?'}: `;
|
|
143
|
-
if (prm.type) {
|
|
144
|
-
const xt = await this.processDataType(prm.type, file);
|
|
145
|
-
const typeDef = xt.kind === 'embedded' ? xt.code : xt.typeName;
|
|
146
|
-
operationBlock.head += `${typeDef};\n`;
|
|
147
|
-
}
|
|
148
|
-
else
|
|
149
|
-
operationBlock.head += `any;\n`;
|
|
150
|
-
}
|
|
151
|
-
operationBlock.head += '\b}\b';
|
|
152
|
-
}
|
|
153
|
-
/** process header params */
|
|
154
|
-
if (headerParams.length) {
|
|
155
|
-
if (argIndex++ > 0)
|
|
156
|
-
operationBlock.head += ', \n';
|
|
157
|
-
operationBlock.head += '\t$headers' + (isHeadersRequired ? '' : '?') + ': {\n\t';
|
|
158
|
-
for (const prm of headerParams) {
|
|
159
|
-
operationBlock.head += `/**\n * ${prm.description || ''}\n */\n`;
|
|
160
|
-
operationBlock.head += `${prm.name}${prm.required ? '' : '?'}: `;
|
|
161
|
-
if (prm.type) {
|
|
162
|
-
const xt = await this.processDataType(prm.type, file);
|
|
163
|
-
const typeDef = xt.kind === 'embedded' ? xt.code : xt.typeName;
|
|
164
|
-
operationBlock.head += `${typeDef};\n`;
|
|
165
|
-
}
|
|
166
|
-
else
|
|
167
|
-
operationBlock.head += `any;\n`;
|
|
168
|
-
}
|
|
169
|
-
operationBlock.head += '\b}\b';
|
|
170
|
-
}
|
|
171
|
-
/* Determine return type */
|
|
172
|
-
// let returnType = '';
|
|
173
|
-
// for (const resp of operation.responses) {
|
|
174
|
-
// if (resp.type) {
|
|
175
|
-
// const typeFile = await this.processDataType(resp.type);
|
|
176
|
-
// // if (typeFile) {
|
|
177
|
-
// // file.addImport(typeFile.filename, [resp.type.name!]);
|
|
178
|
-
// // operationBlock.head += `${type.name};\n`;
|
|
179
|
-
// // continue;
|
|
180
|
-
// // }
|
|
181
|
-
// }
|
|
182
|
-
// }
|
|
183
|
-
operationBlock.head += `\n): HttpRequestObservable<any>{`;
|
|
184
|
-
operationBlock.body = `\n\t`;
|
|
185
|
-
operationBlock.body +=
|
|
186
|
-
`const url = this._prepareUrl('${operation.getFullUrl()}', {` + pathParams.map(p => p.name).join(', ') + '});';
|
|
187
|
-
operationBlock.body +=
|
|
188
|
-
`\nreturn this[kClient].request(url, { method: '${operation.method}'` +
|
|
189
|
-
(hasBody ? ', body: $body' : '') +
|
|
190
|
-
(queryParams.length ? ', params: $params as any' : '') +
|
|
191
|
-
(headerParams.length ? ', headers: $headers as any' : '') +
|
|
192
|
-
'});';
|
|
193
|
-
operationBlock.tail = `\b\n};\n`;
|
|
194
|
-
}
|
|
195
|
-
classBlock.tail = `\b}`;
|
|
196
|
-
return file;
|
|
197
|
-
}
|
|
198
|
-
exports.processHttpController = processHttpController;
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import fs from 'node:fs';
|
|
2
|
-
import path from 'node:path';
|
|
3
|
-
import chalk from 'chalk';
|
|
4
|
-
export function cleanDirectory(dirname) {
|
|
5
|
-
const rootDir = dirname;
|
|
6
|
-
const _cleanDirectory = (targetDir) => {
|
|
7
|
-
if (!fs.existsSync(targetDir))
|
|
8
|
-
return;
|
|
9
|
-
const files = fs.readdirSync(targetDir);
|
|
10
|
-
for (const f of files) {
|
|
11
|
-
const absolutePath = path.join(targetDir, f);
|
|
12
|
-
if (fs.statSync(absolutePath).isDirectory()) {
|
|
13
|
-
_cleanDirectory(absolutePath);
|
|
14
|
-
if (!fs.readdirSync(absolutePath).length) {
|
|
15
|
-
this.emit('verbose', chalk.cyan(`Removing directory ${path.relative(absolutePath, rootDir)}`));
|
|
16
|
-
fs.rmdirSync(absolutePath);
|
|
17
|
-
}
|
|
18
|
-
continue;
|
|
19
|
-
}
|
|
20
|
-
if (path.extname(f) === '.ts') {
|
|
21
|
-
const contents = fs.readFileSync(absolutePath, 'utf-8');
|
|
22
|
-
if (contents.includes('#!oprimp_auto_generated!#')) {
|
|
23
|
-
this.emit('verbose', chalk.cyan(`Removing file ${path.relative(absolutePath, rootDir)}`));
|
|
24
|
-
fs.unlinkSync(absolutePath);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
};
|
|
29
|
-
_cleanDirectory(dirname);
|
|
30
|
-
}
|
|
@@ -1,247 +0,0 @@
|
|
|
1
|
-
import { ComplexType, EnumType, MappedType, MixinType, SimpleType } from '@opra/common';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import { CodeBlock } from '../../code-block.js';
|
|
4
|
-
import { wrapJSDocString } from '../utils/string-utils.js';
|
|
5
|
-
const internalTypeNames = ['any', 'boolean', 'bigint', 'number', 'null', 'string', 'object'];
|
|
6
|
-
export async function processDataType(dataType, currentFile, intent) {
|
|
7
|
-
const doc = dataType.node.getDocument();
|
|
8
|
-
if (doc.id !== this._document?.id) {
|
|
9
|
-
const { generator } = await this.processDocument(doc);
|
|
10
|
-
return await generator.processDataType(dataType, currentFile, intent);
|
|
11
|
-
}
|
|
12
|
-
const typeName = dataType.name;
|
|
13
|
-
if (typeName) {
|
|
14
|
-
if (internalTypeNames.includes(typeName))
|
|
15
|
-
return { kind: 'internal', typeName: dataType.name };
|
|
16
|
-
let file = this._filesMap.get(dataType);
|
|
17
|
-
if (file) {
|
|
18
|
-
if (currentFile)
|
|
19
|
-
currentFile.addImport(file.filename, [typeName]);
|
|
20
|
-
return { kind: 'named', file, typeName: dataType.name };
|
|
21
|
-
}
|
|
22
|
-
if (dataType instanceof SimpleType)
|
|
23
|
-
file = this.addFile(path.join(this._documentRoot, '/simple-types.ts'), true);
|
|
24
|
-
else if (dataType instanceof EnumType)
|
|
25
|
-
file = this.addFile(path.join(this._typesRoot, 'enums', typeName + '.ts'));
|
|
26
|
-
else
|
|
27
|
-
file = this.addFile(path.join(this._typesRoot, 'types', typeName + '.ts'));
|
|
28
|
-
this._filesMap.set(dataType, file);
|
|
29
|
-
if (file.exportTypes.includes(typeName)) {
|
|
30
|
-
if (currentFile)
|
|
31
|
-
currentFile.addImport(file.filename, [typeName]);
|
|
32
|
-
return { kind: 'named', file, typeName: dataType.name };
|
|
33
|
-
}
|
|
34
|
-
file.exportTypes.push(typeName);
|
|
35
|
-
const typesIndexTs = this.addFile(path.join(this._typesRoot, 'index.ts'), true);
|
|
36
|
-
const indexTs = this.addFile('/index.ts', true);
|
|
37
|
-
indexTs.addExport(typesIndexTs.filename);
|
|
38
|
-
const codeBlock = (file.code['type_' + typeName] = new CodeBlock());
|
|
39
|
-
codeBlock.head = `/**\n * ${wrapJSDocString(dataType.description || '')}\n *`;
|
|
40
|
-
codeBlock.head += `
|
|
41
|
-
* @url ${path.posix.join(doc.url || this.serviceUrl, '$schema', '#types/' + typeName)}
|
|
42
|
-
*/
|
|
43
|
-
export `;
|
|
44
|
-
codeBlock.typeDef = (await this.generateTypeDefinition(file, dataType, 'root')) + '\n\n';
|
|
45
|
-
typesIndexTs.addExport(file.filename);
|
|
46
|
-
if (currentFile)
|
|
47
|
-
currentFile.addImport(file.filename, [typeName]);
|
|
48
|
-
return { kind: 'named', file, typeName };
|
|
49
|
-
}
|
|
50
|
-
if (!currentFile)
|
|
51
|
-
throw new TypeError(`You must provide currentFile to generate data type`);
|
|
52
|
-
const code = await this.generateTypeDefinition(currentFile, dataType, intent);
|
|
53
|
-
return { kind: 'embedded', code };
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
*
|
|
57
|
-
*/
|
|
58
|
-
export async function generateTypeDefinition(currentFile, dataType, intent) {
|
|
59
|
-
if (intent === 'root' && !dataType.name) {
|
|
60
|
-
throw new TypeError(`Name required to generate data type code to root intent`);
|
|
61
|
-
}
|
|
62
|
-
if (dataType instanceof EnumType) {
|
|
63
|
-
return await this.generateEnumTypeDefinition(currentFile, dataType, intent);
|
|
64
|
-
}
|
|
65
|
-
if (dataType instanceof ComplexType) {
|
|
66
|
-
return await this.generateComplexTypeDefinition(currentFile, dataType, intent);
|
|
67
|
-
}
|
|
68
|
-
if (dataType instanceof SimpleType) {
|
|
69
|
-
return await this.generateSimpleTypeDefinition(currentFile, dataType, intent);
|
|
70
|
-
}
|
|
71
|
-
if (dataType instanceof MappedType) {
|
|
72
|
-
return await this.generateMappedTypeDefinition(currentFile, dataType, intent);
|
|
73
|
-
}
|
|
74
|
-
if (dataType instanceof MixinType) {
|
|
75
|
-
return await this.generateMixinTypeDefinition(currentFile, dataType, intent);
|
|
76
|
-
}
|
|
77
|
-
/* istanbul ignore next */
|
|
78
|
-
throw new TypeError(`${dataType.kind} data types can not be directly exported`);
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
*
|
|
82
|
-
*/
|
|
83
|
-
export async function generateEnumTypeDefinition(currentFile, dataType, intent) {
|
|
84
|
-
if (intent === 'root') {
|
|
85
|
-
let out = `enum ${dataType.name} {\n\t`;
|
|
86
|
-
for (const [value, info] of Object.entries(dataType.attributes)) {
|
|
87
|
-
// Print JSDoc
|
|
88
|
-
let jsDoc = '';
|
|
89
|
-
if (dataType.attributes[value].description)
|
|
90
|
-
jsDoc += ` * ${dataType.attributes[value].description}\n`;
|
|
91
|
-
if (jsDoc)
|
|
92
|
-
out += `/**\n${jsDoc} */\n`;
|
|
93
|
-
out +=
|
|
94
|
-
`${info.alias || value} = ` +
|
|
95
|
-
(typeof value === 'number' ? value : "'" + String(value).replace("'", "\\'") + "'");
|
|
96
|
-
out += ',\n\n';
|
|
97
|
-
}
|
|
98
|
-
return out + '\b}';
|
|
99
|
-
}
|
|
100
|
-
return ('(' +
|
|
101
|
-
Object.keys(dataType.attributes)
|
|
102
|
-
.map(t => `'${t}'`)
|
|
103
|
-
.join(' | ') +
|
|
104
|
-
')');
|
|
105
|
-
}
|
|
106
|
-
/**
|
|
107
|
-
*
|
|
108
|
-
*/
|
|
109
|
-
export async function generateComplexTypeDefinition(currentFile, dataType, intent) {
|
|
110
|
-
let out = intent === 'root' ? `interface ${dataType.name} ` : '';
|
|
111
|
-
const ownFields = [...dataType.fields.values()].filter(f => f.origin === dataType);
|
|
112
|
-
if (dataType.base) {
|
|
113
|
-
const base = await this.processDataType(dataType.base, currentFile, 'extends');
|
|
114
|
-
let baseDef = base.kind === 'embedded' ? base.code : base.typeName;
|
|
115
|
-
const omitBaseFields = ownFields.filter(f => dataType.base.fields.has(f.name));
|
|
116
|
-
if (omitBaseFields.length)
|
|
117
|
-
baseDef = `Omit<${baseDef}, ${omitBaseFields.map(x => "'" + x.name + "'").join(' | ')}>`;
|
|
118
|
-
if (intent === 'root')
|
|
119
|
-
out += `extends ${baseDef} `;
|
|
120
|
-
else {
|
|
121
|
-
out += baseDef;
|
|
122
|
-
if (!ownFields.length)
|
|
123
|
-
return out;
|
|
124
|
-
out += ' & ';
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
out += '{\n\t';
|
|
128
|
-
let i = 0;
|
|
129
|
-
for (const field of ownFields) {
|
|
130
|
-
if (i++)
|
|
131
|
-
out += '\n';
|
|
132
|
-
// Print JSDoc
|
|
133
|
-
out += `/**\n * ${field.description || ''}\n`;
|
|
134
|
-
if (field.default)
|
|
135
|
-
out += ` * @default ` + field.default + '\n';
|
|
136
|
-
// if (field.format)
|
|
137
|
-
// jsDoc += ` * @format ` + field.format + '\n';
|
|
138
|
-
if (field.exclusive)
|
|
139
|
-
out += ` * @exclusive\n`;
|
|
140
|
-
if (field.readonly)
|
|
141
|
-
out += ` * @readonly\n`;
|
|
142
|
-
if (field.writeonly)
|
|
143
|
-
out += ` * @writeonly\n`;
|
|
144
|
-
if (field.deprecated) {
|
|
145
|
-
out += ` * @deprecated ` + (typeof field.deprecated === 'string' ? field.deprecated : '') + '\n';
|
|
146
|
-
}
|
|
147
|
-
out += ' */\n';
|
|
148
|
-
// Print field name
|
|
149
|
-
if (field.readonly)
|
|
150
|
-
out += 'readonly ';
|
|
151
|
-
out += `${field.name}${field.required ? '' : '?'}: `;
|
|
152
|
-
if (field.fixed) {
|
|
153
|
-
const t = typeof field.fixed;
|
|
154
|
-
out += `${t === 'number' || t === 'boolean' || t === 'bigint' ? field.fixed : "'" + field.fixed + "'"}\n`;
|
|
155
|
-
}
|
|
156
|
-
else {
|
|
157
|
-
const x = await this.processDataType(field.type, currentFile);
|
|
158
|
-
out += (x.kind === 'embedded' ? x.code : x.typeName) + `${field.isArray ? '[]' : ''};\n`;
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
if (dataType.additionalFields)
|
|
162
|
-
out += '[key: string]: any;\n';
|
|
163
|
-
return out + '\b}';
|
|
164
|
-
}
|
|
165
|
-
/**
|
|
166
|
-
*
|
|
167
|
-
*/
|
|
168
|
-
export async function generateSimpleTypeDefinition(currentFile, dataType, intent) {
|
|
169
|
-
let out = intent === 'root' ? `type ${dataType.name} = ` : '';
|
|
170
|
-
out += dataType.nameMappings.js || 'any';
|
|
171
|
-
return intent === 'root' ? out + ';' : out;
|
|
172
|
-
}
|
|
173
|
-
/**
|
|
174
|
-
*
|
|
175
|
-
*/
|
|
176
|
-
export async function generateMixinTypeDefinition(currentFile, dataType, intent) {
|
|
177
|
-
const outArray = [];
|
|
178
|
-
for (const t of dataType.types) {
|
|
179
|
-
const x = await this.processDataType(t, currentFile);
|
|
180
|
-
if (x.kind === 'embedded') {
|
|
181
|
-
outArray.push(x.code.includes('|') ? '(' + x.code + ')' : x.code);
|
|
182
|
-
}
|
|
183
|
-
else
|
|
184
|
-
outArray.push(x.typeName);
|
|
185
|
-
}
|
|
186
|
-
if (intent === 'root')
|
|
187
|
-
return `type ${dataType.name} = ${outArray.join(' & ')}`;
|
|
188
|
-
if (intent === 'extends')
|
|
189
|
-
return outArray.join(', ');
|
|
190
|
-
return outArray.join(' & ');
|
|
191
|
-
}
|
|
192
|
-
/**
|
|
193
|
-
*
|
|
194
|
-
*/
|
|
195
|
-
export async function generateMappedTypeDefinition(currentFile, dataType, intent) {
|
|
196
|
-
let out = intent === 'root' ? `type ${dataType.name} = ` : '';
|
|
197
|
-
const base = await this.processDataType(dataType.base, currentFile);
|
|
198
|
-
const typeDef = base.kind === 'embedded' ? base.code : base.typeName;
|
|
199
|
-
const pick = dataType.pick?.length ? dataType.pick : undefined;
|
|
200
|
-
const omit = !pick && dataType.omit?.length ? dataType.omit : undefined;
|
|
201
|
-
const partial = dataType.partial === true || (Array.isArray(dataType.partial) && dataType.partial.length > 0)
|
|
202
|
-
? dataType.partial
|
|
203
|
-
: undefined;
|
|
204
|
-
const required = dataType.required === true || (Array.isArray(dataType.required) && dataType.required.length > 0)
|
|
205
|
-
? dataType.required
|
|
206
|
-
: undefined;
|
|
207
|
-
if (!(pick || omit || partial || required))
|
|
208
|
-
return typeDef;
|
|
209
|
-
if (partial === true)
|
|
210
|
-
out += 'Partial<';
|
|
211
|
-
else if (partial) {
|
|
212
|
-
out += 'PartialSome<';
|
|
213
|
-
currentFile.addExport('ts-gems', ['PartialSome']);
|
|
214
|
-
}
|
|
215
|
-
if (required === true)
|
|
216
|
-
out += 'Partial<';
|
|
217
|
-
else if (required) {
|
|
218
|
-
out += 'RequiredSome<';
|
|
219
|
-
currentFile.addExport('ts-gems', ['RequiredSome']);
|
|
220
|
-
}
|
|
221
|
-
if (pick)
|
|
222
|
-
out += 'Pick<';
|
|
223
|
-
else if (omit)
|
|
224
|
-
out += 'Omit<';
|
|
225
|
-
out += typeDef;
|
|
226
|
-
if (omit || pick) {
|
|
227
|
-
out +=
|
|
228
|
-
', ' +
|
|
229
|
-
(omit || pick)
|
|
230
|
-
.filter(x => !!x)
|
|
231
|
-
.map(x => `'${x}'`)
|
|
232
|
-
.join(' | ') +
|
|
233
|
-
'>';
|
|
234
|
-
}
|
|
235
|
-
if (partial) {
|
|
236
|
-
if (Array.isArray(partial)) {
|
|
237
|
-
out +=
|
|
238
|
-
', ' +
|
|
239
|
-
partial
|
|
240
|
-
.filter(x => !!x)
|
|
241
|
-
.map(x => `'${x}'`)
|
|
242
|
-
.join(' | ');
|
|
243
|
-
}
|
|
244
|
-
out += '>';
|
|
245
|
-
}
|
|
246
|
-
return out;
|
|
247
|
-
}
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { OpraHttpClient } from '@opra/client';
|
|
2
|
-
import { HttpApi } from '@opra/common';
|
|
3
|
-
import chalk from 'chalk';
|
|
4
|
-
import path from 'path';
|
|
5
|
-
import { pascalCase } from 'putil-varhelpers';
|
|
6
|
-
export async function processDocument(document, options) {
|
|
7
|
-
if (!document || typeof document === 'string') {
|
|
8
|
-
if (document) {
|
|
9
|
-
const out = this._documentsMap.get(document);
|
|
10
|
-
if (out)
|
|
11
|
-
return out;
|
|
12
|
-
}
|
|
13
|
-
this.emit('log', chalk.cyan('Fetching document schema from ') + chalk.blueBright(this.serviceUrl));
|
|
14
|
-
const client = new OpraHttpClient(this.serviceUrl);
|
|
15
|
-
document = await client.fetchDocument({ documentId: document });
|
|
16
|
-
}
|
|
17
|
-
this._document = document;
|
|
18
|
-
let out = this._documentsMap.get(document.id);
|
|
19
|
-
if (out)
|
|
20
|
-
return out;
|
|
21
|
-
out = {
|
|
22
|
-
document,
|
|
23
|
-
generator: this,
|
|
24
|
-
};
|
|
25
|
-
this._documentsMap.set(document.id, out);
|
|
26
|
-
this.emit('log', chalk.white('[' + document.id + '] ') + chalk.cyan('Processing document ') + chalk.magenta(document.info.title));
|
|
27
|
-
if (document.references.size) {
|
|
28
|
-
this.emit('log', chalk.white('[' + document.id + '] ') + chalk.cyan(`Processing references`));
|
|
29
|
-
for (const ref of document.references.values()) {
|
|
30
|
-
const generator = this.extend();
|
|
31
|
-
generator._document = ref;
|
|
32
|
-
generator._documentRoot = '/references/' + (ref.info.title ? pascalCase(ref.info.title) : ref.id);
|
|
33
|
-
generator._typesRoot = path.join(generator._documentRoot, 'models');
|
|
34
|
-
await generator.processDocument(ref, { typesOnly: true });
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
this._fileHeaderDocInfo = `/*
|
|
38
|
-
* ${document.info.title}
|
|
39
|
-
* Id: ${document.id}
|
|
40
|
-
* Version: ${document.info.version}
|
|
41
|
-
* ${this.serviceUrl}
|
|
42
|
-
*/`;
|
|
43
|
-
if (document.types.size) {
|
|
44
|
-
this.emit('log', chalk.white('[' + document.id + ']'), chalk.cyan(`Processing data types`));
|
|
45
|
-
for (const t of document.types.values()) {
|
|
46
|
-
await this.processDataType(t);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
if (options?.typesOnly)
|
|
50
|
-
return out;
|
|
51
|
-
if (document.api instanceof HttpApi) {
|
|
52
|
-
await this.processHttpApi(document.api);
|
|
53
|
-
}
|
|
54
|
-
return out;
|
|
55
|
-
}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
|
-
import { camelCase, pascalCase } from 'putil-varhelpers';
|
|
3
|
-
import { CodeBlock } from '../../code-block.js';
|
|
4
|
-
import { httpControllerNodeScript } from '../http-controller-node.js';
|
|
5
|
-
import { wrapJSDocString } from '../utils/string-utils.js';
|
|
6
|
-
export async function processHttpApi(api) {
|
|
7
|
-
let file = this._filesMap.get(api);
|
|
8
|
-
if (file)
|
|
9
|
-
return file;
|
|
10
|
-
const className = api.name ? pascalCase(api.name) : 'Api';
|
|
11
|
-
file = this.addFile(className + '.ts');
|
|
12
|
-
file.addImport('@opra/client', ['kClient', 'OpraHttpClient']);
|
|
13
|
-
const indexTs = this.addFile('/index.ts', true);
|
|
14
|
-
indexTs.addExport('.' + file.filename);
|
|
15
|
-
const httpApiNodeFile = this.addFile('./http-controller-node.ts');
|
|
16
|
-
httpApiNodeFile.code.content = httpControllerNodeScript;
|
|
17
|
-
const classBlock = (file.code[className] = new CodeBlock());
|
|
18
|
-
classBlock.doc = `/**
|
|
19
|
-
* ${wrapJSDocString(api.description || '')}
|
|
20
|
-
* @class ${className}
|
|
21
|
-
* @url ${path.posix.join(this.serviceUrl, '$schema')}
|
|
22
|
-
*/`;
|
|
23
|
-
classBlock.head = `\nexport class ${className} {\n\t`;
|
|
24
|
-
classBlock.properties = 'readonly [kClient]: OpraHttpClient;';
|
|
25
|
-
const classConstBlock = (classBlock.classConstBlock = new CodeBlock());
|
|
26
|
-
classConstBlock.head = `\n\nconstructor(client: OpraHttpClient) {`;
|
|
27
|
-
classConstBlock.body = `\n\tthis[kClient] = client;`;
|
|
28
|
-
classConstBlock.tail = `\b\n}\n`;
|
|
29
|
-
for (const controller of api.controllers.values()) {
|
|
30
|
-
const generator = this.extend();
|
|
31
|
-
const f = await generator.processHttpController(controller);
|
|
32
|
-
const childClassName = pascalCase(controller.name) + 'Controller';
|
|
33
|
-
file.addImport('.' + f.filename, [childClassName]);
|
|
34
|
-
const property = '$' + controller.name.charAt(0).toLowerCase() + camelCase(controller.name.substring(1));
|
|
35
|
-
classBlock.properties += `\nreadonly ${property}: ${childClassName};`;
|
|
36
|
-
classConstBlock.body += `\nthis.${property} = new ${childClassName}(client);`;
|
|
37
|
-
}
|
|
38
|
-
classBlock.tail = `\b}`;
|
|
39
|
-
return file;
|
|
40
|
-
}
|
|
@@ -1,193 +0,0 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
|
-
import { camelCase, pascalCase } from 'putil-varhelpers';
|
|
3
|
-
import { CodeBlock } from '../../code-block.js';
|
|
4
|
-
import { locateNamedType } from '../utils/locate-named-type.js';
|
|
5
|
-
import { wrapJSDocString } from '../utils/string-utils.js';
|
|
6
|
-
export async function processHttpController(controller) {
|
|
7
|
-
let file = this._filesMap.get(controller);
|
|
8
|
-
if (file)
|
|
9
|
-
return file;
|
|
10
|
-
const className = pascalCase(controller.name) + 'Controller';
|
|
11
|
-
file = this.addFile(path.join(this._apiPath, className + '.ts'));
|
|
12
|
-
file.addImport('@opra/client', ['HttpRequestObservable', 'kClient', 'OpraHttpClient']);
|
|
13
|
-
file.addImport(path.relative(file.dirname, '/http-controller-node.ts'), ['HttpControllerNode']);
|
|
14
|
-
const classBlock = (file.code[className] = new CodeBlock());
|
|
15
|
-
classBlock.doc = `/**
|
|
16
|
-
* ${wrapJSDocString(controller.description || '')}
|
|
17
|
-
* @class ${className}
|
|
18
|
-
* @url ${path.posix.join(this.serviceUrl, '$schema', '#resources/' + className)}
|
|
19
|
-
*/`;
|
|
20
|
-
classBlock.head = `\nexport class ${className} extends HttpControllerNode {\n\t`;
|
|
21
|
-
classBlock.properties = '';
|
|
22
|
-
const classConstBlock = (classBlock.classConstBlock = new CodeBlock());
|
|
23
|
-
classConstBlock.head = `\n\nconstructor(client: OpraHttpClient) {`;
|
|
24
|
-
classConstBlock.body = `\n\tsuper(client);`;
|
|
25
|
-
classConstBlock.tail = `\b\n}\n`;
|
|
26
|
-
if (controller.controllers.size) {
|
|
27
|
-
for (const child of controller.controllers.values()) {
|
|
28
|
-
const generator = this.extend();
|
|
29
|
-
generator._apiPath = path.join(this._apiPath, className);
|
|
30
|
-
const f = await generator.processHttpController(child);
|
|
31
|
-
const childClassName = pascalCase(child.name) + 'Controller';
|
|
32
|
-
file.addImport(f.filename, [childClassName]);
|
|
33
|
-
const property = '$' + child.name.charAt(0).toLowerCase() + camelCase(child.name.substring(1));
|
|
34
|
-
classBlock.properties += `\nreadonly ${property}: ${childClassName};`;
|
|
35
|
-
classConstBlock.body += `\nthis.${property} = new ${childClassName}(client);`;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
/** Process operations */
|
|
39
|
-
for (const operation of controller.operations.values()) {
|
|
40
|
-
const operationBlock = (classBlock['operation_' + operation.name] = new CodeBlock());
|
|
41
|
-
operationBlock.doc = `
|
|
42
|
-
/**
|
|
43
|
-
* ${wrapJSDocString(operation.description || operation.name + ' operation')}`;
|
|
44
|
-
if (operation.parameters.length) {
|
|
45
|
-
const block = new CodeBlock();
|
|
46
|
-
block.doc = '\n *\n * RegExp parameters:';
|
|
47
|
-
let i = 0;
|
|
48
|
-
for (const prm of operation.parameters) {
|
|
49
|
-
if (!(prm.name instanceof RegExp))
|
|
50
|
-
continue;
|
|
51
|
-
i++;
|
|
52
|
-
block.doc +=
|
|
53
|
-
`\n * > ${String(prm.name)} - ${prm.description || ''}` +
|
|
54
|
-
`\n * - location: ${prm.location}` +
|
|
55
|
-
`\n * - type: ${locateNamedType(prm.type)?.name || 'any'}${prm.isArray ? '[' + prm.arraySeparator + ']' : ''}` +
|
|
56
|
-
(prm.required ? `\n * required: ${prm.required}` : '') +
|
|
57
|
-
(prm.deprecated ? `\n * deprecated: ${prm.deprecated}` : '');
|
|
58
|
-
}
|
|
59
|
-
if (i)
|
|
60
|
-
operationBlock.doc += block;
|
|
61
|
-
}
|
|
62
|
-
operationBlock.doc += `\n */\n`;
|
|
63
|
-
operationBlock.head = `${operation.name}(`;
|
|
64
|
-
/** Process operation parameters */
|
|
65
|
-
const mergedParams = [...controller.parameters, ...operation.parameters];
|
|
66
|
-
const pathParams = [];
|
|
67
|
-
const queryParams = [];
|
|
68
|
-
const headerParams = [];
|
|
69
|
-
if (mergedParams.length) {
|
|
70
|
-
const pathParamsMap = {};
|
|
71
|
-
const queryParamsMap = {};
|
|
72
|
-
const headerParamsMap = {};
|
|
73
|
-
for (const prm of mergedParams) {
|
|
74
|
-
if (typeof prm.name !== 'string')
|
|
75
|
-
continue;
|
|
76
|
-
if (prm.location === 'path')
|
|
77
|
-
pathParamsMap[prm.name] = prm;
|
|
78
|
-
if (prm.location === 'query')
|
|
79
|
-
queryParamsMap[prm.name] = prm;
|
|
80
|
-
if (prm.location === 'header')
|
|
81
|
-
headerParamsMap[prm.name] = prm;
|
|
82
|
-
}
|
|
83
|
-
pathParams.push(...Object.values(pathParamsMap));
|
|
84
|
-
queryParams.push(...Object.values(queryParamsMap));
|
|
85
|
-
headerParams.push(...Object.values(headerParamsMap));
|
|
86
|
-
}
|
|
87
|
-
let argIndex = 0;
|
|
88
|
-
for (const prm of pathParams) {
|
|
89
|
-
let typeName;
|
|
90
|
-
if (prm.type) {
|
|
91
|
-
const xt = await this.processDataType(prm.type, file);
|
|
92
|
-
typeName = xt.kind === 'embedded' ? xt.code : xt.typeName;
|
|
93
|
-
}
|
|
94
|
-
else
|
|
95
|
-
typeName = `any`;
|
|
96
|
-
if (argIndex++ > 0)
|
|
97
|
-
operationBlock.head += ', ';
|
|
98
|
-
operationBlock.head += `${prm.name}: ${typeName}`;
|
|
99
|
-
}
|
|
100
|
-
let hasBody = false;
|
|
101
|
-
if (operation.requestBody?.content.length) {
|
|
102
|
-
if (argIndex++ > 0)
|
|
103
|
-
operationBlock.head += ', ';
|
|
104
|
-
let typeArr = [];
|
|
105
|
-
for (const content of operation.requestBody.content) {
|
|
106
|
-
if (content.type) {
|
|
107
|
-
const xt = await this.processDataType(content.type, file);
|
|
108
|
-
const typeName = xt.kind === 'embedded' ? xt.code : xt.typeName;
|
|
109
|
-
typeArr.push(typeName);
|
|
110
|
-
continue;
|
|
111
|
-
}
|
|
112
|
-
typeArr = [];
|
|
113
|
-
break;
|
|
114
|
-
}
|
|
115
|
-
if (typeArr.length) {
|
|
116
|
-
if (operation.requestBody.partial) {
|
|
117
|
-
file.addImport('ts-gems', ['PartialDTO']);
|
|
118
|
-
operationBlock.head += `$body: PartialDTO<${typeArr.join(' | ')}>`;
|
|
119
|
-
}
|
|
120
|
-
else {
|
|
121
|
-
file.addImport('ts-gems', ['DTO']);
|
|
122
|
-
operationBlock.head += `$body: DTO<${typeArr.join(' | ')}>`;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
else
|
|
126
|
-
operationBlock.head += `$body: any`;
|
|
127
|
-
hasBody = true;
|
|
128
|
-
}
|
|
129
|
-
/** process query params */
|
|
130
|
-
const isQueryRequired = queryParams.find(p => p.required);
|
|
131
|
-
const isHeadersRequired = queryParams.find(p => p.required);
|
|
132
|
-
if (queryParams.length) {
|
|
133
|
-
if (argIndex++ > 0)
|
|
134
|
-
operationBlock.head += ', ';
|
|
135
|
-
operationBlock.head += '\n\t$params' + (isHeadersRequired || isQueryRequired ? '' : '?') + ': {\n\t';
|
|
136
|
-
for (const prm of queryParams) {
|
|
137
|
-
operationBlock.head += `/**\n * ${prm.description || ''}\n */\n`;
|
|
138
|
-
operationBlock.head += `${prm.name}${prm.required ? '' : '?'}: `;
|
|
139
|
-
if (prm.type) {
|
|
140
|
-
const xt = await this.processDataType(prm.type, file);
|
|
141
|
-
const typeDef = xt.kind === 'embedded' ? xt.code : xt.typeName;
|
|
142
|
-
operationBlock.head += `${typeDef};\n`;
|
|
143
|
-
}
|
|
144
|
-
else
|
|
145
|
-
operationBlock.head += `any;\n`;
|
|
146
|
-
}
|
|
147
|
-
operationBlock.head += '\b}\b';
|
|
148
|
-
}
|
|
149
|
-
/** process header params */
|
|
150
|
-
if (headerParams.length) {
|
|
151
|
-
if (argIndex++ > 0)
|
|
152
|
-
operationBlock.head += ', \n';
|
|
153
|
-
operationBlock.head += '\t$headers' + (isHeadersRequired ? '' : '?') + ': {\n\t';
|
|
154
|
-
for (const prm of headerParams) {
|
|
155
|
-
operationBlock.head += `/**\n * ${prm.description || ''}\n */\n`;
|
|
156
|
-
operationBlock.head += `${prm.name}${prm.required ? '' : '?'}: `;
|
|
157
|
-
if (prm.type) {
|
|
158
|
-
const xt = await this.processDataType(prm.type, file);
|
|
159
|
-
const typeDef = xt.kind === 'embedded' ? xt.code : xt.typeName;
|
|
160
|
-
operationBlock.head += `${typeDef};\n`;
|
|
161
|
-
}
|
|
162
|
-
else
|
|
163
|
-
operationBlock.head += `any;\n`;
|
|
164
|
-
}
|
|
165
|
-
operationBlock.head += '\b}\b';
|
|
166
|
-
}
|
|
167
|
-
/* Determine return type */
|
|
168
|
-
// let returnType = '';
|
|
169
|
-
// for (const resp of operation.responses) {
|
|
170
|
-
// if (resp.type) {
|
|
171
|
-
// const typeFile = await this.processDataType(resp.type);
|
|
172
|
-
// // if (typeFile) {
|
|
173
|
-
// // file.addImport(typeFile.filename, [resp.type.name!]);
|
|
174
|
-
// // operationBlock.head += `${type.name};\n`;
|
|
175
|
-
// // continue;
|
|
176
|
-
// // }
|
|
177
|
-
// }
|
|
178
|
-
// }
|
|
179
|
-
operationBlock.head += `\n): HttpRequestObservable<any>{`;
|
|
180
|
-
operationBlock.body = `\n\t`;
|
|
181
|
-
operationBlock.body +=
|
|
182
|
-
`const url = this._prepareUrl('${operation.getFullUrl()}', {` + pathParams.map(p => p.name).join(', ') + '});';
|
|
183
|
-
operationBlock.body +=
|
|
184
|
-
`\nreturn this[kClient].request(url, { method: '${operation.method}'` +
|
|
185
|
-
(hasBody ? ', body: $body' : '') +
|
|
186
|
-
(queryParams.length ? ', params: $params as any' : '') +
|
|
187
|
-
(headerParams.length ? ', headers: $headers as any' : '') +
|
|
188
|
-
'});';
|
|
189
|
-
operationBlock.tail = `\b\n};\n`;
|
|
190
|
-
}
|
|
191
|
-
classBlock.tail = `\b}`;
|
|
192
|
-
return file;
|
|
193
|
-
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { ComplexType, DataType, EnumType, MappedType, MixinType, SimpleType } from '@opra/common';
|
|
2
|
-
import { TsFile } from '../ts-file.js';
|
|
3
|
-
import type { TsGenerator } from '../ts-generator';
|
|
4
|
-
type Intent = 'root' | 'extends' | 'property';
|
|
5
|
-
export type ProcessDataTypeResult = {
|
|
6
|
-
kind: 'internal';
|
|
7
|
-
typeName: string;
|
|
8
|
-
} | {
|
|
9
|
-
kind: 'named';
|
|
10
|
-
typeName: string;
|
|
11
|
-
file: TsFile;
|
|
12
|
-
} | {
|
|
13
|
-
kind: 'embedded';
|
|
14
|
-
code: string;
|
|
15
|
-
};
|
|
16
|
-
export declare function processDataType(this: TsGenerator, dataType: DataType, currentFile?: TsFile, intent?: Intent): Promise<ProcessDataTypeResult>;
|
|
17
|
-
/**
|
|
18
|
-
*
|
|
19
|
-
*/
|
|
20
|
-
export declare function generateTypeDefinition(this: TsGenerator, currentFile: TsFile, dataType: DataType, intent?: Intent): Promise<string>;
|
|
21
|
-
/**
|
|
22
|
-
*
|
|
23
|
-
*/
|
|
24
|
-
export declare function generateEnumTypeDefinition(this: TsGenerator, currentFile: TsFile, dataType: EnumType, intent?: Intent): Promise<string>;
|
|
25
|
-
/**
|
|
26
|
-
*
|
|
27
|
-
*/
|
|
28
|
-
export declare function generateComplexTypeDefinition(this: TsGenerator, currentFile: TsFile, dataType: ComplexType, intent?: Intent): Promise<string>;
|
|
29
|
-
/**
|
|
30
|
-
*
|
|
31
|
-
*/
|
|
32
|
-
export declare function generateSimpleTypeDefinition(this: TsGenerator, currentFile: TsFile, dataType: SimpleType, intent?: Intent): Promise<string>;
|
|
33
|
-
/**
|
|
34
|
-
*
|
|
35
|
-
*/
|
|
36
|
-
export declare function generateMixinTypeDefinition(this: TsGenerator, currentFile: TsFile, dataType: MixinType, intent?: Intent): Promise<string>;
|
|
37
|
-
/**
|
|
38
|
-
*
|
|
39
|
-
*/
|
|
40
|
-
export declare function generateMappedTypeDefinition(this: TsGenerator, currentFile: TsFile, dataType: MappedType, intent?: Intent): Promise<string>;
|
|
41
|
-
export {};
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { ApiDocument } from '@opra/common';
|
|
2
|
-
import type { TsGenerator } from '../ts-generator';
|
|
3
|
-
export declare function processDocument(this: TsGenerator, document?: string | ApiDocument, options?: {
|
|
4
|
-
typesOnly?: boolean;
|
|
5
|
-
}): Promise<{
|
|
6
|
-
document: ApiDocument;
|
|
7
|
-
generator: TsGenerator;
|
|
8
|
-
}>;
|