@opra/cli 0.33.13 → 1.0.0-alpha.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) 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/ts-generator/index.js +4 -0
  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 -131
  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/process-resources.js +0 -126
  52. package/esm/api-exporter/process-types.js +0 -249
  53. package/esm/api-exporter/ts-file.js +0 -99
  54. package/esm/utils/get-caller-file.util.js +0 -20
  55. package/types/api-exporter/api-exporter.d.ts +0 -46
  56. package/types/api-exporter/process-resources.d.ts +0 -4
  57. package/types/api-exporter/process-types.d.ts +0 -62
  58. package/types/utils/get-caller-file.util.d.ts +0 -1
  59. /package/cjs/{api-exporter/file-writer.js → file-writer.js} +0 -0
  60. /package/esm/{api-exporter/file-writer.js → file-writer.js} +0 -0
  61. /package/types/{utils → ts-generator/utils}/string-utils.d.ts +0 -0
@@ -0,0 +1,103 @@
1
+ import chalk from 'chalk';
2
+ import { EventEmitter } from 'node:events';
3
+ import fs from 'node:fs';
4
+ import path from 'node:path';
5
+ import process from 'node:process';
6
+ import { FileWriter } from '../file-writer.js';
7
+ import { cleanDirectory } from './processors/clean-directory.js';
8
+ import { generateComplexTypeDefinition, generateEnumTypeDefinition, generateMappedTypeDefinition, generateMixinTypeDefinition, generateSimpleTypeDefinition, processDataType, resolveTypeNameOrDef, } from './processors/process-data-types.js';
9
+ import { processDocument } from './processors/process-document.js';
10
+ import { processHttpApi } from './processors/process-http-api.js';
11
+ import { processHttpController } from './processors/process-http-controller.js';
12
+ import { TsFile } from './ts-file.js';
13
+ /**
14
+ * @class TsGenerator
15
+ */
16
+ export class TsGenerator extends EventEmitter {
17
+ /**
18
+ *
19
+ * @constructor
20
+ */
21
+ constructor(init) {
22
+ super();
23
+ this._started = false;
24
+ this._files = {};
25
+ this.serviceUrl = init.serviceUrl;
26
+ this.cwd = init.cwd || process.cwd();
27
+ this.outDir = init.outDir ? path.resolve(this.cwd, init.outDir) : this.cwd;
28
+ this.fileHeader = init.fileHeader || '';
29
+ this.writer = init.writer || new FileWriter();
30
+ this.options = { importExt: !!init.importExt };
31
+ this._documentsMap = new Map();
32
+ this._filesMap = new WeakMap();
33
+ this.on('log', (message, ...args) => init.logger?.log?.(message, ...args));
34
+ this.on('error', (message, ...args) => init.logger?.error?.(message, ...args));
35
+ this.on('debug', (message, ...args) => init.logger?.debug?.(message, ...args));
36
+ this.on('warn', (message, ...args) => init.logger?.warn?.(message, ...args));
37
+ this.on('verbose', (message, ...args) => init.logger?.verbose?.(message, ...args));
38
+ }
39
+ async generate() {
40
+ if (this._started)
41
+ return;
42
+ this.emit('start');
43
+ try {
44
+ this._started = true;
45
+ this.emit('log', chalk.cyan('Removing old files..'));
46
+ this.cleanDirectory(this.outDir);
47
+ this._apiPath = '/api';
48
+ await this.processDocument();
49
+ const { importExt } = this.options;
50
+ // Write files
51
+ for (const file of Object.values(this._files)) {
52
+ const filename = path.join(this.outDir, file.filename);
53
+ const targetDir = path.dirname(filename);
54
+ fs.mkdirSync(targetDir, { recursive: true });
55
+ await this.writer.writeFile(filename, file.generate({ importExt }));
56
+ }
57
+ }
58
+ catch (e) {
59
+ this.emit('error', e);
60
+ throw e;
61
+ }
62
+ finally {
63
+ this.emit('finish');
64
+ }
65
+ }
66
+ getFile(filePath) {
67
+ return this._files[filePath];
68
+ }
69
+ addFile(filePath, returnExists) {
70
+ if (!(filePath.startsWith('.') || filePath.startsWith('/')))
71
+ filePath = './' + filePath;
72
+ let file = this.getFile(filePath);
73
+ if (file) {
74
+ if (returnExists)
75
+ return file;
76
+ throw new Error(`File "${filePath}" already exists`);
77
+ }
78
+ file = new TsFile(filePath);
79
+ file.code.header = this.fileHeader + (this._fileHeaderDocInfo ? '\n' + this._fileHeaderDocInfo : '') + '\n\n';
80
+ this._files[file.filename] = file;
81
+ return file;
82
+ }
83
+ extend() {
84
+ const instance = {
85
+ options: { ...this.options },
86
+ };
87
+ Object.setPrototypeOf(instance, this);
88
+ return instance;
89
+ }
90
+ }
91
+ (() => {
92
+ TsGenerator.prototype.cleanDirectory = cleanDirectory;
93
+ TsGenerator.prototype.processDocument = processDocument;
94
+ TsGenerator.prototype.processDataType = processDataType;
95
+ TsGenerator.prototype.processHttpApi = processHttpApi;
96
+ TsGenerator.prototype.processHttpController = processHttpController;
97
+ TsGenerator.prototype.generateEnumTypeDefinition = generateEnumTypeDefinition;
98
+ TsGenerator.prototype.generateComplexTypeDefinition = generateComplexTypeDefinition;
99
+ TsGenerator.prototype.generateSimpleTypeDefinition = generateSimpleTypeDefinition;
100
+ TsGenerator.prototype.generateMappedTypeDefinition = generateMappedTypeDefinition;
101
+ TsGenerator.prototype.generateMixinTypeDefinition = generateMixinTypeDefinition;
102
+ TsGenerator.prototype.resolveTypeNameOrDef = resolveTypeNameOrDef;
103
+ })();
@@ -0,0 +1,12 @@
1
+ import { ComplexType, EnumType, MappedType, SimpleType } from '@opra/common';
2
+ export function locateNamedType(type) {
3
+ if (!type)
4
+ return;
5
+ if (type.name)
6
+ return type;
7
+ if (type instanceof SimpleType ||
8
+ type instanceof ComplexType ||
9
+ type instanceof EnumType ||
10
+ type instanceof MappedType)
11
+ return locateNamedType(type.base);
12
+ }
@@ -2,33 +2,33 @@ import jsStringEscape from 'js-string-escape';
2
2
  export function wrapJSDocString(s, indent, currentColumn) {
3
3
  const arr = (s || '')
4
4
  .split(/[ \n\r]/)
5
- .map((x, i, a) => i < a.length - 1 ? x + ' ' : x);
5
+ .map((x, i, a) => (i < a.length - 1 ? x + ' ' : x));
6
6
  return _printLines(arr, {
7
7
  indent,
8
8
  currentColumn,
9
9
  lineStart: '* ',
10
- lineEnd: ''
10
+ lineEnd: '',
11
11
  });
12
12
  }
13
13
  export function wrapQuotedString(s, indent, currentColumn) {
14
14
  const arr = jsStringEscape(s || '')
15
15
  .split(' ')
16
- .map((x, i, a) => i < a.length - 1 ? x + ' ' : x);
17
- return '\'' + _printLines(arr, {
18
- indent,
19
- currentColumn,
20
- lineStart: '\'',
21
- lineEnd: '\' +',
22
- }) + '\'';
16
+ .map((x, i, a) => (i < a.length - 1 ? x + ' ' : x));
17
+ return ("'" +
18
+ _printLines(arr, {
19
+ indent,
20
+ currentColumn,
21
+ lineStart: "'",
22
+ lineEnd: "' +",
23
+ }) +
24
+ "'");
23
25
  }
24
26
  export function wrapStringArray(arr, indent, currentColumn) {
25
- const ar1 = arr
26
- .map((x, i, a) => ('\'' + x + '\'') + (i < a.length - 1 ? ', ' : ''));
27
+ const ar1 = arr.map((x, i, a) => "'" + x + "'" + (i < a.length - 1 ? ', ' : ''));
27
28
  return '[' + _printLines(ar1, { indent, currentColumn }) + ']';
28
29
  }
29
30
  export function wrapTypeArray(arr, indent, currentColumn) {
30
- const ar1 = arr
31
- .map((x, i, a) => x + (i < a.length - 1 ? ' | ' : ''));
31
+ const ar1 = arr.map((x, i, a) => x + (i < a.length - 1 ? ' | ' : ''));
32
32
  return _printLines(ar1, { indent, currentColumn });
33
33
  }
34
34
  function _printLines(arr, opts = {}) {
@@ -38,9 +38,10 @@ function _printLines(arr, opts = {}) {
38
38
  let lineWidth = (opts.lineWidth || 90) - (opts.currentColumn || 0);
39
39
  const l = arr.length;
40
40
  const printLine = (eof) => {
41
- s += (s ? '\n' + ' '.repeat(indent || 0) + (opts.lineStart ? opts.lineStart : '') : '') +
42
- line +
43
- (!eof ? (opts.lineEnd ? opts.lineEnd : '') : '');
41
+ s +=
42
+ (s ? '\n' + ' '.repeat(indent || 0) + (opts.lineStart ? opts.lineStart : '') : '') +
43
+ line +
44
+ (!eof ? (opts.lineEnd ? opts.lineEnd : '') : '');
44
45
  line = '';
45
46
  };
46
47
  for (let i = 0; i < l; i++) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opra/cli",
3
- "version": "0.33.13",
3
+ "version": "1.0.0-alpha.7",
4
4
  "description": "Opra CLI tools",
5
5
  "author": "Panates",
6
6
  "license": "MIT",
@@ -20,8 +20,9 @@
20
20
  "copy:bin": "cp -R bin ../../build/cli/bin",
21
21
  "lint": "eslint . --max-warnings=0",
22
22
  "check": "madge --circular src/**",
23
- "test": "jest",
24
- "cover": "jest --collect-coverage",
23
+ "format": "prettier . --write --log-level=warn",
24
+ "test": "jest --passWithNoTests",
25
+ "cover": "jest --passWithNoTests --collect-coverage",
25
26
  "clean": "npm run clean:src && npm run clean:test && npm run clean:dist && npm run clean:cover",
26
27
  "clean:src": "ts-cleanup -s src --all",
27
28
  "clean:test": "ts-cleanup -s test --all",
@@ -29,9 +30,10 @@
29
30
  "clean:cover": "rimraf ../../coverage/client"
30
31
  },
31
32
  "dependencies": {
32
- "@opra/client": "^0.33.13",
33
+ "@opra/client": "^1.0.0-alpha.7",
34
+ "@opra/common": "^1.0.0-alpha.7",
33
35
  "chalk": "^5.3.0",
34
- "commander": "^11.0.0",
36
+ "commander": "^12.0.0",
35
37
  "js-string-escape": "^1.0.1",
36
38
  "putil-flattentext": "^2.1.1",
37
39
  "putil-varhelpers": "^1.6.5"
@@ -61,4 +63,4 @@
61
63
  "tool",
62
64
  "oprimp"
63
65
  ]
64
- }
66
+ }
@@ -0,0 +1,5 @@
1
+ export declare class CodeBlock {
2
+ [index: string]: any;
3
+ toString(): string;
4
+ [Symbol.toStringTag](): string;
5
+ }
@@ -1,4 +1,4 @@
1
- import { IFileWriter } from '../interfaces/file-writer.interface.js';
1
+ import { IFileWriter } from './interfaces/file-writer.interface.js';
2
2
  export declare class FileWriter implements IFileWriter {
3
3
  writeFile(filename: string, contents: string): void;
4
4
  }
package/types/index.d.ts CHANGED
@@ -1 +1 @@
1
- export * from './api-exporter/api-exporter.js';
1
+ export * from './ts-generator/index.js';
@@ -0,0 +1 @@
1
+ export declare const httpControllerNodeScript = "import { kClient, OpraHttpClient } from '@opra/client';\n\nconst PARAM_PATTERN = /:\\w+/g;\n\nexport class HttpControllerNode {\n readonly [kClient]: OpraHttpClient;\n\n constructor(client: OpraHttpClient) {\n this[kClient] = client;\n }\n \n protected _prepareUrl(url: string, params: Record<string, any>): string {\n return url.replace(PARAM_PATTERN, s => {\n return params[s.substring(1)] || '';\n });\n }\n}\n";
@@ -0,0 +1 @@
1
+ export * from './ts-generator.js';
@@ -0,0 +1,2 @@
1
+ import type { TsGenerator } from '../ts-generator';
2
+ export declare function cleanDirectory(this: TsGenerator, dirname: string): void;
@@ -0,0 +1,30 @@
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 = 'scope' | 'extends' | 'field';
5
+ export declare function processDataType(this: TsGenerator, dataType: DataType): Promise<TsFile | undefined>;
6
+ /**
7
+ *
8
+ */
9
+ export declare function generateEnumTypeDefinition(this: TsGenerator, dataType: EnumType, intent: Intent): Promise<string>;
10
+ /**
11
+ *
12
+ */
13
+ export declare function generateComplexTypeDefinition(this: TsGenerator, dataType: ComplexType, file: TsFile, intent: Intent): Promise<string>;
14
+ /**
15
+ *
16
+ */
17
+ export declare function generateSimpleTypeDefinition(this: TsGenerator, dataType: SimpleType, intent: Intent): Promise<string>;
18
+ /**
19
+ *
20
+ */
21
+ export declare function generateMixinTypeDefinition(this: TsGenerator, dataType: MixinType, file: TsFile, intent: Intent): Promise<string>;
22
+ /**
23
+ *
24
+ */
25
+ export declare function generateMappedTypeDefinition(this: TsGenerator, dataType: MappedType, file: TsFile, intent: Intent): Promise<string>;
26
+ /**
27
+ *
28
+ */
29
+ export declare function resolveTypeNameOrDef(this: TsGenerator, dataType: DataType, file: TsFile, intent: Intent): Promise<string>;
30
+ export {};
@@ -0,0 +1,8 @@
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
+ }>;
@@ -0,0 +1,3 @@
1
+ import { HttpApi } from '@opra/common';
2
+ import type { TsGenerator } from '../ts-generator';
3
+ export declare function processHttpApi(this: TsGenerator, api: HttpApi): Promise<import("../ts-file.js").TsFile>;
@@ -0,0 +1,3 @@
1
+ import { HttpController } from '@opra/common';
2
+ import type { TsGenerator } from '../ts-generator';
3
+ export declare function processHttpController(this: TsGenerator, controller: HttpController): Promise<import("../ts-file.js").TsFile>;
@@ -1,3 +1,4 @@
1
+ import { CodeBlock } from '../code-block.js';
1
2
  export declare class TsFile {
2
3
  readonly filename: string;
3
4
  readonly dirname: string;
@@ -7,11 +8,10 @@ export declare class TsFile {
7
8
  }>;
8
9
  exportFiles: Record<string, string[]>;
9
10
  exportTypes: string[];
10
- header: string;
11
- content: string;
11
+ code: CodeBlock;
12
12
  constructor(filename: string);
13
- addImport: (filename: string, items?: string[], typeImport?: boolean) => void;
14
- addExport: (filename: string, types?: string[]) => void;
13
+ addImport(filename: string, items?: string[], typeImport?: boolean): void;
14
+ addExport(filename: string, types?: string[]): void;
15
15
  generate(options?: {
16
16
  importExt?: boolean;
17
17
  }): string;
@@ -0,0 +1,70 @@
1
+ /// <reference types="node" />
2
+ import { EventEmitter } from 'node:events';
3
+ import { ApiDocument } from '@opra/common';
4
+ import { IFileWriter } from '../interfaces/file-writer.interface.js';
5
+ import { ILogger } from '../interfaces/logger.interface.js';
6
+ import { cleanDirectory } from './processors/clean-directory.js';
7
+ import { generateComplexTypeDefinition, generateEnumTypeDefinition, generateMappedTypeDefinition, generateMixinTypeDefinition, generateSimpleTypeDefinition, processDataType, resolveTypeNameOrDef } from './processors/process-data-types.js';
8
+ import { processDocument } from './processors/process-document.js';
9
+ import { processHttpApi } from './processors/process-http-api.js';
10
+ import { processHttpController } from './processors/process-http-controller.js';
11
+ import { TsFile } from './ts-file.js';
12
+ /**
13
+ * @namespace TsGenerator
14
+ */
15
+ export declare namespace TsGenerator {
16
+ interface Options {
17
+ serviceUrl: string;
18
+ outDir: string;
19
+ cwd?: string;
20
+ logger?: ILogger;
21
+ writer?: IFileWriter;
22
+ fileHeader?: string;
23
+ importExt?: boolean;
24
+ }
25
+ }
26
+ /**
27
+ * @class TsGenerator
28
+ */
29
+ export declare class TsGenerator extends EventEmitter {
30
+ protected cleanDirectory: typeof cleanDirectory;
31
+ protected processDocument: typeof processDocument;
32
+ protected processDataType: typeof processDataType;
33
+ protected processHttpApi: typeof processHttpApi;
34
+ protected processHttpController: typeof processHttpController;
35
+ protected generateEnumTypeDefinition: typeof generateEnumTypeDefinition;
36
+ protected generateComplexTypeDefinition: typeof generateComplexTypeDefinition;
37
+ protected generateSimpleTypeDefinition: typeof generateSimpleTypeDefinition;
38
+ protected generateMappedTypeDefinition: typeof generateMappedTypeDefinition;
39
+ protected generateMixinTypeDefinition: typeof generateMixinTypeDefinition;
40
+ protected resolveTypeNameOrDef: typeof resolveTypeNameOrDef;
41
+ protected _started: boolean;
42
+ protected _document?: ApiDocument;
43
+ protected _documentRoot: string;
44
+ protected _typesRoot: string;
45
+ protected _apiPath: string;
46
+ protected _fileHeaderDocInfo: string;
47
+ protected _files: Record<string, TsFile>;
48
+ protected _documentsMap: Map<string, {
49
+ document: ApiDocument;
50
+ generator: TsGenerator;
51
+ }>;
52
+ protected _filesMap: WeakMap<Object, TsFile>;
53
+ readonly serviceUrl: string;
54
+ readonly outDir: string;
55
+ readonly cwd: string;
56
+ readonly writer: IFileWriter;
57
+ readonly options: {
58
+ importExt: boolean;
59
+ };
60
+ fileHeader: string;
61
+ /**
62
+ *
63
+ * @constructor
64
+ */
65
+ constructor(init: TsGenerator.Options);
66
+ generate(): Promise<void>;
67
+ protected getFile(filePath: string): TsFile;
68
+ protected addFile(filePath: string, returnExists?: boolean): TsFile;
69
+ protected extend(): TsGenerator;
70
+ }
@@ -0,0 +1,2 @@
1
+ import { DataType } from '@opra/common';
2
+ export declare function locateNamedType(type?: DataType): DataType | undefined;
@@ -1,115 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ApiExporter = void 0;
4
- const tslib_1 = require("tslib");
5
- const chalk_1 = tslib_1.__importDefault(require("chalk"));
6
- const node_fs_1 = tslib_1.__importDefault(require("node:fs"));
7
- const node_path_1 = tslib_1.__importDefault(require("node:path"));
8
- const node_process_1 = tslib_1.__importDefault(require("node:process"));
9
- const client_1 = require("@opra/client");
10
- const file_writer_js_1 = require("./file-writer.js");
11
- const process_resources_js_1 = require("./process-resources.js");
12
- const process_types_js_1 = require("./process-types.js");
13
- const ts_file_js_1 = require("./ts-file.js");
14
- class ApiExporter {
15
- constructor(config) {
16
- this.files = {};
17
- this.client = new client_1.OpraHttpClient(config.serviceUrl);
18
- this.cwd = config.cwd || node_process_1.default.cwd();
19
- this.outDir = node_path_1.default.resolve(this.cwd, config.outDir);
20
- this.logger = config.logger || {
21
- log: () => void 0,
22
- error: () => void 0,
23
- debug: () => void 0,
24
- warn: () => void 0,
25
- verbose: () => void 0,
26
- };
27
- this.fileHeader = config.fileHeader || '';
28
- this.writer = config.writer || new file_writer_js_1.FileWriter();
29
- this.serviceClassName = config.name;
30
- this.importExt = config.importExt;
31
- // this.nsMap = nsMap || new ResponsiveMap(); // implement references later
32
- }
33
- async execute() {
34
- this.logger.log(chalk_1.default.cyan('Fetching service metadata from'), chalk_1.default.whiteBright(this.client.serviceUrl));
35
- this.document = await this.client.getMetadata();
36
- this.logger.log(chalk_1.default.cyan('Retrieved service info:\n'), chalk_1.default.white('Title:'), chalk_1.default.whiteBright(this.document.info.title), '\n', chalk_1.default.white('Version:'), chalk_1.default.whiteBright(this.document.info.version), '\n');
37
- this.serviceClassName = (this.serviceClassName || this.document.info.title || 'Service1').replace(/[^\w_$]*/g, '');
38
- this.serviceClassName = this.serviceClassName.charAt(0).toUpperCase() + this.serviceClassName.substring(1);
39
- this.fileHeader += `/*
40
- * ${this.document.info.title}
41
- * Version ${this.document.info.version}
42
- * ${this.client.serviceUrl}
43
- */`;
44
- this.logger.log(chalk_1.default.cyan('Removing old files..'));
45
- this.cleanDirectory(this.outDir);
46
- this.logger.log(chalk_1.default.cyan(`Generating service interface ( ${chalk_1.default.whiteBright(this.serviceClassName)} )`));
47
- node_fs_1.default.mkdirSync(this.outDir, { recursive: true });
48
- this.logger.log(chalk_1.default.cyan('Processing types'));
49
- await this.processTypes();
50
- this.logger.log(chalk_1.default.cyan('Processing resources'));
51
- const rootTs = this.addFile('/' + this.serviceClassName + '.ts');
52
- await this.processResource(this.document.root, this.serviceClassName, rootTs);
53
- const { importExt } = this;
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
- getFile(filePath) {
63
- return this.files[filePath];
64
- }
65
- addFile(filePath, returnExists) {
66
- if (!(filePath.startsWith('.') || filePath.startsWith('/')))
67
- filePath = './' + filePath;
68
- let file = this.getFile(filePath);
69
- if (file) {
70
- if (returnExists)
71
- return file;
72
- throw new Error(`File "${filePath}" already exists`);
73
- }
74
- file = new ts_file_js_1.TsFile(filePath);
75
- file.header = this.fileHeader;
76
- this.files[file.filename] = file;
77
- return file;
78
- }
79
- cleanDirectory(dirname) {
80
- if (!node_fs_1.default.existsSync(dirname))
81
- return;
82
- const files = node_fs_1.default.readdirSync(dirname);
83
- for (const f of files) {
84
- const absolutePath = node_path_1.default.join(dirname, f);
85
- if (node_fs_1.default.statSync(absolutePath).isDirectory()) {
86
- this.cleanDirectory(absolutePath);
87
- if (!node_fs_1.default.readdirSync(absolutePath).length)
88
- node_fs_1.default.rmdirSync(absolutePath);
89
- continue;
90
- }
91
- if (node_path_1.default.extname(f) === '.ts') {
92
- const contents = node_fs_1.default.readFileSync(absolutePath, 'utf-8');
93
- if (contents.includes('#!oprimp_auto_generated!#')) {
94
- node_fs_1.default.unlinkSync(absolutePath);
95
- }
96
- }
97
- }
98
- }
99
- static async execute(config) {
100
- const exporter = new ApiExporter(config);
101
- await exporter.execute();
102
- }
103
- }
104
- exports.ApiExporter = ApiExporter;
105
- (() => {
106
- ApiExporter.prototype.processResource = process_resources_js_1.processResource;
107
- ApiExporter.prototype.processTypes = process_types_js_1.processTypes;
108
- ApiExporter.prototype.generateTypeFile = process_types_js_1.generateTypeFile;
109
- ApiExporter.prototype.generateComplexTypeDefinition = process_types_js_1.generateComplexTypeDefinition;
110
- ApiExporter.prototype.generateSimpleTypeDefinition = process_types_js_1.generateSimpleTypeDefinition;
111
- ApiExporter.prototype.resolveTypeNameOrDef = process_types_js_1.resolveTypeNameOrDef;
112
- ApiExporter.prototype.generateEnumTypeDefinition = process_types_js_1.generateEnumTypeDefinition;
113
- ApiExporter.prototype.generateMixinTypeDefinition = process_types_js_1.generateMixinTypeDefinition;
114
- ApiExporter.prototype.generateMappedTypeDefinition = process_types_js_1.generateMappedTypeDefinition;
115
- })();
@@ -1,131 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.processResource = void 0;
4
- const tslib_1 = require("tslib");
5
- const node_path_1 = tslib_1.__importDefault(require("node:path"));
6
- const common_1 = require("@opra/common");
7
- const string_utils_js_1 = require("../utils/string-utils.js");
8
- async function processResource(resource, className, tsFile) {
9
- tsFile.addImport('@opra/client', ['kClient', 'OpraHttpClient']);
10
- tsFile.content = `\n
11
- /**
12
- * ${(0, string_utils_js_1.wrapJSDocString)(resource.description || '')}
13
- * @class ${className}
14
- * @url ${node_path_1.default.posix.join(this.client.serviceUrl, '#resources/' + className)}
15
- */
16
- export class ${className} {
17
- readonly [kClient]: OpraHttpClient;\n`;
18
- let constructorBody = `
19
- constructor(client: OpraHttpClient) {
20
- this[kClient] = client;\n`;
21
- if (resource instanceof common_1.Container) {
22
- for (const child of resource.resources.values()) {
23
- // Determine class name of child resource
24
- let childClassName = child.name.charAt(0).toUpperCase() + child.name.substring(1);
25
- if (child instanceof common_1.Container)
26
- childClassName += 'Container';
27
- else
28
- childClassName += 'Resource';
29
- // Create TsFile for child resource
30
- const dir = node_path_1.default.dirname(tsFile.filename);
31
- const basename = dir === '/'
32
- ? 'root'
33
- : node_path_1.default.basename(tsFile.filename, node_path_1.default.extname(tsFile.filename));
34
- const childFile = this.addFile(node_path_1.default.join(dir, basename, child.name + '.ts'));
35
- await this.processResource(child, childClassName, childFile);
36
- tsFile.addImport(childFile.filename, [childClassName]);
37
- tsFile.content += `
38
- /**
39
- * ${(0, string_utils_js_1.wrapJSDocString)(child.description || '')}
40
- * @url ${node_path_1.default.posix.join(this.client.serviceUrl, '#resources/' + child.name)}
41
- */
42
- readonly ${child.name}: ${childClassName};\n`;
43
- constructorBody += ` this.${child.name} = new ${childClassName}(client);\n`;
44
- }
45
- }
46
- else if (resource instanceof common_1.Collection) {
47
- tsFile.addImport('@opra/client', ['HttpCollectionNode']);
48
- const typeName = resource.type.name || '';
49
- tsFile.addImport(`/types/${typeName}`, [typeName], true);
50
- constructorBody += ` const node = this[kClient].collection('${resource.getFullPath()}');\n`;
51
- for (const [operation, endpoint] of resource.operations.entries()) {
52
- tsFile.content += `
53
- /**
54
- * ${(0, string_utils_js_1.wrapJSDocString)(endpoint.description || '')}
55
- */
56
- readonly ${operation}: HttpCollectionNode<${typeName}>['${operation}'];\n`;
57
- constructorBody += ` this.${operation} = node.${operation}.bind(node);\n`;
58
- }
59
- }
60
- else if (resource instanceof common_1.Singleton) {
61
- tsFile.addImport('@opra/client', ['HttpSingletonNode']);
62
- const typeName = resource.type.name || '';
63
- tsFile.addImport(`/types/${typeName}`, [typeName], true);
64
- constructorBody += ` const node = this[kClient].singleton('${resource.getFullPath()}');\n`;
65
- for (const [operation, endpoint] of resource.operations.entries()) {
66
- tsFile.content += `
67
- /**
68
- * ${(0, string_utils_js_1.wrapJSDocString)(endpoint.description || '')}
69
- */
70
- readonly ${operation}: HttpSingletonNode<${typeName}>['${operation}'];\n`;
71
- constructorBody += ` this.${operation} = node.${operation}.bind(node);\n`;
72
- }
73
- }
74
- else if (resource instanceof common_1.Storage) {
75
- tsFile.addImport('@opra/client', ['HttpStorageNode']);
76
- constructorBody += ` const node = this[kClient].storage('${resource.getFullPath()}');\n`;
77
- for (const [operation, endpoint] of resource.operations.entries()) {
78
- tsFile.content += `
79
- /**
80
- * ${(0, string_utils_js_1.wrapJSDocString)(endpoint.description || '')}
81
- */`;
82
- if (operation === 'post' && endpoint.returnType) {
83
- const typeName = endpoint.returnType.name || 'any'; // todo
84
- tsFile.addImport(`/types/${typeName}`, [typeName], true);
85
- tsFile.content += `\n readonly ${operation}: HttpStorageNode<${typeName}>['${operation}'];\n`;
86
- }
87
- else
88
- tsFile.content += `\n readonly ${operation}: HttpStorageNode['${operation}'];\n`;
89
- constructorBody += ` this.${operation} = node.${operation}.bind(node);\n`;
90
- }
91
- }
92
- if (resource.actions.size) {
93
- tsFile.addImport('@opra/client', ['HttpRequestObservable']);
94
- for (const [action, endpoint] of resource.actions.entries()) {
95
- let returnTypeDef = endpoint.returnType ?
96
- await this.resolveTypeNameOrDef({
97
- file: tsFile,
98
- dataType: endpoint.returnType,
99
- intent: 'field'
100
- })
101
- : 'any';
102
- if (returnTypeDef.length > 40)
103
- returnTypeDef = '\n\t\t' + returnTypeDef + '\n\b\b';
104
- const actionPath = resource.getFullPath() + '/' + action;
105
- let params = '';
106
- for (const prm of endpoint.parameters.values()) {
107
- const paramTypeDef = await this.resolveTypeNameOrDef({
108
- file: tsFile,
109
- dataType: prm.type,
110
- intent: 'field'
111
- }) || 'any';
112
- params += `${prm.name}: ${paramTypeDef}`;
113
- if (prm.isArray)
114
- params += '[]';
115
- params += ';\n';
116
- }
117
- params = params ? '\n\t\t\tparams: {\n\t' + params + '\b}\n\b\b' : '';
118
- tsFile.content += `
119
- /**
120
- * ${(0, string_utils_js_1.wrapJSDocString)(endpoint.description || '')}
121
- */
122
- ${action}(${params}): HttpRequestObservable<${returnTypeDef}> {\b
123
- return this[kClient].action('${actionPath}'${params ? ', params' : ''});
124
- }
125
- `;
126
- }
127
- }
128
- tsFile.content += constructorBody + ` }\n\n}\n`;
129
- return tsFile.content;
130
- }
131
- exports.processResource = processResource;