@opra/cli 0.12.0 → 0.13.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.
- package/bin/oprimp.mjs +1 -1
- package/cjs/oprimp/delete-files.js +2 -0
- package/cjs/oprimp/generate-resoruces.js +72 -0
- package/cjs/oprimp/generate-service.js +4 -21
- package/cjs/oprimp/generate-types.js +29 -11
- package/cjs/oprimp.js +2 -0
- package/cjs/utils/ts-file.js +10 -6
- package/esm/interfaces/service-generation-context.interface.d.ts +1 -3
- package/esm/oprimp/delete-files.js +2 -0
- package/esm/oprimp/generate-resoruces.d.ts +2 -0
- package/esm/oprimp/generate-resoruces.js +67 -0
- package/esm/oprimp/generate-service.d.ts +1 -0
- package/esm/oprimp/generate-service.js +4 -21
- package/esm/oprimp/generate-types.js +29 -11
- package/esm/oprimp.js +2 -0
- package/esm/utils/ts-file.d.ts +2 -2
- package/esm/utils/ts-file.js +10 -6
- package/package.json +4 -5
package/bin/oprimp.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import '../esm/
|
|
2
|
+
import '../esm/oprimp.js';
|
|
@@ -5,6 +5,8 @@ const tslib_1 = require("tslib");
|
|
|
5
5
|
const fs_1 = tslib_1.__importDefault(require("fs"));
|
|
6
6
|
const path_1 = tslib_1.__importDefault(require("path"));
|
|
7
7
|
function deleteFiles(dirname) {
|
|
8
|
+
if (!fs_1.default.existsSync(dirname))
|
|
9
|
+
return;
|
|
8
10
|
const files = fs_1.default.readdirSync(dirname);
|
|
9
11
|
for (const f of files) {
|
|
10
12
|
const filename = path_1.default.join(dirname, f);
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateResources = 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
|
+
async function generateResources(ctx) {
|
|
12
|
+
const targetDir = path_1.default.join(ctx.absoluteDir, 'resources');
|
|
13
|
+
ctx.logger.log(chalk_1.default.yellow('Generating resources'));
|
|
14
|
+
const resourcesTs = new ts_file_js_1.TsFile();
|
|
15
|
+
resourcesTs.header = ctx.fileHeader;
|
|
16
|
+
let i = 0;
|
|
17
|
+
fs_1.default.mkdirSync(targetDir, { recursive: true });
|
|
18
|
+
const resourceNames = Array.from(ctx.document.resources.keys()).sort();
|
|
19
|
+
for (const resourceName of resourceNames) {
|
|
20
|
+
const resource = ctx.document.getResource(resourceName);
|
|
21
|
+
const tsFile = new ts_file_js_1.TsFile();
|
|
22
|
+
tsFile.header = ctx.fileHeader;
|
|
23
|
+
tsFile.content = `\n/**\n * ${(0, string_utils_js_1.wrapJSDocString)(resource.description || resource.name)}
|
|
24
|
+
* @type ${resource.name}
|
|
25
|
+
* @kind ${resource.kind}
|
|
26
|
+
* @url ${(0, common_1.joinPath)(ctx.serviceUrl, '$metadata/resources/' + resource.name)}
|
|
27
|
+
*/\n`;
|
|
28
|
+
const filename = `./resources/${resource.name}`;
|
|
29
|
+
if (resource instanceof common_1.CollectionResourceInfo) {
|
|
30
|
+
await generateCollectionResource(ctx, resource, tsFile);
|
|
31
|
+
await tsFile.writeFile(ctx, path_1.default.join(targetDir, resource.name + '.ts'));
|
|
32
|
+
resourcesTs.addExport(`${filename}` + ctx.extension);
|
|
33
|
+
i++;
|
|
34
|
+
}
|
|
35
|
+
else if (resource instanceof common_1.SingletonResourceInfo) {
|
|
36
|
+
await generateSingletonResource(ctx, resource, tsFile);
|
|
37
|
+
await tsFile.writeFile(ctx, path_1.default.join(targetDir, resource.name + '.ts'));
|
|
38
|
+
resourcesTs.addExport(`${filename}${ctx.extension}`);
|
|
39
|
+
i++;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
if (i) {
|
|
43
|
+
await resourcesTs.writeFile(ctx, path_1.default.join(ctx.absoluteDir, 'resources.ts'));
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
exports.generateResources = generateResources;
|
|
47
|
+
async function generateCollectionResource(ctx, resource, tsFile) {
|
|
48
|
+
tsFile.header = ctx.fileHeader;
|
|
49
|
+
tsFile.addImport('@opra/client', 'OpraHttpClient', 'HttpCollectionService');
|
|
50
|
+
tsFile.addImport('../types/' + resource.dataType.name + ctx.extension, resource.dataType.name);
|
|
51
|
+
const methods = resource.getHandlerNames()
|
|
52
|
+
.filter(x => x !== 'count')
|
|
53
|
+
.map(x => `'${x}'`).join(' | ');
|
|
54
|
+
tsFile.content = `
|
|
55
|
+
export function ${resource.name}(
|
|
56
|
+
client: OpraHttpClient
|
|
57
|
+
): Pick<HttpCollectionService<${resource.dataType.name}, never>, ${methods}> {
|
|
58
|
+
return client.collection('${resource.name}');
|
|
59
|
+
}
|
|
60
|
+
`;
|
|
61
|
+
}
|
|
62
|
+
async function generateSingletonResource(ctx, resource, tsFile) {
|
|
63
|
+
tsFile.header = ctx.fileHeader;
|
|
64
|
+
tsFile.addImport('@opra/client', 'OpraHttpClient', 'HttpSingletonService');
|
|
65
|
+
tsFile.addImport('../types/' + resource.dataType.name + ctx.extension, resource.dataType.name);
|
|
66
|
+
const methods = resource.getHandlerNames().map(x => `'${x}'`).join(' | ');
|
|
67
|
+
tsFile.content = `
|
|
68
|
+
export function ${resource.name}(client: OpraHttpClient): Pick<HttpSingletonService<${resource.dataType.name}, never>, ${methods}> {
|
|
69
|
+
return client.singleton('${resource.name}');
|
|
70
|
+
}
|
|
71
|
+
`;
|
|
72
|
+
}
|
|
@@ -5,15 +5,9 @@ const tslib_1 = require("tslib");
|
|
|
5
5
|
const fs = tslib_1.__importStar(require("fs"));
|
|
6
6
|
const path_1 = tslib_1.__importDefault(require("path"));
|
|
7
7
|
const process = tslib_1.__importStar(require("process"));
|
|
8
|
-
const ts_file_js_1 = require("../utils/ts-file.js");
|
|
9
8
|
const file_writer_js_1 = require("./file-writer.js");
|
|
9
|
+
const generate_resoruces_js_1 = require("./generate-resoruces.js");
|
|
10
10
|
const generate_types_js_1 = require("./generate-types.js");
|
|
11
|
-
const builtinsMap = {
|
|
12
|
-
base64Binary: 'Buffer',
|
|
13
|
-
dateString: 'string',
|
|
14
|
-
guid: 'string',
|
|
15
|
-
integer: 'number'
|
|
16
|
-
};
|
|
17
11
|
async function generateService(config) {
|
|
18
12
|
const cwd = config.cwd || process.cwd();
|
|
19
13
|
const logger = config.logger || console;
|
|
@@ -25,22 +19,11 @@ async function generateService(config) {
|
|
|
25
19
|
relativeDir: config.outDir,
|
|
26
20
|
absoluteDir: path_1.default.resolve(cwd, config.outDir),
|
|
27
21
|
fileHeader: config.fileHeader || '',
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
builtins: {},
|
|
22
|
+
extension: config.extension,
|
|
23
|
+
writer: config.writer || new file_writer_js_1.FileWriter()
|
|
31
24
|
};
|
|
32
25
|
fs.mkdirSync(ctx.absoluteDir, { recursive: true });
|
|
33
26
|
await (0, generate_types_js_1.generateTypes)(ctx);
|
|
34
|
-
|
|
35
|
-
builtinsTs.header = ctx.fileHeader;
|
|
36
|
-
builtinsTs.content = Object.keys(ctx.builtins)
|
|
37
|
-
.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()))
|
|
38
|
-
.map(s => `export type ${s} = ${builtinsMap[s] || 'any'};`)
|
|
39
|
-
.join('\n');
|
|
40
|
-
if (builtinsTs.content) {
|
|
41
|
-
await builtinsTs.writeFile(ctx, path_1.default.join(ctx.absoluteDir, 'builtins.ts'));
|
|
42
|
-
ctx.indexTs.addExport('./builtins.js');
|
|
43
|
-
}
|
|
44
|
-
await ctx.indexTs.writeFile(ctx, path_1.default.join(ctx.absoluteDir, 'index.ts'));
|
|
27
|
+
await (0, generate_resoruces_js_1.generateResources)(ctx);
|
|
45
28
|
}
|
|
46
29
|
exports.generateService = generateService;
|
|
@@ -8,15 +8,32 @@ const path_1 = tslib_1.__importDefault(require("path"));
|
|
|
8
8
|
const common_1 = require("@opra/common");
|
|
9
9
|
const string_utils_js_1 = require("../utils/string-utils.js");
|
|
10
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
|
+
};
|
|
11
18
|
async function generateTypes(ctx) {
|
|
12
19
|
const targetDir = path_1.default.join(ctx.absoluteDir, 'types');
|
|
13
20
|
ctx.logger.log(chalk_1.default.yellow('Generating 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;
|
|
14
26
|
fs_1.default.mkdirSync(targetDir, { recursive: true });
|
|
15
27
|
const typeNames = Array.from(ctx.document.types.keys()).sort();
|
|
16
28
|
for (const typeName of typeNames) {
|
|
17
29
|
const dataType = ctx.document.getDataType(typeName);
|
|
18
|
-
if (dataType.isBuiltin)
|
|
30
|
+
if (dataType.isBuiltin) {
|
|
31
|
+
if (!builtinsMap[dataType.name])
|
|
32
|
+
continue;
|
|
33
|
+
typesTs.addExport('./types/builtins.js');
|
|
34
|
+
builtinsTs.content += `export type ${dataType.name} = ${builtinsMap[dataType.name]};\n`;
|
|
19
35
|
continue;
|
|
36
|
+
}
|
|
20
37
|
const tsFile = new ts_file_js_1.TsFile();
|
|
21
38
|
tsFile.header = ctx.fileHeader;
|
|
22
39
|
tsFile.content = `\n/**\n * ${(0, string_utils_js_1.wrapJSDocString)(dataType.description || dataType.name)}
|
|
@@ -24,16 +41,21 @@ async function generateTypes(ctx) {
|
|
|
24
41
|
* @kind ${dataType.kind}
|
|
25
42
|
* @url ${(0, common_1.joinPath)(ctx.serviceUrl, '$metadata/types/' + dataType.name)}
|
|
26
43
|
*/\n`;
|
|
44
|
+
const filename = `./types/${dataType.name}`;
|
|
27
45
|
if (dataType instanceof common_1.ComplexType) {
|
|
28
46
|
await generateComplexType(ctx, dataType, tsFile);
|
|
29
47
|
await tsFile.writeFile(ctx, path_1.default.join(targetDir, dataType.name + '.ts'));
|
|
48
|
+
typesTs.addExport(`${filename}` + ctx.extension);
|
|
49
|
+
i++;
|
|
30
50
|
}
|
|
31
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
|
+
}
|
|
32
56
|
}
|
|
33
57
|
exports.generateTypes = generateTypes;
|
|
34
58
|
async function generateComplexType(ctx, dataType, tsFile) {
|
|
35
|
-
const filename = `./types/${dataType.name}`;
|
|
36
|
-
ctx.indexTs.addExport(`${filename}.js`);
|
|
37
59
|
tsFile.header = ctx.fileHeader;
|
|
38
60
|
tsFile.content = `
|
|
39
61
|
export class ${dataType.name} {
|
|
@@ -50,7 +72,7 @@ interface I${dataType.name}`;
|
|
|
50
72
|
if (dataType.extends) {
|
|
51
73
|
tsFile.content += ' extends ' +
|
|
52
74
|
dataType.extends.map(ex => {
|
|
53
|
-
tsFile.addImport('./' + ex.type +
|
|
75
|
+
tsFile.addImport('./' + ex.type + ctx.extension, ex.type);
|
|
54
76
|
let s = '';
|
|
55
77
|
if (ex.omit)
|
|
56
78
|
s += 'Omit<';
|
|
@@ -66,16 +88,12 @@ interface I${dataType.name}`;
|
|
|
66
88
|
}
|
|
67
89
|
const getTypeName = (dt) => {
|
|
68
90
|
if (dt.isBuiltin) {
|
|
69
|
-
if (dt.name
|
|
70
|
-
dt.name === 'boolean' || dt.name === 'object')
|
|
91
|
+
if (!builtinsMap[dt.name])
|
|
71
92
|
return dt.name;
|
|
72
|
-
|
|
73
|
-
return 'Date';
|
|
74
|
-
tsFile.addImport('../builtins.js', dt.name);
|
|
75
|
-
ctx.builtins[dt.name] = true;
|
|
93
|
+
tsFile.addImport('./builtins' + ctx.extension, dt.name);
|
|
76
94
|
return dt.name;
|
|
77
95
|
}
|
|
78
|
-
tsFile.addImport('./' + dt.name +
|
|
96
|
+
tsFile.addImport('./' + dt.name + ctx.extension, dt.name);
|
|
79
97
|
return dt.name;
|
|
80
98
|
};
|
|
81
99
|
tsFile.content += ' {\n\t';
|
package/cjs/oprimp.js
CHANGED
|
@@ -17,6 +17,7 @@ commander_1.program
|
|
|
17
17
|
.argument('<serviceUrl>', 'OPRA service url')
|
|
18
18
|
.argument('<outDir>', 'Output directory')
|
|
19
19
|
.option('--no-color', 'Disables colors in logs messages')
|
|
20
|
+
.option('-e, --extension <extension>', 'File extensions of imports')
|
|
20
21
|
.action(async (serviceUrl, outDir, options) => {
|
|
21
22
|
if (!options.color)
|
|
22
23
|
chalk_1.default.level = 0;
|
|
@@ -30,6 +31,7 @@ commander_1.program
|
|
|
30
31
|
serviceUrl,
|
|
31
32
|
document: metadata,
|
|
32
33
|
outDir,
|
|
34
|
+
extension: (options.extension ? '.' + options.extension : ''),
|
|
33
35
|
fileHeader: '/*\n' +
|
|
34
36
|
' * Generated by OPRA Service Generator \n' +
|
|
35
37
|
' * Version: ' + pkgJson.version + '\n' +
|
package/cjs/utils/ts-file.js
CHANGED
|
@@ -11,15 +11,19 @@ class TsFile {
|
|
|
11
11
|
this.exports = {};
|
|
12
12
|
this.header = '';
|
|
13
13
|
this.content = '';
|
|
14
|
-
this.addImport = (filename, imported) => {
|
|
14
|
+
this.addImport = (filename, ...imported) => {
|
|
15
15
|
this.imports[filename] = this.imports[filename] || [];
|
|
16
|
-
|
|
17
|
-
this.imports[filename].
|
|
16
|
+
imported.forEach(x => {
|
|
17
|
+
if (!this.imports[filename].includes(x))
|
|
18
|
+
this.imports[filename].push(x);
|
|
19
|
+
});
|
|
18
20
|
};
|
|
19
|
-
this.addExport = (filename, exported) => {
|
|
21
|
+
this.addExport = (filename, ...exported) => {
|
|
20
22
|
this.exports[filename] = this.exports[filename] || [];
|
|
21
|
-
|
|
22
|
-
this.exports[filename].
|
|
23
|
+
exported.forEach(x => {
|
|
24
|
+
if (!this.exports[filename].includes(x))
|
|
25
|
+
this.exports[filename].push(x);
|
|
26
|
+
});
|
|
23
27
|
};
|
|
24
28
|
}
|
|
25
29
|
generate() {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { OpraDocument } from '@opra/common';
|
|
2
|
-
import { TsFile } from '../utils/ts-file.js';
|
|
3
2
|
import { IFileWriter } from './file-writer.interface.js';
|
|
4
3
|
import { ILogger } from './logger.interface.js';
|
|
5
4
|
export interface ServiceGenerationContext {
|
|
@@ -10,7 +9,6 @@ export interface ServiceGenerationContext {
|
|
|
10
9
|
relativeDir: string;
|
|
11
10
|
absoluteDir: string;
|
|
12
11
|
fileHeader: string;
|
|
12
|
+
extension?: string;
|
|
13
13
|
writer: IFileWriter;
|
|
14
|
-
indexTs: TsFile;
|
|
15
|
-
builtins: any;
|
|
16
14
|
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { CollectionResourceInfo, joinPath, SingletonResourceInfo } from '@opra/common';
|
|
5
|
+
import { wrapJSDocString } from '../utils/string-utils.js';
|
|
6
|
+
import { TsFile } from '../utils/ts-file.js';
|
|
7
|
+
export async function generateResources(ctx) {
|
|
8
|
+
const targetDir = path.join(ctx.absoluteDir, 'resources');
|
|
9
|
+
ctx.logger.log(chalk.yellow('Generating resources'));
|
|
10
|
+
const resourcesTs = new TsFile();
|
|
11
|
+
resourcesTs.header = ctx.fileHeader;
|
|
12
|
+
let i = 0;
|
|
13
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
14
|
+
const resourceNames = Array.from(ctx.document.resources.keys()).sort();
|
|
15
|
+
for (const resourceName of resourceNames) {
|
|
16
|
+
const resource = ctx.document.getResource(resourceName);
|
|
17
|
+
const tsFile = new TsFile();
|
|
18
|
+
tsFile.header = ctx.fileHeader;
|
|
19
|
+
tsFile.content = `\n/**\n * ${wrapJSDocString(resource.description || resource.name)}
|
|
20
|
+
* @type ${resource.name}
|
|
21
|
+
* @kind ${resource.kind}
|
|
22
|
+
* @url ${joinPath(ctx.serviceUrl, '$metadata/resources/' + resource.name)}
|
|
23
|
+
*/\n`;
|
|
24
|
+
const filename = `./resources/${resource.name}`;
|
|
25
|
+
if (resource instanceof CollectionResourceInfo) {
|
|
26
|
+
await generateCollectionResource(ctx, resource, tsFile);
|
|
27
|
+
await tsFile.writeFile(ctx, path.join(targetDir, resource.name + '.ts'));
|
|
28
|
+
resourcesTs.addExport(`${filename}` + ctx.extension);
|
|
29
|
+
i++;
|
|
30
|
+
}
|
|
31
|
+
else if (resource instanceof SingletonResourceInfo) {
|
|
32
|
+
await generateSingletonResource(ctx, resource, tsFile);
|
|
33
|
+
await tsFile.writeFile(ctx, path.join(targetDir, resource.name + '.ts'));
|
|
34
|
+
resourcesTs.addExport(`${filename}${ctx.extension}`);
|
|
35
|
+
i++;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (i) {
|
|
39
|
+
await resourcesTs.writeFile(ctx, path.join(ctx.absoluteDir, 'resources.ts'));
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
async function generateCollectionResource(ctx, resource, tsFile) {
|
|
43
|
+
tsFile.header = ctx.fileHeader;
|
|
44
|
+
tsFile.addImport('@opra/client', 'OpraHttpClient', 'HttpCollectionService');
|
|
45
|
+
tsFile.addImport('../types/' + resource.dataType.name + ctx.extension, resource.dataType.name);
|
|
46
|
+
const methods = resource.getHandlerNames()
|
|
47
|
+
.filter(x => x !== 'count')
|
|
48
|
+
.map(x => `'${x}'`).join(' | ');
|
|
49
|
+
tsFile.content = `
|
|
50
|
+
export function ${resource.name}(
|
|
51
|
+
client: OpraHttpClient
|
|
52
|
+
): Pick<HttpCollectionService<${resource.dataType.name}, never>, ${methods}> {
|
|
53
|
+
return client.collection('${resource.name}');
|
|
54
|
+
}
|
|
55
|
+
`;
|
|
56
|
+
}
|
|
57
|
+
async function generateSingletonResource(ctx, resource, tsFile) {
|
|
58
|
+
tsFile.header = ctx.fileHeader;
|
|
59
|
+
tsFile.addImport('@opra/client', 'OpraHttpClient', 'HttpSingletonService');
|
|
60
|
+
tsFile.addImport('../types/' + resource.dataType.name + ctx.extension, resource.dataType.name);
|
|
61
|
+
const methods = resource.getHandlerNames().map(x => `'${x}'`).join(' | ');
|
|
62
|
+
tsFile.content = `
|
|
63
|
+
export function ${resource.name}(client: OpraHttpClient): Pick<HttpSingletonService<${resource.dataType.name}, never>, ${methods}> {
|
|
64
|
+
return client.singleton('${resource.name}');
|
|
65
|
+
}
|
|
66
|
+
`;
|
|
67
|
+
}
|
|
@@ -1,15 +1,9 @@
|
|
|
1
1
|
import * as fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import * as process from 'process';
|
|
4
|
-
import { TsFile } from '../utils/ts-file.js';
|
|
5
4
|
import { FileWriter } from './file-writer.js';
|
|
5
|
+
import { generateResources } from './generate-resoruces.js';
|
|
6
6
|
import { generateTypes } from './generate-types.js';
|
|
7
|
-
const builtinsMap = {
|
|
8
|
-
base64Binary: 'Buffer',
|
|
9
|
-
dateString: 'string',
|
|
10
|
-
guid: 'string',
|
|
11
|
-
integer: 'number'
|
|
12
|
-
};
|
|
13
7
|
export async function generateService(config) {
|
|
14
8
|
const cwd = config.cwd || process.cwd();
|
|
15
9
|
const logger = config.logger || console;
|
|
@@ -21,21 +15,10 @@ export async function generateService(config) {
|
|
|
21
15
|
relativeDir: config.outDir,
|
|
22
16
|
absoluteDir: path.resolve(cwd, config.outDir),
|
|
23
17
|
fileHeader: config.fileHeader || '',
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
builtins: {},
|
|
18
|
+
extension: config.extension,
|
|
19
|
+
writer: config.writer || new FileWriter()
|
|
27
20
|
};
|
|
28
21
|
fs.mkdirSync(ctx.absoluteDir, { recursive: true });
|
|
29
22
|
await generateTypes(ctx);
|
|
30
|
-
|
|
31
|
-
builtinsTs.header = ctx.fileHeader;
|
|
32
|
-
builtinsTs.content = Object.keys(ctx.builtins)
|
|
33
|
-
.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()))
|
|
34
|
-
.map(s => `export type ${s} = ${builtinsMap[s] || 'any'};`)
|
|
35
|
-
.join('\n');
|
|
36
|
-
if (builtinsTs.content) {
|
|
37
|
-
await builtinsTs.writeFile(ctx, path.join(ctx.absoluteDir, 'builtins.ts'));
|
|
38
|
-
ctx.indexTs.addExport('./builtins.js');
|
|
39
|
-
}
|
|
40
|
-
await ctx.indexTs.writeFile(ctx, path.join(ctx.absoluteDir, 'index.ts'));
|
|
23
|
+
await generateResources(ctx);
|
|
41
24
|
}
|
|
@@ -4,15 +4,32 @@ import path from 'path';
|
|
|
4
4
|
import { ComplexType, joinPath, UnionType } from '@opra/common';
|
|
5
5
|
import { wrapJSDocString } from '../utils/string-utils.js';
|
|
6
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
|
+
};
|
|
7
14
|
export async function generateTypes(ctx) {
|
|
8
15
|
const targetDir = path.join(ctx.absoluteDir, 'types');
|
|
9
16
|
ctx.logger.log(chalk.yellow('Generating 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;
|
|
10
22
|
fs.mkdirSync(targetDir, { recursive: true });
|
|
11
23
|
const typeNames = Array.from(ctx.document.types.keys()).sort();
|
|
12
24
|
for (const typeName of typeNames) {
|
|
13
25
|
const dataType = ctx.document.getDataType(typeName);
|
|
14
|
-
if (dataType.isBuiltin)
|
|
26
|
+
if (dataType.isBuiltin) {
|
|
27
|
+
if (!builtinsMap[dataType.name])
|
|
28
|
+
continue;
|
|
29
|
+
typesTs.addExport('./types/builtins.js');
|
|
30
|
+
builtinsTs.content += `export type ${dataType.name} = ${builtinsMap[dataType.name]};\n`;
|
|
15
31
|
continue;
|
|
32
|
+
}
|
|
16
33
|
const tsFile = new TsFile();
|
|
17
34
|
tsFile.header = ctx.fileHeader;
|
|
18
35
|
tsFile.content = `\n/**\n * ${wrapJSDocString(dataType.description || dataType.name)}
|
|
@@ -20,15 +37,20 @@ export async function generateTypes(ctx) {
|
|
|
20
37
|
* @kind ${dataType.kind}
|
|
21
38
|
* @url ${joinPath(ctx.serviceUrl, '$metadata/types/' + dataType.name)}
|
|
22
39
|
*/\n`;
|
|
40
|
+
const filename = `./types/${dataType.name}`;
|
|
23
41
|
if (dataType instanceof ComplexType) {
|
|
24
42
|
await generateComplexType(ctx, dataType, tsFile);
|
|
25
43
|
await tsFile.writeFile(ctx, path.join(targetDir, dataType.name + '.ts'));
|
|
44
|
+
typesTs.addExport(`${filename}` + ctx.extension);
|
|
45
|
+
i++;
|
|
26
46
|
}
|
|
27
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
|
+
}
|
|
28
52
|
}
|
|
29
53
|
async function generateComplexType(ctx, dataType, tsFile) {
|
|
30
|
-
const filename = `./types/${dataType.name}`;
|
|
31
|
-
ctx.indexTs.addExport(`${filename}.js`);
|
|
32
54
|
tsFile.header = ctx.fileHeader;
|
|
33
55
|
tsFile.content = `
|
|
34
56
|
export class ${dataType.name} {
|
|
@@ -45,7 +67,7 @@ interface I${dataType.name}`;
|
|
|
45
67
|
if (dataType.extends) {
|
|
46
68
|
tsFile.content += ' extends ' +
|
|
47
69
|
dataType.extends.map(ex => {
|
|
48
|
-
tsFile.addImport('./' + ex.type +
|
|
70
|
+
tsFile.addImport('./' + ex.type + ctx.extension, ex.type);
|
|
49
71
|
let s = '';
|
|
50
72
|
if (ex.omit)
|
|
51
73
|
s += 'Omit<';
|
|
@@ -61,16 +83,12 @@ interface I${dataType.name}`;
|
|
|
61
83
|
}
|
|
62
84
|
const getTypeName = (dt) => {
|
|
63
85
|
if (dt.isBuiltin) {
|
|
64
|
-
if (dt.name
|
|
65
|
-
dt.name === 'boolean' || dt.name === 'object')
|
|
86
|
+
if (!builtinsMap[dt.name])
|
|
66
87
|
return dt.name;
|
|
67
|
-
|
|
68
|
-
return 'Date';
|
|
69
|
-
tsFile.addImport('../builtins.js', dt.name);
|
|
70
|
-
ctx.builtins[dt.name] = true;
|
|
88
|
+
tsFile.addImport('./builtins' + ctx.extension, dt.name);
|
|
71
89
|
return dt.name;
|
|
72
90
|
}
|
|
73
|
-
tsFile.addImport('./' + dt.name +
|
|
91
|
+
tsFile.addImport('./' + dt.name + ctx.extension, dt.name);
|
|
74
92
|
return dt.name;
|
|
75
93
|
};
|
|
76
94
|
tsFile.content += ' {\n\t';
|
package/esm/oprimp.js
CHANGED
|
@@ -14,6 +14,7 @@ program
|
|
|
14
14
|
.argument('<serviceUrl>', 'OPRA service url')
|
|
15
15
|
.argument('<outDir>', 'Output directory')
|
|
16
16
|
.option('--no-color', 'Disables colors in logs messages')
|
|
17
|
+
.option('-e, --extension <extension>', 'File extensions of imports')
|
|
17
18
|
.action(async (serviceUrl, outDir, options) => {
|
|
18
19
|
if (!options.color)
|
|
19
20
|
chalk.level = 0;
|
|
@@ -27,6 +28,7 @@ program
|
|
|
27
28
|
serviceUrl,
|
|
28
29
|
document: metadata,
|
|
29
30
|
outDir,
|
|
31
|
+
extension: (options.extension ? '.' + options.extension : ''),
|
|
30
32
|
fileHeader: '/*\n' +
|
|
31
33
|
' * Generated by OPRA Service Generator \n' +
|
|
32
34
|
' * Version: ' + pkgJson.version + '\n' +
|
package/esm/utils/ts-file.d.ts
CHANGED
|
@@ -4,8 +4,8 @@ export declare class TsFile {
|
|
|
4
4
|
exports: Record<string, string[]>;
|
|
5
5
|
header: string;
|
|
6
6
|
content: string;
|
|
7
|
-
addImport: (filename: string, imported: string) => void;
|
|
8
|
-
addExport: (filename: string, exported
|
|
7
|
+
addImport: (filename: string, ...imported: string[]) => void;
|
|
8
|
+
addExport: (filename: string, ...exported: string[]) => void;
|
|
9
9
|
generate(): string;
|
|
10
10
|
writeFile(ctx: ServiceGenerationContext, filename: string): Promise<void>;
|
|
11
11
|
}
|
package/esm/utils/ts-file.js
CHANGED
|
@@ -7,15 +7,19 @@ export class TsFile {
|
|
|
7
7
|
this.exports = {};
|
|
8
8
|
this.header = '';
|
|
9
9
|
this.content = '';
|
|
10
|
-
this.addImport = (filename, imported) => {
|
|
10
|
+
this.addImport = (filename, ...imported) => {
|
|
11
11
|
this.imports[filename] = this.imports[filename] || [];
|
|
12
|
-
|
|
13
|
-
this.imports[filename].
|
|
12
|
+
imported.forEach(x => {
|
|
13
|
+
if (!this.imports[filename].includes(x))
|
|
14
|
+
this.imports[filename].push(x);
|
|
15
|
+
});
|
|
14
16
|
};
|
|
15
|
-
this.addExport = (filename, exported) => {
|
|
17
|
+
this.addExport = (filename, ...exported) => {
|
|
16
18
|
this.exports[filename] = this.exports[filename] || [];
|
|
17
|
-
|
|
18
|
-
this.exports[filename].
|
|
19
|
+
exported.forEach(x => {
|
|
20
|
+
if (!this.exports[filename].includes(x))
|
|
21
|
+
this.exports[filename].push(x);
|
|
22
|
+
});
|
|
19
23
|
};
|
|
20
24
|
}
|
|
21
25
|
generate() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opra/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "Opra CLI tools",
|
|
5
5
|
"author": "Panates",
|
|
6
6
|
"license": "MIT",
|
|
@@ -28,14 +28,13 @@
|
|
|
28
28
|
"clean:cover": "rimraf ../../coverage/client"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@opra/node-client": "^0.
|
|
31
|
+
"@opra/node-client": "^0.13.0",
|
|
32
32
|
"chalk": "^5.2.0",
|
|
33
33
|
"commander": "^10.0.0",
|
|
34
34
|
"putil-flattentext": "^2.1.1",
|
|
35
35
|
"js-string-escape": "^1.0.1"
|
|
36
36
|
},
|
|
37
|
-
"devDependencies": {
|
|
38
|
-
},
|
|
37
|
+
"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
|
+
}
|