@opra/cli 0.33.11 → 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.
Files changed (63) hide show
  1. package/bin/bin/oprimp.mjs +1 -1
  2. package/bin/oprimp.mjs +1 -1
  3. package/cjs/code-block.js +17 -0
  4. package/cjs/index.js +1 -1
  5. package/cjs/oprimp-cli.js +9 -9
  6. package/cjs/ts-generator/http-controller-node.js +21 -0
  7. package/cjs/{api-exporter → ts-generator}/index.js +1 -1
  8. package/cjs/ts-generator/processors/clean-directory.js +35 -0
  9. package/cjs/ts-generator/processors/process-data-types.js +252 -0
  10. package/cjs/ts-generator/processors/process-document.js +60 -0
  11. package/cjs/ts-generator/processors/process-http-api.js +45 -0
  12. package/cjs/ts-generator/processors/process-http-controller.js +189 -0
  13. package/cjs/ts-generator/ts-file.js +101 -0
  14. package/cjs/ts-generator/ts-generator.js +108 -0
  15. package/cjs/ts-generator/utils/locate-named-type.js +16 -0
  16. package/cjs/{utils → ts-generator/utils}/string-utils.js +17 -16
  17. package/esm/code-block.js +13 -0
  18. package/esm/index.js +1 -1
  19. package/esm/oprimp-cli.js +9 -9
  20. package/esm/ts-generator/http-controller-node.js +18 -0
  21. package/esm/ts-generator/index.js +1 -0
  22. package/esm/ts-generator/processors/clean-directory.js +30 -0
  23. package/esm/ts-generator/processors/process-data-types.js +241 -0
  24. package/esm/ts-generator/processors/process-document.js +55 -0
  25. package/esm/ts-generator/processors/process-http-api.js +40 -0
  26. package/esm/ts-generator/processors/process-http-controller.js +184 -0
  27. package/esm/ts-generator/ts-file.js +96 -0
  28. package/esm/ts-generator/ts-generator.js +103 -0
  29. package/esm/ts-generator/utils/locate-named-type.js +12 -0
  30. package/esm/{utils → ts-generator/utils}/string-utils.js +17 -16
  31. package/package.json +8 -6
  32. package/types/code-block.d.ts +5 -0
  33. package/types/{api-exporter/file-writer.d.ts → file-writer.d.ts} +1 -1
  34. package/types/index.d.ts +1 -1
  35. package/types/ts-generator/http-controller-node.d.ts +1 -0
  36. package/types/ts-generator/index.d.ts +1 -0
  37. package/types/ts-generator/processors/clean-directory.d.ts +2 -0
  38. package/types/ts-generator/processors/process-data-types.d.ts +30 -0
  39. package/types/ts-generator/processors/process-document.d.ts +8 -0
  40. package/types/ts-generator/processors/process-http-api.d.ts +3 -0
  41. package/types/ts-generator/processors/process-http-controller.d.ts +3 -0
  42. package/types/{api-exporter → ts-generator}/ts-file.d.ts +4 -4
  43. package/types/ts-generator/ts-generator.d.ts +70 -0
  44. package/types/ts-generator/utils/locate-named-type.d.ts +2 -0
  45. package/cjs/api-exporter/api-exporter.js +0 -115
  46. package/cjs/api-exporter/process-resources.js +0 -125
  47. package/cjs/api-exporter/process-types.js +0 -261
  48. package/cjs/api-exporter/ts-file.js +0 -104
  49. package/cjs/utils/get-caller-file.util.js +0 -24
  50. package/esm/api-exporter/api-exporter.js +0 -110
  51. package/esm/api-exporter/index.js +0 -1
  52. package/esm/api-exporter/process-resources.js +0 -120
  53. package/esm/api-exporter/process-types.js +0 -249
  54. package/esm/api-exporter/ts-file.js +0 -99
  55. package/esm/utils/get-caller-file.util.js +0 -20
  56. package/types/api-exporter/api-exporter.d.ts +0 -46
  57. package/types/api-exporter/index.d.ts +0 -1
  58. package/types/api-exporter/process-resources.d.ts +0 -4
  59. package/types/api-exporter/process-types.d.ts +0 -62
  60. package/types/utils/get-caller-file.util.d.ts +0 -1
  61. /package/cjs/{api-exporter/file-writer.js → file-writer.js} +0 -0
  62. /package/esm/{api-exporter/file-writer.js → file-writer.js} +0 -0
  63. /package/types/{utils → ts-generator/utils}/string-utils.d.ts +0 -0
@@ -0,0 +1,189 @@
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
+ const type = (0, locate_named_type_js_1.locateNamedType)(prm.type);
94
+ if (argIndex++ > 0)
95
+ operationBlock.head += ', ';
96
+ operationBlock.head += `${prm.name}: ${type?.name || 'any'}`;
97
+ }
98
+ let hasBody = false;
99
+ if (operation.requestBody?.content.length) {
100
+ if (argIndex++ > 0)
101
+ operationBlock.head += ', ';
102
+ let typeArr = [];
103
+ for (const content of operation.requestBody.content) {
104
+ if (content.type) {
105
+ const dtFile = this._filesMap.get(content.type);
106
+ if (dtFile) {
107
+ const typeName = await this.resolveTypeNameOrDef(content.type, dtFile, 'field');
108
+ typeArr.push(typeName);
109
+ file.addImport(dtFile.filename, [typeName]);
110
+ continue;
111
+ }
112
+ }
113
+ typeArr = [];
114
+ break;
115
+ }
116
+ if (typeArr.length) {
117
+ if (operation.requestBody.partial) {
118
+ file.addImport('ts-gems', ['PartialDTO']);
119
+ operationBlock.head += `$body: PartialDTO<${typeArr.join(' | ')}>`;
120
+ }
121
+ else {
122
+ file.addImport('ts-gems', ['DTO']);
123
+ operationBlock.head += `$body: DTO<${typeArr.join(' | ')}>`;
124
+ }
125
+ }
126
+ else
127
+ operationBlock.head += `$body: any`;
128
+ hasBody = true;
129
+ }
130
+ /** process query params */
131
+ const isQueryRequired = queryParams.find(p => p.required);
132
+ const isHeadersRequired = queryParams.find(p => p.required);
133
+ if (queryParams.length) {
134
+ if (argIndex++ > 0)
135
+ operationBlock.head += ', ';
136
+ operationBlock.head += '\n\t$params' + (isHeadersRequired || isQueryRequired ? '' : '?') + ': {\n\t';
137
+ for (const prm of queryParams) {
138
+ const type = (0, locate_named_type_js_1.locateNamedType)(prm.type);
139
+ operationBlock.head += `/**\n * ${prm.description || ''}\n */\n`;
140
+ operationBlock.head += `${prm.name}${prm.required ? '' : '?'}: `;
141
+ if (type?.name) {
142
+ const typeFile = await this.processDataType(type);
143
+ if (typeFile) {
144
+ file.addImport(typeFile.filename, [type.name]);
145
+ operationBlock.head += `${type.name};\n`;
146
+ continue;
147
+ }
148
+ }
149
+ operationBlock.head += `${type?.name || '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
+ const type = (0, locate_named_type_js_1.locateNamedType)(prm.type);
160
+ operationBlock.head += `/**\n * ${prm.description || ''}\n */\n`;
161
+ operationBlock.head += `${prm.name}${prm.required ? '' : '?'}: `;
162
+ if (type?.name) {
163
+ const typeFile = await this.processDataType(type);
164
+ if (typeFile) {
165
+ file.addImport(typeFile.filename, [type.name]);
166
+ operationBlock.head += `${type.name};\n`;
167
+ continue;
168
+ }
169
+ }
170
+ operationBlock.head += `${type?.name || 'any'};\n`;
171
+ }
172
+ operationBlock.head += '\b}\b';
173
+ }
174
+ operationBlock.head += `\n): HttpRequestObservable<any>{`;
175
+ operationBlock.body = `\n\t`;
176
+ operationBlock.body +=
177
+ `const url = this._prepareUrl('${operation.getFullUrl()}', {` + pathParams.map(p => p.name).join(', ') + '});';
178
+ operationBlock.body +=
179
+ `\nreturn this[kClient].request(url, {` +
180
+ (hasBody ? ' body: $body,' : '') +
181
+ (queryParams.length ? ' params: $params as any,' : '') +
182
+ (headerParams.length ? ' headers: $headers as any,' : '') +
183
+ '});';
184
+ operationBlock.tail = `\b\n};\n`;
185
+ }
186
+ classBlock.tail = `\b}`;
187
+ return file;
188
+ }
189
+ exports.processHttpController = processHttpController;
@@ -0,0 +1,101 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TsFile = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const path_1 = tslib_1.__importDefault(require("path"));
6
+ const putil_flattentext_1 = tslib_1.__importDefault(require("putil-flattentext"));
7
+ const code_block_js_1 = require("../code-block.js");
8
+ class TsFile {
9
+ constructor(filename) {
10
+ this.filename = filename;
11
+ this.imports = {};
12
+ this.exportFiles = {};
13
+ this.exportTypes = [];
14
+ this.code = new code_block_js_1.CodeBlock();
15
+ this.dirname = path_1.default.dirname(filename);
16
+ this.code.header = '';
17
+ this.code.imports = '';
18
+ this.code.exports = '';
19
+ }
20
+ addImport(filename, items, typeImport) {
21
+ if (isLocalFile(filename)) {
22
+ filename = path_1.default.relative(this.dirname, path_1.default.resolve(this.dirname, filename));
23
+ if (!filename.startsWith('.'))
24
+ filename = './' + filename;
25
+ }
26
+ if (filename.endsWith('.d.ts'))
27
+ filename = filename.substring(0, filename.length - 5);
28
+ if (filename.endsWith('.ts') || filename.endsWith('.js'))
29
+ filename = filename.substring(0, filename.length - 3);
30
+ const imp = (this.imports[filename] = this.imports[filename] || { items: [], typeImport });
31
+ if (!typeImport)
32
+ imp.typeImport = false;
33
+ items?.forEach(x => {
34
+ if (!imp.items.includes(x))
35
+ imp.items.push(x);
36
+ });
37
+ }
38
+ addExport(filename, types) {
39
+ if (isLocalFile(filename)) {
40
+ filename = path_1.default.relative(this.dirname, path_1.default.resolve(this.dirname, filename));
41
+ if (!filename.startsWith('.'))
42
+ filename = './' + filename;
43
+ }
44
+ if (filename.endsWith('.d.ts'))
45
+ filename = filename.substring(0, filename.length - 5);
46
+ if (filename.endsWith('.ts') || filename.endsWith('.js'))
47
+ filename = filename.substring(0, filename.length - 3);
48
+ this.exportFiles[filename] = this.exportFiles[filename] || [];
49
+ types?.forEach(x => {
50
+ if (!this.exportFiles[filename].includes(x))
51
+ this.exportFiles[filename].push(x);
52
+ });
53
+ }
54
+ generate(options) {
55
+ this.code.imports = Object.keys(this.imports)
56
+ .sort((a, b) => {
57
+ if (a.startsWith('@'))
58
+ return -1;
59
+ if (b.startsWith('@'))
60
+ return 1;
61
+ if (!a.startsWith('.'))
62
+ return -1;
63
+ if (!b.startsWith('.'))
64
+ return 1;
65
+ return a.toLowerCase().localeCompare(b.toLowerCase());
66
+ })
67
+ .map(filename => {
68
+ const imp = this.imports[filename];
69
+ let relFile = filename;
70
+ if (!isPackageName(filename)) {
71
+ if (options?.importExt)
72
+ relFile += '.js';
73
+ }
74
+ return `import${imp.typeImport ? ' type' : ''} ${imp.items.length ? '{ ' + imp.items.join(', ') + ' } from ' : ''}'${relFile}';`;
75
+ })
76
+ .join('\n');
77
+ this.code.exports = Object.keys(this.exportFiles)
78
+ .sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()))
79
+ .map(filename => {
80
+ const types = this.exportFiles[filename];
81
+ if (!isPackageName(filename)) {
82
+ if (options?.importExt)
83
+ filename += '.js';
84
+ }
85
+ return `export ${types.length ? '{ ' + types.join(', ') + ' }' : '*'} from '${filename}';`;
86
+ })
87
+ .join('\n');
88
+ if (this.code.imports || this.code.exports)
89
+ this.code.exports += '\n\n';
90
+ return ('/* #!oprimp_auto_generated!# !! Do NOT remove this line */\n/* eslint-disable */\n' +
91
+ (0, putil_flattentext_1.default)(String(this.code)));
92
+ }
93
+ }
94
+ exports.TsFile = TsFile;
95
+ function isLocalFile(s) {
96
+ return typeof s === 'string' && (s.startsWith('.') || s.startsWith('/'));
97
+ }
98
+ const PACKAGENAME_PATTERN = /^(@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/;
99
+ function isPackageName(s) {
100
+ return PACKAGENAME_PATTERN.test(s);
101
+ }
@@ -0,0 +1,108 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TsGenerator = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const chalk_1 = tslib_1.__importDefault(require("chalk"));
6
+ const node_events_1 = require("node:events");
7
+ const node_fs_1 = tslib_1.__importDefault(require("node:fs"));
8
+ const node_path_1 = tslib_1.__importDefault(require("node:path"));
9
+ const node_process_1 = tslib_1.__importDefault(require("node:process"));
10
+ const file_writer_js_1 = require("../file-writer.js");
11
+ const clean_directory_js_1 = require("./processors/clean-directory.js");
12
+ const process_data_types_js_1 = require("./processors/process-data-types.js");
13
+ const process_document_js_1 = require("./processors/process-document.js");
14
+ const process_http_api_js_1 = require("./processors/process-http-api.js");
15
+ const process_http_controller_js_1 = require("./processors/process-http-controller.js");
16
+ const ts_file_js_1 = require("./ts-file.js");
17
+ /**
18
+ * @class TsGenerator
19
+ */
20
+ class TsGenerator extends node_events_1.EventEmitter {
21
+ /**
22
+ *
23
+ * @constructor
24
+ */
25
+ constructor(init) {
26
+ super();
27
+ this._started = false;
28
+ this._files = {};
29
+ this.serviceUrl = init.serviceUrl;
30
+ this.cwd = init.cwd || node_process_1.default.cwd();
31
+ this.outDir = init.outDir ? node_path_1.default.resolve(this.cwd, init.outDir) : this.cwd;
32
+ this.fileHeader = init.fileHeader || '';
33
+ this.writer = init.writer || new file_writer_js_1.FileWriter();
34
+ this.options = { importExt: !!init.importExt };
35
+ this._documentsMap = new Map();
36
+ this._filesMap = new WeakMap();
37
+ this.on('log', (message, ...args) => init.logger?.log?.(message, ...args));
38
+ this.on('error', (message, ...args) => init.logger?.error?.(message, ...args));
39
+ this.on('debug', (message, ...args) => init.logger?.debug?.(message, ...args));
40
+ this.on('warn', (message, ...args) => init.logger?.warn?.(message, ...args));
41
+ this.on('verbose', (message, ...args) => init.logger?.verbose?.(message, ...args));
42
+ }
43
+ async generate() {
44
+ if (this._started)
45
+ return;
46
+ this.emit('start');
47
+ try {
48
+ this._started = true;
49
+ this.emit('log', chalk_1.default.cyan('Removing old files..'));
50
+ this.cleanDirectory(this.outDir);
51
+ this._apiPath = '/api';
52
+ await this.processDocument();
53
+ const { importExt } = this.options;
54
+ // Write files
55
+ for (const file of Object.values(this._files)) {
56
+ const filename = node_path_1.default.join(this.outDir, file.filename);
57
+ const targetDir = node_path_1.default.dirname(filename);
58
+ node_fs_1.default.mkdirSync(targetDir, { recursive: true });
59
+ await this.writer.writeFile(filename, file.generate({ importExt }));
60
+ }
61
+ }
62
+ catch (e) {
63
+ this.emit('error', e);
64
+ throw e;
65
+ }
66
+ finally {
67
+ this.emit('finish');
68
+ }
69
+ }
70
+ getFile(filePath) {
71
+ return this._files[filePath];
72
+ }
73
+ addFile(filePath, returnExists) {
74
+ if (!(filePath.startsWith('.') || filePath.startsWith('/')))
75
+ filePath = './' + filePath;
76
+ let file = this.getFile(filePath);
77
+ if (file) {
78
+ if (returnExists)
79
+ return file;
80
+ throw new Error(`File "${filePath}" already exists`);
81
+ }
82
+ file = new ts_file_js_1.TsFile(filePath);
83
+ file.code.header = this.fileHeader + (this._fileHeaderDocInfo ? '\n' + this._fileHeaderDocInfo : '') + '\n\n';
84
+ this._files[file.filename] = file;
85
+ return file;
86
+ }
87
+ extend() {
88
+ const instance = {
89
+ options: { ...this.options },
90
+ };
91
+ Object.setPrototypeOf(instance, this);
92
+ return instance;
93
+ }
94
+ }
95
+ exports.TsGenerator = TsGenerator;
96
+ (() => {
97
+ TsGenerator.prototype.cleanDirectory = clean_directory_js_1.cleanDirectory;
98
+ TsGenerator.prototype.processDocument = process_document_js_1.processDocument;
99
+ TsGenerator.prototype.processDataType = process_data_types_js_1.processDataType;
100
+ TsGenerator.prototype.processHttpApi = process_http_api_js_1.processHttpApi;
101
+ TsGenerator.prototype.processHttpController = process_http_controller_js_1.processHttpController;
102
+ TsGenerator.prototype.generateEnumTypeDefinition = process_data_types_js_1.generateEnumTypeDefinition;
103
+ TsGenerator.prototype.generateComplexTypeDefinition = process_data_types_js_1.generateComplexTypeDefinition;
104
+ TsGenerator.prototype.generateSimpleTypeDefinition = process_data_types_js_1.generateSimpleTypeDefinition;
105
+ TsGenerator.prototype.generateMappedTypeDefinition = process_data_types_js_1.generateMappedTypeDefinition;
106
+ TsGenerator.prototype.generateMixinTypeDefinition = process_data_types_js_1.generateMixinTypeDefinition;
107
+ TsGenerator.prototype.resolveTypeNameOrDef = process_data_types_js_1.resolveTypeNameOrDef;
108
+ })();
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.locateNamedType = void 0;
4
+ const common_1 = require("@opra/common");
5
+ function locateNamedType(type) {
6
+ if (!type)
7
+ return;
8
+ if (type.name)
9
+ return type;
10
+ if (type instanceof common_1.SimpleType ||
11
+ type instanceof common_1.ComplexType ||
12
+ type instanceof common_1.EnumType ||
13
+ type instanceof common_1.MappedType)
14
+ return locateNamedType(type.base);
15
+ }
16
+ exports.locateNamedType = locateNamedType;
@@ -6,36 +6,36 @@ const js_string_escape_1 = tslib_1.__importDefault(require("js-string-escape"));
6
6
  function wrapJSDocString(s, indent, currentColumn) {
7
7
  const arr = (s || '')
8
8
  .split(/[ \n\r]/)
9
- .map((x, i, a) => i < a.length - 1 ? x + ' ' : x);
9
+ .map((x, i, a) => (i < a.length - 1 ? x + ' ' : x));
10
10
  return _printLines(arr, {
11
11
  indent,
12
12
  currentColumn,
13
13
  lineStart: '* ',
14
- lineEnd: ''
14
+ lineEnd: '',
15
15
  });
16
16
  }
17
17
  exports.wrapJSDocString = wrapJSDocString;
18
18
  function wrapQuotedString(s, indent, currentColumn) {
19
19
  const arr = (0, js_string_escape_1.default)(s || '')
20
20
  .split(' ')
21
- .map((x, i, a) => i < a.length - 1 ? x + ' ' : x);
22
- return '\'' + _printLines(arr, {
23
- indent,
24
- currentColumn,
25
- lineStart: '\'',
26
- lineEnd: '\' +',
27
- }) + '\'';
21
+ .map((x, i, a) => (i < a.length - 1 ? x + ' ' : x));
22
+ return ("'" +
23
+ _printLines(arr, {
24
+ indent,
25
+ currentColumn,
26
+ lineStart: "'",
27
+ lineEnd: "' +",
28
+ }) +
29
+ "'");
28
30
  }
29
31
  exports.wrapQuotedString = wrapQuotedString;
30
32
  function wrapStringArray(arr, indent, currentColumn) {
31
- const ar1 = arr
32
- .map((x, i, a) => ('\'' + x + '\'') + (i < a.length - 1 ? ', ' : ''));
33
+ const ar1 = arr.map((x, i, a) => "'" + x + "'" + (i < a.length - 1 ? ', ' : ''));
33
34
  return '[' + _printLines(ar1, { indent, currentColumn }) + ']';
34
35
  }
35
36
  exports.wrapStringArray = wrapStringArray;
36
37
  function wrapTypeArray(arr, indent, currentColumn) {
37
- const ar1 = arr
38
- .map((x, i, a) => x + (i < a.length - 1 ? ' | ' : ''));
38
+ const ar1 = arr.map((x, i, a) => x + (i < a.length - 1 ? ' | ' : ''));
39
39
  return _printLines(ar1, { indent, currentColumn });
40
40
  }
41
41
  exports.wrapTypeArray = wrapTypeArray;
@@ -46,9 +46,10 @@ function _printLines(arr, opts = {}) {
46
46
  let lineWidth = (opts.lineWidth || 90) - (opts.currentColumn || 0);
47
47
  const l = arr.length;
48
48
  const printLine = (eof) => {
49
- s += (s ? '\n' + ' '.repeat(indent || 0) + (opts.lineStart ? opts.lineStart : '') : '') +
50
- line +
51
- (!eof ? (opts.lineEnd ? opts.lineEnd : '') : '');
49
+ s +=
50
+ (s ? '\n' + ' '.repeat(indent || 0) + (opts.lineStart ? opts.lineStart : '') : '') +
51
+ line +
52
+ (!eof ? (opts.lineEnd ? opts.lineEnd : '') : '');
52
53
  line = '';
53
54
  };
54
55
  for (let i = 0; i < l; i++) {
@@ -0,0 +1,13 @@
1
+ export class CodeBlock {
2
+ toString() {
3
+ // if (this.content) return this.content;
4
+ let out = '';
5
+ for (const x of Object.values(this)) {
6
+ out += String(x);
7
+ }
8
+ return out;
9
+ }
10
+ [Symbol.toStringTag]() {
11
+ return this.toString();
12
+ }
13
+ }
package/esm/index.js CHANGED
@@ -1 +1 @@
1
- export * from './api-exporter/api-exporter.js';
1
+ export * from './ts-generator/index.js';
package/esm/oprimp-cli.js CHANGED
@@ -4,29 +4,29 @@ import * as console from 'console';
4
4
  import * as fs from 'fs';
5
5
  import path from 'path';
6
6
  import * as process from 'process';
7
- import { ApiExporter } from './api-exporter/api-exporter.js';
8
- import { getCallerFile } from './utils/get-caller-file.util.js';
9
- const dirname = path.dirname(getCallerFile());
7
+ import { getStackFileName } from '@opra/common';
8
+ import { TsGenerator } from './ts-generator/ts-generator.js';
9
+ const dirname = path.dirname(getStackFileName());
10
10
  const pkgJson = JSON.parse(fs.readFileSync(path.resolve(dirname, '../package.json'), 'utf-8'));
11
11
  program
12
12
  .version(pkgJson.version)
13
13
  .argument('<serviceUrl>', 'OPRA service url')
14
14
  .argument('<outDir>', 'Output directory')
15
- .option('--name <name>', 'Name of the service')
16
15
  .option('--ext', 'Adds js extension to imports')
17
16
  .option('--no-color', 'Disables colors in logs messages')
18
17
  .action(async (serviceUrl, outDir, options) => {
19
18
  if (!options.color)
20
19
  chalk.level = 0;
21
- await ApiExporter.execute({
20
+ const generator = new TsGenerator({
22
21
  serviceUrl,
23
22
  logger: console,
24
23
  outDir,
25
- name: options.name,
26
24
  importExt: options.ext,
27
- fileHeader: '/* Generated by OPRA Service Generator, Version ' + pkgJson.version + '*/\n' +
28
- '/* eslint-disable */\n'
29
- }).then(() => console.log(chalk.greenBright('Completed')))
25
+ fileHeader: `/* Generated by OPRA Code Generator, Version ${pkgJson.version} */`,
26
+ });
27
+ await generator
28
+ .generate()
29
+ .then(() => console.log(chalk.greenBright('Completed')))
30
30
  .catch(e => console.error(e.message));
31
31
  });
32
32
  if (process.argv.length < 3)
@@ -0,0 +1,18 @@
1
+ export const httpControllerNodeScript = `import { kClient, OpraHttpClient } from '@opra/client';
2
+
3
+ const PARAM_PATTERN = /:\\w+/g;
4
+
5
+ export class HttpControllerNode {
6
+ readonly [kClient]: OpraHttpClient;
7
+
8
+ constructor(client: OpraHttpClient) {
9
+ this[kClient] = client;
10
+ }
11
+
12
+ protected _prepareUrl(url: string, params: Record<string, any>): string {
13
+ return url.replace(PARAM_PATTERN, s => {
14
+ return params[s.substring(1)] || '';
15
+ });
16
+ }
17
+ }
18
+ `;
@@ -0,0 +1 @@
1
+ export * from './ts-generator.js';
@@ -0,0 +1,30 @@
1
+ import chalk from 'chalk';
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
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
+ }