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