@opra/cli 0.14.2 → 0.15.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 (44) 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.d.ts +46 -0
  10. package/esm/api-exporter/api-exporter.js +102 -0
  11. package/esm/api-exporter/index.d.ts +1 -0
  12. package/esm/api-exporter/index.js +1 -0
  13. package/esm/api-exporter/process-resources.d.ts +6 -0
  14. package/esm/api-exporter/process-resources.js +45 -0
  15. package/esm/api-exporter/process-types.d.ts +54 -0
  16. package/esm/api-exporter/process-types.js +203 -0
  17. package/esm/api-exporter/ts-file.d.ts +18 -0
  18. package/esm/api-exporter/ts-file.js +83 -0
  19. package/esm/index.d.ts +1 -1
  20. package/esm/index.js +1 -1
  21. package/esm/interfaces/service-generation-context.interface.d.ts +2 -2
  22. package/esm/{oprimp.js → oprimp-cli.js} +8 -9
  23. package/package.json +8 -9
  24. package/cjs/oprimp/delete-files.js +0 -27
  25. package/cjs/oprimp/generate-service.js +0 -54
  26. package/cjs/oprimp/process-resoruces.js +0 -59
  27. package/cjs/oprimp/process-types.js +0 -130
  28. package/cjs/utils/ts-file.js +0 -55
  29. package/esm/oprimp/delete-files.d.ts +0 -1
  30. package/esm/oprimp/delete-files.js +0 -22
  31. package/esm/oprimp/generate-service.d.ts +0 -13
  32. package/esm/oprimp/generate-service.js +0 -49
  33. package/esm/oprimp/index.d.ts +0 -1
  34. package/esm/oprimp/index.js +0 -1
  35. package/esm/oprimp/process-resoruces.d.ts +0 -2
  36. package/esm/oprimp/process-resoruces.js +0 -54
  37. package/esm/oprimp/process-types.d.ts +0 -2
  38. package/esm/oprimp/process-types.js +0 -125
  39. package/esm/utils/ts-file.d.ts +0 -11
  40. package/esm/utils/ts-file.js +0 -50
  41. /package/cjs/{oprimp → api-exporter}/file-writer.js +0 -0
  42. /package/esm/{oprimp → api-exporter}/file-writer.d.ts +0 -0
  43. /package/esm/{oprimp → api-exporter}/file-writer.js +0 -0
  44. /package/esm/{oprimp.d.ts → oprimp-cli.d.ts} +0 -0
@@ -0,0 +1 @@
1
+ export * from './api-exporter.js';
@@ -0,0 +1,6 @@
1
+ import type { ApiExporter } from './api-exporter.js';
2
+ /**
3
+ *
4
+ * @param targetDir
5
+ */
6
+ export declare function processResources(this: ApiExporter, targetDir?: string): Promise<void>;
@@ -0,0 +1,45 @@
1
+ import chalk from 'chalk';
2
+ import path from 'node:path';
3
+ import { Collection, joinPath, Singleton } from '@opra/common';
4
+ import { wrapJSDocString } from '../utils/string-utils.js';
5
+ /**
6
+ *
7
+ * @param targetDir
8
+ */
9
+ export async function processResources(targetDir = '') {
10
+ this.logger.log(chalk.yellow('Processing resources'));
11
+ const { document } = this;
12
+ const serviceTs = this.addFile(path.join(targetDir, this.name + '.ts'));
13
+ serviceTs.addImportPackage('@opra/client', ['HttpServiceBase']);
14
+ const indexTs = this.addFile('/index.ts', true);
15
+ indexTs.addExportFile(serviceTs.filename);
16
+ serviceTs.content = `\nexport class ${this.name} extends HttpServiceBase {\n`;
17
+ for (const resource of document.resources.values()) {
18
+ serviceTs.content += `\n/**\n * ${wrapJSDocString(resource.description || resource.name)}
19
+ * @url ${joinPath(this.client.serviceUrl, '$metadata#resources/' + resource.name)}
20
+ */`;
21
+ if (resource instanceof Collection) {
22
+ const typeName = resource.type.name || '';
23
+ serviceTs.addImportPackage('@opra/client', ['HttpCollectionNode']);
24
+ serviceTs.addImportFile('types/' + typeName, [typeName]);
25
+ const operations = Object.keys(resource.operations)
26
+ .map(x => `'${x}'`).join(' | ');
27
+ serviceTs.content += `
28
+ get ${resource.name}(): Pick<HttpCollectionNode<${typeName}>, ${operations}> {
29
+ return this.$client.collection('${resource.name}');
30
+ }\n`;
31
+ }
32
+ else if (resource instanceof Singleton) {
33
+ const typeName = resource.type.name || '';
34
+ serviceTs.addImportPackage('@opra/client', ['HttpSingletonNode']);
35
+ serviceTs.addImportFile('types/' + typeName, [typeName]);
36
+ const operations = Object.keys(resource.operations)
37
+ .map(x => `'${x}'`).join(' | ');
38
+ serviceTs.content += `
39
+ get ${resource.name}(): Pick<HttpSingletonNode<${typeName}>, ${operations}> {
40
+ return this.$client.singleton('${resource.name}');
41
+ }\n`;
42
+ }
43
+ }
44
+ serviceTs.content += '}';
45
+ }
@@ -0,0 +1,54 @@
1
+ import { ComplexType, DataType, EnumType, MappedType, SimpleType, UnionType } from '@opra/common';
2
+ import type { ApiExporter } from './api-exporter.js';
3
+ import { TsFile } from './ts-file.js';
4
+ /**
5
+ *
6
+ * @param targetDir
7
+ */
8
+ export declare function processTypes(this: ApiExporter, targetDir?: string): Promise<void>;
9
+ /**
10
+ *
11
+ * @param dataType
12
+ * @param targetDir
13
+ */
14
+ export declare function generateTypeFile(this: ApiExporter, dataType: DataType, targetDir?: string): Promise<TsFile>;
15
+ /**
16
+ *
17
+ * @param file
18
+ * @param dataType
19
+ * @param forInterface
20
+ */
21
+ export declare function resolveTypeNameOrDef(this: ApiExporter, file: TsFile, dataType: DataType, forInterface?: boolean): Promise<string>;
22
+ /**
23
+ *
24
+ * @param file
25
+ * @param dataType
26
+ * @param forInterface
27
+ */
28
+ export declare function generateComplexTypeDefinition(this: ApiExporter, file: TsFile, dataType: ComplexType, forInterface?: boolean): Promise<string>;
29
+ /**
30
+ *
31
+ * @param file
32
+ * @param dataType
33
+ */
34
+ export declare function generateSimpleTypeDefinition(this: ApiExporter, file: TsFile, dataType: SimpleType): Promise<string>;
35
+ /**
36
+ *
37
+ * @param file
38
+ * @param dataType
39
+ */
40
+ export declare function generateEnumTypeDefinition(this: ApiExporter, file: TsFile, dataType: EnumType): Promise<string>;
41
+ /**
42
+ *
43
+ * @param file
44
+ * @param dataType
45
+ * @param forInterface
46
+ */
47
+ export declare function generateUnionTypeDefinition(this: ApiExporter, file: TsFile, dataType: UnionType, forInterface?: boolean): Promise<string>;
48
+ /**
49
+ *
50
+ * @param file
51
+ * @param dataType
52
+ * @param forInterface
53
+ */
54
+ export declare function generateMappedTypeDefinition(this: ApiExporter, file: TsFile, dataType: MappedType, forInterface?: boolean): Promise<string>;
@@ -0,0 +1,203 @@
1
+ import chalk from 'chalk';
2
+ import path from 'node:path';
3
+ import { ComplexType, EnumType, joinPath, MappedType, SimpleType, UnionType } from '@opra/common';
4
+ import { wrapJSDocString } from '../utils/string-utils.js';
5
+ const internalTypeNames = ['boolean', 'bigint', 'number', 'null', 'string'];
6
+ /**
7
+ *
8
+ * @param targetDir
9
+ */
10
+ export async function processTypes(targetDir = '') {
11
+ this.logger.log(chalk.yellow('Processing types'));
12
+ const { document } = this;
13
+ const typesTs = this.addFile(path.join(targetDir, 'types.ts'));
14
+ for (const dataType of document.types.values()) {
15
+ const expFile = await this.generateTypeFile(dataType, targetDir);
16
+ typesTs.addExportFile(expFile.filename);
17
+ }
18
+ }
19
+ /**
20
+ *
21
+ * @param dataType
22
+ * @param targetDir
23
+ */
24
+ export async function generateTypeFile(dataType, targetDir = '') {
25
+ const typeName = dataType.name;
26
+ if (!typeName)
27
+ throw new TypeError(`DataType has no name`);
28
+ let filePath;
29
+ if (dataType instanceof SimpleType)
30
+ filePath = '/simple-types.ts';
31
+ else if (dataType instanceof ComplexType)
32
+ filePath = `/types/${typeName}.ts`;
33
+ else if (dataType instanceof EnumType) {
34
+ filePath = `/enums/${typeName}.ts`;
35
+ }
36
+ else
37
+ throw new TypeError(`Unimplemented DataType (${dataType.kind})`);
38
+ const file = this.addFile(path.join(targetDir, filePath), true);
39
+ if (file.exportTypes.includes(typeName))
40
+ return file;
41
+ file.exportTypes.push(typeName);
42
+ const indexTs = this.addFile('/index.ts', true);
43
+ indexTs.addExportFile(file.filename);
44
+ file.content += `\n/**\n * ${wrapJSDocString(dataType.description || typeName)}
45
+ * @type ${typeName}
46
+ * @kind ${dataType.kind}
47
+ * @url ${joinPath(this.client.serviceUrl, '$metadata#types/' + typeName)}
48
+ */\n`;
49
+ if (dataType instanceof SimpleType) {
50
+ file.content += `export type ${typeName} = ` + await this.generateSimpleTypeDefinition(file, dataType);
51
+ }
52
+ else if (dataType instanceof EnumType) {
53
+ file.content += `export enum ${typeName} ` + await this.generateEnumTypeDefinition(file, dataType);
54
+ }
55
+ else if (dataType instanceof ComplexType) {
56
+ file.content += `export class ${typeName} {
57
+ constructor(init?: Partial<I${typeName}>) {
58
+ if (init)
59
+ Object.assign(this, init);
60
+ }
61
+ }
62
+
63
+ export interface ${typeName} extends I${typeName} {
64
+ }
65
+
66
+ interface I${typeName} ${await this.generateComplexTypeDefinition(file, dataType, true)}
67
+ `;
68
+ }
69
+ return file;
70
+ }
71
+ /**
72
+ *
73
+ * @param file
74
+ * @param dataType
75
+ * @param forInterface
76
+ */
77
+ export async function resolveTypeNameOrDef(file, dataType, forInterface) {
78
+ if (dataType.name) {
79
+ if (internalTypeNames.includes(dataType.name))
80
+ return dataType.name;
81
+ const f = await this.generateTypeFile(dataType);
82
+ file.addImportFile(f.filename, [dataType.name]);
83
+ return dataType.name;
84
+ }
85
+ if (dataType instanceof ComplexType)
86
+ return this.generateComplexTypeDefinition(file, dataType, forInterface);
87
+ if (dataType instanceof SimpleType)
88
+ return this.generateSimpleTypeDefinition(file, dataType);
89
+ if (dataType instanceof EnumType)
90
+ return this.generateEnumTypeDefinition(file, dataType);
91
+ if (dataType instanceof UnionType)
92
+ return this.generateUnionTypeDefinition(file, dataType, forInterface);
93
+ if (dataType instanceof MappedType)
94
+ return this.generateMappedTypeDefinition(file, dataType, forInterface);
95
+ return 'xxx';
96
+ }
97
+ /**
98
+ *
99
+ * @param file
100
+ * @param dataType
101
+ * @param forInterface
102
+ */
103
+ export async function generateComplexTypeDefinition(file, dataType, forInterface) {
104
+ let out = '';
105
+ if (dataType.base) {
106
+ const base = await this.resolveTypeNameOrDef(file, dataType.base, forInterface);
107
+ out += forInterface ? `extends ${base} ` : `${base} & `;
108
+ }
109
+ out += '{\n\n\t';
110
+ for (const field of dataType.own.fields.values()) {
111
+ // Print JSDoc
112
+ let jsDoc = '';
113
+ if (field.description)
114
+ jsDoc += ` * ${field.description}\n`;
115
+ if (field.default)
116
+ jsDoc += ` * @default ` + field.default + '\n';
117
+ if (field.format)
118
+ jsDoc += ` * @format ` + field.format + '\n';
119
+ if (field.exclusive)
120
+ jsDoc += ` * @exclusive\n`;
121
+ if (field.deprecated)
122
+ jsDoc += ` * @deprecated ` + (typeof field.deprecated === 'string' ? field.deprecated : '') + '\n';
123
+ if (jsDoc)
124
+ out += `/**\n${jsDoc}*/\n`;
125
+ // Print field name
126
+ out += `${field.name}${field.required ? '' : '?'}: `;
127
+ if (field.fixed)
128
+ out += `${field.fixed}`;
129
+ else {
130
+ out += await this.resolveTypeNameOrDef(file, field.type) +
131
+ `${field.isArray ? '[]' : ''};\n\n`;
132
+ }
133
+ }
134
+ if (dataType.additionalFields)
135
+ out += '[key: string]: any;\n';
136
+ return out + '\b}';
137
+ }
138
+ /**
139
+ *
140
+ * @param file
141
+ * @param dataType
142
+ */
143
+ export async function generateSimpleTypeDefinition(file, dataType) {
144
+ if (dataType.ctor === Boolean)
145
+ return 'boolean';
146
+ if (dataType.ctor === String)
147
+ return 'string';
148
+ if (dataType.ctor === Number)
149
+ return 'number';
150
+ if (dataType.ctor === Date)
151
+ return 'Date';
152
+ if (dataType.extendsFrom('bigint'))
153
+ return 'Date';
154
+ if (dataType.extendsFrom('object'))
155
+ return 'object';
156
+ return 'any';
157
+ }
158
+ /**
159
+ *
160
+ * @param file
161
+ * @param dataType
162
+ */
163
+ export async function generateEnumTypeDefinition(file, dataType) {
164
+ let out = '{\n\t';
165
+ for (const [k, v] of Object.entries(dataType.values)) {
166
+ // Print JSDoc
167
+ let jsDoc = '';
168
+ if (dataType.meanings[k])
169
+ jsDoc += ` * ${dataType.meanings[k]}\n`;
170
+ if (jsDoc)
171
+ out += `/**\n${jsDoc}*/\n`;
172
+ out += `${k}`;
173
+ if (v)
174
+ out += ' = ' + (typeof v === 'number' ? v : ('"' + ('' + v).replace('"', '\\"')) + '"');
175
+ out += ',\n\n';
176
+ }
177
+ return out + '\b}';
178
+ }
179
+ /**
180
+ *
181
+ * @param file
182
+ * @param dataType
183
+ * @param forInterface
184
+ */
185
+ export async function generateUnionTypeDefinition(file, dataType, forInterface) {
186
+ // let out = '';
187
+ return (await Promise.all(dataType.types
188
+ .map(t => this.resolveTypeNameOrDef(file, t, forInterface)))).join(forInterface ? ', ' : ' & ');
189
+ }
190
+ /**
191
+ *
192
+ * @param file
193
+ * @param dataType
194
+ * @param forInterface
195
+ */
196
+ export async function generateMappedTypeDefinition(file, dataType, forInterface) {
197
+ return (dataType.pick ? 'Pick<' : 'Omit<') +
198
+ (await this.resolveTypeNameOrDef(file, dataType.type, forInterface)) +
199
+ ', ' +
200
+ (dataType.pick || dataType.omit || [])
201
+ .map(x => `'${x}'`).join(' | ') +
202
+ '>';
203
+ }
@@ -0,0 +1,18 @@
1
+ export declare class TsFile {
2
+ filename: string;
3
+ dirname: string;
4
+ importFiles: Record<string, string[]>;
5
+ exportFiles: Record<string, string[]>;
6
+ exportTypes: string[];
7
+ header: string;
8
+ content: string;
9
+ constructor(filename: string);
10
+ addImportPackage: (name: string, types?: string[]) => void;
11
+ addImportFile: (filename: string, types?: string[]) => void;
12
+ addExportFile: (filename: string, types?: string[]) => void;
13
+ generate(options?: {
14
+ importExt?: string;
15
+ }): string;
16
+ }
17
+ export declare function relativePath(from: string, to: string): string;
18
+ export declare function setExt(filename: string, ext: string): string;
@@ -0,0 +1,83 @@
1
+ import path from 'path';
2
+ import flattenText from 'putil-flattentext';
3
+ export class TsFile {
4
+ constructor(filename) {
5
+ this.filename = filename;
6
+ this.importFiles = {};
7
+ this.exportFiles = {};
8
+ this.exportTypes = [];
9
+ this.header = '';
10
+ this.content = '';
11
+ this.addImportPackage = (name, types) => {
12
+ this.importFiles[name] = this.importFiles[name] || [];
13
+ types?.forEach(x => {
14
+ if (!this.importFiles[name].includes(x))
15
+ this.importFiles[name].push(x);
16
+ });
17
+ };
18
+ this.addImportFile = (filename, types) => {
19
+ filename = path.resolve(this.dirname, filename);
20
+ this.importFiles[filename] = this.importFiles[filename] || [];
21
+ types?.forEach(x => {
22
+ if (!this.importFiles[filename].includes(x))
23
+ this.importFiles[filename].push(x);
24
+ });
25
+ };
26
+ this.addExportFile = (filename, types) => {
27
+ filename = path.resolve(this.dirname, filename);
28
+ if (filename.endsWith('.ts') || filename.endsWith('.js'))
29
+ filename = setExt(filename, '');
30
+ this.exportFiles[filename] = this.exportFiles[filename] || [];
31
+ types?.forEach(x => {
32
+ if (!this.exportFiles[filename].includes(x))
33
+ this.exportFiles[filename].push(x);
34
+ });
35
+ };
36
+ this.dirname = path.dirname(filename);
37
+ }
38
+ generate(options) {
39
+ const dirname = path.dirname(this.filename);
40
+ let output = '/* #!oprimp_auto_generated!# !! Do NOT remove this line */\n' +
41
+ (this.header ? flattenText(this.header) + '\n\n' : '\n');
42
+ const importStr = Object.keys(this.importFiles)
43
+ .sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()))
44
+ .map(filename => {
45
+ const types = this.importFiles[filename];
46
+ let relFile = filename;
47
+ if (path.isAbsolute(filename)) {
48
+ relFile = relativePath(dirname, filename);
49
+ if (options?.importExt)
50
+ relFile = setExt(relFile, options.importExt);
51
+ }
52
+ return `import ${types.length ? '{' + types.join(', ') + '} from ' : ''}'${relFile}';`;
53
+ })
54
+ .join('\n');
55
+ if (importStr)
56
+ output += flattenText(importStr) + '\n';
57
+ output += flattenText(this.content);
58
+ const exportStr = Object.keys(this.exportFiles)
59
+ .sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()))
60
+ .map(filename => {
61
+ const types = this.exportFiles[filename];
62
+ let relFile = filename;
63
+ if (path.isAbsolute(filename)) {
64
+ relFile = relativePath(dirname, filename);
65
+ if (options?.importExt)
66
+ relFile = setExt(relFile, options.importExt);
67
+ }
68
+ return `export ${types.length ? '{' + types.join(', ') + '}' : '*'} from '${relFile}';`;
69
+ })
70
+ .join('\n');
71
+ if (exportStr)
72
+ output += flattenText(exportStr) + '\n';
73
+ return output;
74
+ }
75
+ }
76
+ export function relativePath(from, to) {
77
+ const s = path.relative(from, to);
78
+ return s.startsWith('.') ? s : ('./' + s);
79
+ }
80
+ export function setExt(filename, ext) {
81
+ const e = path.extname(filename);
82
+ return filename.substring(0, filename.length - e.length) + (ext ? '.' + ext : '');
83
+ }
package/esm/index.d.ts CHANGED
@@ -1 +1 @@
1
- export * from './oprimp/index.js';
1
+ export * from './api-exporter/index.js';
package/esm/index.js CHANGED
@@ -1 +1 @@
1
- export * from './oprimp/index.js';
1
+ export * from './api-exporter/index.js';
@@ -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;
@@ -4,9 +4,10 @@ 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 { generateService } from './oprimp/generate-service.js';
7
+ import { ApiExporter } from './api-exporter/api-exporter.js';
8
8
  import { getCallerFile } from './utils/get-caller-file.util.js';
9
- const pkgJson = JSON.parse(fs.readFileSync(path.resolve(path.dirname(getCallerFile()), '../package.json'), 'utf-8'));
9
+ const dirname = path.dirname(getCallerFile());
10
+ const pkgJson = JSON.parse(fs.readFileSync(path.resolve(dirname, '../package.json'), 'utf-8'));
10
11
  program
11
12
  .version(pkgJson.version)
12
13
  .argument('<serviceUrl>', 'OPRA service url')
@@ -17,16 +18,14 @@ program
17
18
  .action(async (serviceUrl, outDir, options) => {
18
19
  if (!options.color)
19
20
  chalk.level = 0;
20
- await generateService({
21
+ await ApiExporter.execute({
21
22
  serviceUrl,
23
+ logger: console,
22
24
  outDir,
23
25
  name: options.name,
24
- extension: (options.ext ? '.js' : ''),
25
- fileHeader: '/*\n' +
26
- ' * Generated by OPRA Service Generator \n' +
27
- ' * Version: ' + pkgJson.version + '\n' +
28
- ' * ' + new Date() + '\n' +
29
- ' */'
26
+ importExt: (options.ext ? 'js' : ''),
27
+ fileHeader: '/* Generated by OPRA Service Generator, Version ' + pkgJson.version + '*/\n' +
28
+ '/* eslint-disable import/extensions,simple-import-sort/imports */\n'
30
29
  });
31
30
  console.log(chalk.greenBright('Completed'));
32
31
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opra/cli",
3
- "version": "0.14.2",
3
+ "version": "0.15.0",
4
4
  "description": "Opra CLI tools",
5
5
  "author": "Panates",
6
6
  "license": "MIT",
@@ -20,22 +20,21 @@
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": "NODE_OPTIONS=--experimental-vm-modules npx jest",
24
- "cover": "NODE_OPTIONS=--experimental-vm-modules npx jest --collect-coverage",
23
+ "test": "jest",
24
+ "cover": "jest --collect-coverage",
25
25
  "clean": "npm run clean:src && npm run clean:dist && npm run clean:cover",
26
26
  "clean:src": "ts-cleanup -s src --all",
27
27
  "clean:dist": "rimraf ../../build/cli ../../build/client",
28
28
  "clean:cover": "rimraf ../../coverage/client"
29
29
  },
30
30
  "dependencies": {
31
- "@opra/node-client": "^0.14.0",
31
+ "@opra/node-client": "^0.15.0",
32
32
  "chalk": "^5.2.0",
33
- "commander": "^10.0.0",
33
+ "commander": "^10.0.1",
34
+ "js-string-escape": "^1.0.1",
34
35
  "putil-flattentext": "^2.1.1",
35
- "putil-varhelpers": "^1.6.5",
36
- "js-string-escape": "^1.0.1"
36
+ "putil-varhelpers": "^1.6.5"
37
37
  },
38
- "devDependencies": {},
39
38
  "type": "module",
40
39
  "types": "esm/index.d.ts",
41
40
  "exports": {
@@ -64,4 +63,4 @@
64
63
  "tool",
65
64
  "oprimp"
66
65
  ]
67
- }
66
+ }
@@ -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 = (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;