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