elit 3.6.5 → 3.6.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Cargo.lock +1 -1
- package/Cargo.toml +1 -1
- package/README.md +6 -0
- package/dist/build.cjs +421 -331
- package/dist/build.d.ts +1 -16
- package/dist/build.js +420 -330
- package/dist/build.mjs +420 -330
- package/dist/chokidar.cjs +219 -182
- package/dist/chokidar.d.ts +25 -10
- package/dist/chokidar.js +217 -182
- package/dist/chokidar.mjs +218 -183
- package/dist/cli.cjs +21608 -20241
- package/dist/cli.d.ts +19 -37
- package/dist/cli.mjs +21262 -19910
- package/dist/config.cjs +357 -350
- package/dist/config.d.ts +19 -240
- package/dist/config.js +520 -515
- package/dist/config.mjs +346 -341
- package/dist/contracts-BeW9k0yZ.d.ts +54 -0
- package/dist/contracts-D7KIS-TK.d.ts +36 -0
- package/dist/coverage.cjs +448 -485
- package/dist/coverage.d.ts +13 -59
- package/dist/coverage.js +447 -484
- package/dist/coverage.mjs +447 -484
- package/dist/database.cjs +819 -828
- package/dist/database.d.ts +8 -24
- package/dist/database.js +818 -829
- package/dist/database.mjs +818 -829
- package/dist/desktop-auto-render.cjs +1700 -1522
- package/dist/desktop-auto-render.d.ts +4 -9
- package/dist/desktop-auto-render.js +1695 -1517
- package/dist/desktop-auto-render.mjs +1696 -1518
- package/dist/desktop.cjs +3 -1
- package/dist/desktop.d.ts +4 -1
- package/dist/desktop.js +1 -1
- package/dist/desktop.mjs +1 -1
- package/dist/dev-build.cjs +830 -0
- package/dist/dev-build.d.ts +53 -0
- package/dist/dev-build.js +3318 -0
- package/dist/dev-build.mjs +797 -0
- package/dist/dom.cjs +717 -590
- package/dist/dom.d.ts +2 -15
- package/dist/dom.js +714 -587
- package/dist/dom.mjs +716 -589
- package/dist/el.cjs +62 -52
- package/dist/el.d.ts +5 -10
- package/dist/el.js +60 -52
- package/dist/el.mjs +60 -52
- package/dist/fs.cjs +72 -63
- package/dist/fs.d.ts +22 -19
- package/dist/fs.js +71 -62
- package/dist/fs.mjs +71 -62
- package/dist/hmr.cjs +40 -14
- package/dist/hmr.d.ts +11 -23
- package/dist/hmr.js +38 -14
- package/dist/hmr.mjs +38 -14
- package/dist/http.cjs +251 -99
- package/dist/http.d.ts +38 -104
- package/dist/http.js +249 -99
- package/dist/http.mjs +249 -99
- package/dist/https.cjs +524 -228
- package/dist/https.d.ts +44 -36
- package/dist/https.js +520 -226
- package/dist/https.mjs +522 -228
- package/dist/index.cjs +7502 -7690
- package/dist/index.d.ts +8 -3
- package/dist/index.js +7486 -7676
- package/dist/index.mjs +7497 -7686
- package/dist/mime-types.cjs +10 -4
- package/dist/mime-types.d.ts +8 -11
- package/dist/mime-types.js +9 -3
- package/dist/mime-types.mjs +9 -3
- package/dist/native.cjs +8616 -8869
- package/dist/native.d.ts +7 -8
- package/dist/native.js +8682 -8935
- package/dist/native.mjs +8615 -8868
- package/dist/path.cjs +83 -77
- package/dist/path.d.ts +29 -29
- package/dist/path.js +82 -76
- package/dist/path.mjs +82 -76
- package/dist/pm.cjs +3300 -0
- package/dist/pm.d.ts +256 -0
- package/dist/pm.js +5638 -0
- package/dist/pm.mjs +3196 -0
- package/dist/preview-build.cjs +712 -0
- package/dist/preview-build.d.ts +59 -0
- package/dist/preview-build.js +3194 -0
- package/dist/preview-build.mjs +676 -0
- package/dist/render-context.cjs +13 -2
- package/dist/render-context.d.ts +9 -31
- package/dist/render-context.js +11 -2
- package/dist/render-context.mjs +11 -2
- package/dist/router.cjs +787 -645
- package/dist/router.d.ts +8 -12
- package/dist/router.js +786 -644
- package/dist/router.mjs +786 -644
- package/dist/runtime.cjs +1 -1
- package/dist/runtime.js +1 -1
- package/dist/runtime.mjs +1 -1
- package/dist/server.cjs +3315 -2603
- package/dist/server.d.ts +49 -4
- package/dist/server.js +7611 -2834
- package/dist/server.mjs +3317 -2607
- package/dist/smtp-server.cjs +128 -0
- package/dist/smtp-server.d.ts +27 -0
- package/dist/smtp-server.js +4199 -0
- package/dist/smtp-server.mjs +100 -0
- package/dist/state-DvEkDehk.d.ts +195 -0
- package/dist/state.cjs +768 -658
- package/dist/state.d.ts +11 -69
- package/dist/state.js +760 -650
- package/dist/state.mjs +767 -657
- package/dist/style.cjs +1011 -968
- package/dist/style.d.ts +13 -127
- package/dist/style.js +1009 -970
- package/dist/style.mjs +1011 -971
- package/dist/test-reporter.cjs +332 -316
- package/dist/test-reporter.d.ts +28 -33
- package/dist/test-reporter.js +328 -312
- package/dist/test-reporter.mjs +328 -312
- package/dist/test-runtime.cjs +927 -968
- package/dist/test-runtime.d.ts +24 -99
- package/dist/test-runtime.js +922 -965
- package/dist/test-runtime.mjs +922 -965
- package/dist/test.cjs +4428 -4273
- package/dist/test.d.ts +2 -8
- package/dist/test.js +4307 -4154
- package/dist/test.mjs +4419 -4267
- package/dist/types-BONVzPtp.d.ts +59 -0
- package/dist/types-BR4wMiVx.d.ts +32 -0
- package/dist/types-C4gKykuG.d.ts +23 -0
- package/dist/types-CIhpN1-K.d.ts +64 -0
- package/dist/types-Ckj8md_j.d.ts +84 -0
- package/dist/types-CpjQTAkX.d.ts +24 -0
- package/dist/types-D0LjrYjS.d.ts +14 -0
- package/dist/types-DAisuVr5.d.ts +75 -0
- package/dist/types-tJn88E1N.d.ts +242 -0
- package/dist/types.d.ts +71 -226
- package/dist/universal.cjs +1 -1
- package/dist/universal.d.ts +1 -5
- package/dist/universal.js +1 -1
- package/dist/universal.mjs +1 -1
- package/dist/websocket-XfyK23zD.d.ts +119 -0
- package/dist/ws.cjs +129 -108
- package/dist/ws.d.ts +21 -131
- package/dist/ws.js +128 -109
- package/dist/ws.mjs +128 -109
- package/dist/wss.cjs +757 -479
- package/dist/wss.d.ts +31 -28
- package/dist/wss.js +755 -479
- package/dist/wss.mjs +758 -482
- package/package.json +16 -1
- package/vendor/epaint-0.31.1/src/image.rs +418 -0
- package/dist/server-CcBFc2F5.d.ts +0 -449
package/dist/database.mjs
CHANGED
|
@@ -6,577 +6,438 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
6
6
|
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
7
7
|
});
|
|
8
8
|
|
|
9
|
-
// src/database.ts
|
|
10
|
-
import vm from "vm";
|
|
9
|
+
// src/server/database/operations.ts
|
|
11
10
|
import fs from "fs";
|
|
12
11
|
import path from "path";
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
if (cachedEsbuildTransformSync !== void 0) {
|
|
18
|
-
return cachedEsbuildTransformSync;
|
|
19
|
-
}
|
|
20
|
-
if (typeof nodeModule.createRequire !== "function") {
|
|
21
|
-
cachedEsbuildTransformSync = null;
|
|
22
|
-
return cachedEsbuildTransformSync;
|
|
23
|
-
}
|
|
24
|
-
try {
|
|
25
|
-
const requireFromApp = nodeModule.createRequire(path.join(process.cwd(), "package.json"));
|
|
26
|
-
const esbuildModule = requireFromApp("esbuild");
|
|
27
|
-
cachedEsbuildTransformSync = typeof esbuildModule?.transformSync === "function" ? esbuildModule.transformSync.bind(esbuildModule) : null;
|
|
28
|
-
} catch {
|
|
29
|
-
cachedEsbuildTransformSync = null;
|
|
30
|
-
}
|
|
31
|
-
return cachedEsbuildTransformSync;
|
|
32
|
-
}
|
|
33
|
-
function parseModuleBindings(specifiers) {
|
|
34
|
-
return specifiers.split(",").map((entry) => entry.trim()).filter((entry) => entry.length > 0).map((entry) => {
|
|
35
|
-
const [imported, local] = entry.split(/\s+as\s+/);
|
|
36
|
-
return {
|
|
37
|
-
imported: (imported || "").trim(),
|
|
38
|
-
local: (local || imported || "").trim()
|
|
39
|
-
};
|
|
40
|
-
}).filter((entry) => entry.imported.length > 0 && entry.local.length > 0);
|
|
41
|
-
}
|
|
42
|
-
function formatNamedImportBindings(specifiers) {
|
|
43
|
-
return parseModuleBindings(specifiers).map(({ imported, local }) => imported === local ? imported : `${imported}: ${local}`).join(", ");
|
|
44
|
-
}
|
|
45
|
-
function formatNamedExportAssignments(specifiers) {
|
|
46
|
-
return parseModuleBindings(specifiers).map(({ imported, local }) => `module.exports.${local} = ${imported};`).join("\n");
|
|
12
|
+
|
|
13
|
+
// src/server/database/source-utils.ts
|
|
14
|
+
function escapeRegExp(value) {
|
|
15
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
47
16
|
}
|
|
48
|
-
function
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
if (
|
|
56
|
-
|
|
17
|
+
function findMatchingBlockEnd(source, openIndex) {
|
|
18
|
+
let depth = 0;
|
|
19
|
+
let stringChar = null;
|
|
20
|
+
for (let index = openIndex; index < source.length; index += 1) {
|
|
21
|
+
const char = source[index];
|
|
22
|
+
const nextChar = source[index + 1];
|
|
23
|
+
if (stringChar) {
|
|
24
|
+
if (char === "\\") {
|
|
25
|
+
index += 1;
|
|
26
|
+
continue;
|
|
57
27
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
28
|
+
if (char === stringChar) {
|
|
29
|
+
stringChar = null;
|
|
30
|
+
}
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
if (char === "/" && nextChar === "/") {
|
|
34
|
+
index += 2;
|
|
35
|
+
while (index < source.length && source[index] !== "\n") {
|
|
36
|
+
index += 1;
|
|
37
|
+
}
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
if (char === "/" && nextChar === "*") {
|
|
41
|
+
index += 2;
|
|
42
|
+
while (index < source.length && !(source[index] === "*" && source[index + 1] === "/")) {
|
|
43
|
+
index += 1;
|
|
44
|
+
}
|
|
45
|
+
index += 1;
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
if (char === '"' || char === "'" || char === "`") {
|
|
49
|
+
stringChar = char;
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
if (char === "{") {
|
|
53
|
+
depth += 1;
|
|
54
|
+
} else if (char === "}") {
|
|
55
|
+
depth -= 1;
|
|
56
|
+
if (depth === 0) {
|
|
57
|
+
return index;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
66
60
|
}
|
|
61
|
+
return source.length - 1;
|
|
67
62
|
}
|
|
68
|
-
function
|
|
69
|
-
|
|
63
|
+
function findInitializerEnd(source, startIndex) {
|
|
64
|
+
let braceDepth = 0;
|
|
65
|
+
let bracketDepth = 0;
|
|
66
|
+
let parenDepth = 0;
|
|
67
|
+
let stringChar = null;
|
|
68
|
+
for (let index = startIndex; index < source.length; index += 1) {
|
|
69
|
+
const char = source[index];
|
|
70
|
+
const nextChar = source[index + 1];
|
|
71
|
+
if (stringChar) {
|
|
72
|
+
if (char === "\\") {
|
|
73
|
+
index += 1;
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
if (char === stringChar) {
|
|
77
|
+
stringChar = null;
|
|
78
|
+
}
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
if (char === "/" && nextChar === "/") {
|
|
82
|
+
index += 2;
|
|
83
|
+
while (index < source.length && source[index] !== "\n") {
|
|
84
|
+
index += 1;
|
|
85
|
+
}
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
if (char === "/" && nextChar === "*") {
|
|
89
|
+
index += 2;
|
|
90
|
+
while (index < source.length && !(source[index] === "*" && source[index + 1] === "/")) {
|
|
91
|
+
index += 1;
|
|
92
|
+
}
|
|
93
|
+
index += 1;
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
if (char === '"' || char === "'" || char === "`") {
|
|
97
|
+
stringChar = char;
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
if (char === "{") {
|
|
101
|
+
braceDepth += 1;
|
|
102
|
+
} else if (char === "}") {
|
|
103
|
+
braceDepth = Math.max(0, braceDepth - 1);
|
|
104
|
+
} else if (char === "[") {
|
|
105
|
+
bracketDepth += 1;
|
|
106
|
+
} else if (char === "]") {
|
|
107
|
+
bracketDepth = Math.max(0, bracketDepth - 1);
|
|
108
|
+
} else if (char === "(") {
|
|
109
|
+
parenDepth += 1;
|
|
110
|
+
} else if (char === ")") {
|
|
111
|
+
parenDepth = Math.max(0, parenDepth - 1);
|
|
112
|
+
} else if (char === ";" && braceDepth === 0 && bracketDepth === 0 && parenDepth === 0) {
|
|
113
|
+
return index;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return source.length;
|
|
70
117
|
}
|
|
71
|
-
function
|
|
72
|
-
const trimmed =
|
|
73
|
-
return
|
|
118
|
+
function looksLikeDeclarationSnippet(source) {
|
|
119
|
+
const trimmed = source.trim();
|
|
120
|
+
return /^(?:export\s+)?(?:async\s+function\b|function\b|class\b|(?:const|let|var)\b)/.test(trimmed);
|
|
74
121
|
}
|
|
75
|
-
function
|
|
76
|
-
const
|
|
77
|
-
|
|
122
|
+
function replaceExistingBindingValue(source, bindingName, serializedValue) {
|
|
123
|
+
const escapedName = escapeRegExp(bindingName);
|
|
124
|
+
const declarationRegex = new RegExp(`(?:export\\s+)?(?:const|let|var)\\s+${escapedName}(?:\\s*:\\s*[^=;]+)?\\s*=`, "m");
|
|
125
|
+
const declarationMatch = declarationRegex.exec(source);
|
|
126
|
+
if (!declarationMatch || declarationMatch.index === void 0) {
|
|
78
127
|
return null;
|
|
79
128
|
}
|
|
80
|
-
const
|
|
81
|
-
if (
|
|
129
|
+
const equalsIndex = source.indexOf("=", declarationMatch.index);
|
|
130
|
+
if (equalsIndex === -1) {
|
|
82
131
|
return null;
|
|
83
132
|
}
|
|
84
|
-
|
|
133
|
+
const initializerEnd = findInitializerEnd(source, equalsIndex + 1);
|
|
134
|
+
const suffix = initializerEnd < source.length ? source.slice(initializerEnd) : ";";
|
|
135
|
+
return `${source.slice(0, equalsIndex + 1)} ${serializedValue}${suffix}`;
|
|
85
136
|
}
|
|
86
|
-
function
|
|
87
|
-
|
|
88
|
-
|
|
137
|
+
function toInitializerSource(code) {
|
|
138
|
+
if (typeof code === "function") {
|
|
139
|
+
return code.toString().trim();
|
|
140
|
+
}
|
|
141
|
+
if (typeof code === "string") {
|
|
142
|
+
const trimmed = code.trim();
|
|
143
|
+
if (looksLikeDeclarationSnippet(trimmed) || /=>/.test(trimmed) || /^(?:\{|\[|\(|"|'|`|\d|-\d|true\b|false\b|null\b|undefined\b|new\b|await\b)/.test(trimmed)) {
|
|
144
|
+
return trimmed;
|
|
145
|
+
}
|
|
146
|
+
return valueToCode(code, 0);
|
|
147
|
+
}
|
|
148
|
+
return valueToCode(code, 0);
|
|
89
149
|
}
|
|
90
|
-
function
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
150
|
+
function shouldUseDeclarationSource(code) {
|
|
151
|
+
return typeof code === "function" || typeof code === "string" && looksLikeDeclarationSnippet(code);
|
|
152
|
+
}
|
|
153
|
+
function normalizeFunctionDeclaration(name, code) {
|
|
154
|
+
const trimmed = code.trim().replace(/^export\s+/, "");
|
|
155
|
+
if (/^async\s+function\s+[A-Za-z_$][\w$]*/.test(trimmed)) {
|
|
156
|
+
return trimmed.replace(/^async\s+function\s+[A-Za-z_$][\w$]*/, `async function ${name}`);
|
|
95
157
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
if (sideEffectModulePath !== null) {
|
|
99
|
-
return `${indentation}require(${JSON.stringify(sideEffectModulePath)});`;
|
|
158
|
+
if (/^async\s+function\s*\(/.test(trimmed)) {
|
|
159
|
+
return trimmed.replace(/^async\s+function\s*\(/, `async function ${name}(`);
|
|
100
160
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
return null;
|
|
161
|
+
if (/^function\s+[A-Za-z_$][\w$]*/.test(trimmed)) {
|
|
162
|
+
return trimmed.replace(/^function\s+[A-Za-z_$][\w$]*/, `function ${name}`);
|
|
104
163
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
if (!clause || modulePath === null) {
|
|
108
|
-
return null;
|
|
164
|
+
if (/^function\s*\(/.test(trimmed)) {
|
|
165
|
+
return trimmed.replace(/^function\s*\(/, `function ${name}(`);
|
|
109
166
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
`${indentation}const ${bindingName} = require(${JSON.stringify(modulePath)});`,
|
|
119
|
-
`${indentation}const ${defaultName} = ${resolveDefaultImport(bindingName)};`
|
|
120
|
-
].join("\n")
|
|
121
|
-
};
|
|
122
|
-
};
|
|
123
|
-
if (clause.startsWith("* as ")) {
|
|
124
|
-
const namespaceName = clause.slice(5).trim();
|
|
125
|
-
return isSimpleIdentifier(namespaceName) ? `${indentation}const ${namespaceName} = require(${JSON.stringify(modulePath)});` : null;
|
|
167
|
+
return `function ${name}() {
|
|
168
|
+
${trimmed}
|
|
169
|
+
}`;
|
|
170
|
+
}
|
|
171
|
+
function normalizeClassDeclaration(name, code) {
|
|
172
|
+
const trimmed = code.trim().replace(/^export\s+/, "");
|
|
173
|
+
if (/^class\s+[A-Za-z_$][\w$]*/.test(trimmed)) {
|
|
174
|
+
return trimmed.replace(/^class\s+[A-Za-z_$][\w$]*/, `class ${name}`);
|
|
126
175
|
}
|
|
127
|
-
if (
|
|
128
|
-
|
|
129
|
-
return namedBindings.length > 0 ? `${indentation}const { ${formatNamedImportBindings(namedBindings)} } = require(${JSON.stringify(modulePath)});` : null;
|
|
176
|
+
if (/^class(?:\s+extends\b|\s*\{)/.test(trimmed)) {
|
|
177
|
+
return trimmed.replace(/^class/, `class ${name}`);
|
|
130
178
|
}
|
|
131
|
-
|
|
132
|
-
if (commaIndex !== -1) {
|
|
133
|
-
const defaultName = clause.slice(0, commaIndex).trim();
|
|
134
|
-
const remainder = clause.slice(commaIndex + 1).trim();
|
|
135
|
-
const defaultImport = buildDefaultImport(defaultName);
|
|
136
|
-
if (!defaultImport) {
|
|
137
|
-
return null;
|
|
138
|
-
}
|
|
139
|
-
if (remainder.startsWith("* as ")) {
|
|
140
|
-
const namespaceName = remainder.slice(5).trim();
|
|
141
|
-
if (!isSimpleIdentifier(namespaceName)) {
|
|
142
|
-
return null;
|
|
143
|
-
}
|
|
144
|
-
return `${defaultImport.code}
|
|
145
|
-
${indentation}const ${namespaceName} = ${defaultImport.bindingName};`;
|
|
146
|
-
}
|
|
147
|
-
if (remainder.startsWith("{") && remainder.endsWith("}")) {
|
|
148
|
-
const namedBindings = remainder.slice(1, -1).trim();
|
|
149
|
-
if (!namedBindings) {
|
|
150
|
-
return null;
|
|
151
|
-
}
|
|
152
|
-
return `${defaultImport.code}
|
|
153
|
-
${indentation}const { ${formatNamedImportBindings(namedBindings)} } = ${defaultImport.bindingName};`;
|
|
154
|
-
}
|
|
155
|
-
return null;
|
|
156
|
-
}
|
|
157
|
-
return buildDefaultImport(clause)?.code ?? null;
|
|
179
|
+
return `class ${name} ${trimmed}`;
|
|
158
180
|
}
|
|
159
|
-
function
|
|
160
|
-
const
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
return `${indentation}${trimmed.slice("export ".length)}`;
|
|
181
|
+
function findDeclaration(source, name) {
|
|
182
|
+
const escaped = escapeRegExp(name);
|
|
183
|
+
const matches = [];
|
|
184
|
+
const valueRegex = new RegExp(`(?:export\\s+)?(?:const|let|var)\\s+${escaped}(?:\\s*:\\s*[^=;]+)?\\s*=`, "m");
|
|
185
|
+
const valueMatch = valueRegex.exec(source);
|
|
186
|
+
if (valueMatch && valueMatch.index !== void 0) {
|
|
187
|
+
const equalsIndex = source.indexOf("=", valueMatch.index);
|
|
188
|
+
if (equalsIndex !== -1) {
|
|
189
|
+
const initializerEnd = findInitializerEnd(source, equalsIndex + 1);
|
|
190
|
+
const end = initializerEnd < source.length && source[initializerEnd] === ";" ? initializerEnd + 1 : initializerEnd;
|
|
191
|
+
matches.push({
|
|
192
|
+
kind: "valueDecl",
|
|
193
|
+
start: valueMatch.index,
|
|
194
|
+
end,
|
|
195
|
+
exported: /^\s*export\b/.test(valueMatch[0]),
|
|
196
|
+
prefixEnd: equalsIndex + 1
|
|
197
|
+
});
|
|
198
|
+
}
|
|
178
199
|
}
|
|
179
|
-
const
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
200
|
+
const functionRegex = new RegExp(`(?:export\\s+)?(?:async\\s+)?function\\s+${escaped}\\s*\\(`, "m");
|
|
201
|
+
const functionMatch = functionRegex.exec(source);
|
|
202
|
+
if (functionMatch && functionMatch.index !== void 0) {
|
|
203
|
+
const braceOpen = source.indexOf("{", functionMatch.index);
|
|
204
|
+
if (braceOpen !== -1) {
|
|
205
|
+
const braceClose = findMatchingBlockEnd(source, braceOpen);
|
|
206
|
+
const end = braceClose + 1 < source.length && source[braceClose + 1] === ";" ? braceClose + 2 : braceClose + 1;
|
|
207
|
+
matches.push({
|
|
208
|
+
kind: "functionDecl",
|
|
209
|
+
start: functionMatch.index,
|
|
210
|
+
end,
|
|
211
|
+
exported: /^\s*export\b/.test(functionMatch[0])
|
|
212
|
+
});
|
|
213
|
+
}
|
|
183
214
|
}
|
|
184
|
-
const
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
215
|
+
const classRegex = new RegExp(`(?:export\\s+)?class\\s+${escaped}(?=\\s|\\{)`, "m");
|
|
216
|
+
const classMatch = classRegex.exec(source);
|
|
217
|
+
if (classMatch && classMatch.index !== void 0) {
|
|
218
|
+
const braceOpen = source.indexOf("{", classMatch.index);
|
|
219
|
+
if (braceOpen !== -1) {
|
|
220
|
+
const braceClose = findMatchingBlockEnd(source, braceOpen);
|
|
221
|
+
const end = braceClose + 1 < source.length && source[braceClose + 1] === ";" ? braceClose + 2 : braceClose + 1;
|
|
222
|
+
matches.push({
|
|
223
|
+
kind: "classDecl",
|
|
224
|
+
start: classMatch.index,
|
|
225
|
+
end,
|
|
226
|
+
exported: /^\s*export\b/.test(classMatch[0])
|
|
227
|
+
});
|
|
228
|
+
}
|
|
188
229
|
}
|
|
189
|
-
if (
|
|
190
|
-
|
|
191
|
-
return specifiers.length > 0 ? `${indentation}${formatNamedExportAssignments(specifiers)}` : null;
|
|
230
|
+
if (matches.length === 0) {
|
|
231
|
+
return null;
|
|
192
232
|
}
|
|
193
|
-
|
|
233
|
+
matches.sort((left, right) => left.start - right.start);
|
|
234
|
+
return matches[0];
|
|
194
235
|
}
|
|
195
|
-
function
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
const namedExports = /* @__PURE__ */ new Set();
|
|
199
|
-
const nextImportBinding = () => `__vm_import_${importCounter++}`;
|
|
200
|
-
const resolveDefaultImport = (bindingName) => `${bindingName} && Object.prototype.hasOwnProperty.call(${bindingName}, "default") ? ${bindingName}.default : ${bindingName}`;
|
|
201
|
-
const code = source.split(/\r?\n/).map((line) => rewriteImportLine(line, nextImportBinding, resolveDefaultImport) ?? rewriteExportLine(line, namedExports, () => {
|
|
202
|
-
hasDefaultExport = true;
|
|
203
|
-
}) ?? line).join("\n");
|
|
204
|
-
const exportFooter = [...namedExports].map((name) => `module.exports.${name} = ${name};`);
|
|
205
|
-
if (hasDefaultExport) {
|
|
206
|
-
exportFooter.push("module.exports.default = module.exports;");
|
|
236
|
+
function createStructuredReplacement(kind, name, code) {
|
|
237
|
+
if (!shouldUseDeclarationSource(code)) {
|
|
238
|
+
return `const ${name} = ${toInitializerSource(code)};`;
|
|
207
239
|
}
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
` : code;
|
|
240
|
+
const source = code.toString();
|
|
241
|
+
return kind === "functionDecl" ? normalizeFunctionDeclaration(name, source) : normalizeClassDeclaration(name, source);
|
|
211
242
|
}
|
|
212
|
-
function
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
if (!esbuildTransformSync) {
|
|
218
|
-
throw new Error(`JSX database execution requires the esbuild package (${filename}).`);
|
|
243
|
+
function createDeclarationSnippet(name, code) {
|
|
244
|
+
if (typeof code === "function") {
|
|
245
|
+
const fnSource = code.toString().trim();
|
|
246
|
+
if (/^(?:async\s+)?function\b/.test(fnSource)) {
|
|
247
|
+
return `export ${normalizeFunctionDeclaration(name, fnSource)}`;
|
|
219
248
|
}
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
}
|
|
249
|
+
if (/^class\b/.test(fnSource)) {
|
|
250
|
+
return `export ${normalizeClassDeclaration(name, fnSource)}`;
|
|
251
|
+
}
|
|
252
|
+
return `export const ${name} = ${fnSource};`;
|
|
224
253
|
}
|
|
225
|
-
if (
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
};
|
|
230
|
-
} catch (error) {
|
|
231
|
-
const esbuildTransformSync = getEsbuildTransformSync();
|
|
232
|
-
if (!esbuildTransformSync) {
|
|
233
|
-
throw error;
|
|
234
|
-
}
|
|
235
|
-
return esbuildTransformSync(source, {
|
|
236
|
-
loader,
|
|
237
|
-
format: options.format
|
|
238
|
-
});
|
|
254
|
+
if (typeof code === "string") {
|
|
255
|
+
const trimmed = code.trim();
|
|
256
|
+
if (looksLikeDeclarationSnippet(trimmed)) {
|
|
257
|
+
return trimmed;
|
|
239
258
|
}
|
|
240
259
|
}
|
|
241
|
-
return {
|
|
242
|
-
code: rewriteModuleSyntaxToCommonJs(source)
|
|
243
|
-
};
|
|
260
|
+
return `export const ${name} = ${toInitializerSource(code)};`;
|
|
244
261
|
}
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
if (fs.existsSync(pkgPath)) {
|
|
259
|
-
this.pkgScriptDB = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
|
|
260
|
-
}
|
|
261
|
-
this.language = options?.language || "ts";
|
|
262
|
-
this.transpiler = transpileVmModule;
|
|
263
|
-
this.registerModules = options?.registerModules || {};
|
|
264
|
-
this._registerModules = { ...this.registerModules };
|
|
265
|
-
this._registerModules.require = ((moduleId) => this.createRequire(moduleId)).bind(this);
|
|
266
|
-
this.ctx = vm.createContext(this._registerModules);
|
|
262
|
+
function valueToCode(val, depth = 0) {
|
|
263
|
+
const indentUnit = " ";
|
|
264
|
+
const indent = indentUnit.repeat(depth);
|
|
265
|
+
const indentInner = indentUnit.repeat(depth + 1);
|
|
266
|
+
if (val === null) return "null";
|
|
267
|
+
const t = typeof val;
|
|
268
|
+
if (t === "string") return JSON.stringify(val);
|
|
269
|
+
if (t === "number" || t === "boolean") return String(val);
|
|
270
|
+
if (t === "function") return val.toString();
|
|
271
|
+
if (Array.isArray(val)) {
|
|
272
|
+
if (val.length === 0) return "[]";
|
|
273
|
+
const items = val.map((v) => valueToCode(v, depth + 1));
|
|
274
|
+
return "[\n" + items.map((it) => indentInner + it).join(",\n") + "\n" + indent + "]";
|
|
267
275
|
}
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
const
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
return originalRequire(moduleId);
|
|
278
|
-
}
|
|
279
|
-
throw e;
|
|
280
|
-
}
|
|
281
|
-
}).bind(this);
|
|
282
|
-
this.ctx = vm.createContext(this._registerModules);
|
|
276
|
+
if (t === "object") {
|
|
277
|
+
const keys = Object.keys(val);
|
|
278
|
+
if (keys.length === 0) return "{}";
|
|
279
|
+
const entries = keys.map((k) => {
|
|
280
|
+
const keyPart = isIdentifier(k) ? k : JSON.stringify(k);
|
|
281
|
+
const v = valueToCode(val[k], depth + 1);
|
|
282
|
+
return indentInner + keyPart + ": " + v;
|
|
283
|
+
});
|
|
284
|
+
return "{\n" + entries.join(",\n") + "\n" + indent + "}";
|
|
283
285
|
}
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
moduleId = "./" + relativePath;
|
|
293
|
-
console.log("[createRequire] Resolved @db/ alias to:", moduleId);
|
|
294
|
-
}
|
|
295
|
-
if (moduleId.startsWith("./") || moduleId.startsWith("../")) {
|
|
296
|
-
const dbDir = this.DATABASE_DIR || process.cwd();
|
|
297
|
-
const fullPath = path.join(dbDir, moduleId);
|
|
298
|
-
console.log("[createRequire] Full path:", fullPath);
|
|
299
|
-
let actualPath = fullPath;
|
|
300
|
-
if (fs.existsSync(fullPath)) {
|
|
301
|
-
actualPath = fullPath;
|
|
302
|
-
} else {
|
|
303
|
-
const extensions = [".ts", ".tsx", ".mts", ".cts", ".js", ".mjs", ".cjs"];
|
|
304
|
-
for (const ext of extensions) {
|
|
305
|
-
if (fs.existsSync(fullPath + ext)) {
|
|
306
|
-
actualPath = fullPath + ext;
|
|
307
|
-
break;
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
console.log("[createRequire] Actual path:", actualPath);
|
|
312
|
-
if (!actualPath || !fs.existsSync(actualPath)) {
|
|
313
|
-
console.log("[createRequire] File not found, throwing error");
|
|
314
|
-
throw new Error(`Module '${moduleId}' not found at ${fullPath}`);
|
|
315
|
-
}
|
|
316
|
-
if (actualPath.endsWith(".ts") || actualPath.endsWith(".tsx") || actualPath.endsWith(".mts") || actualPath.endsWith(".cts") || actualPath.endsWith(".js") || actualPath.endsWith(".mjs")) {
|
|
317
|
-
const content = fs.readFileSync(actualPath, "utf8");
|
|
318
|
-
const loader = actualPath.endsWith(".ts") || actualPath.endsWith(".mts") || actualPath.endsWith(".cts") ? "ts" : actualPath.endsWith(".tsx") ? "tsx" : "js";
|
|
319
|
-
const js = this.transpiler(content, {
|
|
320
|
-
loader,
|
|
321
|
-
format: "cjs",
|
|
322
|
-
filename: actualPath
|
|
323
|
-
}).code;
|
|
324
|
-
const moduleWrapper = { exports: {} };
|
|
325
|
-
const moduleContext = vm.createContext({
|
|
326
|
-
...this._registerModules,
|
|
327
|
-
module: moduleWrapper,
|
|
328
|
-
exports: moduleWrapper.exports
|
|
329
|
-
});
|
|
330
|
-
vm.runInContext(js, moduleContext, { filename: actualPath });
|
|
331
|
-
console.log("[createRequire] Returning exports:", moduleWrapper.exports);
|
|
332
|
-
return moduleWrapper.exports;
|
|
333
|
-
}
|
|
334
|
-
const result = __require(actualPath);
|
|
335
|
-
console.log("[createRequire] Returning (JS):", result);
|
|
336
|
-
return result;
|
|
337
|
-
}
|
|
338
|
-
return __require(moduleId);
|
|
286
|
+
return String(val);
|
|
287
|
+
}
|
|
288
|
+
function isIdentifier(key) {
|
|
289
|
+
return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key);
|
|
290
|
+
}
|
|
291
|
+
function buildDatabaseModuleSource(dbName, code, existingSource) {
|
|
292
|
+
if (typeof code === "string") {
|
|
293
|
+
return code;
|
|
339
294
|
}
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
let resolvedPath = query;
|
|
343
|
-
for (const [alias, target] of Object.entries(aliases)) {
|
|
344
|
-
if (resolvedPath.startsWith(alias + "/")) {
|
|
345
|
-
resolvedPath = resolvedPath.replace(alias, target);
|
|
346
|
-
break;
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
resolvedPath = path.normalize(resolvedPath);
|
|
350
|
-
return fileList.find((file) => {
|
|
351
|
-
const normalizedFile = path.normalize(file);
|
|
352
|
-
const fileWithoutExt = normalizedFile.replace(/\.[^/.]+$/, "");
|
|
353
|
-
return normalizedFile === resolvedPath || fileWithoutExt === resolvedPath || normalizedFile === resolvedPath + ".ts" || normalizedFile === resolvedPath + ".js";
|
|
354
|
-
});
|
|
295
|
+
if (typeof code === "function") {
|
|
296
|
+
return code.toString();
|
|
355
297
|
}
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
const
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
console.log("[moduleLinker] Resolved path:", dbResult);
|
|
362
|
-
if (dbResult) {
|
|
363
|
-
try {
|
|
364
|
-
const actualModule = await import(dbResult);
|
|
365
|
-
const exportNames = Object.keys(actualModule);
|
|
366
|
-
return new vm.SyntheticModule(
|
|
367
|
-
exportNames,
|
|
368
|
-
function() {
|
|
369
|
-
exportNames.forEach((key) => {
|
|
370
|
-
this.setExport(key, actualModule[key]);
|
|
371
|
-
});
|
|
372
|
-
},
|
|
373
|
-
{ identifier: specifier, context: referencingModule.context }
|
|
374
|
-
);
|
|
375
|
-
} catch (err) {
|
|
376
|
-
console.error(`Failed to load database module ${specifier}:`, err);
|
|
377
|
-
throw err;
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
const allowedPackages = Object.keys(this.pkgScriptDB.dependencies || {});
|
|
381
|
-
if (allowedPackages.includes(specifier)) {
|
|
382
|
-
try {
|
|
383
|
-
const modulePath = path.join(this.SCRIPTDB_DIR, "node_modules", specifier);
|
|
384
|
-
const actualModule = await import(modulePath);
|
|
385
|
-
const exportNames = Object.keys(actualModule);
|
|
386
|
-
return new vm.SyntheticModule(
|
|
387
|
-
exportNames,
|
|
388
|
-
function() {
|
|
389
|
-
exportNames.forEach((key) => {
|
|
390
|
-
this.setExport(key, actualModule[key]);
|
|
391
|
-
});
|
|
392
|
-
},
|
|
393
|
-
{ identifier: specifier, context: referencingModule.context }
|
|
394
|
-
);
|
|
395
|
-
} catch (err) {
|
|
396
|
-
console.error(`Failed to load workspace module ${specifier}:`, err);
|
|
397
|
-
throw err;
|
|
398
|
-
}
|
|
298
|
+
const serializedValue = valueToCode(code, 0);
|
|
299
|
+
if (existingSource && isIdentifier(dbName)) {
|
|
300
|
+
const updatedSource = replaceExistingBindingValue(existingSource, dbName, serializedValue);
|
|
301
|
+
if (updatedSource) {
|
|
302
|
+
return updatedSource;
|
|
399
303
|
}
|
|
400
|
-
throw new Error(`Module ${specifier} is not allowed or not found.`);
|
|
401
304
|
}
|
|
402
|
-
|
|
403
|
-
const
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
return `const { ${imports} } = require(${quote}${modulePath}${quote});`;
|
|
442
|
-
}
|
|
443
|
-
);
|
|
444
|
-
processedCode = processedCode.replace(
|
|
445
|
-
/import\s+(\w+)\s+from\s+(['"])([^'"]+)\2/g,
|
|
446
|
-
(_match, name, quote, modulePath) => {
|
|
447
|
-
return `const ${name} = require(${quote}${modulePath}${quote});`;
|
|
305
|
+
if (isIdentifier(dbName)) {
|
|
306
|
+
return `const ${dbName} = ${serializedValue};
|
|
307
|
+
|
|
308
|
+
export { ${dbName} };
|
|
309
|
+
export default ${dbName};
|
|
310
|
+
`;
|
|
311
|
+
}
|
|
312
|
+
return `const value = ${serializedValue};
|
|
313
|
+
|
|
314
|
+
export default value;
|
|
315
|
+
`;
|
|
316
|
+
}
|
|
317
|
+
function removeDatabaseModuleEntry(source, fnName) {
|
|
318
|
+
let nextSource = source;
|
|
319
|
+
const escaped = fnName.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
|
|
320
|
+
const startRe = new RegExp(
|
|
321
|
+
`function\\s+${escaped}\\s*\\(|\\bclass\\s+${escaped}\\b|\\b(?:const|let|var)\\s+${escaped}\\s*=\\s*(?:function\\b|class\\b|\\(|\\{|\\[)`,
|
|
322
|
+
"m"
|
|
323
|
+
);
|
|
324
|
+
const startMatch = nextSource.match(startRe);
|
|
325
|
+
if (startMatch && startMatch.index !== void 0) {
|
|
326
|
+
const startIdx = startMatch.index;
|
|
327
|
+
const len = nextSource.length;
|
|
328
|
+
const idxCurly = nextSource.indexOf("{", startIdx);
|
|
329
|
+
const idxBracket = nextSource.indexOf("[", startIdx);
|
|
330
|
+
let braceOpen = -1;
|
|
331
|
+
if (idxCurly === -1) braceOpen = idxBracket;
|
|
332
|
+
else if (idxBracket === -1) braceOpen = idxCurly;
|
|
333
|
+
else braceOpen = Math.min(idxCurly, idxBracket);
|
|
334
|
+
if (braceOpen !== -1) {
|
|
335
|
+
const openingChar = nextSource[braceOpen];
|
|
336
|
+
const closingChar = openingChar === "[" ? "]" : "}";
|
|
337
|
+
let index = braceOpen + 1;
|
|
338
|
+
let depth = 1;
|
|
339
|
+
while (index < len && depth > 0) {
|
|
340
|
+
const char = nextSource[index];
|
|
341
|
+
if (char === openingChar) depth += 1;
|
|
342
|
+
else if (char === closingChar) depth -= 1;
|
|
343
|
+
index += 1;
|
|
448
344
|
}
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
console.log("[run] DATABASE_DIR:", this.DATABASE_DIR);
|
|
454
|
-
try {
|
|
455
|
-
const moduleWrapper = { exports: {} };
|
|
456
|
-
const initialExports = moduleWrapper.exports;
|
|
457
|
-
const originalModule = this._registerModules.module;
|
|
458
|
-
const originalExports = this._registerModules.exports;
|
|
459
|
-
this._registerModules.module = moduleWrapper;
|
|
460
|
-
this._registerModules.exports = moduleWrapper.exports;
|
|
461
|
-
this.ctx = vm.createContext(this._registerModules);
|
|
462
|
-
let result;
|
|
463
|
-
try {
|
|
464
|
-
result = vm.runInContext(processedCode, this.ctx, {
|
|
465
|
-
filename: path.join(this.SCRIPTDB_DIR, "virtual-entry.js")
|
|
466
|
-
});
|
|
467
|
-
} finally {
|
|
468
|
-
if (originalModule) {
|
|
469
|
-
this._registerModules.module = originalModule;
|
|
470
|
-
} else {
|
|
471
|
-
delete this._registerModules.module;
|
|
472
|
-
}
|
|
473
|
-
if (originalExports) {
|
|
474
|
-
this._registerModules.exports = originalExports;
|
|
475
|
-
} else {
|
|
476
|
-
delete this._registerModules.exports;
|
|
477
|
-
}
|
|
478
|
-
this.ctx = vm.createContext(this._registerModules);
|
|
345
|
+
const braceClose = index;
|
|
346
|
+
let endIdx = braceClose;
|
|
347
|
+
if (nextSource.slice(braceClose, braceClose + 1) === ";") {
|
|
348
|
+
endIdx = braceClose + 1;
|
|
479
349
|
}
|
|
480
|
-
const
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
350
|
+
const before = nextSource.slice(0, startIdx);
|
|
351
|
+
const after = nextSource.slice(endIdx);
|
|
352
|
+
nextSource = before + after;
|
|
353
|
+
} else {
|
|
354
|
+
const semi = nextSource.indexOf(";", startIdx);
|
|
355
|
+
let endIdx = semi !== -1 ? semi + 1 : nextSource.indexOf("\n\n", startIdx);
|
|
356
|
+
if (endIdx === -1) endIdx = len;
|
|
357
|
+
nextSource = nextSource.slice(0, startIdx) + nextSource.slice(endIdx);
|
|
488
358
|
}
|
|
489
359
|
}
|
|
490
|
-
|
|
360
|
+
const exportRe = new RegExp(
|
|
361
|
+
`export\\s+const\\s+${escaped}\\s*:\\s*any\\s*=\\s*${escaped}\\s*;?`,
|
|
362
|
+
"g"
|
|
363
|
+
);
|
|
364
|
+
nextSource = nextSource.replace(exportRe, "");
|
|
365
|
+
return nextSource.replace(/\n{3,}/g, "\n\n");
|
|
366
|
+
}
|
|
367
|
+
function updateDatabaseModuleSource(source, fnName, code) {
|
|
368
|
+
let nextSource = source;
|
|
369
|
+
const declaration = findDeclaration(nextSource, fnName);
|
|
370
|
+
if (declaration) {
|
|
371
|
+
if (declaration.kind === "valueDecl" && declaration.prefixEnd !== void 0) {
|
|
372
|
+
const initializer = toInitializerSource(code);
|
|
373
|
+
nextSource = nextSource.slice(0, declaration.start) + nextSource.slice(declaration.start, declaration.prefixEnd) + ` ${initializer};` + nextSource.slice(declaration.end);
|
|
374
|
+
} else if (declaration.kind === "functionDecl") {
|
|
375
|
+
const replacement = createStructuredReplacement("functionDecl", fnName, code);
|
|
376
|
+
nextSource = nextSource.slice(0, declaration.start) + `${declaration.exported ? "export " : ""}${replacement.replace(/^export\s+/, "")}` + nextSource.slice(declaration.end);
|
|
377
|
+
} else {
|
|
378
|
+
const replacement = createStructuredReplacement("classDecl", fnName, code);
|
|
379
|
+
nextSource = nextSource.slice(0, declaration.start) + `${declaration.exported ? "export " : ""}${replacement.replace(/^export\s+/, "")}` + nextSource.slice(declaration.end);
|
|
380
|
+
}
|
|
381
|
+
} else {
|
|
382
|
+
const snippet = createDeclarationSnippet(fnName, code);
|
|
383
|
+
const separator = nextSource.trim().length > 0 ? "\n\n" : "";
|
|
384
|
+
nextSource = `${nextSource.trimEnd()}${separator}${snippet}
|
|
385
|
+
`;
|
|
386
|
+
}
|
|
387
|
+
return {
|
|
388
|
+
source: nextSource,
|
|
389
|
+
changed: nextSource !== source
|
|
390
|
+
};
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
// src/server/database/operations.ts
|
|
394
|
+
function getDatabaseDirectory(options) {
|
|
395
|
+
return options?.dir || path.join(process.cwd(), "databases");
|
|
396
|
+
}
|
|
397
|
+
function getDatabasePath(dbName, options) {
|
|
398
|
+
return path.join(getDatabaseDirectory(options), `${dbName}.ts`);
|
|
399
|
+
}
|
|
491
400
|
function create(dbName, code, options) {
|
|
492
|
-
const
|
|
493
|
-
const dbPath = path.join(DIR, `${dbName}.ts`);
|
|
401
|
+
const dbPath = getDatabasePath(dbName, options);
|
|
494
402
|
fs.appendFileSync(dbPath, code.toString(), "utf8");
|
|
495
403
|
}
|
|
496
404
|
function read(dbName, options) {
|
|
497
|
-
const
|
|
498
|
-
const dbPath = path.join(DIR, `${dbName}.ts`);
|
|
405
|
+
const dbPath = getDatabasePath(dbName, options);
|
|
499
406
|
if (!fs.existsSync(dbPath)) {
|
|
500
407
|
throw new Error(`Database '${dbName}' not found`);
|
|
501
408
|
}
|
|
502
409
|
return fs.readFileSync(dbPath, "utf8");
|
|
503
410
|
}
|
|
504
411
|
function remove(dbName, fnName, options) {
|
|
505
|
-
const
|
|
506
|
-
const dbPath = path.join(DIR, `${dbName}.ts`);
|
|
412
|
+
const dbPath = getDatabasePath(dbName, options);
|
|
507
413
|
if (!fs.existsSync(dbPath)) return false;
|
|
508
414
|
if (!fnName) {
|
|
509
415
|
const bak2 = `${dbPath}.bak`;
|
|
510
416
|
try {
|
|
511
417
|
fs.copyFileSync(dbPath, bak2);
|
|
512
|
-
} catch
|
|
418
|
+
} catch {
|
|
513
419
|
}
|
|
514
420
|
try {
|
|
515
421
|
fs.unlinkSync(dbPath);
|
|
516
422
|
return "Removed successfully";
|
|
517
|
-
} catch
|
|
423
|
+
} catch {
|
|
518
424
|
return "Removed failed";
|
|
519
425
|
}
|
|
520
426
|
}
|
|
521
427
|
const bak = `${dbPath}.bak`;
|
|
522
428
|
try {
|
|
523
429
|
fs.copyFileSync(dbPath, bak);
|
|
524
|
-
} catch
|
|
525
|
-
}
|
|
526
|
-
let src = fs.readFileSync(dbPath, "utf8");
|
|
527
|
-
const escaped = fnName.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
|
|
528
|
-
const startRe = new RegExp(
|
|
529
|
-
`function\\s+${escaped}\\s*\\(|\\bclass\\s+${escaped}\\b|\\b(?:const|let|var)\\s+${escaped}\\s*=\\s*(?:function\\b|class\\b|\\(|\\{|\\[)`,
|
|
530
|
-
"m"
|
|
531
|
-
);
|
|
532
|
-
const startMatch = src.match(startRe);
|
|
533
|
-
if (startMatch) {
|
|
534
|
-
const startIdx = startMatch.index;
|
|
535
|
-
const len = src.length;
|
|
536
|
-
const idxCurly = src.indexOf("{", startIdx);
|
|
537
|
-
const idxBracket = src.indexOf("[", startIdx);
|
|
538
|
-
let braceOpen = -1;
|
|
539
|
-
if (idxCurly === -1) braceOpen = idxBracket;
|
|
540
|
-
else if (idxBracket === -1) braceOpen = idxCurly;
|
|
541
|
-
else braceOpen = Math.min(idxCurly, idxBracket);
|
|
542
|
-
if (braceOpen !== -1) {
|
|
543
|
-
const openingChar = src[braceOpen];
|
|
544
|
-
const closingChar = openingChar === "[" ? "]" : "}";
|
|
545
|
-
let i = braceOpen + 1;
|
|
546
|
-
let depth = 1;
|
|
547
|
-
while (i < len && depth > 0) {
|
|
548
|
-
const ch = src[i];
|
|
549
|
-
if (ch === openingChar) depth++;
|
|
550
|
-
else if (ch === closingChar) depth--;
|
|
551
|
-
i++;
|
|
552
|
-
}
|
|
553
|
-
let braceClose = i;
|
|
554
|
-
let endIdx = braceClose;
|
|
555
|
-
if (src.slice(braceClose, braceClose + 1) === ";")
|
|
556
|
-
endIdx = braceClose + 1;
|
|
557
|
-
const before = src.slice(0, startIdx);
|
|
558
|
-
const after = src.slice(endIdx);
|
|
559
|
-
src = before + after;
|
|
560
|
-
} else {
|
|
561
|
-
const semi = src.indexOf(";", startIdx);
|
|
562
|
-
let endIdx = semi !== -1 ? semi + 1 : src.indexOf("\n\n", startIdx);
|
|
563
|
-
if (endIdx === -1) endIdx = len;
|
|
564
|
-
src = src.slice(0, startIdx) + src.slice(endIdx);
|
|
565
|
-
}
|
|
430
|
+
} catch {
|
|
566
431
|
}
|
|
567
|
-
const
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
);
|
|
571
|
-
src = src.replace(exportRe, "");
|
|
572
|
-
src = src.replace(/\n{3,}/g, "\n\n");
|
|
573
|
-
fs.writeFileSync(dbPath, src, "utf8");
|
|
432
|
+
const source = fs.readFileSync(dbPath, "utf8");
|
|
433
|
+
const nextSource = removeDatabaseModuleEntry(source, fnName);
|
|
434
|
+
fs.writeFileSync(dbPath, nextSource, "utf8");
|
|
574
435
|
return `Removed ${fnName} from database ${dbName}.`;
|
|
575
436
|
}
|
|
576
437
|
function rename(oldName, newName, options) {
|
|
577
|
-
const
|
|
578
|
-
const oldPath = path.join(
|
|
579
|
-
const newPath = path.join(
|
|
438
|
+
const dir = getDatabaseDirectory(options);
|
|
439
|
+
const oldPath = path.join(dir, `${oldName}.ts`);
|
|
440
|
+
const newPath = path.join(dir, `${newName}.ts`);
|
|
580
441
|
if (!fs.existsSync(oldPath)) {
|
|
581
442
|
return `Error: File '${oldName}.ts' does not exist in the database`;
|
|
582
443
|
}
|
|
@@ -590,352 +451,271 @@ function rename(oldName, newName, options) {
|
|
|
590
451
|
return `Error renaming file: ${error instanceof Error ? error.message : String(error)}`;
|
|
591
452
|
}
|
|
592
453
|
}
|
|
593
|
-
function
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
let stringChar = null;
|
|
599
|
-
for (let index = openIndex; index < source.length; index += 1) {
|
|
600
|
-
const char = source[index];
|
|
601
|
-
const nextChar = source[index + 1];
|
|
602
|
-
if (stringChar) {
|
|
603
|
-
if (char === "\\") {
|
|
604
|
-
index += 1;
|
|
605
|
-
continue;
|
|
606
|
-
}
|
|
607
|
-
if (char === stringChar) {
|
|
608
|
-
stringChar = null;
|
|
609
|
-
}
|
|
610
|
-
continue;
|
|
611
|
-
}
|
|
612
|
-
if (char === "/" && nextChar === "/") {
|
|
613
|
-
index += 2;
|
|
614
|
-
while (index < source.length && source[index] !== "\n") {
|
|
615
|
-
index += 1;
|
|
616
|
-
}
|
|
617
|
-
continue;
|
|
618
|
-
}
|
|
619
|
-
if (char === "/" && nextChar === "*") {
|
|
620
|
-
index += 2;
|
|
621
|
-
while (index < source.length && !(source[index] === "*" && source[index + 1] === "/")) {
|
|
622
|
-
index += 1;
|
|
623
|
-
}
|
|
624
|
-
index += 1;
|
|
625
|
-
continue;
|
|
626
|
-
}
|
|
627
|
-
if (char === '"' || char === "'" || char === "`") {
|
|
628
|
-
stringChar = char;
|
|
629
|
-
continue;
|
|
630
|
-
}
|
|
631
|
-
if (char === "{") {
|
|
632
|
-
depth += 1;
|
|
633
|
-
} else if (char === "}") {
|
|
634
|
-
depth -= 1;
|
|
635
|
-
if (depth === 0) {
|
|
636
|
-
return index;
|
|
637
|
-
}
|
|
638
|
-
}
|
|
639
|
-
}
|
|
640
|
-
return source.length - 1;
|
|
454
|
+
function save(dbName, code, options) {
|
|
455
|
+
const dbPath = getDatabasePath(dbName, options);
|
|
456
|
+
const existingSource = fs.existsSync(dbPath) ? fs.readFileSync(dbPath, "utf8") : void 0;
|
|
457
|
+
const fileContent = buildDatabaseModuleSource(dbName, code, existingSource);
|
|
458
|
+
fs.writeFileSync(dbPath, fileContent, "utf8");
|
|
641
459
|
}
|
|
642
|
-
function
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
const nextChar = source[index + 1];
|
|
650
|
-
if (stringChar) {
|
|
651
|
-
if (char === "\\") {
|
|
652
|
-
index += 1;
|
|
653
|
-
continue;
|
|
654
|
-
}
|
|
655
|
-
if (char === stringChar) {
|
|
656
|
-
stringChar = null;
|
|
657
|
-
}
|
|
658
|
-
continue;
|
|
659
|
-
}
|
|
660
|
-
if (char === "/" && nextChar === "/") {
|
|
661
|
-
index += 2;
|
|
662
|
-
while (index < source.length && source[index] !== "\n") {
|
|
663
|
-
index += 1;
|
|
664
|
-
}
|
|
665
|
-
continue;
|
|
666
|
-
}
|
|
667
|
-
if (char === "/" && nextChar === "*") {
|
|
668
|
-
index += 2;
|
|
669
|
-
while (index < source.length && !(source[index] === "*" && source[index + 1] === "/")) {
|
|
670
|
-
index += 1;
|
|
671
|
-
}
|
|
672
|
-
index += 1;
|
|
673
|
-
continue;
|
|
674
|
-
}
|
|
675
|
-
if (char === '"' || char === "'" || char === "`") {
|
|
676
|
-
stringChar = char;
|
|
677
|
-
continue;
|
|
678
|
-
}
|
|
679
|
-
if (char === "{") {
|
|
680
|
-
braceDepth += 1;
|
|
681
|
-
} else if (char === "}") {
|
|
682
|
-
braceDepth = Math.max(0, braceDepth - 1);
|
|
683
|
-
} else if (char === "[") {
|
|
684
|
-
bracketDepth += 1;
|
|
685
|
-
} else if (char === "]") {
|
|
686
|
-
bracketDepth = Math.max(0, bracketDepth - 1);
|
|
687
|
-
} else if (char === "(") {
|
|
688
|
-
parenDepth += 1;
|
|
689
|
-
} else if (char === ")") {
|
|
690
|
-
parenDepth = Math.max(0, parenDepth - 1);
|
|
691
|
-
} else if (char === ";" && braceDepth === 0 && bracketDepth === 0 && parenDepth === 0) {
|
|
692
|
-
return index;
|
|
460
|
+
function update(dbName, fnName, code, options) {
|
|
461
|
+
const dbPath = getDatabasePath(dbName, options);
|
|
462
|
+
if (!fs.existsSync(dbPath)) {
|
|
463
|
+
try {
|
|
464
|
+
fs.writeFileSync(dbPath, "", "utf8");
|
|
465
|
+
} catch {
|
|
466
|
+
return `Failed to create dbPath file: ${dbPath}`;
|
|
693
467
|
}
|
|
694
468
|
}
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
}
|
|
701
|
-
function replaceExistingBindingValue(source, bindingName, serializedValue) {
|
|
702
|
-
const escapedName = escapeRegExp(bindingName);
|
|
703
|
-
const declarationRegex = new RegExp(`(?:export\\s+)?(?:const|let|var)\\s+${escapedName}(?:\\s*:\\s*[^=;]+)?\\s*=`, "m");
|
|
704
|
-
const declarationMatch = declarationRegex.exec(source);
|
|
705
|
-
if (!declarationMatch || declarationMatch.index === void 0) {
|
|
706
|
-
return null;
|
|
707
|
-
}
|
|
708
|
-
const equalsIndex = source.indexOf("=", declarationMatch.index);
|
|
709
|
-
if (equalsIndex === -1) {
|
|
710
|
-
return null;
|
|
469
|
+
const source = fs.readFileSync(dbPath, "utf8");
|
|
470
|
+
const result = updateDatabaseModuleSource(source, fnName, code);
|
|
471
|
+
fs.writeFileSync(dbPath, result.source, "utf8");
|
|
472
|
+
if (!result.changed) {
|
|
473
|
+
return `Saved ${fnName} to database ${dbName}.`;
|
|
711
474
|
}
|
|
712
|
-
|
|
713
|
-
const suffix = initializerEnd < source.length ? source.slice(initializerEnd) : ";";
|
|
714
|
-
return `${source.slice(0, equalsIndex + 1)} ${serializedValue}${suffix}`;
|
|
475
|
+
return `Updated ${dbName} with ${fnName}.`;
|
|
715
476
|
}
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
477
|
+
|
|
478
|
+
// src/server/database/vm.ts
|
|
479
|
+
import fs2 from "fs";
|
|
480
|
+
import path3 from "path";
|
|
481
|
+
import vm from "vm";
|
|
482
|
+
|
|
483
|
+
// src/server/database/transpile.ts
|
|
484
|
+
import path2 from "path";
|
|
485
|
+
import * as nodeModule from "module";
|
|
486
|
+
var stripTypeScriptTypes2 = typeof nodeModule.stripTypeScriptTypes === "function" ? nodeModule.stripTypeScriptTypes : void 0;
|
|
487
|
+
var cachedEsbuildTransformSync;
|
|
488
|
+
function getEsbuildTransformSync() {
|
|
489
|
+
if (cachedEsbuildTransformSync !== void 0) {
|
|
490
|
+
return cachedEsbuildTransformSync;
|
|
719
491
|
}
|
|
720
|
-
if (typeof
|
|
721
|
-
|
|
492
|
+
if (typeof nodeModule.createRequire !== "function") {
|
|
493
|
+
cachedEsbuildTransformSync = null;
|
|
494
|
+
return cachedEsbuildTransformSync;
|
|
722
495
|
}
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
const
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
}
|
|
496
|
+
try {
|
|
497
|
+
const requireFromApp = nodeModule.createRequire(path2.join(process.cwd(), "package.json"));
|
|
498
|
+
const esbuildModule = requireFromApp("esbuild");
|
|
499
|
+
cachedEsbuildTransformSync = typeof esbuildModule?.transformSync === "function" ? esbuildModule.transformSync.bind(esbuildModule) : null;
|
|
500
|
+
} catch {
|
|
501
|
+
cachedEsbuildTransformSync = null;
|
|
730
502
|
}
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
503
|
+
return cachedEsbuildTransformSync;
|
|
504
|
+
}
|
|
505
|
+
function parseModuleBindings(specifiers) {
|
|
506
|
+
return specifiers.split(",").map((entry) => entry.trim()).filter((entry) => entry.length > 0).map((entry) => {
|
|
507
|
+
const [imported, local] = entry.split(/\s+as\s+/);
|
|
508
|
+
return {
|
|
509
|
+
imported: (imported || "").trim(),
|
|
510
|
+
local: (local || imported || "").trim()
|
|
511
|
+
};
|
|
512
|
+
}).filter((entry) => entry.imported.length > 0 && entry.local.length > 0);
|
|
513
|
+
}
|
|
514
|
+
function formatNamedImportBindings(specifiers) {
|
|
515
|
+
return parseModuleBindings(specifiers).map(({ imported, local }) => imported === local ? imported : `${imported}: ${local}`).join(", ");
|
|
516
|
+
}
|
|
517
|
+
function formatNamedExportAssignments(specifiers) {
|
|
518
|
+
return parseModuleBindings(specifiers).map(({ imported, local }) => `module.exports.${local} = ${imported};`).join("\n");
|
|
519
|
+
}
|
|
520
|
+
function stripTypescriptSource(source, filename) {
|
|
521
|
+
if (!stripTypeScriptTypes2) {
|
|
522
|
+
throw new Error("TypeScript database execution requires Node.js 22+ or the esbuild package.");
|
|
523
|
+
}
|
|
524
|
+
const originalEmitWarning = process.emitWarning;
|
|
525
|
+
try {
|
|
526
|
+
process.emitWarning = ((warning, ...args) => {
|
|
527
|
+
if (typeof warning === "string" && warning.includes("stripTypeScriptTypes")) {
|
|
528
|
+
return;
|
|
529
|
+
}
|
|
530
|
+
return originalEmitWarning.call(process, warning, ...args);
|
|
531
|
+
});
|
|
532
|
+
return stripTypeScriptTypes2(source, {
|
|
533
|
+
mode: "transform",
|
|
534
|
+
sourceUrl: filename
|
|
535
|
+
});
|
|
536
|
+
} finally {
|
|
537
|
+
process.emitWarning = originalEmitWarning;
|
|
737
538
|
}
|
|
738
|
-
return `const value = ${serializedValue};
|
|
739
|
-
|
|
740
|
-
export default value;
|
|
741
|
-
`;
|
|
742
539
|
}
|
|
743
|
-
function
|
|
744
|
-
|
|
745
|
-
|
|
540
|
+
function isSimpleIdentifier(value) {
|
|
541
|
+
return /^[A-Za-z_$][\w$]*$/.test(value);
|
|
542
|
+
}
|
|
543
|
+
function stripOptionalLineTerminator(value) {
|
|
544
|
+
const trimmed = value.trim();
|
|
545
|
+
return trimmed.endsWith(";") ? trimmed.slice(0, -1).trimEnd() : trimmed;
|
|
546
|
+
}
|
|
547
|
+
function parseQuotedModulePath(value) {
|
|
548
|
+
const trimmed = value.trim();
|
|
549
|
+
if (trimmed.length < 2) {
|
|
550
|
+
return null;
|
|
746
551
|
}
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
return trimmed;
|
|
751
|
-
}
|
|
752
|
-
return valueToCode(code, 0);
|
|
552
|
+
const quote = trimmed[0];
|
|
553
|
+
if (quote !== '"' && quote !== "'" || trimmed[trimmed.length - 1] !== quote) {
|
|
554
|
+
return null;
|
|
753
555
|
}
|
|
754
|
-
return
|
|
556
|
+
return trimmed.slice(1, -1);
|
|
755
557
|
}
|
|
756
|
-
function
|
|
757
|
-
|
|
558
|
+
function getLineIndentation(line) {
|
|
559
|
+
const match = line.match(/^\s*/);
|
|
560
|
+
return match?.[0] ?? "";
|
|
758
561
|
}
|
|
759
|
-
function
|
|
760
|
-
const
|
|
761
|
-
|
|
762
|
-
|
|
562
|
+
function rewriteImportLine(line, nextImportBinding, resolveDefaultImport) {
|
|
563
|
+
const indentation = getLineIndentation(line);
|
|
564
|
+
const trimmed = stripOptionalLineTerminator(line);
|
|
565
|
+
if (!trimmed.startsWith("import ")) {
|
|
566
|
+
return null;
|
|
763
567
|
}
|
|
764
|
-
|
|
765
|
-
|
|
568
|
+
const importBody = trimmed.slice("import ".length).trim();
|
|
569
|
+
const sideEffectModulePath = parseQuotedModulePath(importBody);
|
|
570
|
+
if (sideEffectModulePath !== null) {
|
|
571
|
+
return `${indentation}require(${JSON.stringify(sideEffectModulePath)});`;
|
|
766
572
|
}
|
|
767
|
-
|
|
768
|
-
|
|
573
|
+
const fromIndex = importBody.lastIndexOf(" from ");
|
|
574
|
+
if (fromIndex === -1) {
|
|
575
|
+
return null;
|
|
769
576
|
}
|
|
770
|
-
|
|
771
|
-
|
|
577
|
+
const clause = importBody.slice(0, fromIndex).trim();
|
|
578
|
+
const modulePath = parseQuotedModulePath(importBody.slice(fromIndex + 6));
|
|
579
|
+
if (!clause || modulePath === null) {
|
|
580
|
+
return null;
|
|
772
581
|
}
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
}
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
582
|
+
const buildDefaultImport = (defaultName) => {
|
|
583
|
+
if (!isSimpleIdentifier(defaultName)) {
|
|
584
|
+
return null;
|
|
585
|
+
}
|
|
586
|
+
const bindingName = nextImportBinding();
|
|
587
|
+
return {
|
|
588
|
+
bindingName,
|
|
589
|
+
code: [
|
|
590
|
+
`${indentation}const ${bindingName} = require(${JSON.stringify(modulePath)});`,
|
|
591
|
+
`${indentation}const ${defaultName} = ${resolveDefaultImport(bindingName)};`
|
|
592
|
+
].join("\n")
|
|
593
|
+
};
|
|
594
|
+
};
|
|
595
|
+
if (clause.startsWith("* as ")) {
|
|
596
|
+
const namespaceName = clause.slice(5).trim();
|
|
597
|
+
return isSimpleIdentifier(namespaceName) ? `${indentation}const ${namespaceName} = require(${JSON.stringify(modulePath)});` : null;
|
|
781
598
|
}
|
|
782
|
-
if (
|
|
783
|
-
|
|
599
|
+
if (clause.startsWith("{") && clause.endsWith("}")) {
|
|
600
|
+
const namedBindings = clause.slice(1, -1).trim();
|
|
601
|
+
return namedBindings.length > 0 ? `${indentation}const { ${formatNamedImportBindings(namedBindings)} } = require(${JSON.stringify(modulePath)});` : null;
|
|
784
602
|
}
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
if (valueMatch && valueMatch.index !== void 0) {
|
|
793
|
-
const equalsIndex = source.indexOf("=", valueMatch.index);
|
|
794
|
-
if (equalsIndex !== -1) {
|
|
795
|
-
const initializerEnd = findInitializerEnd(source, equalsIndex + 1);
|
|
796
|
-
const end = initializerEnd < source.length && source[initializerEnd] === ";" ? initializerEnd + 1 : initializerEnd;
|
|
797
|
-
matches.push({
|
|
798
|
-
kind: "valueDecl",
|
|
799
|
-
start: valueMatch.index,
|
|
800
|
-
end,
|
|
801
|
-
exported: /^\s*export\b/.test(valueMatch[0]),
|
|
802
|
-
prefixEnd: equalsIndex + 1
|
|
803
|
-
});
|
|
603
|
+
const commaIndex = clause.indexOf(",");
|
|
604
|
+
if (commaIndex !== -1) {
|
|
605
|
+
const defaultName = clause.slice(0, commaIndex).trim();
|
|
606
|
+
const remainder = clause.slice(commaIndex + 1).trim();
|
|
607
|
+
const defaultImport = buildDefaultImport(defaultName);
|
|
608
|
+
if (!defaultImport) {
|
|
609
|
+
return null;
|
|
804
610
|
}
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
const end = braceClose + 1 < source.length && source[braceClose + 1] === ";" ? braceClose + 2 : braceClose + 1;
|
|
813
|
-
matches.push({
|
|
814
|
-
kind: "functionDecl",
|
|
815
|
-
start: functionMatch.index,
|
|
816
|
-
end,
|
|
817
|
-
exported: /^\s*export\b/.test(functionMatch[0])
|
|
818
|
-
});
|
|
611
|
+
if (remainder.startsWith("* as ")) {
|
|
612
|
+
const namespaceName = remainder.slice(5).trim();
|
|
613
|
+
if (!isSimpleIdentifier(namespaceName)) {
|
|
614
|
+
return null;
|
|
615
|
+
}
|
|
616
|
+
return `${defaultImport.code}
|
|
617
|
+
${indentation}const ${namespaceName} = ${defaultImport.bindingName};`;
|
|
819
618
|
}
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
const end = braceClose + 1 < source.length && source[braceClose + 1] === ";" ? braceClose + 2 : braceClose + 1;
|
|
828
|
-
matches.push({
|
|
829
|
-
kind: "classDecl",
|
|
830
|
-
start: classMatch.index,
|
|
831
|
-
end,
|
|
832
|
-
exported: /^\s*export\b/.test(classMatch[0])
|
|
833
|
-
});
|
|
619
|
+
if (remainder.startsWith("{") && remainder.endsWith("}")) {
|
|
620
|
+
const namedBindings = remainder.slice(1, -1).trim();
|
|
621
|
+
if (!namedBindings) {
|
|
622
|
+
return null;
|
|
623
|
+
}
|
|
624
|
+
return `${defaultImport.code}
|
|
625
|
+
${indentation}const { ${formatNamedImportBindings(namedBindings)} } = ${defaultImport.bindingName};`;
|
|
834
626
|
}
|
|
835
|
-
}
|
|
836
|
-
if (matches.length === 0) {
|
|
837
627
|
return null;
|
|
838
628
|
}
|
|
839
|
-
|
|
840
|
-
return matches[0];
|
|
629
|
+
return buildDefaultImport(clause)?.code ?? null;
|
|
841
630
|
}
|
|
842
|
-
function
|
|
843
|
-
|
|
844
|
-
|
|
631
|
+
function rewriteExportLine(line, namedExports, markDefaultExport) {
|
|
632
|
+
const trimmed = stripOptionalLineTerminator(line);
|
|
633
|
+
if (!trimmed.startsWith("export ")) {
|
|
634
|
+
return null;
|
|
845
635
|
}
|
|
846
|
-
const
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
if (typeof code === "function") {
|
|
851
|
-
const fnSource = code.toString().trim();
|
|
852
|
-
if (/^(?:async\s+)?function\b/.test(fnSource)) {
|
|
853
|
-
return `export ${normalizeFunctionDeclaration(name, fnSource)}`;
|
|
854
|
-
}
|
|
855
|
-
if (/^class\b/.test(fnSource)) {
|
|
856
|
-
return `export ${normalizeClassDeclaration(name, fnSource)}`;
|
|
857
|
-
}
|
|
858
|
-
return `export const ${name} = ${fnSource};`;
|
|
636
|
+
const indentation = getLineIndentation(line);
|
|
637
|
+
if (trimmed.startsWith("export default ")) {
|
|
638
|
+
markDefaultExport();
|
|
639
|
+
return `${indentation}module.exports = ${trimmed.slice("export default ".length)}`;
|
|
859
640
|
}
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
}
|
|
641
|
+
const valueDeclarationMatch = /^export\s+(const|let|var)\s+([A-Za-z_$][\w$]*)\b/.exec(trimmed);
|
|
642
|
+
if (valueDeclarationMatch) {
|
|
643
|
+
namedExports.add(valueDeclarationMatch[2]);
|
|
644
|
+
return `${indentation}${trimmed.slice("export ".length)}`;
|
|
865
645
|
}
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
const dbPath = path.join(DIR, `${dbName}.ts`);
|
|
871
|
-
const fileContent = buildDatabaseModuleSource(dbName, code, dbPath);
|
|
872
|
-
fs.writeFileSync(dbPath, fileContent, "utf8");
|
|
873
|
-
}
|
|
874
|
-
function update(dbName, fnName, code, options) {
|
|
875
|
-
const DIR = options?.dir || path.join(process.cwd(), "databases");
|
|
876
|
-
const dbPath = path.join(DIR, `${dbName}.ts`);
|
|
877
|
-
if (!fs.existsSync(dbPath)) {
|
|
878
|
-
try {
|
|
879
|
-
fs.writeFileSync(dbPath, "", "utf8");
|
|
880
|
-
} catch {
|
|
881
|
-
return `Failed to create dbPath file: ${dbPath}`;
|
|
882
|
-
}
|
|
646
|
+
const asyncFunctionMatch = /^export\s+async\s+function\s+([A-Za-z_$][\w$]*)\b/.exec(trimmed);
|
|
647
|
+
if (asyncFunctionMatch) {
|
|
648
|
+
namedExports.add(asyncFunctionMatch[1]);
|
|
649
|
+
return `${indentation}${trimmed.slice("export ".length)}`;
|
|
883
650
|
}
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
if (declaration.kind === "valueDecl" && declaration.prefixEnd !== void 0) {
|
|
889
|
-
const initializer = toInitializerSource(code);
|
|
890
|
-
src = src.slice(0, declaration.start) + src.slice(declaration.start, declaration.prefixEnd) + ` ${initializer};` + src.slice(declaration.end);
|
|
891
|
-
} else if (declaration.kind === "functionDecl") {
|
|
892
|
-
const replacement = createStructuredReplacement("functionDecl", fnName, code);
|
|
893
|
-
src = src.slice(0, declaration.start) + `${declaration.exported ? "export " : ""}${replacement.replace(/^export\s+/, "")}` + src.slice(declaration.end);
|
|
894
|
-
} else {
|
|
895
|
-
const replacement = createStructuredReplacement("classDecl", fnName, code);
|
|
896
|
-
src = src.slice(0, declaration.start) + `${declaration.exported ? "export " : ""}${replacement.replace(/^export\s+/, "")}` + src.slice(declaration.end);
|
|
897
|
-
}
|
|
898
|
-
} else {
|
|
899
|
-
const snippet = createDeclarationSnippet(fnName, code);
|
|
900
|
-
const separator = src.trim().length > 0 ? "\n\n" : "";
|
|
901
|
-
src = `${src.trimEnd()}${separator}${snippet}
|
|
902
|
-
`;
|
|
651
|
+
const functionMatch = /^export\s+function\s+([A-Za-z_$][\w$]*)\b/.exec(trimmed);
|
|
652
|
+
if (functionMatch) {
|
|
653
|
+
namedExports.add(functionMatch[1]);
|
|
654
|
+
return `${indentation}${trimmed.slice("export ".length)}`;
|
|
903
655
|
}
|
|
904
|
-
|
|
905
|
-
if (
|
|
906
|
-
|
|
656
|
+
const classMatch = /^export\s+class\s+([A-Za-z_$][\w$]*)\b/.exec(trimmed);
|
|
657
|
+
if (classMatch) {
|
|
658
|
+
namedExports.add(classMatch[1]);
|
|
659
|
+
return `${indentation}${trimmed.slice("export ".length)}`;
|
|
907
660
|
}
|
|
908
|
-
|
|
661
|
+
if (trimmed.startsWith("export {") && trimmed.endsWith("}")) {
|
|
662
|
+
const specifiers = trimmed.slice("export {".length, -1).trim();
|
|
663
|
+
return specifiers.length > 0 ? `${indentation}${formatNamedExportAssignments(specifiers)}` : null;
|
|
664
|
+
}
|
|
665
|
+
return null;
|
|
909
666
|
}
|
|
910
|
-
function
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
const
|
|
914
|
-
|
|
915
|
-
const
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
return "[\n" + items.map((it) => indentInner + it).join(",\n") + "\n" + indent + "]";
|
|
667
|
+
function rewriteModuleSyntaxToCommonJs(source) {
|
|
668
|
+
let importCounter = 0;
|
|
669
|
+
let hasDefaultExport = false;
|
|
670
|
+
const namedExports = /* @__PURE__ */ new Set();
|
|
671
|
+
const nextImportBinding = () => `__vm_import_${importCounter++}`;
|
|
672
|
+
const resolveDefaultImport = (bindingName) => `${bindingName} && Object.prototype.hasOwnProperty.call(${bindingName}, "default") ? ${bindingName}.default : ${bindingName}`;
|
|
673
|
+
const code = source.split(/\r?\n/).map((line) => rewriteImportLine(line, nextImportBinding, resolveDefaultImport) ?? rewriteExportLine(line, namedExports, () => {
|
|
674
|
+
hasDefaultExport = true;
|
|
675
|
+
}) ?? line).join("\n");
|
|
676
|
+
const exportFooter = [...namedExports].map((name) => `module.exports.${name} = ${name};`);
|
|
677
|
+
if (hasDefaultExport) {
|
|
678
|
+
exportFooter.push("module.exports.default = module.exports;");
|
|
923
679
|
}
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
680
|
+
return exportFooter.length > 0 ? `${code.trimEnd()}
|
|
681
|
+
${exportFooter.join("\n")}
|
|
682
|
+
` : code;
|
|
683
|
+
}
|
|
684
|
+
function transpileVmModule(source, options = {}) {
|
|
685
|
+
const loader = options.loader || "js";
|
|
686
|
+
const filename = options.filename || `virtual.${loader}`;
|
|
687
|
+
if (loader === "tsx" || loader === "jsx") {
|
|
688
|
+
const esbuildTransformSync = getEsbuildTransformSync();
|
|
689
|
+
if (!esbuildTransformSync) {
|
|
690
|
+
throw new Error(`JSX database execution requires the esbuild package (${filename}).`);
|
|
691
|
+
}
|
|
692
|
+
return esbuildTransformSync(source, {
|
|
693
|
+
loader,
|
|
694
|
+
format: options.format
|
|
931
695
|
});
|
|
932
|
-
return "{\n" + entries.join(",\n") + "\n" + indent + "}";
|
|
933
696
|
}
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
697
|
+
if (loader === "ts") {
|
|
698
|
+
try {
|
|
699
|
+
return {
|
|
700
|
+
code: rewriteModuleSyntaxToCommonJs(stripTypescriptSource(source, filename))
|
|
701
|
+
};
|
|
702
|
+
} catch (error) {
|
|
703
|
+
const esbuildTransformSync = getEsbuildTransformSync();
|
|
704
|
+
if (!esbuildTransformSync) {
|
|
705
|
+
throw error;
|
|
706
|
+
}
|
|
707
|
+
return esbuildTransformSync(source, {
|
|
708
|
+
loader,
|
|
709
|
+
format: options.format
|
|
710
|
+
});
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
return {
|
|
714
|
+
code: rewriteModuleSyntaxToCommonJs(source)
|
|
715
|
+
};
|
|
938
716
|
}
|
|
717
|
+
|
|
718
|
+
// src/server/database/vm.ts
|
|
939
719
|
async function SystemModuleResolver(customOptions) {
|
|
940
720
|
const moduleRegistry = /* @__PURE__ */ new Map();
|
|
941
721
|
moduleRegistry.set("update", (dbName, fnName, code) => update(dbName, fnName, code, customOptions));
|
|
@@ -944,7 +724,6 @@ async function SystemModuleResolver(customOptions) {
|
|
|
944
724
|
moduleRegistry.set("save", (dbName, code) => save(dbName, code, customOptions));
|
|
945
725
|
moduleRegistry.set("read", (dbName) => read(dbName, customOptions));
|
|
946
726
|
const context = {
|
|
947
|
-
// Add require-like functionality
|
|
948
727
|
require: (moduleName) => {
|
|
949
728
|
const module = moduleRegistry.get(moduleName);
|
|
950
729
|
if (!module) {
|
|
@@ -952,7 +731,6 @@ async function SystemModuleResolver(customOptions) {
|
|
|
952
731
|
}
|
|
953
732
|
return module.default || module;
|
|
954
733
|
},
|
|
955
|
-
// Add import functionality (simulated)
|
|
956
734
|
import: async (moduleName) => {
|
|
957
735
|
const module = moduleRegistry.get(moduleName);
|
|
958
736
|
if (!module) {
|
|
@@ -968,6 +746,236 @@ async function SystemModuleResolver(customOptions) {
|
|
|
968
746
|
}
|
|
969
747
|
return context;
|
|
970
748
|
}
|
|
749
|
+
var VM = class {
|
|
750
|
+
constructor(options) {
|
|
751
|
+
this.pkgScriptDB = {};
|
|
752
|
+
this.options = options || {};
|
|
753
|
+
this.DATABASE_DIR = options?.dir || path3.join(process.cwd(), "databases");
|
|
754
|
+
this.SCRIPTDB_DIR = process.cwd();
|
|
755
|
+
if (!fs2.existsSync(this.DATABASE_DIR)) {
|
|
756
|
+
fs2.mkdirSync(this.DATABASE_DIR, { recursive: true });
|
|
757
|
+
}
|
|
758
|
+
if (!fs2.existsSync(this.SCRIPTDB_DIR)) {
|
|
759
|
+
fs2.mkdirSync(this.SCRIPTDB_DIR, { recursive: true });
|
|
760
|
+
}
|
|
761
|
+
const pkgPath = path3.join(this.SCRIPTDB_DIR, "package.json");
|
|
762
|
+
if (fs2.existsSync(pkgPath)) {
|
|
763
|
+
this.pkgScriptDB = JSON.parse(fs2.readFileSync(pkgPath, "utf8"));
|
|
764
|
+
}
|
|
765
|
+
this.language = options?.language || "ts";
|
|
766
|
+
this.transpiler = transpileVmModule;
|
|
767
|
+
this.registerModules = options?.registerModules || {};
|
|
768
|
+
this._registerModules = { ...this.registerModules };
|
|
769
|
+
this._registerModules.require = ((moduleId) => this.createRequire(moduleId)).bind(this);
|
|
770
|
+
this.ctx = vm.createContext(this._registerModules);
|
|
771
|
+
}
|
|
772
|
+
register(context) {
|
|
773
|
+
this.registerModules = { ...this.registerModules, ...context };
|
|
774
|
+
this._registerModules = { ...this._registerModules, ...context };
|
|
775
|
+
const originalRequire = context.require;
|
|
776
|
+
this._registerModules.require = ((moduleId) => {
|
|
777
|
+
try {
|
|
778
|
+
return this.createRequire(moduleId);
|
|
779
|
+
} catch (error) {
|
|
780
|
+
if (originalRequire && !moduleId.startsWith("@db/") && !moduleId.startsWith("./") && !moduleId.startsWith("../")) {
|
|
781
|
+
return originalRequire(moduleId);
|
|
782
|
+
}
|
|
783
|
+
throw error;
|
|
784
|
+
}
|
|
785
|
+
}).bind(this);
|
|
786
|
+
this.ctx = vm.createContext(this._registerModules);
|
|
787
|
+
}
|
|
788
|
+
createRequire(moduleId) {
|
|
789
|
+
if (!moduleId) {
|
|
790
|
+
console.error("[createRequire] moduleId is undefined");
|
|
791
|
+
return {};
|
|
792
|
+
}
|
|
793
|
+
if (moduleId.startsWith("@db/")) {
|
|
794
|
+
const relativePath = moduleId.substring(4);
|
|
795
|
+
moduleId = "./" + relativePath;
|
|
796
|
+
}
|
|
797
|
+
if (moduleId.startsWith("./") || moduleId.startsWith("../")) {
|
|
798
|
+
const dbDir = this.DATABASE_DIR || process.cwd();
|
|
799
|
+
const fullPath = path3.join(dbDir, moduleId);
|
|
800
|
+
let actualPath = fullPath;
|
|
801
|
+
if (fs2.existsSync(fullPath)) {
|
|
802
|
+
actualPath = fullPath;
|
|
803
|
+
} else {
|
|
804
|
+
const extensions = [".ts", ".tsx", ".mts", ".cts", ".js", ".mjs", ".cjs"];
|
|
805
|
+
for (const ext of extensions) {
|
|
806
|
+
if (fs2.existsSync(fullPath + ext)) {
|
|
807
|
+
actualPath = fullPath + ext;
|
|
808
|
+
break;
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
if (!actualPath || !fs2.existsSync(actualPath)) {
|
|
813
|
+
throw new Error(`Module '${moduleId}' not found at ${fullPath}`);
|
|
814
|
+
}
|
|
815
|
+
if (actualPath.endsWith(".ts") || actualPath.endsWith(".tsx") || actualPath.endsWith(".mts") || actualPath.endsWith(".cts") || actualPath.endsWith(".js") || actualPath.endsWith(".mjs")) {
|
|
816
|
+
const content = fs2.readFileSync(actualPath, "utf8");
|
|
817
|
+
const loader = actualPath.endsWith(".ts") || actualPath.endsWith(".mts") || actualPath.endsWith(".cts") ? "ts" : actualPath.endsWith(".tsx") ? "tsx" : "js";
|
|
818
|
+
const js = this.transpiler(content, {
|
|
819
|
+
loader,
|
|
820
|
+
format: "cjs",
|
|
821
|
+
filename: actualPath
|
|
822
|
+
}).code;
|
|
823
|
+
const moduleWrapper = { exports: {} };
|
|
824
|
+
const moduleContext = vm.createContext({
|
|
825
|
+
...this._registerModules,
|
|
826
|
+
module: moduleWrapper,
|
|
827
|
+
exports: moduleWrapper.exports
|
|
828
|
+
});
|
|
829
|
+
vm.runInContext(js, moduleContext, { filename: actualPath });
|
|
830
|
+
return moduleWrapper.exports;
|
|
831
|
+
}
|
|
832
|
+
return __require(actualPath);
|
|
833
|
+
}
|
|
834
|
+
return __require(moduleId);
|
|
835
|
+
}
|
|
836
|
+
resolvePath(fileList, query) {
|
|
837
|
+
const aliases = { "@db": this.DATABASE_DIR };
|
|
838
|
+
let resolvedPath = query;
|
|
839
|
+
for (const [alias, target] of Object.entries(aliases)) {
|
|
840
|
+
if (resolvedPath.startsWith(alias + "/")) {
|
|
841
|
+
resolvedPath = resolvedPath.replace(alias, target);
|
|
842
|
+
break;
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
resolvedPath = path3.normalize(resolvedPath);
|
|
846
|
+
return fileList.find((file) => {
|
|
847
|
+
const normalizedFile = path3.normalize(file);
|
|
848
|
+
const fileWithoutExt = normalizedFile.replace(/\.[^/.]+$/, "");
|
|
849
|
+
return normalizedFile === resolvedPath || fileWithoutExt === resolvedPath || normalizedFile === resolvedPath + ".ts" || normalizedFile === resolvedPath + ".js";
|
|
850
|
+
});
|
|
851
|
+
}
|
|
852
|
+
async moduleLinker(specifier, referencingModule) {
|
|
853
|
+
const dbFiles = fs2.readdirSync(this.DATABASE_DIR).filter((file) => file.endsWith(".ts")).map((file) => path3.join(this.DATABASE_DIR, file));
|
|
854
|
+
const dbResult = this.resolvePath(dbFiles, specifier);
|
|
855
|
+
if (dbResult) {
|
|
856
|
+
try {
|
|
857
|
+
const actualModule = await import(dbResult);
|
|
858
|
+
const exportNames = Object.keys(actualModule);
|
|
859
|
+
return new vm.SyntheticModule(
|
|
860
|
+
exportNames,
|
|
861
|
+
function() {
|
|
862
|
+
exportNames.forEach((key) => {
|
|
863
|
+
this.setExport(key, actualModule[key]);
|
|
864
|
+
});
|
|
865
|
+
},
|
|
866
|
+
{ identifier: specifier, context: referencingModule.context }
|
|
867
|
+
);
|
|
868
|
+
} catch (err) {
|
|
869
|
+
console.error(`Failed to load database module ${specifier}:`, err);
|
|
870
|
+
throw err;
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
const allowedPackages = Object.keys(this.pkgScriptDB.dependencies || {});
|
|
874
|
+
if (allowedPackages.includes(specifier)) {
|
|
875
|
+
try {
|
|
876
|
+
const modulePath = path3.join(this.SCRIPTDB_DIR, "node_modules", specifier);
|
|
877
|
+
const actualModule = await import(modulePath);
|
|
878
|
+
const exportNames = Object.keys(actualModule);
|
|
879
|
+
return new vm.SyntheticModule(
|
|
880
|
+
exportNames,
|
|
881
|
+
function() {
|
|
882
|
+
exportNames.forEach((key) => {
|
|
883
|
+
this.setExport(key, actualModule[key]);
|
|
884
|
+
});
|
|
885
|
+
},
|
|
886
|
+
{ identifier: specifier, context: referencingModule.context }
|
|
887
|
+
);
|
|
888
|
+
} catch (err) {
|
|
889
|
+
console.error(`Failed to load workspace module ${specifier}:`, err);
|
|
890
|
+
throw err;
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
throw new Error(`Module ${specifier} is not allowed or not found.`);
|
|
894
|
+
}
|
|
895
|
+
async run(code) {
|
|
896
|
+
const logs = [];
|
|
897
|
+
const customConsole = ["log", "error", "warn", "info", "debug", "trace"].reduce((acc, type) => {
|
|
898
|
+
acc[type] = (...args) => logs.push({ type, args });
|
|
899
|
+
return acc;
|
|
900
|
+
}, {});
|
|
901
|
+
this.register({
|
|
902
|
+
console: customConsole
|
|
903
|
+
});
|
|
904
|
+
const systemModules = await SystemModuleResolver(this.options);
|
|
905
|
+
this.register(systemModules);
|
|
906
|
+
const js = this.transpiler(code, {
|
|
907
|
+
loader: this.language,
|
|
908
|
+
format: "cjs",
|
|
909
|
+
filename: path3.join(this.SCRIPTDB_DIR, `virtual-entry.${this.language}`)
|
|
910
|
+
}).code;
|
|
911
|
+
const SourceTextModule = vm.SourceTextModule;
|
|
912
|
+
if (typeof SourceTextModule === "function") {
|
|
913
|
+
const mod = new SourceTextModule(js, { context: this.ctx, identifier: path3.join(this.SCRIPTDB_DIR, "virtual-entry.js") });
|
|
914
|
+
await mod.link(this.moduleLinker.bind(this));
|
|
915
|
+
await mod.evaluate();
|
|
916
|
+
return {
|
|
917
|
+
namespace: mod.namespace,
|
|
918
|
+
logs
|
|
919
|
+
};
|
|
920
|
+
}
|
|
921
|
+
let processedCode = js;
|
|
922
|
+
processedCode = processedCode.replace(
|
|
923
|
+
/var\s+(\w+)\s+=\s+require\((['"])([^'"]+)\2\);/g,
|
|
924
|
+
(_match, varName, quote, modulePath) => {
|
|
925
|
+
return `const ${varName} = require(${quote}${modulePath}${quote});`;
|
|
926
|
+
}
|
|
927
|
+
);
|
|
928
|
+
processedCode = processedCode.replace(
|
|
929
|
+
/import\s+\{([^}]+)\}\s+from\s+(['"])([^'"]+)\2/g,
|
|
930
|
+
(_match, imports, quote, modulePath) => {
|
|
931
|
+
return `const { ${imports} } = require(${quote}${modulePath}${quote});`;
|
|
932
|
+
}
|
|
933
|
+
);
|
|
934
|
+
processedCode = processedCode.replace(
|
|
935
|
+
/import\s+(\w+)\s+from\s+(['"])([^'"]+)\2/g,
|
|
936
|
+
(_match, name, quote, modulePath) => {
|
|
937
|
+
return `const ${name} = require(${quote}${modulePath}${quote});`;
|
|
938
|
+
}
|
|
939
|
+
);
|
|
940
|
+
processedCode = processedCode.replace(/import\(([^)]+)\)/g, "require($1)");
|
|
941
|
+
try {
|
|
942
|
+
const moduleWrapper = { exports: {} };
|
|
943
|
+
const initialExports = moduleWrapper.exports;
|
|
944
|
+
const originalModule = this._registerModules.module;
|
|
945
|
+
const originalExports = this._registerModules.exports;
|
|
946
|
+
this._registerModules.module = moduleWrapper;
|
|
947
|
+
this._registerModules.exports = moduleWrapper.exports;
|
|
948
|
+
this.ctx = vm.createContext(this._registerModules);
|
|
949
|
+
let result;
|
|
950
|
+
try {
|
|
951
|
+
result = vm.runInContext(processedCode, this.ctx, {
|
|
952
|
+
filename: path3.join(this.SCRIPTDB_DIR, "virtual-entry.js")
|
|
953
|
+
});
|
|
954
|
+
} finally {
|
|
955
|
+
if (originalModule) {
|
|
956
|
+
this._registerModules.module = originalModule;
|
|
957
|
+
} else {
|
|
958
|
+
delete this._registerModules.module;
|
|
959
|
+
}
|
|
960
|
+
if (originalExports) {
|
|
961
|
+
this._registerModules.exports = originalExports;
|
|
962
|
+
} else {
|
|
963
|
+
delete this._registerModules.exports;
|
|
964
|
+
}
|
|
965
|
+
this.ctx = vm.createContext(this._registerModules);
|
|
966
|
+
}
|
|
967
|
+
const hasExplicitExports = moduleWrapper.exports !== initialExports || typeof initialExports === "object" && initialExports !== null && Object.keys(initialExports).length > 0;
|
|
968
|
+
return {
|
|
969
|
+
namespace: hasExplicitExports ? moduleWrapper.exports : result,
|
|
970
|
+
logs
|
|
971
|
+
};
|
|
972
|
+
} catch (error) {
|
|
973
|
+
throw error;
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
};
|
|
977
|
+
|
|
978
|
+
// src/server/database/database.ts
|
|
971
979
|
var Database = class {
|
|
972
980
|
constructor(options) {
|
|
973
981
|
this.options = {
|
|
@@ -983,40 +991,21 @@ var Database = class {
|
|
|
983
991
|
async execute(code) {
|
|
984
992
|
return await this.vm.run(code);
|
|
985
993
|
}
|
|
986
|
-
// ===== Database Helper Methods =====
|
|
987
|
-
/**
|
|
988
|
-
* Create a new database file with the given code
|
|
989
|
-
*/
|
|
990
994
|
create(dbName, code) {
|
|
991
995
|
return create(dbName, code, this.options);
|
|
992
996
|
}
|
|
993
|
-
/**
|
|
994
|
-
* Read the contents of a database file
|
|
995
|
-
*/
|
|
996
997
|
read(dbName) {
|
|
997
998
|
return read(dbName, this.options);
|
|
998
999
|
}
|
|
999
|
-
/**
|
|
1000
|
-
* Remove a function or the entire database file
|
|
1001
|
-
*/
|
|
1002
1000
|
remove(dbName, fnName) {
|
|
1003
1001
|
return remove(dbName, fnName || "", this.options);
|
|
1004
1002
|
}
|
|
1005
|
-
/**
|
|
1006
|
-
* Rename a database file
|
|
1007
|
-
*/
|
|
1008
1003
|
rename(oldName, newName) {
|
|
1009
1004
|
return rename(oldName, newName, this.options);
|
|
1010
1005
|
}
|
|
1011
|
-
/**
|
|
1012
|
-
* Save code to a database file (overwrites existing content)
|
|
1013
|
-
*/
|
|
1014
1006
|
save(dbName, code) {
|
|
1015
1007
|
return save(dbName, code, this.options);
|
|
1016
1008
|
}
|
|
1017
|
-
/**
|
|
1018
|
-
* Update a function in a database file
|
|
1019
|
-
*/
|
|
1020
1009
|
update(dbName, fnName, code) {
|
|
1021
1010
|
return update(dbName, fnName, code, this.options);
|
|
1022
1011
|
}
|