@opra/cli 0.33.9 → 0.33.10
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/cjs/api-exporter/process-resources.js +10 -2
- package/cjs/api-exporter/process-types.js +101 -106
- package/cjs/index.js +1 -1
- package/esm/api-exporter/process-resources.js +10 -2
- package/esm/api-exporter/process-types.js +99 -104
- package/esm/index.js +1 -1
- package/package.json +2 -2
- package/types/api-exporter/process-types.d.ts +32 -22
- package/types/index.d.ts +1 -1
|
@@ -87,14 +87,22 @@ export class ${className} {
|
|
|
87
87
|
tsFile.addImport('@opra/client', ['HttpRequestObservable']);
|
|
88
88
|
for (const [action, endpoint] of resource.actions.entries()) {
|
|
89
89
|
let returnTypeDef = endpoint.returnType ?
|
|
90
|
-
await this.resolveTypeNameOrDef(
|
|
90
|
+
await this.resolveTypeNameOrDef({
|
|
91
|
+
file: tsFile,
|
|
92
|
+
dataType: endpoint.returnType,
|
|
93
|
+
intent: 'field'
|
|
94
|
+
})
|
|
91
95
|
: 'any';
|
|
92
96
|
if (returnTypeDef.length > 40)
|
|
93
97
|
returnTypeDef = '\n\t\t' + returnTypeDef + '\n\b\b';
|
|
94
98
|
const actionPath = resource.getFullPath() + '/' + action;
|
|
95
99
|
let params = '';
|
|
96
100
|
for (const prm of endpoint.parameters.values()) {
|
|
97
|
-
const paramTypeDef = await this.resolveTypeNameOrDef(
|
|
101
|
+
const paramTypeDef = await this.resolveTypeNameOrDef({
|
|
102
|
+
file: tsFile,
|
|
103
|
+
dataType: prm.type,
|
|
104
|
+
intent: 'field'
|
|
105
|
+
}) || 'any';
|
|
98
106
|
params += `${prm.name}: ${paramTypeDef}`;
|
|
99
107
|
if (prm.isArray)
|
|
100
108
|
params += '[]';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.generateMappedTypeDefinition = exports.generateMixinTypeDefinition = exports.
|
|
3
|
+
exports.generateMappedTypeDefinition = exports.generateMixinTypeDefinition = exports.generateSimpleTypeDefinition = exports.generateComplexTypeDefinition = exports.generateEnumTypeDefinition = exports.resolveTypeNameOrDef = exports.generateTypeFile = exports.processTypes = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const node_path_1 = tslib_1.__importDefault(require("node:path"));
|
|
6
6
|
const common_1 = require("@opra/common");
|
|
@@ -42,82 +42,102 @@ async function generateTypeFile(dataType) {
|
|
|
42
42
|
file.exportTypes.push(typeName);
|
|
43
43
|
const indexTs = this.addFile('/index.ts', true);
|
|
44
44
|
indexTs.addExport(file.filename);
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
* @enum ${typeName}
|
|
50
|
-
* @url ${node_path_1.default.posix.join(this.client.serviceUrl, '#types/' + typeName)}
|
|
51
|
-
*/
|
|
52
|
-
export enum ${typeName} ` + await this.generateEnumTypeDefinition(file, dataType);
|
|
53
|
-
}
|
|
54
|
-
// Export ComplexType
|
|
55
|
-
if (dataType instanceof common_1.ComplexType) {
|
|
56
|
-
file.content += `
|
|
57
|
-
/**\n * ${(0, string_utils_js_1.wrapJSDocString)(dataType.description || '')}
|
|
58
|
-
* @interface ${typeName}
|
|
59
|
-
* @url ${node_path_1.default.posix.join(this.client.serviceUrl, '#types/' + typeName)}
|
|
60
|
-
*/
|
|
61
|
-
export interface ${typeName} ${await this.generateComplexTypeDefinition(file, dataType, true)}`;
|
|
62
|
-
}
|
|
63
|
-
// Export SimpleType
|
|
64
|
-
if (dataType instanceof common_1.SimpleType) {
|
|
45
|
+
file.content += `
|
|
46
|
+
/**
|
|
47
|
+
* ${typeName}`;
|
|
48
|
+
if (dataType.description)
|
|
65
49
|
file.content += `
|
|
66
|
-
|
|
67
|
-
|
|
50
|
+
* ${(0, string_utils_js_1.wrapJSDocString)(dataType.description || '')}`;
|
|
51
|
+
file.content += `
|
|
68
52
|
* @url ${node_path_1.default.posix.join(this.client.serviceUrl, '#types/' + typeName)}
|
|
69
53
|
*/
|
|
70
|
-
export
|
|
71
|
-
|
|
54
|
+
export `;
|
|
55
|
+
if (dataType instanceof common_1.EnumType)
|
|
56
|
+
file.content += await this.generateEnumTypeDefinition({ file, dataType, intent: 'scope' });
|
|
57
|
+
else if (dataType instanceof common_1.ComplexType)
|
|
58
|
+
file.content += await this.generateComplexTypeDefinition({ file, dataType, intent: 'scope' });
|
|
59
|
+
else if (dataType instanceof common_1.SimpleType)
|
|
60
|
+
file.content += await this.generateSimpleTypeDefinition({ file, dataType, intent: 'scope' });
|
|
61
|
+
else
|
|
62
|
+
throw new TypeError(`${dataType.kind} data type (${typeName}) can not be directly exported`);
|
|
63
|
+
file.content += '\n';
|
|
72
64
|
typesTs.addExport(file.filename);
|
|
73
65
|
return file;
|
|
74
66
|
}
|
|
75
67
|
exports.generateTypeFile = generateTypeFile;
|
|
76
68
|
/**
|
|
77
69
|
*
|
|
78
|
-
* @param file
|
|
79
|
-
* @param dataType
|
|
80
|
-
* @param forInterface
|
|
81
70
|
*/
|
|
82
|
-
async function resolveTypeNameOrDef(
|
|
71
|
+
async function resolveTypeNameOrDef(args) {
|
|
72
|
+
const { dataType } = args;
|
|
83
73
|
if (dataType.name && !dataType.isEmbedded) {
|
|
84
74
|
if (internalTypeNames.includes(dataType.name))
|
|
85
75
|
return dataType.name;
|
|
86
76
|
const f = await this.generateTypeFile(dataType);
|
|
87
77
|
if (!f)
|
|
88
78
|
return '';
|
|
89
|
-
file.addImport(f.filename, [dataType.name], true);
|
|
79
|
+
args.file.addImport(f.filename, [dataType.name], true);
|
|
90
80
|
return dataType.name;
|
|
91
81
|
}
|
|
92
82
|
if (dataType instanceof common_1.SimpleType)
|
|
93
|
-
return this.generateSimpleTypeDefinition(
|
|
83
|
+
return this.generateSimpleTypeDefinition({ ...args, dataType });
|
|
94
84
|
if (dataType instanceof common_1.EnumType)
|
|
95
|
-
return this.generateEnumTypeDefinition(
|
|
85
|
+
return this.generateEnumTypeDefinition({ ...args, dataType });
|
|
96
86
|
if (dataType instanceof common_1.MixinType)
|
|
97
|
-
return this.generateMixinTypeDefinition(
|
|
87
|
+
return this.generateMixinTypeDefinition({ ...args, dataType });
|
|
98
88
|
if (dataType instanceof common_1.MappedType)
|
|
99
|
-
return this.generateMappedTypeDefinition(
|
|
89
|
+
return this.generateMappedTypeDefinition({ ...args, dataType });
|
|
100
90
|
if (dataType instanceof common_1.ComplexType)
|
|
101
|
-
return this.generateComplexTypeDefinition(
|
|
91
|
+
return this.generateComplexTypeDefinition({ ...args, dataType });
|
|
102
92
|
return '';
|
|
103
93
|
}
|
|
104
94
|
exports.resolveTypeNameOrDef = resolveTypeNameOrDef;
|
|
105
95
|
/**
|
|
106
96
|
*
|
|
107
|
-
* @param file
|
|
108
|
-
* @param dataType
|
|
109
|
-
* @param forInterface
|
|
110
97
|
*/
|
|
111
|
-
async function
|
|
112
|
-
|
|
98
|
+
async function generateEnumTypeDefinition(args) {
|
|
99
|
+
const { dataType } = args;
|
|
100
|
+
if (args.intent === 'field')
|
|
101
|
+
return '(' +
|
|
102
|
+
Object.keys(dataType.values)
|
|
103
|
+
.map(t => `'${t}'`)
|
|
104
|
+
.join(' | ') +
|
|
105
|
+
')';
|
|
106
|
+
if (args.intent !== 'scope')
|
|
107
|
+
throw new TypeError(`Can't generate EnumType for "${args.intent}" intent`);
|
|
108
|
+
if (!dataType.name)
|
|
109
|
+
throw new TypeError(`Name required to generate EnumType for "${args.intent}" intent`);
|
|
110
|
+
let out = `enum ${dataType.name} {\n\t`;
|
|
111
|
+
for (const [value, info] of Object.entries(dataType.values)) {
|
|
112
|
+
// Print JSDoc
|
|
113
|
+
let jsDoc = '';
|
|
114
|
+
if (dataType.values[value].description)
|
|
115
|
+
jsDoc += ` * ${dataType.values[value].description}\n`;
|
|
116
|
+
if (jsDoc)
|
|
117
|
+
out += `/**\n${jsDoc} */\n`;
|
|
118
|
+
out += `${info.key || value} = ` +
|
|
119
|
+
(typeof value === 'number' ? value : ('\'' + (String(value)).replace('\'', '\\\'')) + '\'');
|
|
120
|
+
out += ',\n\n';
|
|
121
|
+
}
|
|
122
|
+
return out + '\b}';
|
|
123
|
+
}
|
|
124
|
+
exports.generateEnumTypeDefinition = generateEnumTypeDefinition;
|
|
125
|
+
/**
|
|
126
|
+
*
|
|
127
|
+
*/
|
|
128
|
+
async function generateComplexTypeDefinition(args) {
|
|
129
|
+
const { intent, dataType } = args;
|
|
130
|
+
if (intent === 'scope' && !dataType.name)
|
|
131
|
+
throw new TypeError(`Name required to generate ComplexType for "${args.intent}" intent`);
|
|
132
|
+
let out = intent === 'scope' ? `interface ${dataType.name} ` : '';
|
|
113
133
|
if (dataType.base) {
|
|
114
|
-
const base = await this.resolveTypeNameOrDef(file, dataType.base,
|
|
134
|
+
const base = await this.resolveTypeNameOrDef({ file: args.file, dataType: dataType.base, intent: 'extends' });
|
|
115
135
|
const omitFields = [...dataType.own.fields.keys()]
|
|
116
136
|
.filter(k => dataType.base?.fields.has(k));
|
|
117
137
|
const baseDef = omitFields.length
|
|
118
138
|
? `Omit<${base}, ${omitFields.map(x => "'" + x + "'").join(' | ')}>`
|
|
119
139
|
: `${base}`;
|
|
120
|
-
if (
|
|
140
|
+
if (intent === 'scope')
|
|
121
141
|
out += `extends ${baseDef} `;
|
|
122
142
|
else {
|
|
123
143
|
out += baseDef;
|
|
@@ -127,29 +147,25 @@ async function generateComplexTypeDefinition(file, dataType, forInterface) {
|
|
|
127
147
|
}
|
|
128
148
|
}
|
|
129
149
|
out += '{\n\t';
|
|
150
|
+
let i = 0;
|
|
130
151
|
for (const field of dataType.own.fields.values()) {
|
|
152
|
+
if (i++)
|
|
153
|
+
out += '\n';
|
|
131
154
|
// Print JSDoc
|
|
132
|
-
|
|
133
|
-
if (field.description)
|
|
134
|
-
jsDoc += ` * ${field.description}\n`;
|
|
135
|
-
if (field.type.name)
|
|
136
|
-
jsDoc += ` * @type ${field.type.name}\n`;
|
|
155
|
+
out += `/**\n * ${field.description || ''}\n`;
|
|
137
156
|
if (field.default)
|
|
138
|
-
|
|
157
|
+
out += ` * @default ` + field.default + '\n';
|
|
139
158
|
// if (field.format)
|
|
140
159
|
// jsDoc += ` * @format ` + field.format + '\n';
|
|
141
160
|
if (field.exclusive)
|
|
142
|
-
|
|
161
|
+
out += ` * @exclusive\n`;
|
|
143
162
|
if (field.readonly)
|
|
144
|
-
|
|
163
|
+
out += ` * @readonly\n`;
|
|
145
164
|
if (field.writeonly)
|
|
146
|
-
|
|
165
|
+
out += ` * @writeonly\n`;
|
|
147
166
|
if (field.deprecated)
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
out += `\n/**\n${jsDoc} */\n`;
|
|
151
|
-
else
|
|
152
|
-
out += `\n`;
|
|
167
|
+
out += ` * @deprecated ` + (typeof field.deprecated === 'string' ? field.deprecated : '') + '\n';
|
|
168
|
+
out += ' */\n';
|
|
153
169
|
// Print field name
|
|
154
170
|
if (field.readonly)
|
|
155
171
|
out += 'readonly ';
|
|
@@ -159,7 +175,7 @@ async function generateComplexTypeDefinition(file, dataType, forInterface) {
|
|
|
159
175
|
out += `${t === 'number' || t === 'boolean' || t === 'bigint' ? field.fixed : "'" + field.fixed + "'"}\n`;
|
|
160
176
|
}
|
|
161
177
|
else {
|
|
162
|
-
out += await this.resolveTypeNameOrDef(file, field.type) +
|
|
178
|
+
out += await this.resolveTypeNameOrDef({ file: args.file, dataType: field.type, intent: 'field' }) +
|
|
163
179
|
`${field.isArray ? '[]' : ''};\n`;
|
|
164
180
|
}
|
|
165
181
|
}
|
|
@@ -170,68 +186,47 @@ async function generateComplexTypeDefinition(file, dataType, forInterface) {
|
|
|
170
186
|
exports.generateComplexTypeDefinition = generateComplexTypeDefinition;
|
|
171
187
|
/**
|
|
172
188
|
*
|
|
173
|
-
* @param file
|
|
174
|
-
* @param dataType
|
|
175
189
|
*/
|
|
176
|
-
async function generateSimpleTypeDefinition(
|
|
190
|
+
async function generateSimpleTypeDefinition(args) {
|
|
191
|
+
const { intent, dataType } = args;
|
|
192
|
+
if (intent === 'scope' && !dataType.name)
|
|
193
|
+
throw new TypeError(`Name required to generate SimpleType for "${args.intent}" intent`);
|
|
194
|
+
let out = intent === 'scope' ? `type ${dataType.name} = ` : '';
|
|
177
195
|
if (dataType.extendsFrom('boolean'))
|
|
178
|
-
|
|
179
|
-
if (dataType.extendsFrom('string'))
|
|
180
|
-
|
|
181
|
-
if (dataType.extendsFrom('number') || dataType.extendsFrom('integer'))
|
|
182
|
-
|
|
183
|
-
if (dataType.extendsFrom('date') || dataType.extendsFrom('datetime'))
|
|
184
|
-
|
|
185
|
-
if (dataType.extendsFrom('approxdate') || dataType.extendsFrom('approxdatetime'))
|
|
186
|
-
|
|
187
|
-
if (dataType.extendsFrom('bigint'))
|
|
188
|
-
|
|
189
|
-
if (dataType.extendsFrom('object'))
|
|
190
|
-
|
|
191
|
-
|
|
196
|
+
out += 'boolean';
|
|
197
|
+
else if (dataType.extendsFrom('string'))
|
|
198
|
+
out += 'string';
|
|
199
|
+
else if (dataType.extendsFrom('number') || dataType.extendsFrom('integer'))
|
|
200
|
+
out += 'number';
|
|
201
|
+
else if (dataType.extendsFrom('date') || dataType.extendsFrom('datetime'))
|
|
202
|
+
out += 'Date';
|
|
203
|
+
else if (dataType.extendsFrom('approxdate') || dataType.extendsFrom('approxdatetime'))
|
|
204
|
+
out += 'string';
|
|
205
|
+
else if (dataType.extendsFrom('bigint'))
|
|
206
|
+
out += 'bigint';
|
|
207
|
+
else if (dataType.extendsFrom('object'))
|
|
208
|
+
out += 'object';
|
|
209
|
+
else
|
|
210
|
+
out += 'any';
|
|
211
|
+
return intent === 'scope' ? out + ';' : out;
|
|
192
212
|
}
|
|
193
213
|
exports.generateSimpleTypeDefinition = generateSimpleTypeDefinition;
|
|
194
214
|
/**
|
|
195
215
|
*
|
|
196
|
-
* @param file
|
|
197
|
-
* @param dataType
|
|
198
216
|
*/
|
|
199
|
-
async function
|
|
200
|
-
|
|
201
|
-
for (const [value, info] of Object.entries(dataType.values)) {
|
|
202
|
-
// Print JSDoc
|
|
203
|
-
let jsDoc = '';
|
|
204
|
-
if (dataType.values[value].description)
|
|
205
|
-
jsDoc += ` * ${dataType.values[value].description}\n`;
|
|
206
|
-
if (jsDoc)
|
|
207
|
-
out += `/**\n${jsDoc} */\n`;
|
|
208
|
-
out += `${info.key || value} = ` +
|
|
209
|
-
(typeof value === 'number' ? value : ('\'' + (String(value)).replace('\'', '\\\'')) + '\'');
|
|
210
|
-
out += ',\n\n';
|
|
211
|
-
}
|
|
212
|
-
return out + '\b}';
|
|
213
|
-
}
|
|
214
|
-
exports.generateEnumTypeDefinition = generateEnumTypeDefinition;
|
|
215
|
-
/**
|
|
216
|
-
*
|
|
217
|
-
* @param file
|
|
218
|
-
* @param dataType
|
|
219
|
-
* @param forInterface
|
|
220
|
-
*/
|
|
221
|
-
async function generateMixinTypeDefinition(file, dataType, forInterface) {
|
|
222
|
-
// let out = '';
|
|
217
|
+
async function generateMixinTypeDefinition(args) {
|
|
218
|
+
const { file, dataType, intent } = args;
|
|
223
219
|
return (await Promise.all(dataType.types
|
|
224
|
-
.map(t => this.resolveTypeNameOrDef(file, t,
|
|
220
|
+
.map(t => this.resolveTypeNameOrDef({ file, dataType: t, intent })))).map(t => t.includes('|') ? '(' + t + ')' : t)
|
|
221
|
+
.join(intent === 'extends' ? ', ' : ' & ');
|
|
225
222
|
}
|
|
226
223
|
exports.generateMixinTypeDefinition = generateMixinTypeDefinition;
|
|
227
224
|
/**
|
|
228
225
|
*
|
|
229
|
-
* @param file
|
|
230
|
-
* @param dataType
|
|
231
|
-
* @param forInterface
|
|
232
226
|
*/
|
|
233
|
-
async function generateMappedTypeDefinition(
|
|
234
|
-
const
|
|
227
|
+
async function generateMappedTypeDefinition(args) {
|
|
228
|
+
const { dataType } = args;
|
|
229
|
+
const typeDef = await this.resolveTypeNameOrDef({ ...args, dataType: dataType.base });
|
|
235
230
|
const pick = dataType.pick?.length ? dataType.pick : undefined;
|
|
236
231
|
const omit = !pick && dataType.omit?.length ? dataType.omit : undefined;
|
|
237
232
|
const partial = dataType.partial === true || Array.isArray(dataType.partial) && dataType.partial.length > 0
|
package/cjs/index.js
CHANGED
|
@@ -83,14 +83,22 @@ export class ${className} {
|
|
|
83
83
|
tsFile.addImport('@opra/client', ['HttpRequestObservable']);
|
|
84
84
|
for (const [action, endpoint] of resource.actions.entries()) {
|
|
85
85
|
let returnTypeDef = endpoint.returnType ?
|
|
86
|
-
await this.resolveTypeNameOrDef(
|
|
86
|
+
await this.resolveTypeNameOrDef({
|
|
87
|
+
file: tsFile,
|
|
88
|
+
dataType: endpoint.returnType,
|
|
89
|
+
intent: 'field'
|
|
90
|
+
})
|
|
87
91
|
: 'any';
|
|
88
92
|
if (returnTypeDef.length > 40)
|
|
89
93
|
returnTypeDef = '\n\t\t' + returnTypeDef + '\n\b\b';
|
|
90
94
|
const actionPath = resource.getFullPath() + '/' + action;
|
|
91
95
|
let params = '';
|
|
92
96
|
for (const prm of endpoint.parameters.values()) {
|
|
93
|
-
const paramTypeDef = await this.resolveTypeNameOrDef(
|
|
97
|
+
const paramTypeDef = await this.resolveTypeNameOrDef({
|
|
98
|
+
file: tsFile,
|
|
99
|
+
dataType: prm.type,
|
|
100
|
+
intent: 'field'
|
|
101
|
+
}) || 'any';
|
|
94
102
|
params += `${prm.name}: ${paramTypeDef}`;
|
|
95
103
|
if (prm.isArray)
|
|
96
104
|
params += '[]';
|
|
@@ -37,80 +37,99 @@ export async function generateTypeFile(dataType) {
|
|
|
37
37
|
file.exportTypes.push(typeName);
|
|
38
38
|
const indexTs = this.addFile('/index.ts', true);
|
|
39
39
|
indexTs.addExport(file.filename);
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
* @enum ${typeName}
|
|
45
|
-
* @url ${path.posix.join(this.client.serviceUrl, '#types/' + typeName)}
|
|
46
|
-
*/
|
|
47
|
-
export enum ${typeName} ` + await this.generateEnumTypeDefinition(file, dataType);
|
|
48
|
-
}
|
|
49
|
-
// Export ComplexType
|
|
50
|
-
if (dataType instanceof ComplexType) {
|
|
51
|
-
file.content += `
|
|
52
|
-
/**\n * ${wrapJSDocString(dataType.description || '')}
|
|
53
|
-
* @interface ${typeName}
|
|
54
|
-
* @url ${path.posix.join(this.client.serviceUrl, '#types/' + typeName)}
|
|
55
|
-
*/
|
|
56
|
-
export interface ${typeName} ${await this.generateComplexTypeDefinition(file, dataType, true)}`;
|
|
57
|
-
}
|
|
58
|
-
// Export SimpleType
|
|
59
|
-
if (dataType instanceof SimpleType) {
|
|
40
|
+
file.content += `
|
|
41
|
+
/**
|
|
42
|
+
* ${typeName}`;
|
|
43
|
+
if (dataType.description)
|
|
60
44
|
file.content += `
|
|
61
|
-
|
|
62
|
-
|
|
45
|
+
* ${wrapJSDocString(dataType.description || '')}`;
|
|
46
|
+
file.content += `
|
|
63
47
|
* @url ${path.posix.join(this.client.serviceUrl, '#types/' + typeName)}
|
|
64
48
|
*/
|
|
65
|
-
export
|
|
66
|
-
|
|
49
|
+
export `;
|
|
50
|
+
if (dataType instanceof EnumType)
|
|
51
|
+
file.content += await this.generateEnumTypeDefinition({ file, dataType, intent: 'scope' });
|
|
52
|
+
else if (dataType instanceof ComplexType)
|
|
53
|
+
file.content += await this.generateComplexTypeDefinition({ file, dataType, intent: 'scope' });
|
|
54
|
+
else if (dataType instanceof SimpleType)
|
|
55
|
+
file.content += await this.generateSimpleTypeDefinition({ file, dataType, intent: 'scope' });
|
|
56
|
+
else
|
|
57
|
+
throw new TypeError(`${dataType.kind} data type (${typeName}) can not be directly exported`);
|
|
58
|
+
file.content += '\n';
|
|
67
59
|
typesTs.addExport(file.filename);
|
|
68
60
|
return file;
|
|
69
61
|
}
|
|
70
62
|
/**
|
|
71
63
|
*
|
|
72
|
-
* @param file
|
|
73
|
-
* @param dataType
|
|
74
|
-
* @param forInterface
|
|
75
64
|
*/
|
|
76
|
-
export async function resolveTypeNameOrDef(
|
|
65
|
+
export async function resolveTypeNameOrDef(args) {
|
|
66
|
+
const { dataType } = args;
|
|
77
67
|
if (dataType.name && !dataType.isEmbedded) {
|
|
78
68
|
if (internalTypeNames.includes(dataType.name))
|
|
79
69
|
return dataType.name;
|
|
80
70
|
const f = await this.generateTypeFile(dataType);
|
|
81
71
|
if (!f)
|
|
82
72
|
return '';
|
|
83
|
-
file.addImport(f.filename, [dataType.name], true);
|
|
73
|
+
args.file.addImport(f.filename, [dataType.name], true);
|
|
84
74
|
return dataType.name;
|
|
85
75
|
}
|
|
86
76
|
if (dataType instanceof SimpleType)
|
|
87
|
-
return this.generateSimpleTypeDefinition(
|
|
77
|
+
return this.generateSimpleTypeDefinition({ ...args, dataType });
|
|
88
78
|
if (dataType instanceof EnumType)
|
|
89
|
-
return this.generateEnumTypeDefinition(
|
|
79
|
+
return this.generateEnumTypeDefinition({ ...args, dataType });
|
|
90
80
|
if (dataType instanceof MixinType)
|
|
91
|
-
return this.generateMixinTypeDefinition(
|
|
81
|
+
return this.generateMixinTypeDefinition({ ...args, dataType });
|
|
92
82
|
if (dataType instanceof MappedType)
|
|
93
|
-
return this.generateMappedTypeDefinition(
|
|
83
|
+
return this.generateMappedTypeDefinition({ ...args, dataType });
|
|
94
84
|
if (dataType instanceof ComplexType)
|
|
95
|
-
return this.generateComplexTypeDefinition(
|
|
85
|
+
return this.generateComplexTypeDefinition({ ...args, dataType });
|
|
96
86
|
return '';
|
|
97
87
|
}
|
|
98
88
|
/**
|
|
99
89
|
*
|
|
100
|
-
* @param file
|
|
101
|
-
* @param dataType
|
|
102
|
-
* @param forInterface
|
|
103
90
|
*/
|
|
104
|
-
export async function
|
|
105
|
-
|
|
91
|
+
export async function generateEnumTypeDefinition(args) {
|
|
92
|
+
const { dataType } = args;
|
|
93
|
+
if (args.intent === 'field')
|
|
94
|
+
return '(' +
|
|
95
|
+
Object.keys(dataType.values)
|
|
96
|
+
.map(t => `'${t}'`)
|
|
97
|
+
.join(' | ') +
|
|
98
|
+
')';
|
|
99
|
+
if (args.intent !== 'scope')
|
|
100
|
+
throw new TypeError(`Can't generate EnumType for "${args.intent}" intent`);
|
|
101
|
+
if (!dataType.name)
|
|
102
|
+
throw new TypeError(`Name required to generate EnumType for "${args.intent}" intent`);
|
|
103
|
+
let out = `enum ${dataType.name} {\n\t`;
|
|
104
|
+
for (const [value, info] of Object.entries(dataType.values)) {
|
|
105
|
+
// Print JSDoc
|
|
106
|
+
let jsDoc = '';
|
|
107
|
+
if (dataType.values[value].description)
|
|
108
|
+
jsDoc += ` * ${dataType.values[value].description}\n`;
|
|
109
|
+
if (jsDoc)
|
|
110
|
+
out += `/**\n${jsDoc} */\n`;
|
|
111
|
+
out += `${info.key || value} = ` +
|
|
112
|
+
(typeof value === 'number' ? value : ('\'' + (String(value)).replace('\'', '\\\'')) + '\'');
|
|
113
|
+
out += ',\n\n';
|
|
114
|
+
}
|
|
115
|
+
return out + '\b}';
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
*
|
|
119
|
+
*/
|
|
120
|
+
export async function generateComplexTypeDefinition(args) {
|
|
121
|
+
const { intent, dataType } = args;
|
|
122
|
+
if (intent === 'scope' && !dataType.name)
|
|
123
|
+
throw new TypeError(`Name required to generate ComplexType for "${args.intent}" intent`);
|
|
124
|
+
let out = intent === 'scope' ? `interface ${dataType.name} ` : '';
|
|
106
125
|
if (dataType.base) {
|
|
107
|
-
const base = await this.resolveTypeNameOrDef(file, dataType.base,
|
|
126
|
+
const base = await this.resolveTypeNameOrDef({ file: args.file, dataType: dataType.base, intent: 'extends' });
|
|
108
127
|
const omitFields = [...dataType.own.fields.keys()]
|
|
109
128
|
.filter(k => dataType.base?.fields.has(k));
|
|
110
129
|
const baseDef = omitFields.length
|
|
111
130
|
? `Omit<${base}, ${omitFields.map(x => "'" + x + "'").join(' | ')}>`
|
|
112
131
|
: `${base}`;
|
|
113
|
-
if (
|
|
132
|
+
if (intent === 'scope')
|
|
114
133
|
out += `extends ${baseDef} `;
|
|
115
134
|
else {
|
|
116
135
|
out += baseDef;
|
|
@@ -120,29 +139,25 @@ export async function generateComplexTypeDefinition(file, dataType, forInterface
|
|
|
120
139
|
}
|
|
121
140
|
}
|
|
122
141
|
out += '{\n\t';
|
|
142
|
+
let i = 0;
|
|
123
143
|
for (const field of dataType.own.fields.values()) {
|
|
144
|
+
if (i++)
|
|
145
|
+
out += '\n';
|
|
124
146
|
// Print JSDoc
|
|
125
|
-
|
|
126
|
-
if (field.description)
|
|
127
|
-
jsDoc += ` * ${field.description}\n`;
|
|
128
|
-
if (field.type.name)
|
|
129
|
-
jsDoc += ` * @type ${field.type.name}\n`;
|
|
147
|
+
out += `/**\n * ${field.description || ''}\n`;
|
|
130
148
|
if (field.default)
|
|
131
|
-
|
|
149
|
+
out += ` * @default ` + field.default + '\n';
|
|
132
150
|
// if (field.format)
|
|
133
151
|
// jsDoc += ` * @format ` + field.format + '\n';
|
|
134
152
|
if (field.exclusive)
|
|
135
|
-
|
|
153
|
+
out += ` * @exclusive\n`;
|
|
136
154
|
if (field.readonly)
|
|
137
|
-
|
|
155
|
+
out += ` * @readonly\n`;
|
|
138
156
|
if (field.writeonly)
|
|
139
|
-
|
|
157
|
+
out += ` * @writeonly\n`;
|
|
140
158
|
if (field.deprecated)
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
out += `\n/**\n${jsDoc} */\n`;
|
|
144
|
-
else
|
|
145
|
-
out += `\n`;
|
|
159
|
+
out += ` * @deprecated ` + (typeof field.deprecated === 'string' ? field.deprecated : '') + '\n';
|
|
160
|
+
out += ' */\n';
|
|
146
161
|
// Print field name
|
|
147
162
|
if (field.readonly)
|
|
148
163
|
out += 'readonly ';
|
|
@@ -152,7 +167,7 @@ export async function generateComplexTypeDefinition(file, dataType, forInterface
|
|
|
152
167
|
out += `${t === 'number' || t === 'boolean' || t === 'bigint' ? field.fixed : "'" + field.fixed + "'"}\n`;
|
|
153
168
|
}
|
|
154
169
|
else {
|
|
155
|
-
out += await this.resolveTypeNameOrDef(file, field.type) +
|
|
170
|
+
out += await this.resolveTypeNameOrDef({ file: args.file, dataType: field.type, intent: 'field' }) +
|
|
156
171
|
`${field.isArray ? '[]' : ''};\n`;
|
|
157
172
|
}
|
|
158
173
|
}
|
|
@@ -162,65 +177,45 @@ export async function generateComplexTypeDefinition(file, dataType, forInterface
|
|
|
162
177
|
}
|
|
163
178
|
/**
|
|
164
179
|
*
|
|
165
|
-
* @param file
|
|
166
|
-
* @param dataType
|
|
167
180
|
*/
|
|
168
|
-
export async function generateSimpleTypeDefinition(
|
|
181
|
+
export async function generateSimpleTypeDefinition(args) {
|
|
182
|
+
const { intent, dataType } = args;
|
|
183
|
+
if (intent === 'scope' && !dataType.name)
|
|
184
|
+
throw new TypeError(`Name required to generate SimpleType for "${args.intent}" intent`);
|
|
185
|
+
let out = intent === 'scope' ? `type ${dataType.name} = ` : '';
|
|
169
186
|
if (dataType.extendsFrom('boolean'))
|
|
170
|
-
|
|
171
|
-
if (dataType.extendsFrom('string'))
|
|
172
|
-
|
|
173
|
-
if (dataType.extendsFrom('number') || dataType.extendsFrom('integer'))
|
|
174
|
-
|
|
175
|
-
if (dataType.extendsFrom('date') || dataType.extendsFrom('datetime'))
|
|
176
|
-
|
|
177
|
-
if (dataType.extendsFrom('approxdate') || dataType.extendsFrom('approxdatetime'))
|
|
178
|
-
|
|
179
|
-
if (dataType.extendsFrom('bigint'))
|
|
180
|
-
|
|
181
|
-
if (dataType.extendsFrom('object'))
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
*
|
|
187
|
-
* @param file
|
|
188
|
-
* @param dataType
|
|
189
|
-
*/
|
|
190
|
-
export async function generateEnumTypeDefinition(file, dataType) {
|
|
191
|
-
let out = '{\n\t';
|
|
192
|
-
for (const [value, info] of Object.entries(dataType.values)) {
|
|
193
|
-
// Print JSDoc
|
|
194
|
-
let jsDoc = '';
|
|
195
|
-
if (dataType.values[value].description)
|
|
196
|
-
jsDoc += ` * ${dataType.values[value].description}\n`;
|
|
197
|
-
if (jsDoc)
|
|
198
|
-
out += `/**\n${jsDoc} */\n`;
|
|
199
|
-
out += `${info.key || value} = ` +
|
|
200
|
-
(typeof value === 'number' ? value : ('\'' + (String(value)).replace('\'', '\\\'')) + '\'');
|
|
201
|
-
out += ',\n\n';
|
|
202
|
-
}
|
|
203
|
-
return out + '\b}';
|
|
187
|
+
out += 'boolean';
|
|
188
|
+
else if (dataType.extendsFrom('string'))
|
|
189
|
+
out += 'string';
|
|
190
|
+
else if (dataType.extendsFrom('number') || dataType.extendsFrom('integer'))
|
|
191
|
+
out += 'number';
|
|
192
|
+
else if (dataType.extendsFrom('date') || dataType.extendsFrom('datetime'))
|
|
193
|
+
out += 'Date';
|
|
194
|
+
else if (dataType.extendsFrom('approxdate') || dataType.extendsFrom('approxdatetime'))
|
|
195
|
+
out += 'string';
|
|
196
|
+
else if (dataType.extendsFrom('bigint'))
|
|
197
|
+
out += 'bigint';
|
|
198
|
+
else if (dataType.extendsFrom('object'))
|
|
199
|
+
out += 'object';
|
|
200
|
+
else
|
|
201
|
+
out += 'any';
|
|
202
|
+
return intent === 'scope' ? out + ';' : out;
|
|
204
203
|
}
|
|
205
204
|
/**
|
|
206
205
|
*
|
|
207
|
-
* @param file
|
|
208
|
-
* @param dataType
|
|
209
|
-
* @param forInterface
|
|
210
206
|
*/
|
|
211
|
-
export async function generateMixinTypeDefinition(
|
|
212
|
-
|
|
207
|
+
export async function generateMixinTypeDefinition(args) {
|
|
208
|
+
const { file, dataType, intent } = args;
|
|
213
209
|
return (await Promise.all(dataType.types
|
|
214
|
-
.map(t => this.resolveTypeNameOrDef(file, t,
|
|
210
|
+
.map(t => this.resolveTypeNameOrDef({ file, dataType: t, intent })))).map(t => t.includes('|') ? '(' + t + ')' : t)
|
|
211
|
+
.join(intent === 'extends' ? ', ' : ' & ');
|
|
215
212
|
}
|
|
216
213
|
/**
|
|
217
214
|
*
|
|
218
|
-
* @param file
|
|
219
|
-
* @param dataType
|
|
220
|
-
* @param forInterface
|
|
221
215
|
*/
|
|
222
|
-
export async function generateMappedTypeDefinition(
|
|
223
|
-
const
|
|
216
|
+
export async function generateMappedTypeDefinition(args) {
|
|
217
|
+
const { dataType } = args;
|
|
218
|
+
const typeDef = await this.resolveTypeNameOrDef({ ...args, dataType: dataType.base });
|
|
224
219
|
const pick = dataType.pick?.length ? dataType.pick : undefined;
|
|
225
220
|
const omit = !pick && dataType.omit?.length ? dataType.omit : undefined;
|
|
226
221
|
const partial = dataType.partial === true || Array.isArray(dataType.partial) && dataType.partial.length > 0
|
package/esm/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export * from './api-exporter/
|
|
1
|
+
export * from './api-exporter/api-exporter.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opra/cli",
|
|
3
|
-
"version": "0.33.
|
|
3
|
+
"version": "0.33.10",
|
|
4
4
|
"description": "Opra CLI tools",
|
|
5
5
|
"author": "Panates",
|
|
6
6
|
"license": "MIT",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"clean:cover": "rimraf ../../coverage/client"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@opra/client": "^0.33.
|
|
32
|
+
"@opra/client": "^0.33.10",
|
|
33
33
|
"chalk": "^5.3.0",
|
|
34
34
|
"commander": "^11.0.0",
|
|
35
35
|
"js-string-escape": "^1.0.1",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ComplexType, DataType, EnumType, MappedType, MixinType, SimpleType } from '@opra/common';
|
|
2
2
|
import type { ApiExporter } from './api-exporter.js';
|
|
3
3
|
import { TsFile } from './ts-file.js';
|
|
4
|
+
type Intent = 'scope' | 'extends' | 'field';
|
|
4
5
|
/**
|
|
5
6
|
*
|
|
6
7
|
*/
|
|
@@ -12,41 +13,50 @@ export declare function processTypes(this: ApiExporter): Promise<void>;
|
|
|
12
13
|
export declare function generateTypeFile(this: ApiExporter, dataType: DataType): Promise<TsFile | undefined>;
|
|
13
14
|
/**
|
|
14
15
|
*
|
|
15
|
-
* @param file
|
|
16
|
-
* @param dataType
|
|
17
|
-
* @param forInterface
|
|
18
16
|
*/
|
|
19
|
-
export declare function resolveTypeNameOrDef(this: ApiExporter,
|
|
17
|
+
export declare function resolveTypeNameOrDef(this: ApiExporter, args: {
|
|
18
|
+
file: TsFile;
|
|
19
|
+
dataType: DataType;
|
|
20
|
+
intent: Intent;
|
|
21
|
+
}): Promise<string>;
|
|
20
22
|
/**
|
|
21
23
|
*
|
|
22
|
-
* @param file
|
|
23
|
-
* @param dataType
|
|
24
|
-
* @param forInterface
|
|
25
24
|
*/
|
|
26
|
-
export declare function
|
|
25
|
+
export declare function generateEnumTypeDefinition(this: ApiExporter, args: {
|
|
26
|
+
file: TsFile;
|
|
27
|
+
dataType: EnumType;
|
|
28
|
+
intent: Intent;
|
|
29
|
+
}): Promise<string>;
|
|
27
30
|
/**
|
|
28
31
|
*
|
|
29
|
-
* @param file
|
|
30
|
-
* @param dataType
|
|
31
32
|
*/
|
|
32
|
-
export declare function
|
|
33
|
+
export declare function generateComplexTypeDefinition(this: ApiExporter, args: {
|
|
34
|
+
file: TsFile;
|
|
35
|
+
dataType: ComplexType;
|
|
36
|
+
intent: Intent;
|
|
37
|
+
}): Promise<string>;
|
|
33
38
|
/**
|
|
34
39
|
*
|
|
35
|
-
* @param file
|
|
36
|
-
* @param dataType
|
|
37
40
|
*/
|
|
38
|
-
export declare function
|
|
41
|
+
export declare function generateSimpleTypeDefinition(this: ApiExporter, args: {
|
|
42
|
+
file: TsFile;
|
|
43
|
+
dataType: SimpleType;
|
|
44
|
+
intent: Intent;
|
|
45
|
+
}): Promise<string>;
|
|
39
46
|
/**
|
|
40
47
|
*
|
|
41
|
-
* @param file
|
|
42
|
-
* @param dataType
|
|
43
|
-
* @param forInterface
|
|
44
48
|
*/
|
|
45
|
-
export declare function generateMixinTypeDefinition(this: ApiExporter,
|
|
49
|
+
export declare function generateMixinTypeDefinition(this: ApiExporter, args: {
|
|
50
|
+
file: TsFile;
|
|
51
|
+
dataType: MixinType;
|
|
52
|
+
intent: Intent;
|
|
53
|
+
}): Promise<string>;
|
|
46
54
|
/**
|
|
47
55
|
*
|
|
48
|
-
* @param file
|
|
49
|
-
* @param dataType
|
|
50
|
-
* @param forInterface
|
|
51
56
|
*/
|
|
52
|
-
export declare function generateMappedTypeDefinition(this: ApiExporter,
|
|
57
|
+
export declare function generateMappedTypeDefinition(this: ApiExporter, args: {
|
|
58
|
+
file: TsFile;
|
|
59
|
+
dataType: MappedType;
|
|
60
|
+
intent: Intent;
|
|
61
|
+
}): Promise<string>;
|
|
62
|
+
export {};
|
package/types/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export * from './api-exporter/
|
|
1
|
+
export * from './api-exporter/api-exporter.js';
|