datagrok-tools 4.14.1 → 4.14.3
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/CHANGELOG.md +7 -0
- package/bin/commands/api.js +67 -34
- package/bin/commands/check.js +3 -2
- package/bin/commands/help.js +3 -1
- package/bin/commands/link.js +96 -18
- package/bin/utils/func-generation.js +49 -2
- package/bin/utils/utils.js +20 -3
- package/package.json +1 -1
- package/plugins/func-gen-plugin.js +209 -131
package/CHANGELOG.md
CHANGED
package/bin/commands/api.js
CHANGED
|
@@ -12,18 +12,24 @@ var utils = _interopRequireWildcard(require("../utils/utils"));
|
|
|
12
12
|
var color = _interopRequireWildcard(require("../utils/color-utils"));
|
|
13
13
|
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
14
14
|
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
15
|
+
const sep = '\n';
|
|
16
|
+
const packageFuncDirs = ['package.ts', 'package.g.ts'];
|
|
17
|
+
const apiFile = 'package-api.ts';
|
|
18
|
+
const curDir = process.cwd();
|
|
19
|
+
const srcDir = _path.default.join(curDir, 'src');
|
|
20
|
+
const funcFilePath = _path.default.join(_fs.default.existsSync(srcDir) ? srcDir : curDir, apiFile);
|
|
21
|
+
const packagePath = _path.default.join(curDir, 'package.json');
|
|
22
|
+
const names = new Set();
|
|
23
|
+
const _package = JSON.parse(_fs.default.readFileSync(packagePath, {
|
|
24
|
+
encoding: 'utf-8'
|
|
25
|
+
}));
|
|
15
26
|
function generateQueryWrappers() {
|
|
16
|
-
const curDir = process.cwd();
|
|
17
27
|
const queriesDir = _path.default.join(curDir, 'queries');
|
|
18
28
|
if (!_fs.default.existsSync(queriesDir)) {
|
|
19
29
|
color.warn(`Directory ${queriesDir} not found`);
|
|
20
30
|
console.log('Skipping API generation for queries...');
|
|
21
31
|
return;
|
|
22
32
|
}
|
|
23
|
-
const packagePath = _path.default.join(curDir, 'package.json');
|
|
24
|
-
const _package = JSON.parse(_fs.default.readFileSync(packagePath, {
|
|
25
|
-
encoding: 'utf-8'
|
|
26
|
-
}));
|
|
27
33
|
const files = _ignoreWalk.default.sync({
|
|
28
34
|
path: './queries',
|
|
29
35
|
ignoreFiles: ['.npmignore', '.gitignore']
|
|
@@ -34,44 +40,30 @@ function generateQueryWrappers() {
|
|
|
34
40
|
const filepath = _path.default.join(queriesDir, file);
|
|
35
41
|
const script = _fs.default.readFileSync(filepath, 'utf8');
|
|
36
42
|
if (!script) continue;
|
|
37
|
-
const queries = script.split(
|
|
43
|
+
const queries = script.split(/--\s*end/).map(q => q.trim()).filter(q => q.length > 0);
|
|
38
44
|
for (const q of queries) {
|
|
39
45
|
const name = utils.getScriptName(q, utils.commentMap[utils.queryExtension]);
|
|
40
46
|
if (!name) continue;
|
|
47
|
+
checkNameColision(name);
|
|
41
48
|
const tb = new utils.TemplateBuilder(utils.queryWrapperTemplate).replace('FUNC_NAME', name).replace('FUNC_NAME_LOWERCASE', name).replace('PACKAGE_NAMESPACE', _package.name);
|
|
49
|
+
const description = utils.getScriptDescription(q, utils.commentMap[utils.queryExtension]);
|
|
42
50
|
const inputs = utils.getScriptInputs(q, utils.commentMap[utils.queryExtension]);
|
|
43
51
|
const outputType = utils.getScriptOutputType(q, utils.commentMap[utils.queryExtension]);
|
|
44
|
-
tb.replace('PARAMS_OBJECT', inputs).replace('TYPED_PARAMS', inputs)
|
|
45
|
-
|
|
46
|
-
.replace('OUTPUT_TYPE', outputType === 'void' ? utils.dgToTsTypeMap['dataframe'] : outputType);
|
|
47
|
-
wrappers.push(tb.build());
|
|
52
|
+
tb.replace('PARAMS_OBJECT', inputs).replace('TYPED_PARAMS', inputs).replace('FUNC_DESCRIPTION', description).replace('OUTPUT_TYPE', outputType === 'void' ? utils.dgToTsTypeMap['dataframe'] : outputType);
|
|
53
|
+
wrappers.push(tb.build(1));
|
|
48
54
|
}
|
|
49
55
|
}
|
|
50
|
-
|
|
51
|
-
const queryFileName = 'queries-api.ts';
|
|
52
|
-
const queryFilePath = _path.default.join(_fs.default.existsSync(srcDir) ? srcDir : curDir, queryFileName);
|
|
53
|
-
if (_fs.default.existsSync(queryFilePath)) {
|
|
54
|
-
color.warn(`The file ${queryFilePath} already exists`);
|
|
55
|
-
console.log('Rewriting its contents...');
|
|
56
|
-
}
|
|
57
|
-
const sep = '\n';
|
|
58
|
-
_fs.default.writeFileSync(queryFilePath, utils.dgImports + sep + wrappers.join(sep.repeat(2)) + sep, 'utf8');
|
|
59
|
-
color.success(`Successfully generated file ${queryFileName}${sep}`);
|
|
56
|
+
saveWrappersToFile('queries', wrappers);
|
|
60
57
|
}
|
|
61
58
|
function generateScriptWrappers() {
|
|
62
|
-
const curDir = process.cwd();
|
|
63
59
|
const scriptsDir = _path.default.join(curDir, 'scripts');
|
|
64
60
|
if (!_fs.default.existsSync(scriptsDir)) {
|
|
65
61
|
color.warn(`Directory ${scriptsDir} not found`);
|
|
66
62
|
console.log('Skipping API generation for scripts...');
|
|
67
63
|
return;
|
|
68
64
|
}
|
|
69
|
-
const packagePath = _path.default.join(curDir, 'package.json');
|
|
70
|
-
const _package = JSON.parse(_fs.default.readFileSync(packagePath, {
|
|
71
|
-
encoding: 'utf-8'
|
|
72
|
-
}));
|
|
73
65
|
const files = _ignoreWalk.default.sync({
|
|
74
|
-
path:
|
|
66
|
+
path: scriptsDir,
|
|
75
67
|
ignoreFiles: ['.npmignore', '.gitignore']
|
|
76
68
|
});
|
|
77
69
|
const wrappers = [];
|
|
@@ -83,23 +75,62 @@ function generateScriptWrappers() {
|
|
|
83
75
|
if (!script) continue;
|
|
84
76
|
const name = utils.getScriptName(script, utils.commentMap[extension]);
|
|
85
77
|
if (!name) continue;
|
|
78
|
+
const description = utils.getScriptDescription(script);
|
|
79
|
+
checkNameColision(name);
|
|
86
80
|
const tb = new utils.TemplateBuilder(utils.scriptWrapperTemplate).replace('FUNC_NAME', name).replace('FUNC_NAME_LOWERCASE', name).replace('PACKAGE_NAMESPACE', _package.name);
|
|
87
81
|
const inputs = utils.getScriptInputs(script);
|
|
88
82
|
const outputType = utils.getScriptOutputType(script);
|
|
89
|
-
tb.replace('PARAMS_OBJECT', inputs).replace('TYPED_PARAMS', inputs).replace('OUTPUT_TYPE', outputType);
|
|
83
|
+
tb.replace('PARAMS_OBJECT', inputs).replace('TYPED_PARAMS', inputs).replace('FUNC_DESCRIPTION', description).replace('OUTPUT_TYPE', outputType);
|
|
90
84
|
wrappers.push(tb.build(1));
|
|
91
85
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
86
|
+
saveWrappersToFile('scripts', wrappers);
|
|
87
|
+
}
|
|
88
|
+
function generateFunctionWrappers() {
|
|
89
|
+
let filesToParse = packageFuncDirs.map(e => _path.default.join(curDir, 'src', e)).filter(e => _fs.default.existsSync(e));
|
|
90
|
+
const annotaionRegex = /(?:\/\/[^\n]*\n)+export[^{]*/g;
|
|
91
|
+
const nameRegex = /\s*export(?:\sasync)?\s*function\s*([^\s(]*)/;
|
|
92
|
+
const wrappers = [];
|
|
93
|
+
for (const file of filesToParse) {
|
|
94
|
+
const fileData = _fs.default.readFileSync(file, 'utf8');
|
|
95
|
+
const annotations = fileData.matchAll(annotaionRegex);
|
|
96
|
+
if (annotations === null) return;
|
|
97
|
+
for (let annotation of annotations) {
|
|
98
|
+
const name = (annotation[0].match(nameRegex) ?? [undefined, undefined])[1];
|
|
99
|
+
const description = utils.getScriptDescription(annotation[0], utils.commentMap[utils.jsExtention]);
|
|
100
|
+
if (!name) continue;
|
|
101
|
+
const annotationInputs = utils.getScriptInputs(annotation[0], utils.commentMap[utils.jsExtention]);
|
|
102
|
+
const annotationOutputDir = utils.getScriptOutputType(annotation[0], utils.commentMap[utils.jsExtention]);
|
|
103
|
+
let outputType = '';
|
|
104
|
+
for (let outputAnnotation of annotationOutputDir) {
|
|
105
|
+
if (outputType != '') {
|
|
106
|
+
outputType = 'any';
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
outputType = utils.dgToTsTypeMap[outputAnnotation[1]] ?? 'any';
|
|
110
|
+
}
|
|
111
|
+
checkNameColision(name);
|
|
112
|
+
const tb = new utils.TemplateBuilder(utils.scriptWrapperTemplate).replace('FUNC_NAME', name).replace('FUNC_NAME_LOWERCASE', name).replace('PACKAGE_NAMESPACE', _package.name).replace('PARAMS_OBJECT', annotationInputs).replace('FUNC_DESCRIPTION', description).replace('TYPED_PARAMS', annotationInputs).replace('OUTPUT_TYPE', outputType);
|
|
113
|
+
wrappers.push(tb.build(1));
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
saveWrappersToFile('funcs', wrappers);
|
|
117
|
+
}
|
|
118
|
+
function saveWrappersToFile(namespaceName, wrappers) {
|
|
119
|
+
if (!_fs.default.existsSync(funcFilePath)) createApiFile();
|
|
120
|
+
const scriptApi = new utils.TemplateBuilder(utils.namespaceTemplate).replace('PACKAGE_NAMESPACE', namespaceName).replace('NAME', wrappers.join(sep.repeat(2)));
|
|
121
|
+
_fs.default.appendFileSync(funcFilePath, sep + scriptApi.build() + sep);
|
|
122
|
+
color.success(`Successfully generated file ${apiFile}${sep}`);
|
|
123
|
+
}
|
|
124
|
+
function createApiFile() {
|
|
95
125
|
if (_fs.default.existsSync(funcFilePath)) {
|
|
96
126
|
color.warn(`The file ${funcFilePath} already exists`);
|
|
97
127
|
console.log('Rewriting its contents...');
|
|
98
128
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
129
|
+
_fs.default.writeFileSync(funcFilePath, utils.dgImports + sep, 'utf8');
|
|
130
|
+
}
|
|
131
|
+
function checkNameColision(name) {
|
|
132
|
+
if (names.has(name)) console.log('There is collision in name ' + name);
|
|
133
|
+
names.add(name);
|
|
103
134
|
}
|
|
104
135
|
function api(args) {
|
|
105
136
|
const nOptions = Object.keys(args).length - 1;
|
|
@@ -108,7 +139,9 @@ function api(args) {
|
|
|
108
139
|
color.error('File `package.json` not found. Run the command from the package directory');
|
|
109
140
|
return false;
|
|
110
141
|
}
|
|
142
|
+
createApiFile();
|
|
111
143
|
generateScriptWrappers();
|
|
112
144
|
generateQueryWrappers();
|
|
145
|
+
generateFunctionWrappers();
|
|
113
146
|
return true;
|
|
114
147
|
}
|
package/bin/commands/check.js
CHANGED
|
@@ -21,6 +21,7 @@ var testUtils = _interopRequireWildcard(require("../utils/test-utils"));
|
|
|
21
21
|
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
22
22
|
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
23
23
|
const warns = ['Latest package version', 'Datagrok API version should contain'];
|
|
24
|
+
const forbidenNames = ['function', 'class', 'export'];
|
|
24
25
|
function check(args) {
|
|
25
26
|
const nOptions = Object.keys(args).length - 1;
|
|
26
27
|
if (args['_'].length !== 1 || nOptions > 2 || nOptions > 0 && !args.r && !args.recursive) return false;
|
|
@@ -314,6 +315,8 @@ function checkFuncSignatures(packagePath, files) {
|
|
|
314
315
|
warnings.push(`File ${file}, function ${f.name}:\n${vr.message}`);
|
|
315
316
|
}
|
|
316
317
|
}
|
|
318
|
+
let wrongInputNames = f.inputs.filter(e => forbidenNames.includes(e?.name ?? ''));
|
|
319
|
+
if (wrongInputNames.length > 0) warnings.push(`File ${file}, function ${f.name}: Wrong input names: (${wrongInputNames.map(e => e.name).join(', ')})`);
|
|
317
320
|
if (f.isInvalidateOnWithoutCache) warnings.push(`File ${file}, function ${f.name}: Can't use invalidateOn without cache, please follow this example: 'meta.cache.invalidateOn'`);
|
|
318
321
|
if (f.cache) if (!utils.cahceValues.includes(f.cache)) warnings.push(`File ${file}, function ${f.name}: unsupposed variable for cache : ${f.cache}`);
|
|
319
322
|
if (f.invalidateOn) if (!utils.isValidCron(f.invalidateOn)) warnings.push(`File ${file}, function ${f.name}: unsupposed variable for invalidateOn : ${f.invalidateOn}`);
|
|
@@ -394,8 +397,6 @@ function checkPackageFile(packagePath, json, options) {
|
|
|
394
397
|
}
|
|
395
398
|
if (!hasRCDependency) {
|
|
396
399
|
for (let dependency of Object.keys(json.dependencies ?? {})) {
|
|
397
|
-
console.log(dependency);
|
|
398
|
-
console.log((json.dependencies ?? {})[dependency]);
|
|
399
400
|
if (/\d+.\d+.\d+-rc(.[A-Za-z0-9]*.[A-Za-z0-9]*)?/.test((json.devDependencies ?? {})[dependency])) {
|
|
400
401
|
hasRCDependency = true;
|
|
401
402
|
break;
|
package/bin/commands/help.js
CHANGED
|
@@ -191,10 +191,12 @@ https://datagrok.ai/help/develop/how-to/test-packages#local-testing
|
|
|
191
191
|
const HELP_LINK = `
|
|
192
192
|
Usage: grok link
|
|
193
193
|
|
|
194
|
-
Link \`datagrok-api
|
|
194
|
+
Link \`datagrok-api\`, all necessary libraries and packages for local development by \`npm link\` command
|
|
195
195
|
|
|
196
196
|
Options:
|
|
197
197
|
--dev Links also dev dependencies
|
|
198
|
+
--path Instead of npm linking sets dependecies in package.json to local
|
|
199
|
+
--unlink Unlinks packages and sets last versions instead of local path in package.json dependencies
|
|
198
200
|
--verbose Prints detailed information about linked packages
|
|
199
201
|
`;
|
|
200
202
|
|
package/bin/commands/link.js
CHANGED
|
@@ -11,10 +11,10 @@ var _utils = require("../utils/utils");
|
|
|
11
11
|
/* eslint-disable valid-jsdoc */
|
|
12
12
|
|
|
13
13
|
const repositoryDirNameRegex = new RegExp(_path.default.join('1', '2')[1] + 'public$');
|
|
14
|
-
const excludedPackages = ['@datagrok/diff-grok'];
|
|
14
|
+
const excludedPackages = ['@datagrok/diff-grok', ''];
|
|
15
15
|
const curDir = process.cwd();
|
|
16
|
-
let devMode = false;
|
|
17
16
|
let repositoryDir = curDir;
|
|
17
|
+
let currentPackage;
|
|
18
18
|
let localPackageDependencies;
|
|
19
19
|
let packagesToLink;
|
|
20
20
|
while (_path.default.dirname(repositoryDir) !== repositoryDir) {
|
|
@@ -22,6 +22,9 @@ while (_path.default.dirname(repositoryDir) !== repositoryDir) {
|
|
|
22
22
|
repositoryDir = _path.default.dirname(repositoryDir);
|
|
23
23
|
}
|
|
24
24
|
let verbose = false;
|
|
25
|
+
let pathMode = false;
|
|
26
|
+
let devMode = false;
|
|
27
|
+
let unlink = false;
|
|
25
28
|
const apiDir = _path.default.join(repositoryDir, 'js-api');
|
|
26
29
|
const libDir = _path.default.join(repositoryDir, 'libraries');
|
|
27
30
|
const packageDir = _path.default.join(repositoryDir, 'packages');
|
|
@@ -30,22 +33,38 @@ const libName = '@datagrok-libraries/';
|
|
|
30
33
|
const packageName = '@datagrok/';
|
|
31
34
|
async function link(args) {
|
|
32
35
|
verbose = args.verbose ?? false;
|
|
36
|
+
devMode = args.dev ?? false;
|
|
37
|
+
pathMode = args.path ?? false;
|
|
38
|
+
unlink = args.unlink ?? false;
|
|
33
39
|
localPackageDependencies = [];
|
|
34
40
|
packagesToLink = new Set();
|
|
35
|
-
if (args.dev !== undefined) devMode = args.dev;
|
|
36
41
|
collectPackagesData(curDir);
|
|
37
|
-
|
|
38
|
-
|
|
42
|
+
currentPackage = new PackageData(curDir);
|
|
43
|
+
if (unlink) {
|
|
44
|
+
await unlinkPackages();
|
|
45
|
+
console.log('Package unlinked');
|
|
46
|
+
} else {
|
|
47
|
+
await linkPackages();
|
|
48
|
+
if (pathMode) console.log('Updated dependencies to local in package.json');else console.log('All packages/libraries linked to your package by nmp link command');
|
|
49
|
+
}
|
|
39
50
|
return true;
|
|
40
51
|
}
|
|
41
52
|
function collectPackagesData(packagePath = curDir) {
|
|
42
53
|
const packageJsonPath = _path.default.join(packagePath, 'package.json');
|
|
43
|
-
if (!_fs.default.existsSync(packageJsonPath)) return
|
|
54
|
+
if (!_fs.default.existsSync(packageJsonPath)) return {
|
|
55
|
+
dependencies: [],
|
|
56
|
+
version: '0.0.1',
|
|
57
|
+
name: ''
|
|
58
|
+
};
|
|
44
59
|
const json = JSON.parse(_fs.default.readFileSync(packageJsonPath, 'utf-8'));
|
|
45
|
-
let
|
|
46
|
-
|
|
47
|
-
if (devMode)
|
|
48
|
-
return
|
|
60
|
+
let dependencies = [];
|
|
61
|
+
dependencies = dependencies.concat(collectPacakgeDataFromJsonObject(json.dependencies));
|
|
62
|
+
if (devMode) dependencies = dependencies.concat(collectPacakgeDataFromJsonObject(json.devDependencies));
|
|
63
|
+
return {
|
|
64
|
+
dependencies: dependencies,
|
|
65
|
+
version: json.version,
|
|
66
|
+
name: json.name
|
|
67
|
+
};
|
|
49
68
|
}
|
|
50
69
|
function collectPacakgeDataFromJsonObject(object) {
|
|
51
70
|
let result = [];
|
|
@@ -62,11 +81,38 @@ function parsePackageDependencies(dependencyName, pathToLink) {
|
|
|
62
81
|
let result = [];
|
|
63
82
|
if (!packagesToLink.has(dependencyName)) {
|
|
64
83
|
packagesToLink.add(dependencyName);
|
|
65
|
-
localPackageDependencies.push(new PackageData(
|
|
84
|
+
localPackageDependencies.push(new PackageData(pathToLink));
|
|
66
85
|
}
|
|
67
86
|
result.push(dependencyName);
|
|
68
87
|
return result;
|
|
69
88
|
}
|
|
89
|
+
async function unlinkPackages() {
|
|
90
|
+
const packaegs = [...localPackageDependencies];
|
|
91
|
+
if (currentPackage) packaegs.push(currentPackage);
|
|
92
|
+
for (let packageData of packaegs) {
|
|
93
|
+
if (excludedPackages.includes(packageData.name)) continue;
|
|
94
|
+
if (verbose) console.log(`Package ${packageData.name} is unlinking`);
|
|
95
|
+
const packageJsonPath = _path.default.join(packageData.packagePath, 'package.json');
|
|
96
|
+
const packageJson = JSON.parse(_fs.default.readFileSync(packageJsonPath, 'utf8'));
|
|
97
|
+
packageJson.dependencies = updateDependenciesToVersion(packageData, packageJson.dependencies);
|
|
98
|
+
if (devMode) packageJson.devDependencies = updateDependenciesToVersion(packageData, packageJson.devDependencies);
|
|
99
|
+
_fs.default.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
|
|
100
|
+
await (0, _utils.runScript)(`npm unlink ${packageData.name}`, packageData.packagePath);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
function updateDependenciesToVersion(packageData, dependecyNode) {
|
|
104
|
+
for (let dependency of packageData.dependencies) {
|
|
105
|
+
if (excludedPackages.includes(dependency)) continue;
|
|
106
|
+
if (dependecyNode[dependency]) {
|
|
107
|
+
const packageToLink = (localPackageDependencies.filter(e => e.name === dependency) ?? [])[0];
|
|
108
|
+
if (packageToLink) {
|
|
109
|
+
const startIndex = packageToLink.packagePath.indexOf(`public${_path.default.sep}`) + `public${_path.default.sep}`.length;
|
|
110
|
+
if (startIndex !== -1) dependecyNode[dependency] = `^${packageToLink.version}`;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return dependecyNode;
|
|
115
|
+
}
|
|
70
116
|
async function linkPackages() {
|
|
71
117
|
let anyChanges = true;
|
|
72
118
|
for (let element of excludedPackages) packagesToLink.delete(element);
|
|
@@ -79,24 +125,56 @@ async function linkPackages() {
|
|
|
79
125
|
let mapElements = localPackageDependencies.filter(x => x.dependencies.every(i => !packagesToLink.has(i)) && packagesToLink.has(x.name) && !excludedPackages.includes(x.name));
|
|
80
126
|
if (mapElements.length === 0) break;
|
|
81
127
|
for (let element of mapElements) {
|
|
82
|
-
if (verbose) console.log(`Package ${element.name}
|
|
128
|
+
if (verbose) console.log(`Package ${element.name} is linking`);
|
|
129
|
+
if (pathMode) await linkPathMode(element);
|
|
83
130
|
await (0, _utils.runScript)(`npm install`, element.packagePath);
|
|
84
|
-
await (0, _utils.runScript)(`npm
|
|
85
|
-
|
|
131
|
+
if (pathMode) await (0, _utils.runScript)(`npm run build`, element.packagePath);
|
|
132
|
+
if (!pathMode) await linkNpmMode(element);
|
|
86
133
|
packagesToLink.delete(element.name);
|
|
87
134
|
anyChanges = true;
|
|
88
135
|
}
|
|
89
136
|
if (anyChanges === false) throw new Error(`There is loop with next packages: ${JSON.stringify(Array.from(packagesToLink)).toString()}`);
|
|
90
137
|
}
|
|
91
138
|
let names = localPackageDependencies.map(x => x.name);
|
|
139
|
+
if (currentPackage && pathMode) await linkPathMode(currentPackage);
|
|
92
140
|
await (0, _utils.runScript)(`npm install`, curDir);
|
|
93
|
-
await (0, _utils.runScript)(`npm link ${names.join(' ')}`, curDir);
|
|
141
|
+
if (pathMode === false) await (0, _utils.runScript)(`npm link ${names.join(' ')}`, curDir);
|
|
142
|
+
}
|
|
143
|
+
async function linkNpmMode(packageData) {
|
|
144
|
+
await (0, _utils.runScript)(`npm link ${packageData.dependencies.join(' ')}`, packageData.packagePath);
|
|
145
|
+
await (0, _utils.runScript)(`npm link`, packageData.packagePath);
|
|
146
|
+
}
|
|
147
|
+
async function linkPathMode(packageData) {
|
|
148
|
+
const packageJsonPath = _path.default.join(packageData.packagePath, 'package.json');
|
|
149
|
+
const packageJson = JSON.parse(_fs.default.readFileSync(packageJsonPath, 'utf8'));
|
|
150
|
+
packageJson.dependencies = packageJson.dependencies || {};
|
|
151
|
+
packageJson.devDependencies = packageJson.devDependencies || {};
|
|
152
|
+
packageJson.dependencies = updateDependenciesToLocal(packageData, packageJson.dependencies);
|
|
153
|
+
if (devMode) packageJson.devDependencies = updateDependenciesToLocal(packageData, packageJson.devDependencies);
|
|
154
|
+
_fs.default.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
|
|
155
|
+
}
|
|
156
|
+
function updateDependenciesToLocal(packageData, dependecyNode) {
|
|
157
|
+
const dirNames = packageData.packagePath.split(_path.default.sep);
|
|
158
|
+
const backRoute = `../`.repeat(dirNames.length - dirNames.indexOf('public') - 1);
|
|
159
|
+
for (let dependency of packageData.dependencies) {
|
|
160
|
+
if (excludedPackages.includes(dependency)) continue;
|
|
161
|
+
if (dependecyNode[dependency]) {
|
|
162
|
+
const packageToLink = (localPackageDependencies.filter(e => e.name === dependency) ?? [])[0];
|
|
163
|
+
if (packageToLink) {
|
|
164
|
+
const startIndex = packageToLink.packagePath.indexOf(`public${_path.default.sep}`) + `public${_path.default.sep}`.length;
|
|
165
|
+
if (startIndex !== -1) dependecyNode[dependency] = `${backRoute}${packageToLink.packagePath.substring(startIndex).replaceAll(_path.default.sep, '/')}`;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return dependecyNode;
|
|
94
170
|
}
|
|
95
171
|
class PackageData {
|
|
96
172
|
dependencies = [];
|
|
97
|
-
constructor(
|
|
98
|
-
|
|
173
|
+
constructor(packagePath) {
|
|
174
|
+
let packageJsonData = collectPackagesData(packagePath);
|
|
175
|
+
this.name = packageJsonData.name;
|
|
99
176
|
this.packagePath = packagePath;
|
|
100
|
-
this.dependencies =
|
|
177
|
+
this.dependencies = packageJsonData.dependencies;
|
|
178
|
+
this.version = packageJsonData.version;
|
|
101
179
|
}
|
|
102
180
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.FUNC_TYPES = void 0;
|
|
6
|
+
exports.dgAnnotationTypes = exports.FUNC_TYPES = void 0;
|
|
7
7
|
exports.generateClassFunc = generateClassFunc;
|
|
8
8
|
exports.generateExport = generateExport;
|
|
9
9
|
exports.generateFunc = generateFunc;
|
|
@@ -22,6 +22,53 @@ let pseudoParams = exports.pseudoParams = /*#__PURE__*/function (pseudoParams) {
|
|
|
22
22
|
}({});
|
|
23
23
|
const nonMetaData = ['sidebar', 'editor'];
|
|
24
24
|
const decoratorOptionToAnnotation = new Map([['initialValue', 'default']]);
|
|
25
|
+
const dgAnnotationTypes = exports.dgAnnotationTypes = {
|
|
26
|
+
INT: "int",
|
|
27
|
+
BIG_INT: "bigint",
|
|
28
|
+
FLOAT: "double",
|
|
29
|
+
NUM: "num",
|
|
30
|
+
QNUM: "qnum",
|
|
31
|
+
BOOL: "bool",
|
|
32
|
+
STRING: "string",
|
|
33
|
+
STRING_LIST: "string_list",
|
|
34
|
+
DATE_TIME: "datetime",
|
|
35
|
+
OBJECT: "object",
|
|
36
|
+
BYTE_ARRAY: "byte_array",
|
|
37
|
+
DATA_FRAME: "dataframe",
|
|
38
|
+
DATA_FRAME_LIST: "dataframe_list",
|
|
39
|
+
CELL: "cell",
|
|
40
|
+
COLUMN: "column",
|
|
41
|
+
COLUMN_LIST: "column_list",
|
|
42
|
+
GRAPHICS: "graphics",
|
|
43
|
+
FILE: "file",
|
|
44
|
+
BLOB: "blob",
|
|
45
|
+
ROW_FILTER: "tablerowfiltercall",
|
|
46
|
+
COLUMN_FILTER: "colfiltercall",
|
|
47
|
+
BIT_SET: "bitset",
|
|
48
|
+
MAP: "map",
|
|
49
|
+
DYNAMIC: "dynamic",
|
|
50
|
+
VIEWER: "viewer",
|
|
51
|
+
LIST: "list",
|
|
52
|
+
SEM_VALUE: "semantic_value",
|
|
53
|
+
FUNC: "func",
|
|
54
|
+
FUNC_CALL: "funccall",
|
|
55
|
+
PROPERTY: "property",
|
|
56
|
+
CATEGORICAL: "categorical",
|
|
57
|
+
NUMERICAL: "numerical",
|
|
58
|
+
GRID_CELL_RENDER_ARGS: "GridCellRenderArgs",
|
|
59
|
+
ELEMENT: "element",
|
|
60
|
+
VIEW: "view",
|
|
61
|
+
TABLE_VIEW: "TableView",
|
|
62
|
+
USER: "User",
|
|
63
|
+
MENU: "Menu",
|
|
64
|
+
PROJECT: "Project",
|
|
65
|
+
SEMANTIC_VALUE: "semantic_value",
|
|
66
|
+
EVENT_DATA: "event_data",
|
|
67
|
+
PROGRESS_INDICATOR: "progressindicator",
|
|
68
|
+
CREDENTIALS: "Credentials",
|
|
69
|
+
SCRIPT_ENVIRONMENT: "ScriptEnvironment",
|
|
70
|
+
NOTEBOOK: "Notebook"
|
|
71
|
+
};
|
|
25
72
|
let FUNC_TYPES = exports.FUNC_TYPES = /*#__PURE__*/function (FUNC_TYPES) {
|
|
26
73
|
FUNC_TYPES["APP"] = "app";
|
|
27
74
|
FUNC_TYPES["CELL_RENDERER"] = "cellRenderer";
|
|
@@ -379,7 +426,7 @@ const primitives = new Set(['string', 'string[]', 'number', 'number[]', 'boolean
|
|
|
379
426
|
|
|
380
427
|
/** Generates a DG function. */
|
|
381
428
|
function generateFunc(annotation, funcName, sep = '\n', className = '', inputs = [], isAsync = false) {
|
|
382
|
-
let funcSigNature = inputs.map(e => `${e.name}: ${primitives.has(e.type ?? '') ? e.type : 'any'}`).join(', ');
|
|
429
|
+
let funcSigNature = inputs.map(e => `${e.name}: ${primitives.has(e.type ?? '') ? e.type : typesToAnnotation[e.type?.replace('[]', '') ?? ''] ? e.type : 'any'}`).join(', ');
|
|
383
430
|
let funcArguments = inputs.map(e => e.name).join(', ');
|
|
384
431
|
return annotation + `export ${isAsync ? 'async ' : ''}function ${funcName}(${funcSigNature}) {${sep} return ${className.length > 0 ? `${className}.` : ''}${funcName}(${funcArguments});${sep}}${sep.repeat(2)}`;
|
|
385
432
|
}
|
package/bin/utils/utils.js
CHANGED
|
@@ -9,9 +9,11 @@ exports.camelCaseToKebab = camelCaseToKebab;
|
|
|
9
9
|
exports.checkScriptLocation = checkScriptLocation;
|
|
10
10
|
exports.commentMap = void 0;
|
|
11
11
|
exports.delay = delay;
|
|
12
|
+
exports.descriptionToComment = descriptionToComment;
|
|
12
13
|
exports.fileParamRegex = exports.dgToTsTypeMap = exports.dgImports = void 0;
|
|
13
14
|
exports.friendlyNameToName = friendlyNameToName;
|
|
14
15
|
exports.getParam = getParam;
|
|
16
|
+
exports.getScriptDescription = getScriptDescription;
|
|
15
17
|
exports.getScriptInputs = getScriptInputs;
|
|
16
18
|
exports.getScriptName = getScriptName;
|
|
17
19
|
exports.getScriptOutputType = getScriptOutputType;
|
|
@@ -19,6 +21,7 @@ exports.headerTags = void 0;
|
|
|
19
21
|
exports.isEmpty = isEmpty;
|
|
20
22
|
exports.isPackageDir = isPackageDir;
|
|
21
23
|
exports.isValidCron = isValidCron;
|
|
24
|
+
exports.jsExtention = void 0;
|
|
22
25
|
exports.kebabToCamelCase = kebabToCamelCase;
|
|
23
26
|
exports.mapURL = mapURL;
|
|
24
27
|
exports.queryWrapperTemplate = exports.queryExtension = exports.propertyTypes = exports.namespaceTemplate = exports.nameRegex = exports.nameAnnRegex = void 0;
|
|
@@ -49,6 +52,10 @@ function kebabToCamelCase(s, firstUpper = true) {
|
|
|
49
52
|
s = s.replace(/-./g, x => x.toUpperCase()[1]);
|
|
50
53
|
return (firstUpper ? s[0].toUpperCase() : s[0].toLowerCase()) + s.slice(1);
|
|
51
54
|
}
|
|
55
|
+
function descriptionToComment(s) {
|
|
56
|
+
if (s.length === 0) return '';
|
|
57
|
+
return '//' + s + '\n';
|
|
58
|
+
}
|
|
52
59
|
function spaceToCamelCase(s, firstUpper = true) {
|
|
53
60
|
s = s.replace(/\s+./g, x => x[x.length - 1].toUpperCase());
|
|
54
61
|
return (firstUpper ? s[0].toUpperCase() : s[0].toLowerCase()) + s.slice(1);
|
|
@@ -97,6 +104,7 @@ const replacers = exports.replacers = {
|
|
|
97
104
|
NAME_PREFIX: (s, name) => s.replace(/#{NAME_PREFIX}/g, name.slice(0, 3)),
|
|
98
105
|
PACKAGE_DETECTORS_NAME: (s, name) => s.replace(/#{PACKAGE_DETECTORS_NAME}/g, kebabToCamelCase(name)),
|
|
99
106
|
PACKAGE_NAMESPACE: (s, name) => s.replace(/#{PACKAGE_NAMESPACE}/g, kebabToCamelCase(removeScope(name))),
|
|
107
|
+
FUNC_DESCRIPTION: (s, desc) => s.replace(/#{FUNC_DESCRIPTION}/g, descriptionToComment(desc)),
|
|
100
108
|
FUNC_NAME: (s, name) => s.replace(/#{FUNC_NAME}/g, friendlyNameToName(name)),
|
|
101
109
|
FUNC_NAME_LOWERCASE: (s, name) => s.replace(/#{FUNC_NAME_LOWERCASE}/g, friendlyNameToName(name, false)),
|
|
102
110
|
PARAMS_OBJECT: (s, params) => s.replace(/#{PARAMS_OBJECT}/g, params.length ? `{ ${params.map(p => p.name).join(', ')} }` : `{}`),
|
|
@@ -138,6 +146,7 @@ const commentMap = exports.commentMap = {
|
|
|
138
146
|
'.sql': '--'
|
|
139
147
|
};
|
|
140
148
|
const queryExtension = exports.queryExtension = '.sql';
|
|
149
|
+
const jsExtention = exports.jsExtention = '.js';
|
|
141
150
|
const scriptExtensions = exports.scriptExtensions = ['.jl', '.m', '.py', '.R'];
|
|
142
151
|
function checkScriptLocation(filepath) {
|
|
143
152
|
if (!(filepath.startsWith('scripts/') || filepath.startsWith('projects/') || filepath.startsWith('dockerfiles/')) && scriptExtensions.some(ext => filepath.endsWith(ext))) return false;
|
|
@@ -170,7 +179,8 @@ const dgToTsTypeMap = exports.dgToTsTypeMap = {
|
|
|
170
179
|
dataframe: 'DG.DataFrame',
|
|
171
180
|
column: 'DG.Column',
|
|
172
181
|
column_list: 'string[]',
|
|
173
|
-
file: 'DG.FileInfo'
|
|
182
|
+
file: 'DG.FileInfo',
|
|
183
|
+
view: 'DG.View'
|
|
174
184
|
};
|
|
175
185
|
const propertyTypes = exports.propertyTypes = ['bool', 'int', 'double', 'string', 'datetime', 'object', 'column', 'dataframe', 'bitset', 'cell', 'string_list', 'map'];
|
|
176
186
|
const headerTags = exports.headerTags = ['name', 'description', 'help-url', 'input', 'output', 'tags', 'sample', 'language', 'returns', 'test', 'sidebar', 'condition', 'top-menu', 'environment', 'require', 'editor-for', 'schedule', 'reference', 'editor', 'meta'];
|
|
@@ -204,11 +214,18 @@ function getScriptInputs(script, comment = '#') {
|
|
|
204
214
|
return inputs;
|
|
205
215
|
}
|
|
206
216
|
;
|
|
217
|
+
function getScriptDescription(script, comment = '#') {
|
|
218
|
+
const regex = new RegExp(`${comment}\\s*description:\\s([^\n]*)`);
|
|
219
|
+
const rexegRes = script.match(regex) || [];
|
|
220
|
+
const desc = rexegRes[1] || '';
|
|
221
|
+
return desc;
|
|
222
|
+
}
|
|
223
|
+
;
|
|
207
224
|
const dgImports = exports.dgImports = `import * as grok from 'datagrok-api/grok';\nimport * as DG from 'datagrok-api/dg';\n\n`;
|
|
208
|
-
const scriptWrapperTemplate = exports.scriptWrapperTemplate =
|
|
225
|
+
const scriptWrapperTemplate = exports.scriptWrapperTemplate = `#{FUNC_DESCRIPTION}export async function #{FUNC_NAME_LOWERCASE}(#{TYPED_PARAMS}): Promise<#{OUTPUT_TYPE}> {
|
|
209
226
|
return await grok.functions.call('#{PACKAGE_NAMESPACE}:#{FUNC_NAME}', #{PARAMS_OBJECT});
|
|
210
227
|
}`;
|
|
211
|
-
const queryWrapperTemplate = exports.queryWrapperTemplate =
|
|
228
|
+
const queryWrapperTemplate = exports.queryWrapperTemplate = `#{FUNC_DESCRIPTION}export async function #{FUNC_NAME_LOWERCASE}(#{TYPED_PARAMS}): Promise<#{OUTPUT_TYPE}> {
|
|
212
229
|
return await grok.data.query('#{PACKAGE_NAMESPACE}:#{FUNC_NAME}', #{PARAMS_OBJECT});
|
|
213
230
|
}`;
|
|
214
231
|
const namespaceTemplate = exports.namespaceTemplate = `export namespace #{PACKAGE_NAMESPACE} {\n#{NAME}\n}`;
|
package/package.json
CHANGED
|
@@ -2,17 +2,18 @@ const fs = require("fs");
|
|
|
2
2
|
const path = require("path");
|
|
3
3
|
|
|
4
4
|
const tsParser = require("@typescript-eslint/typescript-estree");
|
|
5
|
-
const generate = require(
|
|
5
|
+
const generate = require("@babel/generator").default;
|
|
6
6
|
|
|
7
7
|
const {
|
|
8
8
|
reservedDecorators,
|
|
9
9
|
getFuncAnnotation,
|
|
10
10
|
generateImport,
|
|
11
11
|
generateExport,
|
|
12
|
-
typesToAnnotation
|
|
12
|
+
typesToAnnotation,
|
|
13
|
+
dgAnnotationTypes,
|
|
13
14
|
} = require("../bin/utils/func-generation");
|
|
14
15
|
|
|
15
|
-
const baseImport = '
|
|
16
|
+
const baseImport = "import * as DG from 'datagrok-api/dg';\n";
|
|
16
17
|
|
|
17
18
|
class FuncGeneratorPlugin {
|
|
18
19
|
constructor(options = { outputPath: "./src/package.g.ts" }) {
|
|
@@ -33,9 +34,8 @@ class FuncGeneratorPlugin {
|
|
|
33
34
|
|
|
34
35
|
for (const file of tsFiles) {
|
|
35
36
|
const content = fs.readFileSync(file, "utf-8");
|
|
36
|
-
if(!content.includes(
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
if (!content.includes("@grok.decorators.")) continue;
|
|
38
|
+
|
|
39
39
|
if (!content) continue;
|
|
40
40
|
const ast = tsParser.parse(content, {
|
|
41
41
|
sourceType: "module",
|
|
@@ -51,73 +51,134 @@ class FuncGeneratorPlugin {
|
|
|
51
51
|
const decorators = node.decorators;
|
|
52
52
|
if (!decorators || decorators.length === 0) return;
|
|
53
53
|
|
|
54
|
-
if (node?.type === "ClassDeclaration")
|
|
55
|
-
this._addNodeData(
|
|
54
|
+
if (node?.type === "ClassDeclaration")
|
|
55
|
+
this._addNodeData(
|
|
56
|
+
node,
|
|
57
|
+
file,
|
|
58
|
+
srcDirPath,
|
|
59
|
+
functions,
|
|
60
|
+
imports,
|
|
61
|
+
genImports,
|
|
62
|
+
genExports
|
|
63
|
+
);
|
|
56
64
|
|
|
57
65
|
if (node?.type === "MethodDefinition")
|
|
58
|
-
this._addNodeData(
|
|
66
|
+
this._addNodeData(
|
|
67
|
+
node,
|
|
68
|
+
file,
|
|
69
|
+
srcDirPath,
|
|
70
|
+
functions,
|
|
71
|
+
imports,
|
|
72
|
+
genImports,
|
|
73
|
+
genExports,
|
|
74
|
+
parentClass
|
|
75
|
+
);
|
|
59
76
|
});
|
|
60
77
|
this._insertImports([...imports]);
|
|
61
78
|
fs.appendFileSync(this.options.outputPath, functions.join(""), "utf-8");
|
|
62
79
|
}
|
|
63
80
|
this._checkPackageFileForDecoratorsExport(packageFilePath);
|
|
64
|
-
// Uncommment to add obvious import/export
|
|
81
|
+
// Uncommment to add obvious import/export
|
|
65
82
|
// this._writeToPackageFile(packageFilePath, genImports, genExports);
|
|
66
|
-
|
|
67
83
|
});
|
|
68
84
|
}
|
|
69
85
|
|
|
70
|
-
_addNodeData(
|
|
71
|
-
|
|
86
|
+
_addNodeData(
|
|
87
|
+
node,
|
|
88
|
+
file,
|
|
89
|
+
srcDirPath,
|
|
90
|
+
functions,
|
|
91
|
+
imports,
|
|
92
|
+
genImports,
|
|
93
|
+
genExports,
|
|
94
|
+
parent = undefined
|
|
95
|
+
) {
|
|
96
|
+
if (
|
|
97
|
+
!node.decorators ||
|
|
98
|
+
!node.decorators.length ||
|
|
99
|
+
node.decorators?.length === 0
|
|
100
|
+
)
|
|
72
101
|
return;
|
|
73
102
|
|
|
74
103
|
function modifyImportPath(dirPath, filePath) {
|
|
75
104
|
const relativePath = path.relative(dirPath, filePath);
|
|
76
|
-
return `./${relativePath
|
|
105
|
+
return `./${relativePath
|
|
106
|
+
.slice(0, relativePath.length - 3)
|
|
107
|
+
.replace(/\\/g, "/")}`;
|
|
77
108
|
}
|
|
78
109
|
|
|
79
|
-
const decorator =
|
|
80
|
-
const exp
|
|
110
|
+
const decorator = node.decorators[0];
|
|
111
|
+
const exp = decorator.expression;
|
|
81
112
|
const name = exp.callee?.property?.name || exp.callee?.name;
|
|
82
113
|
const identifierName = node.id?.name || node.key?.name;
|
|
83
114
|
const className = parent?.id?.name || parent?.key?.name;
|
|
84
115
|
|
|
85
116
|
if (!name) return;
|
|
86
117
|
|
|
87
|
-
const decoratorOptions = this._readDecoratorOptions(
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
118
|
+
const decoratorOptions = this._readDecoratorOptions(
|
|
119
|
+
exp.arguments[0].properties
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
decoratorOptions.set("tags", [
|
|
123
|
+
...(reservedDecorators[name]["metadata"]["tags"] ?? []),
|
|
124
|
+
...(decoratorOptions.get("tags") ?? []),
|
|
125
|
+
]);
|
|
126
|
+
const functionParams =
|
|
127
|
+
node?.type === "MethodDefinition" ? this._readMethodParamas(node) : [];
|
|
128
|
+
const annotationByReturnType = node?.type === "MethodDefinition" ? this._readReturnType(node) : "";
|
|
129
|
+
|
|
130
|
+
const annotationByReturnTypeObj = {
|
|
131
|
+
name: "result",
|
|
132
|
+
type: annotationByReturnType,
|
|
133
|
+
};
|
|
92
134
|
const isMethodAsync = this._isMethodAsync(node);
|
|
93
|
-
let importString = generateImport(
|
|
135
|
+
let importString = generateImport(
|
|
136
|
+
node?.type === "MethodDefinition" ? className : identifierName,
|
|
137
|
+
modifyImportPath(path.dirname(this.options.outputPath), file)
|
|
138
|
+
);
|
|
94
139
|
imports.add(importString);
|
|
95
|
-
const funcName = `${
|
|
140
|
+
const funcName = `${
|
|
141
|
+
node?.type === "MethodDefinition" ? "" : "_"
|
|
142
|
+
}${identifierName}`;
|
|
96
143
|
const funcAnnotaionOptions = {
|
|
97
|
-
...reservedDecorators[name][
|
|
98
|
-
...(annotationByReturnType
|
|
144
|
+
...reservedDecorators[name]["metadata"],
|
|
145
|
+
...(annotationByReturnType
|
|
146
|
+
? { outputs: [annotationByReturnTypeObj ?? {}] }
|
|
147
|
+
: {}),
|
|
99
148
|
...Object.fromEntries(decoratorOptions),
|
|
100
|
-
...{inputs: functionParams},
|
|
101
|
-
...{isAsync: isMethodAsync}
|
|
102
|
-
};
|
|
103
|
-
if (!funcAnnotaionOptions.name)
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
149
|
+
...{ inputs: functionParams },
|
|
150
|
+
...{ isAsync: isMethodAsync },
|
|
151
|
+
};
|
|
152
|
+
if (!funcAnnotaionOptions.name) funcAnnotaionOptions.name = identifierName;
|
|
153
|
+
functions.push(
|
|
154
|
+
reservedDecorators[name]["genFunc"](
|
|
155
|
+
getFuncAnnotation(funcAnnotaionOptions),
|
|
156
|
+
identifierName,
|
|
157
|
+
"\n",
|
|
158
|
+
className ?? "",
|
|
159
|
+
functionParams,
|
|
160
|
+
funcAnnotaionOptions.isAsync ?? false
|
|
161
|
+
)
|
|
162
|
+
);
|
|
163
|
+
genImports.push(
|
|
164
|
+
generateImport(
|
|
165
|
+
funcName,
|
|
166
|
+
modifyImportPath(srcDirPath, this.options.outputPath)
|
|
167
|
+
)
|
|
168
|
+
);
|
|
107
169
|
genExports.push(generateExport(funcName));
|
|
108
170
|
}
|
|
109
171
|
|
|
110
|
-
_isMethodAsync(node){
|
|
172
|
+
_isMethodAsync(node) {
|
|
111
173
|
let result = false;
|
|
112
|
-
if (node.type ===
|
|
113
|
-
result = node.value.async;
|
|
174
|
+
if (node.type === "MethodDefinition") result = node.value.async;
|
|
114
175
|
return result;
|
|
115
176
|
}
|
|
116
177
|
|
|
117
|
-
_readImports
|
|
118
|
-
const importRegex = /(import(?:[\s\w{},*]+from\s*)?['
|
|
178
|
+
_readImports(content) {
|
|
179
|
+
const importRegex = /(import(?:[\s\w{},*]+from\s*)?['']([^'']+)[''];)/g;
|
|
119
180
|
const results = [];
|
|
120
|
-
|
|
181
|
+
|
|
121
182
|
let match;
|
|
122
183
|
while ((match = importRegex.exec(content)) !== null) {
|
|
123
184
|
results.push(`${match[1]}\n`);
|
|
@@ -125,68 +186,79 @@ class FuncGeneratorPlugin {
|
|
|
125
186
|
return results;
|
|
126
187
|
}
|
|
127
188
|
|
|
128
|
-
_readDecoratorOptions(properties){
|
|
189
|
+
_readDecoratorOptions(properties) {
|
|
129
190
|
const resultMap = new Map();
|
|
130
191
|
|
|
131
|
-
for(let prop of properties)
|
|
192
|
+
for (let prop of properties)
|
|
132
193
|
resultMap.set(prop.key.name, this._evalLiteral(prop.value));
|
|
133
|
-
|
|
134
194
|
return resultMap;
|
|
135
195
|
}
|
|
136
196
|
|
|
137
197
|
_evalLiteral(node) {
|
|
138
198
|
if (!node) return null;
|
|
139
|
-
|
|
140
199
|
switch (node.type) {
|
|
141
|
-
case
|
|
200
|
+
case "Literal":
|
|
142
201
|
return node.value;
|
|
143
202
|
|
|
144
|
-
case
|
|
145
|
-
return node.elements.map(el => this._evalLiteral(el));
|
|
203
|
+
case "ArrayExpression":
|
|
204
|
+
return node.elements.map((el) => this._evalLiteral(el));
|
|
205
|
+
|
|
206
|
+
case "MemberExpression":
|
|
207
|
+
return dgAnnotationTypes[node?.property?.name ?? ""] ?? "dynamic";
|
|
146
208
|
|
|
147
|
-
case
|
|
209
|
+
case "ObjectExpression":
|
|
148
210
|
return Object.fromEntries(
|
|
149
|
-
node.properties.map(p => {
|
|
211
|
+
node.properties.map((p) => {
|
|
150
212
|
return [p.key.name || p.key.value, this._evalLiteral(p.value)];
|
|
151
213
|
})
|
|
152
214
|
);
|
|
153
215
|
|
|
154
216
|
default:
|
|
155
|
-
return
|
|
217
|
+
return "";
|
|
156
218
|
}
|
|
157
219
|
}
|
|
158
220
|
|
|
159
221
|
_readMethodParamas(node) {
|
|
160
|
-
const params = node?.value?.params?.map(param => {
|
|
161
|
-
let baseParam =
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
222
|
+
const params = node?.value?.params?.map((param) => {
|
|
223
|
+
let baseParam =
|
|
224
|
+
param.type === "TSNonNullExpression" ? param.expression : param;
|
|
225
|
+
const options =
|
|
226
|
+
param.decorators?.length > 0
|
|
227
|
+
? Object.fromEntries(
|
|
228
|
+
this._readDecoratorOptions(
|
|
229
|
+
param.decorators[0]?.expression?.arguments[0].properties
|
|
230
|
+
)
|
|
231
|
+
)
|
|
232
|
+
: undefined;
|
|
233
|
+
|
|
234
|
+
// Commented code finds value by default of function's variable
|
|
235
|
+
// let defaultValue = undefined;
|
|
236
|
+
if (baseParam.type === "AssignmentPattern") {
|
|
168
237
|
// if (baseParam?.right?.type === 'Literal')
|
|
169
238
|
// defaultValue = baseParam?.right?.raw;
|
|
170
239
|
baseParam = baseParam?.left;
|
|
171
|
-
}
|
|
240
|
+
}
|
|
172
241
|
|
|
173
|
-
if (baseParam.type ===
|
|
242
|
+
if (baseParam.type === "RestElement" || baseParam.type === "Identifier") {
|
|
174
243
|
let name =
|
|
175
|
-
baseParam.type ===
|
|
244
|
+
baseParam.type === "RestElement"
|
|
176
245
|
? `...${baseParam.argument.name}`
|
|
177
246
|
: baseParam.name;
|
|
178
247
|
if (baseParam?.argument?.typeAnnotation)
|
|
179
|
-
name +=
|
|
180
|
-
|
|
181
|
-
|
|
248
|
+
name +=
|
|
249
|
+
": " +
|
|
250
|
+
generate(baseParam.argument.typeAnnotation.typeAnnotation).code;
|
|
251
|
+
|
|
252
|
+
let type = "";
|
|
182
253
|
if (baseParam?.typeAnnotation?.typeAnnotation)
|
|
183
254
|
type = generate(baseParam.typeAnnotation.typeAnnotation).code;
|
|
184
|
-
else
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
if(type !==
|
|
189
|
-
type += `<${params.map((e)=>e.typeName.name).join(
|
|
255
|
+
else type = "any";
|
|
256
|
+
|
|
257
|
+
let params =
|
|
258
|
+
baseParam.typeAnnotation.typeAnnotation.typeArguments?.params;
|
|
259
|
+
if (type !== "any" && params && params.length > 0)
|
|
260
|
+
type += `<${params.map((e) => e.typeName.name).join(",")}>`;
|
|
261
|
+
|
|
190
262
|
return { name: name, type: type, options: options };
|
|
191
263
|
}
|
|
192
264
|
// Commented code belove sets more strong types for ObjectPatterns and ArrayPatterns
|
|
@@ -213,7 +285,7 @@ class FuncGeneratorPlugin {
|
|
|
213
285
|
// });
|
|
214
286
|
// name = `[${elements.join(', ')}]`;
|
|
215
287
|
// }
|
|
216
|
-
|
|
288
|
+
|
|
217
289
|
// let type = '';
|
|
218
290
|
// if (baseParam.typeAnnotation)
|
|
219
291
|
// type = generate(baseParam.typeAnnotation.typeAnnotation).code;
|
|
@@ -222,7 +294,7 @@ class FuncGeneratorPlugin {
|
|
|
222
294
|
|
|
223
295
|
// return { name: name, type: type, options: options };
|
|
224
296
|
// }
|
|
225
|
-
return { name:
|
|
297
|
+
return { name: "value", type: "any", options: undefined };
|
|
226
298
|
});
|
|
227
299
|
return params;
|
|
228
300
|
}
|
|
@@ -248,79 +320,81 @@ class FuncGeneratorPlugin {
|
|
|
248
320
|
|
|
249
321
|
_walk(node, visitor, parent = null) {
|
|
250
322
|
if (!node || typeof node !== "object") return;
|
|
251
|
-
|
|
323
|
+
|
|
252
324
|
visitor(node, parent);
|
|
253
|
-
|
|
325
|
+
|
|
254
326
|
for (const key in node) {
|
|
255
327
|
const value = node[key];
|
|
256
328
|
if (Array.isArray(value)) {
|
|
257
329
|
value.forEach((child) => {
|
|
258
330
|
if (child && typeof child.type === "string") {
|
|
259
|
-
this._walk(
|
|
331
|
+
this._walk(
|
|
332
|
+
child,
|
|
333
|
+
visitor,
|
|
334
|
+
node.type === "ClassDeclaration" ? node : parent
|
|
335
|
+
);
|
|
260
336
|
}
|
|
261
337
|
});
|
|
262
338
|
} else if (value && typeof value.type === "string") {
|
|
263
|
-
this._walk(
|
|
339
|
+
this._walk(
|
|
340
|
+
value,
|
|
341
|
+
visitor,
|
|
342
|
+
node.type === "ClassDeclaration" ? node : parent
|
|
343
|
+
);
|
|
264
344
|
}
|
|
265
345
|
}
|
|
266
346
|
}
|
|
267
347
|
|
|
268
|
-
|
|
269
|
-
let resultType =
|
|
348
|
+
_readReturnType(node) {
|
|
349
|
+
let resultType = "dynamic";
|
|
270
350
|
let isArray = false;
|
|
271
|
-
|
|
272
|
-
if (
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
else{
|
|
293
|
-
if (annotation.type === 'TSTypeReference')
|
|
294
|
-
resultType = annotation.typeName?.right?.name ?? annotation.typeName?.name;
|
|
295
|
-
else if (annotation.type !== 'TSArrayType')
|
|
296
|
-
resultType = this._getTypeNameFromNode(annotation);
|
|
297
|
-
else if (annotation.elementType.type !== 'TSTypeReference'){
|
|
298
|
-
isArray = true;
|
|
299
|
-
resultType = this._getTypeNameFromNode(annotation?.elementType);
|
|
300
|
-
}
|
|
301
|
-
else{
|
|
302
|
-
isArray = true;
|
|
303
|
-
resultType = (annotation?.elementType?.typeName?.name || annotation?.elementType?.typeName?.right?.name);
|
|
304
|
-
}
|
|
351
|
+
let annotation = node.value?.returnType?.typeAnnotation;
|
|
352
|
+
if (
|
|
353
|
+
annotation &&
|
|
354
|
+
annotation.type !== "TSUnionType" &&
|
|
355
|
+
annotation.type !== "TSIntersectionType"
|
|
356
|
+
) {
|
|
357
|
+
// if (annotation?.typeName?.name === "Promise") {
|
|
358
|
+
// const argumnets = annotation.typeArguments?.params;
|
|
359
|
+
// if (argumnets && argumnets.length === 1) {
|
|
360
|
+
// annotation = argumnets[0];
|
|
361
|
+
// } else annotation = {};
|
|
362
|
+
// }
|
|
363
|
+
|
|
364
|
+
if (annotation.typeName || annotation.type === "TSTypeReference")
|
|
365
|
+
resultType =
|
|
366
|
+
annotation.typeName?.right?.name ?? annotation.typeName?.name;
|
|
367
|
+
else if (annotation.type !== "TSArrayType"){
|
|
368
|
+
resultType = this._getTypeNameFromNode(annotation);
|
|
305
369
|
}
|
|
306
|
-
|
|
370
|
+
else if (annotation.elementType.type !== "TSTypeReference") {
|
|
371
|
+
isArray = true;
|
|
372
|
+
resultType = this._getTypeNameFromNode(annotation?.elementType);
|
|
373
|
+
} else {
|
|
374
|
+
isArray = true;
|
|
375
|
+
resultType =
|
|
376
|
+
annotation?.elementType?.typeName?.name ||
|
|
377
|
+
annotation?.elementType?.typeName?.right?.name;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
307
381
|
resultType = typesToAnnotation[resultType];
|
|
308
|
-
if (isArray && resultType)
|
|
309
|
-
|
|
310
|
-
return resultType;
|
|
382
|
+
if (isArray && resultType) resultType = `list`;
|
|
383
|
+
return resultType ?? 'dynamic';
|
|
311
384
|
}
|
|
312
385
|
|
|
386
|
+
|
|
313
387
|
_getTypeNameFromNode(typeNode) {
|
|
314
|
-
if (typeNode.type ===
|
|
388
|
+
if (typeNode.type === "TSTypeReference") {
|
|
315
389
|
return typeNode.typeName.name;
|
|
316
|
-
} else if (typeNode.type ===
|
|
317
|
-
return
|
|
318
|
-
} else if (typeNode.type ===
|
|
319
|
-
return
|
|
320
|
-
} else if (typeNode.type ===
|
|
321
|
-
return
|
|
322
|
-
} else if (typeNode.type ===
|
|
323
|
-
return
|
|
390
|
+
} else if (typeNode.type === "TSVoidKeyword") {
|
|
391
|
+
return "void";
|
|
392
|
+
} else if (typeNode.type === "TSNumberKeyword") {
|
|
393
|
+
return "number";
|
|
394
|
+
} else if (typeNode.type === "TSStringKeyword") {
|
|
395
|
+
return "string";
|
|
396
|
+
} else if (typeNode.type === "TSBooleanKeyword") {
|
|
397
|
+
return "boolean";
|
|
324
398
|
} else {
|
|
325
399
|
return typeNode.type;
|
|
326
400
|
}
|
|
@@ -330,11 +404,13 @@ class FuncGeneratorPlugin {
|
|
|
330
404
|
fs.writeFileSync(this.options.outputPath, baseImport);
|
|
331
405
|
}
|
|
332
406
|
|
|
333
|
-
_checkPackageFileForDecoratorsExport(packagePath){
|
|
407
|
+
_checkPackageFileForDecoratorsExport(packagePath) {
|
|
334
408
|
const content = fs.readFileSync(packagePath, "utf-8");
|
|
335
409
|
const decoratorsExportRegex = /export\s*\*\s*from\s*'\.\/package\.g';/;
|
|
336
410
|
if (!decoratorsExportRegex.test(content))
|
|
337
|
-
console.warn(
|
|
411
|
+
console.warn(
|
|
412
|
+
`\nWARNING: Your package doesn't export package.g.ts file to package.ts \n please add 'export * from './package.g';' to the package.ts file.\n`
|
|
413
|
+
);
|
|
338
414
|
}
|
|
339
415
|
|
|
340
416
|
_writeToPackageFile(filePath, imports, exp) {
|
|
@@ -352,14 +428,16 @@ class FuncGeneratorPlugin {
|
|
|
352
428
|
_insertImports(importArray) {
|
|
353
429
|
if (fs.existsSync(this.options.outputPath)) {
|
|
354
430
|
const content = fs.readFileSync(this.options.outputPath, "utf-8");
|
|
355
|
-
if (content)
|
|
356
|
-
importArray.push(content);
|
|
431
|
+
if (content) importArray.push(content);
|
|
357
432
|
const output = importArray.join("");
|
|
358
433
|
fs.writeFileSync(this.options.outputPath, `${output}`, "utf-8");
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
|
|
434
|
+
} else
|
|
435
|
+
fs.writeFileSync(
|
|
436
|
+
this.options.outputPath,
|
|
437
|
+
`${baseImport}\n${importArray.join("")}`,
|
|
438
|
+
"utf-8"
|
|
439
|
+
);
|
|
362
440
|
}
|
|
363
441
|
}
|
|
364
442
|
|
|
365
|
-
module.exports = FuncGeneratorPlugin;
|
|
443
|
+
module.exports = FuncGeneratorPlugin;
|