@opra/cli 0.14.3 → 0.16.0

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 (56) hide show
  1. package/bin/oprimp.mjs +1 -1
  2. package/cjs/api-exporter/api-exporter.js +107 -0
  3. package/cjs/{oprimp → api-exporter}/index.js +1 -1
  4. package/cjs/api-exporter/process-resources.js +50 -0
  5. package/cjs/api-exporter/process-types.js +215 -0
  6. package/cjs/api-exporter/ts-file.js +90 -0
  7. package/cjs/index.js +1 -1
  8. package/cjs/{oprimp.js → oprimp-cli.js} +8 -9
  9. package/esm/api-exporter/api-exporter.js +107 -0
  10. package/esm/api-exporter/file-writer.js +11 -0
  11. package/esm/api-exporter/index.js +4 -0
  12. package/esm/api-exporter/process-resources.js +50 -0
  13. package/esm/api-exporter/process-types.js +215 -0
  14. package/esm/api-exporter/ts-file.js +90 -0
  15. package/esm/index.js +4 -1
  16. package/esm/interfaces/file-writer.interface.js +2 -1
  17. package/esm/interfaces/logger.interface.js +2 -1
  18. package/esm/interfaces/service-generation-context.interface.js +2 -1
  19. package/esm/oprimp-cli.js +35 -0
  20. package/esm/utils/get-caller-file.util.js +5 -1
  21. package/esm/utils/string-utils.js +14 -6
  22. package/package.json +10 -10
  23. package/types/api-exporter/api-exporter.d.ts +46 -0
  24. package/types/api-exporter/index.d.ts +1 -0
  25. package/types/api-exporter/process-resources.d.ts +6 -0
  26. package/types/api-exporter/process-types.d.ts +54 -0
  27. package/types/api-exporter/ts-file.d.ts +18 -0
  28. package/types/index.d.ts +1 -0
  29. package/{esm → types}/interfaces/service-generation-context.interface.d.ts +2 -2
  30. package/cjs/oprimp/delete-files.js +0 -27
  31. package/cjs/oprimp/generate-service.js +0 -54
  32. package/cjs/oprimp/process-resoruces.js +0 -59
  33. package/cjs/oprimp/process-types.js +0 -130
  34. package/cjs/utils/ts-file.js +0 -55
  35. package/esm/index.d.ts +0 -1
  36. package/esm/oprimp/delete-files.d.ts +0 -1
  37. package/esm/oprimp/delete-files.js +0 -22
  38. package/esm/oprimp/file-writer.js +0 -6
  39. package/esm/oprimp/generate-service.d.ts +0 -13
  40. package/esm/oprimp/generate-service.js +0 -49
  41. package/esm/oprimp/index.d.ts +0 -1
  42. package/esm/oprimp/index.js +0 -1
  43. package/esm/oprimp/process-resoruces.d.ts +0 -2
  44. package/esm/oprimp/process-resoruces.js +0 -54
  45. package/esm/oprimp/process-types.d.ts +0 -2
  46. package/esm/oprimp/process-types.js +0 -125
  47. package/esm/oprimp.js +0 -33
  48. package/esm/utils/ts-file.d.ts +0 -11
  49. package/esm/utils/ts-file.js +0 -50
  50. /package/cjs/{oprimp → api-exporter}/file-writer.js +0 -0
  51. /package/{esm/oprimp → types/api-exporter}/file-writer.d.ts +0 -0
  52. /package/{esm → types}/interfaces/file-writer.interface.d.ts +0 -0
  53. /package/{esm → types}/interfaces/logger.interface.d.ts +0 -0
  54. /package/{esm/oprimp.d.ts → types/oprimp-cli.d.ts} +0 -0
  55. /package/{esm → types}/utils/get-caller-file.util.d.ts +0 -0
  56. /package/{esm → types}/utils/string-utils.d.ts +0 -0
@@ -1,9 +1,9 @@
1
- import { OpraDocument } from '@opra/common';
1
+ import { ApiDocument } from '@opra/common';
2
2
  import { IFileWriter } from './file-writer.interface.js';
3
3
  import { ILogger } from './logger.interface.js';
4
4
  export interface ServiceGenerationContext {
5
5
  serviceUrl: string;
6
- document: OpraDocument;
6
+ document: ApiDocument;
7
7
  name: string;
8
8
  cwd: string;
9
9
  logger: ILogger;
@@ -1,27 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.deleteFiles = void 0;
4
- const tslib_1 = require("tslib");
5
- const fs_1 = tslib_1.__importDefault(require("fs"));
6
- const path_1 = tslib_1.__importDefault(require("path"));
7
- function deleteFiles(dirname) {
8
- if (!fs_1.default.existsSync(dirname))
9
- return;
10
- const files = fs_1.default.readdirSync(dirname);
11
- for (const f of files) {
12
- const filename = path_1.default.join(dirname, f);
13
- if (fs_1.default.statSync(filename).isDirectory()) {
14
- deleteFiles(filename);
15
- if (!fs_1.default.readdirSync(filename).length)
16
- fs_1.default.rmdirSync(filename);
17
- continue;
18
- }
19
- if (path_1.default.extname(f) === '.ts') {
20
- const contents = fs_1.default.readFileSync(filename, 'utf-8');
21
- if (contents.includes('#!oprimp_auto_generated!#')) {
22
- fs_1.default.unlinkSync(filename);
23
- }
24
- }
25
- }
26
- }
27
- exports.deleteFiles = deleteFiles;
@@ -1,54 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.generateService = void 0;
4
- const tslib_1 = require("tslib");
5
- const chalk_1 = tslib_1.__importDefault(require("chalk"));
6
- const console_1 = tslib_1.__importDefault(require("console"));
7
- const fs = tslib_1.__importStar(require("fs"));
8
- const path_1 = tslib_1.__importDefault(require("path"));
9
- const process = tslib_1.__importStar(require("process"));
10
- const node_client_1 = require("@opra/node-client");
11
- const ts_file_js_1 = require("../utils/ts-file.js");
12
- const delete_files_js_1 = require("./delete-files.js");
13
- const file_writer_js_1 = require("./file-writer.js");
14
- const process_resoruces_js_1 = require("./process-resoruces.js");
15
- const process_types_js_1 = require("./process-types.js");
16
- async function generateService(config) {
17
- const cwd = config.cwd || process.cwd();
18
- const logger = config.logger || console_1.default;
19
- try {
20
- console_1.default.log(chalk_1.default.yellow('Fetching service metadata from'), chalk_1.default.whiteBright(config.serviceUrl));
21
- const client = await node_client_1.OpraHttpClient.create(config.serviceUrl);
22
- const metadata = client.metadata;
23
- console_1.default.log(chalk_1.default.yellow('Retrieved service info:'), chalk_1.default.whiteBright(metadata.info.title), '-', chalk_1.default.whiteBright(metadata.info.version));
24
- console_1.default.log(chalk_1.default.yellow('Removing old files..'));
25
- (0, delete_files_js_1.deleteFiles)(config.outDir);
26
- let name = (config.name || metadata.info.title || 'Service1').replace(/[^\w_$]*/g, '');
27
- name = name.charAt(0).toUpperCase() + name.substring(1);
28
- const ctx = {
29
- serviceUrl: config.serviceUrl,
30
- document: client.metadata,
31
- name,
32
- logger,
33
- cwd,
34
- relativeDir: config.outDir,
35
- absoluteDir: path_1.default.resolve(cwd, config.outDir),
36
- fileHeader: config.fileHeader || '',
37
- extension: config.extension,
38
- writer: config.writer || new file_writer_js_1.FileWriter()
39
- };
40
- fs.mkdirSync(ctx.absoluteDir, { recursive: true });
41
- await (0, process_types_js_1.processTypes)(ctx);
42
- await (0, process_resoruces_js_1.processResources)(ctx);
43
- const indexTs = new ts_file_js_1.TsFile();
44
- indexTs.header = ctx.fileHeader;
45
- indexTs.addExport('./' + ctx.name + ctx.extension);
46
- indexTs.addExport('./types' + ctx.extension);
47
- await indexTs.writeFile(ctx, path_1.default.join(ctx.absoluteDir, 'index.ts'));
48
- }
49
- catch (error) {
50
- logger.error(chalk_1.default.red(error.message));
51
- process.exit(1);
52
- }
53
- }
54
- exports.generateService = generateService;
@@ -1,59 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.processResources = void 0;
4
- const tslib_1 = require("tslib");
5
- const chalk_1 = tslib_1.__importDefault(require("chalk"));
6
- const path_1 = tslib_1.__importDefault(require("path"));
7
- const common_1 = require("@opra/common");
8
- const string_utils_js_1 = require("../utils/string-utils.js");
9
- const ts_file_js_1 = require("../utils/ts-file.js");
10
- async function processResources(ctx) {
11
- const targetDir = ctx.absoluteDir;
12
- ctx.logger.log(chalk_1.default.yellow('Processing resources'));
13
- const serviceTs = new ts_file_js_1.TsFile();
14
- serviceTs.header = ctx.fileHeader;
15
- serviceTs.addImport('@opra/client', 'OpraHttpClient');
16
- serviceTs.content = `
17
- const kClient = Symbol('client');
18
-
19
- export class ${ctx.name} {
20
- static kClient = kClient;
21
- [kClient]: OpraHttpClient;
22
-
23
- constructor(client: OpraHttpClient) {
24
- this[kClient] = client;
25
- }
26
- `;
27
- const resourceNames = Array.from(ctx.document.resources.keys()).sort();
28
- for (const resourceName of resourceNames) {
29
- const resource = ctx.document.getResource(resourceName);
30
- serviceTs.content += `\n/**\n * ${(0, string_utils_js_1.wrapJSDocString)(resource.description || resource.name)}
31
- * @url ${(0, common_1.joinPath)(ctx.serviceUrl, '$metadata/resources/' + resource.name)}
32
- */`;
33
- if (resource instanceof common_1.CollectionResourceInfo) {
34
- serviceTs.addImport('@opra/client', 'HttpCollectionService');
35
- serviceTs.addImport('./types/' + resource.dataType.name + ctx.extension, resource.dataType.name);
36
- const methods = resource.getHandlerNames()
37
- .filter(x => x !== 'count')
38
- .map(x => `'${x}'`).join(' | ');
39
- serviceTs.content += `
40
- get ${resource.name}(): Pick<HttpCollectionService<${resource.dataType.name}, never>, ${methods}> {
41
- return this[kClient].collection('${resource.name}');
42
- }\n`;
43
- }
44
- else if (resource instanceof common_1.SingletonResourceInfo) {
45
- serviceTs.addImport('@opra/client', 'HttpSingletonService');
46
- serviceTs.addImport('./types/' + resource.dataType.name + ctx.extension, resource.dataType.name);
47
- const methods = resource.getHandlerNames()
48
- .map(x => `'${x}'`).join(' | ');
49
- serviceTs.content += `
50
- get ${resource.name}(): Pick<HttpSingletonService<${resource.dataType.name}, never>, ${methods}> {
51
- return this[kClient].singleton('${resource.name}');
52
- }\n`;
53
- }
54
- }
55
- serviceTs.content += `
56
- }\n`;
57
- await serviceTs.writeFile(ctx, path_1.default.join(targetDir, ctx.name + '.ts'));
58
- }
59
- exports.processResources = processResources;
@@ -1,130 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.processTypes = void 0;
4
- const tslib_1 = require("tslib");
5
- const chalk_1 = tslib_1.__importDefault(require("chalk"));
6
- const fs_1 = tslib_1.__importDefault(require("fs"));
7
- const path_1 = tslib_1.__importDefault(require("path"));
8
- const common_1 = require("@opra/common");
9
- const string_utils_js_1 = require("../utils/string-utils.js");
10
- const ts_file_js_1 = require("../utils/ts-file.js");
11
- const builtinsMap = {
12
- base64Binary: 'Buffer',
13
- dateString: 'string',
14
- guid: 'string',
15
- integer: 'number',
16
- date: 'Date'
17
- };
18
- async function processTypes(ctx) {
19
- const targetDir = path_1.default.join(ctx.absoluteDir, 'types');
20
- ctx.logger.log(chalk_1.default.yellow('Processing types'));
21
- const typesTs = new ts_file_js_1.TsFile();
22
- typesTs.header = ctx.fileHeader;
23
- let i = 0;
24
- const builtinsTs = new ts_file_js_1.TsFile();
25
- typesTs.header = ctx.fileHeader;
26
- fs_1.default.mkdirSync(targetDir, { recursive: true });
27
- const typeNames = Array.from(ctx.document.types.keys()).sort();
28
- for (const typeName of typeNames) {
29
- const dataType = ctx.document.getDataType(typeName);
30
- if (dataType.isBuiltin) {
31
- if (!builtinsMap[dataType.name])
32
- continue;
33
- typesTs.addExport('./types/builtins' + ctx.extension);
34
- builtinsTs.content += `export type ${dataType.name} = ${builtinsMap[dataType.name]};\n`;
35
- continue;
36
- }
37
- const tsFile = new ts_file_js_1.TsFile();
38
- tsFile.header = ctx.fileHeader;
39
- tsFile.content = `\n/**\n * ${(0, string_utils_js_1.wrapJSDocString)(dataType.description || dataType.name)}
40
- * @type ${dataType.name}
41
- * @kind ${dataType.kind}
42
- * @url ${(0, common_1.joinPath)(ctx.serviceUrl, '$metadata/types/' + dataType.name)}
43
- */\n`;
44
- const filename = `./types/${dataType.name}`;
45
- if (dataType instanceof common_1.ComplexType) {
46
- await generateComplexType(ctx, dataType, tsFile);
47
- await tsFile.writeFile(ctx, path_1.default.join(targetDir, dataType.name + '.ts'));
48
- typesTs.addExport(`${filename}` + ctx.extension);
49
- i++;
50
- }
51
- }
52
- await builtinsTs.writeFile(ctx, path_1.default.join(targetDir, 'builtins.ts'));
53
- if (i) {
54
- await typesTs.writeFile(ctx, path_1.default.join(ctx.absoluteDir, 'types.ts'));
55
- }
56
- }
57
- exports.processTypes = processTypes;
58
- async function generateComplexType(ctx, dataType, tsFile) {
59
- tsFile.header = ctx.fileHeader;
60
- tsFile.content = `
61
- export class ${dataType.name} {
62
- constructor(init?: Partial<I${dataType.name}>) {
63
- if (init)
64
- Object.assign(this, init);
65
- }
66
- }
67
-
68
- export interface ${dataType.name} extends I${dataType.name} {
69
- }
70
-
71
- interface I${dataType.name}`;
72
- if (dataType.extends) {
73
- tsFile.content += ' extends ' +
74
- dataType.extends.map(ex => {
75
- tsFile.addImport('./' + ex.type + ctx.extension, ex.type);
76
- let s = '';
77
- if (ex.omit)
78
- s += 'Omit<';
79
- if (ex.pick)
80
- s += 'Pick<';
81
- s += ex.type;
82
- if (ex.pick)
83
- s += ex.pick.map(x => `'${x}`).join(' | ') + '>';
84
- if (ex.omit)
85
- s += ex.omit.map(x => `'${x}`).join(' | ') + '>';
86
- return s;
87
- }).join(', ');
88
- }
89
- const getTypeName = (dt) => {
90
- if (dt.isBuiltin) {
91
- if (!builtinsMap[dt.name])
92
- return dt.name;
93
- tsFile.addImport('./builtins' + ctx.extension, dt.name);
94
- return dt.name;
95
- }
96
- tsFile.addImport('./' + dt.name + ctx.extension, dt.name);
97
- return dt.name;
98
- };
99
- tsFile.content += ' {\n\t';
100
- for (const f of dataType.ownFields.values()) {
101
- const fieldType = ctx.document.getDataType(f.type);
102
- // Print JSDoc
103
- tsFile.content += `/**\n * ${f.description || f.name}\n`;
104
- if (f.default)
105
- tsFile.content += ` * @default ` + f.default + '\n';
106
- if (f.format)
107
- tsFile.content += ` * @format ` + f.format + '\n';
108
- if (f.exclusive)
109
- tsFile.content += ` * @exclusive\n`;
110
- if (f.deprecated)
111
- tsFile.content += ` * @deprecated ` + (typeof f.deprecated === 'string' ? f.deprecated : '') + '\n';
112
- tsFile.content += ` */\n`;
113
- // Print field name
114
- tsFile.content += `${f.name}${f.required ? '' : '?'}: `;
115
- if (f.fixed)
116
- tsFile.content += `${f.fixed}`;
117
- else {
118
- if (fieldType instanceof common_1.UnionType) {
119
- const s = fieldType.types.map(t => getTypeName(t)).join(' | ');
120
- tsFile.content += `(${s})`;
121
- }
122
- else
123
- tsFile.content += `${getTypeName(fieldType)}`;
124
- tsFile.content += `${f.isArray ? '[]' : ''};\n\n`;
125
- }
126
- }
127
- if (dataType.additionalFields)
128
- tsFile.content += '[key: string]: any;\n';
129
- tsFile.content += '\b\b}\n';
130
- }
@@ -1,55 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.TsFile = void 0;
4
- const tslib_1 = require("tslib");
5
- const chalk_1 = tslib_1.__importDefault(require("chalk"));
6
- const path_1 = tslib_1.__importDefault(require("path"));
7
- const putil_flattentext_1 = tslib_1.__importDefault(require("putil-flattentext"));
8
- class TsFile {
9
- constructor() {
10
- this.imports = {};
11
- this.exports = {};
12
- this.header = '';
13
- this.content = '';
14
- this.addImport = (filename, ...imported) => {
15
- this.imports[filename] = this.imports[filename] || [];
16
- imported.forEach(x => {
17
- if (!this.imports[filename].includes(x))
18
- this.imports[filename].push(x);
19
- });
20
- };
21
- this.addExport = (filename, ...exported) => {
22
- this.exports[filename] = this.exports[filename] || [];
23
- exported.forEach(x => {
24
- if (!this.exports[filename].includes(x))
25
- this.exports[filename].push(x);
26
- });
27
- };
28
- }
29
- generate() {
30
- let output = '/* #!oprimp_auto_generated!# !! Do NOT remove this line */\n' +
31
- (this.header ? (0, putil_flattentext_1.default)(this.header) + '\n\n' : '\n');
32
- const importStr = Object.keys(this.imports)
33
- .sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()))
34
- .map(i => `import { ${this.imports[i].join(', ')} } from '${i}';`)
35
- .join('\n');
36
- if (importStr)
37
- output += (0, putil_flattentext_1.default)(importStr) + '\n';
38
- output += (0, putil_flattentext_1.default)(this.content);
39
- const exportStr = Object.keys(this.exports)
40
- .sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()))
41
- .map(i => {
42
- const a = this.exports[i];
43
- return `export ${a.length ? '{' + a.join(', ') + '}' : '*'} from '${i}';`;
44
- })
45
- .join('\n');
46
- if (exportStr)
47
- output += (0, putil_flattentext_1.default)(exportStr) + '\n';
48
- return output;
49
- }
50
- async writeFile(ctx, filename) {
51
- await ctx.writer.writeFile(filename, this.generate());
52
- ctx.logger.log(' - Written', chalk_1.default.whiteBright('./' + path_1.default.relative(ctx.absoluteDir, filename)));
53
- }
54
- }
55
- exports.TsFile = TsFile;
package/esm/index.d.ts DELETED
@@ -1 +0,0 @@
1
- export * from './oprimp/index.js';
@@ -1 +0,0 @@
1
- export declare function deleteFiles(dirname: string): void;
@@ -1,22 +0,0 @@
1
- import fs from 'fs';
2
- import path from 'path';
3
- export function deleteFiles(dirname) {
4
- if (!fs.existsSync(dirname))
5
- return;
6
- const files = fs.readdirSync(dirname);
7
- for (const f of files) {
8
- const filename = path.join(dirname, f);
9
- if (fs.statSync(filename).isDirectory()) {
10
- deleteFiles(filename);
11
- if (!fs.readdirSync(filename).length)
12
- fs.rmdirSync(filename);
13
- continue;
14
- }
15
- if (path.extname(f) === '.ts') {
16
- const contents = fs.readFileSync(filename, 'utf-8');
17
- if (contents.includes('#!oprimp_auto_generated!#')) {
18
- fs.unlinkSync(filename);
19
- }
20
- }
21
- }
22
- }
@@ -1,6 +0,0 @@
1
- import fs from 'fs';
2
- export class FileWriter {
3
- writeFile(filename, contents) {
4
- fs.writeFileSync(filename, contents, 'utf-8');
5
- }
6
- }
@@ -1,13 +0,0 @@
1
- import { IFileWriter } from '../interfaces/file-writer.interface.js';
2
- import { ILogger } from '../interfaces/logger.interface.js';
3
- export interface ServiceGenerateConfig {
4
- serviceUrl: string;
5
- outDir: string;
6
- name?: string;
7
- cwd?: string;
8
- logger?: ILogger;
9
- writer?: IFileWriter;
10
- fileHeader?: string;
11
- extension?: string;
12
- }
13
- export declare function generateService(config: ServiceGenerateConfig): Promise<void>;
@@ -1,49 +0,0 @@
1
- import chalk from 'chalk';
2
- import console from 'console';
3
- import * as fs from 'fs';
4
- import path from 'path';
5
- import * as process from 'process';
6
- import { OpraHttpClient } from '@opra/node-client';
7
- import { TsFile } from '../utils/ts-file.js';
8
- import { deleteFiles } from './delete-files.js';
9
- import { FileWriter } from './file-writer.js';
10
- import { processResources } from './process-resoruces.js';
11
- import { processTypes } from './process-types.js';
12
- export async function generateService(config) {
13
- const cwd = config.cwd || process.cwd();
14
- const logger = config.logger || console;
15
- try {
16
- console.log(chalk.yellow('Fetching service metadata from'), chalk.whiteBright(config.serviceUrl));
17
- const client = await OpraHttpClient.create(config.serviceUrl);
18
- const metadata = client.metadata;
19
- console.log(chalk.yellow('Retrieved service info:'), chalk.whiteBright(metadata.info.title), '-', chalk.whiteBright(metadata.info.version));
20
- console.log(chalk.yellow('Removing old files..'));
21
- deleteFiles(config.outDir);
22
- let name = (config.name || metadata.info.title || 'Service1').replace(/[^\w_$]*/g, '');
23
- name = name.charAt(0).toUpperCase() + name.substring(1);
24
- const ctx = {
25
- serviceUrl: config.serviceUrl,
26
- document: client.metadata,
27
- name,
28
- logger,
29
- cwd,
30
- relativeDir: config.outDir,
31
- absoluteDir: path.resolve(cwd, config.outDir),
32
- fileHeader: config.fileHeader || '',
33
- extension: config.extension,
34
- writer: config.writer || new FileWriter()
35
- };
36
- fs.mkdirSync(ctx.absoluteDir, { recursive: true });
37
- await processTypes(ctx);
38
- await processResources(ctx);
39
- const indexTs = new TsFile();
40
- indexTs.header = ctx.fileHeader;
41
- indexTs.addExport('./' + ctx.name + ctx.extension);
42
- indexTs.addExport('./types' + ctx.extension);
43
- await indexTs.writeFile(ctx, path.join(ctx.absoluteDir, 'index.ts'));
44
- }
45
- catch (error) {
46
- logger.error(chalk.red(error.message));
47
- process.exit(1);
48
- }
49
- }
@@ -1 +0,0 @@
1
- export * from './generate-service.js';
@@ -1 +0,0 @@
1
- export * from './generate-service.js';
@@ -1,2 +0,0 @@
1
- import { ServiceGenerationContext } from '../interfaces/service-generation-context.interface.js';
2
- export declare function processResources(ctx: ServiceGenerationContext): Promise<void>;
@@ -1,54 +0,0 @@
1
- import chalk from 'chalk';
2
- import path from 'path';
3
- import { CollectionResourceInfo, joinPath, SingletonResourceInfo } from '@opra/common';
4
- import { wrapJSDocString } from '../utils/string-utils.js';
5
- import { TsFile } from '../utils/ts-file.js';
6
- export async function processResources(ctx) {
7
- const targetDir = ctx.absoluteDir;
8
- ctx.logger.log(chalk.yellow('Processing resources'));
9
- const serviceTs = new TsFile();
10
- serviceTs.header = ctx.fileHeader;
11
- serviceTs.addImport('@opra/client', 'OpraHttpClient');
12
- serviceTs.content = `
13
- const kClient = Symbol('client');
14
-
15
- export class ${ctx.name} {
16
- static kClient = kClient;
17
- [kClient]: OpraHttpClient;
18
-
19
- constructor(client: OpraHttpClient) {
20
- this[kClient] = client;
21
- }
22
- `;
23
- const resourceNames = Array.from(ctx.document.resources.keys()).sort();
24
- for (const resourceName of resourceNames) {
25
- const resource = ctx.document.getResource(resourceName);
26
- serviceTs.content += `\n/**\n * ${wrapJSDocString(resource.description || resource.name)}
27
- * @url ${joinPath(ctx.serviceUrl, '$metadata/resources/' + resource.name)}
28
- */`;
29
- if (resource instanceof CollectionResourceInfo) {
30
- serviceTs.addImport('@opra/client', 'HttpCollectionService');
31
- serviceTs.addImport('./types/' + resource.dataType.name + ctx.extension, resource.dataType.name);
32
- const methods = resource.getHandlerNames()
33
- .filter(x => x !== 'count')
34
- .map(x => `'${x}'`).join(' | ');
35
- serviceTs.content += `
36
- get ${resource.name}(): Pick<HttpCollectionService<${resource.dataType.name}, never>, ${methods}> {
37
- return this[kClient].collection('${resource.name}');
38
- }\n`;
39
- }
40
- else if (resource instanceof SingletonResourceInfo) {
41
- serviceTs.addImport('@opra/client', 'HttpSingletonService');
42
- serviceTs.addImport('./types/' + resource.dataType.name + ctx.extension, resource.dataType.name);
43
- const methods = resource.getHandlerNames()
44
- .map(x => `'${x}'`).join(' | ');
45
- serviceTs.content += `
46
- get ${resource.name}(): Pick<HttpSingletonService<${resource.dataType.name}, never>, ${methods}> {
47
- return this[kClient].singleton('${resource.name}');
48
- }\n`;
49
- }
50
- }
51
- serviceTs.content += `
52
- }\n`;
53
- await serviceTs.writeFile(ctx, path.join(targetDir, ctx.name + '.ts'));
54
- }
@@ -1,2 +0,0 @@
1
- import { ServiceGenerationContext } from '../interfaces/service-generation-context.interface.js';
2
- export declare function processTypes(ctx: ServiceGenerationContext): Promise<void>;
@@ -1,125 +0,0 @@
1
- import chalk from 'chalk';
2
- import fs from 'fs';
3
- import path from 'path';
4
- import { ComplexType, joinPath, UnionType } from '@opra/common';
5
- import { wrapJSDocString } from '../utils/string-utils.js';
6
- import { TsFile } from '../utils/ts-file.js';
7
- const builtinsMap = {
8
- base64Binary: 'Buffer',
9
- dateString: 'string',
10
- guid: 'string',
11
- integer: 'number',
12
- date: 'Date'
13
- };
14
- export async function processTypes(ctx) {
15
- const targetDir = path.join(ctx.absoluteDir, 'types');
16
- ctx.logger.log(chalk.yellow('Processing types'));
17
- const typesTs = new TsFile();
18
- typesTs.header = ctx.fileHeader;
19
- let i = 0;
20
- const builtinsTs = new TsFile();
21
- typesTs.header = ctx.fileHeader;
22
- fs.mkdirSync(targetDir, { recursive: true });
23
- const typeNames = Array.from(ctx.document.types.keys()).sort();
24
- for (const typeName of typeNames) {
25
- const dataType = ctx.document.getDataType(typeName);
26
- if (dataType.isBuiltin) {
27
- if (!builtinsMap[dataType.name])
28
- continue;
29
- typesTs.addExport('./types/builtins' + ctx.extension);
30
- builtinsTs.content += `export type ${dataType.name} = ${builtinsMap[dataType.name]};\n`;
31
- continue;
32
- }
33
- const tsFile = new TsFile();
34
- tsFile.header = ctx.fileHeader;
35
- tsFile.content = `\n/**\n * ${wrapJSDocString(dataType.description || dataType.name)}
36
- * @type ${dataType.name}
37
- * @kind ${dataType.kind}
38
- * @url ${joinPath(ctx.serviceUrl, '$metadata/types/' + dataType.name)}
39
- */\n`;
40
- const filename = `./types/${dataType.name}`;
41
- if (dataType instanceof ComplexType) {
42
- await generateComplexType(ctx, dataType, tsFile);
43
- await tsFile.writeFile(ctx, path.join(targetDir, dataType.name + '.ts'));
44
- typesTs.addExport(`${filename}` + ctx.extension);
45
- i++;
46
- }
47
- }
48
- await builtinsTs.writeFile(ctx, path.join(targetDir, 'builtins.ts'));
49
- if (i) {
50
- await typesTs.writeFile(ctx, path.join(ctx.absoluteDir, 'types.ts'));
51
- }
52
- }
53
- async function generateComplexType(ctx, dataType, tsFile) {
54
- tsFile.header = ctx.fileHeader;
55
- tsFile.content = `
56
- export class ${dataType.name} {
57
- constructor(init?: Partial<I${dataType.name}>) {
58
- if (init)
59
- Object.assign(this, init);
60
- }
61
- }
62
-
63
- export interface ${dataType.name} extends I${dataType.name} {
64
- }
65
-
66
- interface I${dataType.name}`;
67
- if (dataType.extends) {
68
- tsFile.content += ' extends ' +
69
- dataType.extends.map(ex => {
70
- tsFile.addImport('./' + ex.type + ctx.extension, ex.type);
71
- let s = '';
72
- if (ex.omit)
73
- s += 'Omit<';
74
- if (ex.pick)
75
- s += 'Pick<';
76
- s += ex.type;
77
- if (ex.pick)
78
- s += ex.pick.map(x => `'${x}`).join(' | ') + '>';
79
- if (ex.omit)
80
- s += ex.omit.map(x => `'${x}`).join(' | ') + '>';
81
- return s;
82
- }).join(', ');
83
- }
84
- const getTypeName = (dt) => {
85
- if (dt.isBuiltin) {
86
- if (!builtinsMap[dt.name])
87
- return dt.name;
88
- tsFile.addImport('./builtins' + ctx.extension, dt.name);
89
- return dt.name;
90
- }
91
- tsFile.addImport('./' + dt.name + ctx.extension, dt.name);
92
- return dt.name;
93
- };
94
- tsFile.content += ' {\n\t';
95
- for (const f of dataType.ownFields.values()) {
96
- const fieldType = ctx.document.getDataType(f.type);
97
- // Print JSDoc
98
- tsFile.content += `/**\n * ${f.description || f.name}\n`;
99
- if (f.default)
100
- tsFile.content += ` * @default ` + f.default + '\n';
101
- if (f.format)
102
- tsFile.content += ` * @format ` + f.format + '\n';
103
- if (f.exclusive)
104
- tsFile.content += ` * @exclusive\n`;
105
- if (f.deprecated)
106
- tsFile.content += ` * @deprecated ` + (typeof f.deprecated === 'string' ? f.deprecated : '') + '\n';
107
- tsFile.content += ` */\n`;
108
- // Print field name
109
- tsFile.content += `${f.name}${f.required ? '' : '?'}: `;
110
- if (f.fixed)
111
- tsFile.content += `${f.fixed}`;
112
- else {
113
- if (fieldType instanceof UnionType) {
114
- const s = fieldType.types.map(t => getTypeName(t)).join(' | ');
115
- tsFile.content += `(${s})`;
116
- }
117
- else
118
- tsFile.content += `${getTypeName(fieldType)}`;
119
- tsFile.content += `${f.isArray ? '[]' : ''};\n\n`;
120
- }
121
- }
122
- if (dataType.additionalFields)
123
- tsFile.content += '[key: string]: any;\n';
124
- tsFile.content += '\b\b}\n';
125
- }