dbgate-tools 7.1.8-alpha.7 → 7.1.9
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/lib/ScriptWriter.js +15 -2
- package/lib/packageTools.d.ts +9 -0
- package/lib/packageTools.js +66 -3
- package/lib/stringTools.js +25 -27
- package/package.json +3 -3
package/lib/ScriptWriter.js
CHANGED
|
@@ -26,6 +26,7 @@ class ScriptWriterJavaScript {
|
|
|
26
26
|
this._put();
|
|
27
27
|
}
|
|
28
28
|
assignCore(variableName, functionName, props) {
|
|
29
|
+
(0, packageTools_1.assertValidJsIdentifier)(variableName, 'variableName');
|
|
29
30
|
this._put(`const ${variableName} = await ${functionName}(${JSON.stringify(props)});`);
|
|
30
31
|
}
|
|
31
32
|
assign(variableName, functionName, props) {
|
|
@@ -33,15 +34,20 @@ class ScriptWriterJavaScript {
|
|
|
33
34
|
this.packageNames.push(...(0, packageTools_1.extractShellApiPlugins)(functionName, props));
|
|
34
35
|
}
|
|
35
36
|
assignValue(variableName, jsonValue) {
|
|
37
|
+
(0, packageTools_1.assertValidJsIdentifier)(variableName, 'variableName');
|
|
36
38
|
this._put(`const ${variableName} = ${JSON.stringify(jsonValue)};`);
|
|
37
39
|
}
|
|
38
40
|
requirePackage(packageName) {
|
|
39
41
|
this.packageNames.push(packageName);
|
|
40
42
|
}
|
|
41
43
|
copyStream(sourceVar, targetVar, colmapVar = null, progressName) {
|
|
44
|
+
(0, packageTools_1.assertValidJsIdentifier)(sourceVar, 'sourceVar');
|
|
45
|
+
(0, packageTools_1.assertValidJsIdentifier)(targetVar, 'targetVar');
|
|
42
46
|
let opts = '{';
|
|
43
|
-
if (colmapVar)
|
|
47
|
+
if (colmapVar) {
|
|
48
|
+
(0, packageTools_1.assertValidJsIdentifier)(colmapVar, 'colmapVar');
|
|
44
49
|
opts += `columns: ${colmapVar}, `;
|
|
50
|
+
}
|
|
45
51
|
if (progressName)
|
|
46
52
|
opts += `progressName: ${JSON.stringify(progressName)}, `;
|
|
47
53
|
opts += '}';
|
|
@@ -68,7 +74,7 @@ class ScriptWriterJavaScript {
|
|
|
68
74
|
return prefix + this.s;
|
|
69
75
|
}
|
|
70
76
|
zipDirectory(inputDirectory, outputFile) {
|
|
71
|
-
this._put(`await dbgateApi.zipDirectory(
|
|
77
|
+
this._put(`await dbgateApi.zipDirectory(${JSON.stringify(inputDirectory)}, ${JSON.stringify(outputFile)});`);
|
|
72
78
|
}
|
|
73
79
|
}
|
|
74
80
|
exports.ScriptWriterJavaScript = ScriptWriterJavaScript;
|
|
@@ -171,6 +177,8 @@ class ScriptWriterEval {
|
|
|
171
177
|
endLine() { }
|
|
172
178
|
requirePackage(packageName) { }
|
|
173
179
|
async assign(variableName, functionName, props) {
|
|
180
|
+
(0, packageTools_1.assertValidJsIdentifier)(variableName, 'variableName');
|
|
181
|
+
(0, packageTools_1.assertValidShellApiFunctionName)(functionName);
|
|
174
182
|
const func = (0, packageTools_1.evalShellApiFunctionName)(functionName, this.dbgateApi, this.requirePlugin);
|
|
175
183
|
this.variables[variableName] = await func((0, cloneDeepWith_1.default)(props, node => {
|
|
176
184
|
if (node === null || node === void 0 ? void 0 : node.$hostConnection) {
|
|
@@ -179,9 +187,14 @@ class ScriptWriterEval {
|
|
|
179
187
|
}));
|
|
180
188
|
}
|
|
181
189
|
assignValue(variableName, jsonValue) {
|
|
190
|
+
(0, packageTools_1.assertValidJsIdentifier)(variableName, 'variableName');
|
|
182
191
|
this.variables[variableName] = jsonValue;
|
|
183
192
|
}
|
|
184
193
|
async copyStream(sourceVar, targetVar, colmapVar = null, progressName) {
|
|
194
|
+
(0, packageTools_1.assertValidJsIdentifier)(sourceVar, 'sourceVar');
|
|
195
|
+
(0, packageTools_1.assertValidJsIdentifier)(targetVar, 'targetVar');
|
|
196
|
+
if (colmapVar != null)
|
|
197
|
+
(0, packageTools_1.assertValidJsIdentifier)(colmapVar, 'colmapVar');
|
|
185
198
|
await this.dbgateApi.copyStream(this.variables[sourceVar], this.variables[targetVar], {
|
|
186
199
|
progressName: (0, cloneDeepWith_1.default)(progressName, node => {
|
|
187
200
|
if (node === null || node === void 0 ? void 0 : node.$runid) {
|
package/lib/packageTools.d.ts
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
import type { EngineDriver, ExtensionsDirectory } from 'dbgate-types';
|
|
2
|
+
export declare function isValidJsIdentifier(name: string): boolean;
|
|
3
|
+
export declare function assertValidJsIdentifier(name: string, label: string): void;
|
|
4
|
+
/**
|
|
5
|
+
* Validates a shell API function name.
|
|
6
|
+
* Allowed forms:
|
|
7
|
+
* - "someFunctionName" (plain identifier, resolved as dbgateApi.someFunctionName)
|
|
8
|
+
* - "funcName@dbgate-plugin-xxx" (namespaced, resolved as plugin.shellApi.funcName)
|
|
9
|
+
*/
|
|
10
|
+
export declare function assertValidShellApiFunctionName(functionName: string): void;
|
|
2
11
|
export declare function extractShellApiPlugins(functionName: any, props: any): string[];
|
|
3
12
|
export declare function extractPackageName(name: any): string;
|
|
4
13
|
export declare function compileShellApiFunctionName(functionName: any): string;
|
package/lib/packageTools.js
CHANGED
|
@@ -3,10 +3,66 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.findEngineDriver = exports.evalShellApiFunctionName = exports.compileShellApiFunctionName = exports.extractPackageName = exports.extractShellApiPlugins = void 0;
|
|
6
|
+
exports.findEngineDriver = exports.evalShellApiFunctionName = exports.compileShellApiFunctionName = exports.extractPackageName = exports.extractShellApiPlugins = exports.assertValidShellApiFunctionName = exports.assertValidJsIdentifier = exports.isValidJsIdentifier = void 0;
|
|
7
7
|
const camelCase_1 = __importDefault(require("lodash/camelCase"));
|
|
8
8
|
const isString_1 = __importDefault(require("lodash/isString"));
|
|
9
9
|
const isPlainObject_1 = __importDefault(require("lodash/isPlainObject"));
|
|
10
|
+
const JS_IDENTIFIER_RE = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
|
|
11
|
+
// ECMAScript reserved words, strict-mode keywords, and async-context keywords
|
|
12
|
+
// that cannot be used as variable or function names in the generated scripts.
|
|
13
|
+
// Sources: ECMA-262 §12.7.2 (reserved words), §12.7.3 (strict mode), §14 (contextual).
|
|
14
|
+
const JS_RESERVED_WORDS = new Set([
|
|
15
|
+
// Keywords
|
|
16
|
+
'break', 'case', 'catch', 'class', 'const', 'continue', 'debugger', 'default',
|
|
17
|
+
'delete', 'do', 'else', 'export', 'extends', 'false', 'finally', 'for',
|
|
18
|
+
'function', 'if', 'import', 'in', 'instanceof', 'let', 'new', 'null', 'return',
|
|
19
|
+
'static', 'super', 'switch', 'this', 'throw', 'true', 'try', 'typeof', 'var',
|
|
20
|
+
'void', 'while', 'with', 'yield',
|
|
21
|
+
// Strict-mode reserved words
|
|
22
|
+
'implements', 'interface', 'package', 'private', 'protected', 'public',
|
|
23
|
+
// Async context keywords
|
|
24
|
+
'async', 'await',
|
|
25
|
+
// Future reserved
|
|
26
|
+
'enum',
|
|
27
|
+
'eval', 'arguments',
|
|
28
|
+
]);
|
|
29
|
+
function isValidJsIdentifier(name) {
|
|
30
|
+
return typeof name === 'string' && JS_IDENTIFIER_RE.test(name) && !JS_RESERVED_WORDS.has(name);
|
|
31
|
+
}
|
|
32
|
+
exports.isValidJsIdentifier = isValidJsIdentifier;
|
|
33
|
+
function assertValidJsIdentifier(name, label) {
|
|
34
|
+
if (!isValidJsIdentifier(name)) {
|
|
35
|
+
throw new Error(`DBGM-00000 Invalid ${label}: ${String(name).substring(0, 100)}`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
exports.assertValidJsIdentifier = assertValidJsIdentifier;
|
|
39
|
+
/**
|
|
40
|
+
* Validates a shell API function name.
|
|
41
|
+
* Allowed forms:
|
|
42
|
+
* - "someFunctionName" (plain identifier, resolved as dbgateApi.someFunctionName)
|
|
43
|
+
* - "funcName@dbgate-plugin-xxx" (namespaced, resolved as plugin.shellApi.funcName)
|
|
44
|
+
*/
|
|
45
|
+
function assertValidShellApiFunctionName(functionName) {
|
|
46
|
+
if (typeof functionName !== 'string') {
|
|
47
|
+
throw new Error('DBGM-00000 functionName must be a string');
|
|
48
|
+
}
|
|
49
|
+
const nsMatch = functionName.match(/^([^@]+)@([^@]+)$/);
|
|
50
|
+
if (nsMatch) {
|
|
51
|
+
if (!isValidJsIdentifier(nsMatch[1])) {
|
|
52
|
+
throw new Error(`DBGM-00000 Invalid function part in functionName: ${nsMatch[1].substring(0, 100)}`);
|
|
53
|
+
}
|
|
54
|
+
if (!/^dbgate-plugin-[a-zA-Z0-9_-]+$/.test(nsMatch[2])) {
|
|
55
|
+
throw new Error(`DBGM-00000 Invalid plugin package in functionName: ${nsMatch[2].substring(0, 100)}`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
if (!isValidJsIdentifier(functionName)) {
|
|
60
|
+
throw new Error(`DBGM-00000 Invalid functionName: ${functionName.substring(0, 100)}`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
exports.assertValidShellApiFunctionName = assertValidShellApiFunctionName;
|
|
65
|
+
const VALID_PLUGIN_NAME_RE = /^dbgate-plugin-[a-zA-Z0-9_-]+$/;
|
|
10
66
|
function extractShellApiPlugins(functionName, props) {
|
|
11
67
|
const res = [];
|
|
12
68
|
const nsMatch = functionName.match(/^([^@]+)@([^@]+)/);
|
|
@@ -19,6 +75,11 @@ function extractShellApiPlugins(functionName, props) {
|
|
|
19
75
|
res.push(nsMatchEngine[2]);
|
|
20
76
|
}
|
|
21
77
|
}
|
|
78
|
+
for (const plugin of res) {
|
|
79
|
+
if (!VALID_PLUGIN_NAME_RE.test(plugin)) {
|
|
80
|
+
throw new Error(`DBGM-00000 Invalid plugin name: ${String(plugin).substring(0, 100)}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
22
83
|
return res;
|
|
23
84
|
}
|
|
24
85
|
exports.extractShellApiPlugins = extractShellApiPlugins;
|
|
@@ -33,7 +94,8 @@ function extractPackageName(name) {
|
|
|
33
94
|
}
|
|
34
95
|
exports.extractPackageName = extractPackageName;
|
|
35
96
|
function compileShellApiFunctionName(functionName) {
|
|
36
|
-
|
|
97
|
+
assertValidShellApiFunctionName(functionName);
|
|
98
|
+
const nsMatch = functionName.match(/^([^@]+)@([^@]+)$/);
|
|
37
99
|
if (nsMatch) {
|
|
38
100
|
return `${(0, camelCase_1.default)(nsMatch[2])}.shellApi.${nsMatch[1]}`;
|
|
39
101
|
}
|
|
@@ -41,7 +103,8 @@ function compileShellApiFunctionName(functionName) {
|
|
|
41
103
|
}
|
|
42
104
|
exports.compileShellApiFunctionName = compileShellApiFunctionName;
|
|
43
105
|
function evalShellApiFunctionName(functionName, dbgateApi, requirePlugin) {
|
|
44
|
-
|
|
106
|
+
assertValidShellApiFunctionName(functionName);
|
|
107
|
+
const nsMatch = functionName.match(/^([^@]+)@([^@]+)$/);
|
|
45
108
|
if (nsMatch) {
|
|
46
109
|
return requirePlugin(nsMatch[2]).shellApi[nsMatch[1]];
|
|
47
110
|
}
|
package/lib/stringTools.js
CHANGED
|
@@ -98,22 +98,24 @@ function parseCellValue(value, editorTypes) {
|
|
|
98
98
|
return null;
|
|
99
99
|
}
|
|
100
100
|
if (editorTypes === null || editorTypes === void 0 ? void 0 : editorTypes.parseHexAsBuffer) {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
101
|
+
if (editorTypes === null || editorTypes === void 0 ? void 0 : editorTypes.parseUuid) {
|
|
102
|
+
const mUuid3 = value.match(uuid3WrapperRegex);
|
|
103
|
+
if (mUuid3) {
|
|
104
|
+
const base64Uuid3 = uuidToBase64(mUuid3[1]);
|
|
105
|
+
if (base64Uuid3 != null)
|
|
106
|
+
return { $binary: { base64: base64Uuid3, subType: '03' } };
|
|
107
|
+
}
|
|
108
|
+
const mUuid4 = value.match(uuid4WrapperRegex);
|
|
109
|
+
if (mUuid4) {
|
|
110
|
+
const base64Uuid4 = uuidToBase64(mUuid4[1]);
|
|
111
|
+
if (base64Uuid4 != null)
|
|
112
|
+
return { $binary: { base64: base64Uuid4, subType: '04' } };
|
|
113
|
+
}
|
|
114
|
+
if (uuidRegex.test(value)) {
|
|
115
|
+
const base64UuidPlain = uuidToBase64(value);
|
|
116
|
+
if (base64UuidPlain != null)
|
|
117
|
+
return { $binary: { base64: base64UuidPlain, subType: '04' } };
|
|
118
|
+
}
|
|
117
119
|
}
|
|
118
120
|
const mHex = value.match(/^0x([0-9a-fA-F][0-9a-fA-F])+$/);
|
|
119
121
|
if (mHex) {
|
|
@@ -301,24 +303,20 @@ function stringifyCellValue(value, intent, editorTypes, gridFormattingOptions, j
|
|
|
301
303
|
return { value: 'false', gridStyle: 'valueCellStyle' };
|
|
302
304
|
if ((_a = value === null || value === void 0 ? void 0 : value.$binary) === null || _a === void 0 ? void 0 : _a.base64) {
|
|
303
305
|
const subType = value.$binary.subType;
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
}
|
|
310
|
-
// For editing intents: tag with subType so parseCellValue can round-trip it
|
|
306
|
+
const isUuidType = subType === '03' || subType === '04' || (editorTypes === null || editorTypes === void 0 ? void 0 : editorTypes.parseUuid);
|
|
307
|
+
const uuidStr = isUuidType ? base64ToUuid(value.$binary.base64) : null;
|
|
308
|
+
if (uuidStr != null) {
|
|
309
|
+
// MongoDB editing intents: wrap with UUID()/UUID3() so parseCellValue can round-trip it
|
|
310
|
+
if ((editorTypes === null || editorTypes === void 0 ? void 0 : editorTypes.parseUuid) && intent !== 'gridCellIntent' && intent !== 'exportIntent' && intent !== 'clipboardIntent' && intent !== 'stringConversionIntent') {
|
|
311
311
|
const tag = subType === '03' ? 'UUID3' : 'UUID';
|
|
312
312
|
return { value: `${tag}("${uuidStr}")`, gridStyle: 'valueCellStyle' };
|
|
313
313
|
}
|
|
314
|
+
return { value: uuidStr, gridStyle: 'valueCellStyle' };
|
|
314
315
|
}
|
|
315
316
|
if (intent === 'gridCellIntent' && value.$binary.base64.length > exports.MAX_GRID_BINARY_SIZE) {
|
|
316
317
|
return { value: `(Field too large, ${formatByteSize(Math.round(value.$binary.base64.length * 3 / 4))})`, gridStyle: 'nullCellStyle' };
|
|
317
318
|
}
|
|
318
|
-
return {
|
|
319
|
-
value: base64ToHex(value.$binary.base64),
|
|
320
|
-
gridStyle: 'valueCellStyle',
|
|
321
|
-
};
|
|
319
|
+
return { value: base64ToHex(value.$binary.base64), gridStyle: 'valueCellStyle' };
|
|
322
320
|
}
|
|
323
321
|
if (value === null || value === void 0 ? void 0 : value.$decimal) {
|
|
324
322
|
return {
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "7.1.
|
|
2
|
+
"version": "7.1.9",
|
|
3
3
|
"name": "dbgate-tools",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"typings": "lib/index.d.ts",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
],
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@types/node": "^13.7.0",
|
|
29
|
-
"dbgate-types": "7.1.
|
|
29
|
+
"dbgate-types": "7.1.9",
|
|
30
30
|
"jest": "^28.1.3",
|
|
31
31
|
"ts-jest": "^28.0.7",
|
|
32
32
|
"typescript": "^4.4.3"
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"blueimp-md5": "^2.19.0",
|
|
36
36
|
"dbgate-query-splitter": "^4.12.0",
|
|
37
|
-
"dbgate-sqltree": "7.1.
|
|
37
|
+
"dbgate-sqltree": "7.1.9",
|
|
38
38
|
"debug": "^4.3.4",
|
|
39
39
|
"json-stable-stringify": "^1.0.1",
|
|
40
40
|
"lodash": "^4.17.21",
|