elit 3.6.6 → 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 (153) hide show
  1. package/Cargo.lock +1 -1
  2. package/Cargo.toml +1 -1
  3. package/dist/build.cjs +421 -331
  4. package/dist/build.d.ts +1 -19
  5. package/dist/build.js +420 -330
  6. package/dist/build.mjs +420 -330
  7. package/dist/chokidar.cjs +219 -182
  8. package/dist/chokidar.d.ts +25 -10
  9. package/dist/chokidar.js +217 -182
  10. package/dist/chokidar.mjs +218 -183
  11. package/dist/cli.cjs +22439 -21563
  12. package/dist/cli.d.ts +19 -37
  13. package/dist/cli.mjs +24113 -23252
  14. package/dist/config.cjs +357 -350
  15. package/dist/config.d.ts +17 -245
  16. package/dist/config.js +520 -515
  17. package/dist/config.mjs +346 -341
  18. package/dist/contracts-BeW9k0yZ.d.ts +54 -0
  19. package/dist/contracts-D7KIS-TK.d.ts +36 -0
  20. package/dist/coverage.cjs +448 -485
  21. package/dist/coverage.d.ts +13 -62
  22. package/dist/coverage.js +447 -484
  23. package/dist/coverage.mjs +447 -484
  24. package/dist/database.cjs +819 -828
  25. package/dist/database.d.ts +8 -24
  26. package/dist/database.js +818 -829
  27. package/dist/database.mjs +818 -829
  28. package/dist/desktop-auto-render.cjs +1700 -1523
  29. package/dist/desktop-auto-render.d.ts +4 -12
  30. package/dist/desktop-auto-render.js +1695 -1518
  31. package/dist/desktop-auto-render.mjs +1696 -1519
  32. package/dist/desktop.cjs +3 -1
  33. package/dist/desktop.d.ts +4 -1
  34. package/dist/desktop.js +1 -1
  35. package/dist/desktop.mjs +1 -1
  36. package/dist/dev-build.cjs +830 -0
  37. package/dist/dev-build.d.ts +53 -0
  38. package/dist/dev-build.js +3318 -0
  39. package/dist/dev-build.mjs +797 -0
  40. package/dist/dom.cjs +717 -591
  41. package/dist/dom.d.ts +2 -17
  42. package/dist/dom.js +714 -588
  43. package/dist/dom.mjs +716 -590
  44. package/dist/el.cjs +62 -52
  45. package/dist/el.d.ts +5 -12
  46. package/dist/el.js +60 -52
  47. package/dist/el.mjs +60 -52
  48. package/dist/fs.cjs +72 -63
  49. package/dist/fs.d.ts +22 -19
  50. package/dist/fs.js +71 -62
  51. package/dist/fs.mjs +71 -62
  52. package/dist/hmr.cjs +40 -14
  53. package/dist/hmr.d.ts +11 -23
  54. package/dist/hmr.js +38 -14
  55. package/dist/hmr.mjs +38 -14
  56. package/dist/http.cjs +251 -99
  57. package/dist/http.d.ts +38 -104
  58. package/dist/http.js +249 -99
  59. package/dist/http.mjs +249 -99
  60. package/dist/https.cjs +524 -228
  61. package/dist/https.d.ts +44 -36
  62. package/dist/https.js +520 -226
  63. package/dist/https.mjs +522 -228
  64. package/dist/index.cjs +7502 -7691
  65. package/dist/index.d.ts +6 -3
  66. package/dist/index.js +7486 -7677
  67. package/dist/index.mjs +7497 -7687
  68. package/dist/mime-types.cjs +10 -4
  69. package/dist/mime-types.d.ts +8 -11
  70. package/dist/mime-types.js +9 -3
  71. package/dist/mime-types.mjs +9 -3
  72. package/dist/native.cjs +8616 -8870
  73. package/dist/native.d.ts +7 -10
  74. package/dist/native.js +8682 -8936
  75. package/dist/native.mjs +8615 -8869
  76. package/dist/path.cjs +83 -77
  77. package/dist/path.d.ts +29 -29
  78. package/dist/path.js +82 -76
  79. package/dist/path.mjs +82 -76
  80. package/dist/pm.cjs +3300 -0
  81. package/dist/pm.d.ts +256 -0
  82. package/dist/pm.js +5638 -0
  83. package/dist/pm.mjs +3196 -0
  84. package/dist/preview-build.cjs +712 -0
  85. package/dist/preview-build.d.ts +59 -0
  86. package/dist/preview-build.js +3194 -0
  87. package/dist/preview-build.mjs +676 -0
  88. package/dist/render-context.cjs +13 -2
  89. package/dist/render-context.d.ts +9 -34
  90. package/dist/render-context.js +11 -2
  91. package/dist/render-context.mjs +11 -2
  92. package/dist/router.cjs +787 -646
  93. package/dist/router.d.ts +8 -14
  94. package/dist/router.js +786 -645
  95. package/dist/router.mjs +786 -645
  96. package/dist/runtime.cjs +1 -1
  97. package/dist/runtime.js +1 -1
  98. package/dist/runtime.mjs +1 -1
  99. package/dist/server.cjs +3254 -2684
  100. package/dist/server.d.ts +47 -5
  101. package/dist/server.js +3427 -2859
  102. package/dist/server.mjs +3397 -2829
  103. package/dist/smtp-server.cjs +16 -3
  104. package/dist/smtp-server.d.ts +12 -26
  105. package/dist/smtp-server.js +18 -5
  106. package/dist/smtp-server.mjs +16 -3
  107. package/dist/state-DvEkDehk.d.ts +195 -0
  108. package/dist/state.cjs +768 -659
  109. package/dist/state.d.ts +11 -71
  110. package/dist/state.js +760 -651
  111. package/dist/state.mjs +767 -658
  112. package/dist/style.cjs +1011 -968
  113. package/dist/style.d.ts +13 -127
  114. package/dist/style.js +1009 -970
  115. package/dist/style.mjs +1011 -971
  116. package/dist/test-reporter.cjs +332 -316
  117. package/dist/test-reporter.d.ts +28 -33
  118. package/dist/test-reporter.js +328 -312
  119. package/dist/test-reporter.mjs +328 -312
  120. package/dist/test-runtime.cjs +927 -968
  121. package/dist/test-runtime.d.ts +24 -99
  122. package/dist/test-runtime.js +922 -965
  123. package/dist/test-runtime.mjs +922 -965
  124. package/dist/test.cjs +4428 -4273
  125. package/dist/test.d.ts +2 -8
  126. package/dist/test.js +4307 -4154
  127. package/dist/test.mjs +4419 -4267
  128. package/dist/types-BONVzPtp.d.ts +59 -0
  129. package/dist/types-BR4wMiVx.d.ts +32 -0
  130. package/dist/types-C4gKykuG.d.ts +23 -0
  131. package/dist/types-CIhpN1-K.d.ts +64 -0
  132. package/dist/types-Ckj8md_j.d.ts +84 -0
  133. package/dist/types-CpjQTAkX.d.ts +24 -0
  134. package/dist/types-D0LjrYjS.d.ts +14 -0
  135. package/dist/types-DAisuVr5.d.ts +75 -0
  136. package/dist/types-tJn88E1N.d.ts +242 -0
  137. package/dist/types.d.ts +50 -237
  138. package/dist/universal.cjs +1 -1
  139. package/dist/universal.d.ts +1 -7
  140. package/dist/universal.js +1 -1
  141. package/dist/universal.mjs +1 -1
  142. package/dist/websocket-XfyK23zD.d.ts +119 -0
  143. package/dist/ws.cjs +129 -108
  144. package/dist/ws.d.ts +21 -131
  145. package/dist/ws.js +128 -109
  146. package/dist/ws.mjs +128 -109
  147. package/dist/wss.cjs +757 -479
  148. package/dist/wss.d.ts +31 -28
  149. package/dist/wss.js +755 -479
  150. package/dist/wss.mjs +758 -482
  151. package/package.json +8 -1
  152. package/vendor/epaint-0.31.1/src/image.rs +418 -0
  153. package/dist/server-uMQvZAll.d.ts +0 -458
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
- var import_node_vm = __toESM(require("vm"));
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
- var nodeModule = __toESM(require("module"));
46
- var stripTypeScriptTypes2 = typeof nodeModule.stripTypeScriptTypes === "function" ? nodeModule.stripTypeScriptTypes : void 0;
47
- var cachedEsbuildTransformSync;
48
- function getEsbuildTransformSync() {
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 stripTypescriptSource(source, filename) {
81
- if (!stripTypeScriptTypes2) {
82
- throw new Error("TypeScript database execution requires Node.js 22+ or the esbuild package.");
83
- }
84
- const originalEmitWarning = process.emitWarning;
85
- try {
86
- process.emitWarning = ((warning, ...args) => {
87
- if (typeof warning === "string" && warning.includes("stripTypeScriptTypes")) {
88
- return;
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
- return originalEmitWarning.call(process, warning, ...args);
91
- });
92
- return stripTypeScriptTypes2(source, {
93
- mode: "transform",
94
- sourceUrl: filename
95
- });
96
- } finally {
97
- process.emitWarning = originalEmitWarning;
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 isSimpleIdentifier(value) {
101
- return /^[A-Za-z_$][\w$]*$/.test(value);
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 stripOptionalLineTerminator(value) {
104
- const trimmed = value.trim();
105
- return trimmed.endsWith(";") ? trimmed.slice(0, -1).trimEnd() : trimmed;
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 parseQuotedModulePath(value) {
108
- const trimmed = value.trim();
109
- if (trimmed.length < 2) {
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 quote = trimmed[0];
113
- if (quote !== '"' && quote !== "'" || trimmed[trimmed.length - 1] !== quote) {
163
+ const equalsIndex = source.indexOf("=", declarationMatch.index);
164
+ if (equalsIndex === -1) {
114
165
  return null;
115
166
  }
116
- return trimmed.slice(1, -1);
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 getLineIndentation(line) {
119
- const match = line.match(/^\s*/);
120
- return match?.[0] ?? "";
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 rewriteImportLine(line, nextImportBinding, resolveDefaultImport) {
123
- const indentation = getLineIndentation(line);
124
- const trimmed = stripOptionalLineTerminator(line);
125
- if (!trimmed.startsWith("import ")) {
126
- return null;
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
- const importBody = trimmed.slice("import ".length).trim();
129
- const sideEffectModulePath = parseQuotedModulePath(importBody);
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
- const fromIndex = importBody.lastIndexOf(" from ");
134
- if (fromIndex === -1) {
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
- const clause = importBody.slice(0, fromIndex).trim();
138
- const modulePath = parseQuotedModulePath(importBody.slice(fromIndex + 6));
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
- const buildDefaultImport = (defaultName) => {
143
- if (!isSimpleIdentifier(defaultName)) {
144
- return null;
145
- }
146
- const bindingName = nextImportBinding();
147
- return {
148
- bindingName,
149
- code: [
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 (clause.startsWith("{") && clause.endsWith("}")) {
160
- const namedBindings = clause.slice(1, -1).trim();
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
- const commaIndex = clause.indexOf(",");
164
- if (commaIndex !== -1) {
165
- const defaultName = clause.slice(0, commaIndex).trim();
166
- const remainder = clause.slice(commaIndex + 1).trim();
167
- const defaultImport = buildDefaultImport(defaultName);
168
- if (!defaultImport) {
169
- return null;
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
- if (remainder.startsWith("* as ")) {
172
- const namespaceName = remainder.slice(5).trim();
173
- if (!isSimpleIdentifier(namespaceName)) {
174
- return null;
175
- }
176
- return `${defaultImport.code}
177
- ${indentation}const ${namespaceName} = ${defaultImport.bindingName};`;
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
- if (remainder.startsWith("{") && remainder.endsWith("}")) {
180
- const namedBindings = remainder.slice(1, -1).trim();
181
- if (!namedBindings) {
182
- return null;
183
- }
184
- return `${defaultImport.code}
185
- ${indentation}const { ${formatNamedImportBindings(namedBindings)} } = ${defaultImport.bindingName};`;
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
- return buildDefaultImport(clause)?.code ?? null;
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
- const indentation = getLineIndentation(line);
197
- if (trimmed.startsWith("export default ")) {
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 rewriteModuleSyntaxToCommonJs(source) {
228
- let importCounter = 0;
229
- let hasDefaultExport = false;
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
- return exportFooter.length > 0 ? `${code.trimEnd()}
241
- ${exportFooter.join("\n")}
242
- ` : code;
274
+ const source = code.toString();
275
+ return kind === "functionDecl" ? normalizeFunctionDeclaration(name, source) : normalizeClassDeclaration(name, source);
243
276
  }
244
- function transpileVmModule(source, options = {}) {
245
- const loader = options.loader || "js";
246
- const filename = options.filename || `virtual.${loader}`;
247
- if (loader === "tsx" || loader === "jsx") {
248
- const esbuildTransformSync = getEsbuildTransformSync();
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
- return esbuildTransformSync(source, {
253
- loader,
254
- format: options.format
255
- });
283
+ if (/^class\b/.test(fnSource)) {
284
+ return `export ${normalizeClassDeclaration(name, fnSource)}`;
285
+ }
286
+ return `export const ${name} = ${fnSource};`;
256
287
  }
257
- if (loader === "ts") {
258
- try {
259
- return {
260
- code: rewriteModuleSyntaxToCommonJs(stripTypescriptSource(source, filename))
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
- var VM = class {
278
- constructor(options) {
279
- this.pkgScriptDB = {};
280
- this.options = options || {};
281
- this.DATABASE_DIR = options?.dir || import_node_path.default.join(process.cwd(), "databases");
282
- this.SCRIPTDB_DIR = process.cwd();
283
- if (!import_node_fs.default.existsSync(this.DATABASE_DIR)) {
284
- import_node_fs.default.mkdirSync(this.DATABASE_DIR, { recursive: true });
285
- }
286
- if (!import_node_fs.default.existsSync(this.SCRIPTDB_DIR)) {
287
- import_node_fs.default.mkdirSync(this.SCRIPTDB_DIR, { recursive: true });
288
- }
289
- const pkgPath = import_node_path.default.join(this.SCRIPTDB_DIR, "package.json");
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
- register(context) {
301
- this.registerModules = { ...this.registerModules, ...context };
302
- this._registerModules = { ...this._registerModules, ...context };
303
- const originalRequire = context.require;
304
- this._registerModules.require = ((moduleId) => {
305
- try {
306
- return this.createRequire(moduleId);
307
- } catch (e) {
308
- if (originalRequire && !moduleId.startsWith("@db/") && !moduleId.startsWith("./") && !moduleId.startsWith("../")) {
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
- createRequire(moduleId) {
317
- if (!moduleId) {
318
- console.error("[createRequire] moduleId is undefined");
319
- return {};
320
- }
321
- console.log("[createRequire] Loading module:", moduleId, "from DATABASE_DIR:", this.DATABASE_DIR);
322
- if (moduleId.startsWith("@db/")) {
323
- const relativePath = moduleId.substring(4);
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
- resolvePath(fileList, query) {
373
- const aliases = { "@db": this.DATABASE_DIR };
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
- async moduleLinker(specifier, referencingModule) {
389
- console.log("[moduleLinker] Loading specifier:", specifier, "from DATABASE_DIR:", this.DATABASE_DIR);
390
- 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));
391
- console.log("[moduleLinker] Database files:", dbFiles);
392
- const dbResult = this.resolvePath(dbFiles, specifier);
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
- async run(code) {
435
- const logs = [];
436
- const customConsole = ["log", "error", "warn", "info", "debug", "trace"].reduce((acc, type) => {
437
- acc[type] = (...args) => logs.push({ type, args });
438
- return acc;
439
- }, {});
440
- this.register({
441
- console: customConsole
442
- });
443
- const systemModules = await SystemModuleResolver(this.options);
444
- this.register(systemModules);
445
- const js = this.transpiler(code, {
446
- loader: this.language,
447
- format: "cjs",
448
- filename: import_node_path.default.join(this.SCRIPTDB_DIR, `virtual-entry.${this.language}`)
449
- }).code;
450
- console.log("[run] Transpiled code:", js);
451
- const SourceTextModule = import_node_vm.default.SourceTextModule;
452
- console.log("[run] SourceTextModule available:", typeof SourceTextModule === "function");
453
- if (typeof SourceTextModule === "function") {
454
- const mod = new SourceTextModule(js, { context: this.ctx, identifier: import_node_path.default.join(this.SCRIPTDB_DIR, "virtual-entry.js") });
455
- await mod.link(this.moduleLinker.bind(this));
456
- await mod.evaluate();
457
- return {
458
- namespace: mod.namespace,
459
- logs
460
- };
461
- }
462
- let processedCode = js;
463
- console.log("[run] Original transpiled code:", processedCode);
464
- processedCode = processedCode.replace(
465
- /var\s+(\w+)\s+=\s+require\((['"])([^'"]+)\2\);/g,
466
- (_match, varName, quote, modulePath) => {
467
- return `const ${varName} = require(${quote}${modulePath}${quote});`;
468
- }
469
- );
470
- processedCode = processedCode.replace(
471
- /import\s+\{([^}]+)\}\s+from\s+(['"])([^'"]+)\2/g,
472
- (_match, imports, quote, modulePath) => {
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
- processedCode = processedCode.replace(/import\(([^)]+)\)/g, "require($1)");
483
- console.log("[run] Processed code:", processedCode);
484
- console.log("[run] Context has require:", typeof this._registerModules.require);
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 hasExplicitExports = moduleWrapper.exports !== initialExports || typeof initialExports === "object" && initialExports !== null && Object.keys(initialExports).length > 0;
513
- return {
514
- namespace: hasExplicitExports ? moduleWrapper.exports : result,
515
- logs
516
- };
517
- } catch (e) {
518
- console.log("[run] Error executing code:", e);
519
- throw e;
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 DIR = options?.dir || import_node_path.default.join(process.cwd(), "databases");
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 DIR = options?.dir || import_node_path.default.join(process.cwd(), "databases");
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 DIR = options?.dir || import_node_path.default.join(process.cwd(), "databases");
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 (e) {
452
+ } catch {
545
453
  }
546
454
  try {
547
455
  import_node_fs.default.unlinkSync(dbPath);
548
456
  return "Removed successfully";
549
- } catch (e) {
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 (e) {
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 exportRe = new RegExp(
600
- `export\\s+const\\s+${escaped}\\s*:\\s*any\\s*=\\s*${escaped}\\s*;?`,
601
- "g"
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 DIR = options?.dir || import_node_path.default.join(process.cwd(), "databases");
610
- const oldPath = import_node_path.default.join(DIR, `${oldName}.ts`);
611
- const newPath = import_node_path.default.join(DIR, `${newName}.ts`);
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 escapeRegExp(value) {
626
- return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
627
- }
628
- function findMatchingBlockEnd(source, openIndex) {
629
- let depth = 0;
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 findInitializerEnd(source, startIndex) {
675
- let braceDepth = 0;
676
- let bracketDepth = 0;
677
- let parenDepth = 0;
678
- let stringChar = null;
679
- for (let index = startIndex; index < source.length; index += 1) {
680
- const char = source[index];
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
- return source.length;
728
- }
729
- function looksLikeDeclarationSnippet(source) {
730
- const trimmed = source.trim();
731
- return /^(?:export\s+)?(?:async\s+function\b|function\b|class\b|(?:const|let|var)\b)/.test(trimmed);
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
- const initializerEnd = findInitializerEnd(source, equalsIndex + 1);
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
- function buildDatabaseModuleSource(dbName, code, dbPath) {
749
- if (typeof code === "string") {
750
- return code;
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 code === "function") {
753
- return code.toString();
526
+ if (typeof nodeModule.createRequire !== "function") {
527
+ cachedEsbuildTransformSync = null;
528
+ return cachedEsbuildTransformSync;
754
529
  }
755
- const serializedValue = valueToCode(code, 0);
756
- if (import_node_fs.default.existsSync(dbPath) && isIdentifier(dbName)) {
757
- const existingSource = import_node_fs.default.readFileSync(dbPath, "utf8");
758
- const updatedSource = replaceExistingBindingValue(existingSource, dbName, serializedValue);
759
- if (updatedSource) {
760
- return updatedSource;
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
- if (isIdentifier(dbName)) {
764
- return `const ${dbName} = ${serializedValue};
765
-
766
- export { ${dbName} };
767
- export default ${dbName};
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 toInitializerSource(code) {
776
- if (typeof code === "function") {
777
- return code.toString().trim();
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
- if (typeof code === "string") {
780
- const trimmed = code.trim();
781
- if (looksLikeDeclarationSnippet(trimmed) || /=>/.test(trimmed) || /^(?:\{|\[|\(|"|'|`|\d|-\d|true\b|false\b|null\b|undefined\b|new\b|await\b)/.test(trimmed)) {
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 valueToCode(code, 0);
590
+ return trimmed.slice(1, -1);
787
591
  }
788
- function shouldUseDeclarationSource(code) {
789
- return typeof code === "function" || typeof code === "string" && looksLikeDeclarationSnippet(code);
592
+ function getLineIndentation(line) {
593
+ const match = line.match(/^\s*/);
594
+ return match?.[0] ?? "";
790
595
  }
791
- function normalizeFunctionDeclaration(name, code) {
792
- const trimmed = code.trim().replace(/^export\s+/, "");
793
- if (/^async\s+function\s+[A-Za-z_$][\w$]*/.test(trimmed)) {
794
- return trimmed.replace(/^async\s+function\s+[A-Za-z_$][\w$]*/, `async function ${name}`);
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
- if (/^async\s+function\s*\(/.test(trimmed)) {
797
- return trimmed.replace(/^async\s+function\s*\(/, `async function ${name}(`);
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
- if (/^function\s+[A-Za-z_$][\w$]*/.test(trimmed)) {
800
- return trimmed.replace(/^function\s+[A-Za-z_$][\w$]*/, `function ${name}`);
607
+ const fromIndex = importBody.lastIndexOf(" from ");
608
+ if (fromIndex === -1) {
609
+ return null;
801
610
  }
802
- if (/^function\s*\(/.test(trimmed)) {
803
- return trimmed.replace(/^function\s*\(/, `function ${name}(`);
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
- return `function ${name}() {
806
- ${trimmed}
807
- }`;
808
- }
809
- function normalizeClassDeclaration(name, code) {
810
- const trimmed = code.trim().replace(/^export\s+/, "");
811
- if (/^class\s+[A-Za-z_$][\w$]*/.test(trimmed)) {
812
- return trimmed.replace(/^class\s+[A-Za-z_$][\w$]*/, `class ${name}`);
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 (/^class(?:\s+extends\b|\s*\{)/.test(trimmed)) {
815
- return trimmed.replace(/^class/, `class ${name}`);
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
- return `class ${name} ${trimmed}`;
818
- }
819
- function findDeclaration(source, name) {
820
- const escaped = escapeRegExp(name);
821
- const matches = [];
822
- const valueRegex = new RegExp(`(?:export\\s+)?(?:const|let|var)\\s+${escaped}(?:\\s*:\\s*[^=;]+)?\\s*=`, "m");
823
- const valueMatch = valueRegex.exec(source);
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
- const functionRegex = new RegExp(`(?:export\\s+)?(?:async\\s+)?function\\s+${escaped}\\s*\\(`, "m");
839
- const functionMatch = functionRegex.exec(source);
840
- if (functionMatch && functionMatch.index !== void 0) {
841
- const braceOpen = source.indexOf("{", functionMatch.index);
842
- if (braceOpen !== -1) {
843
- const braceClose = findMatchingBlockEnd(source, braceOpen);
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
- const classRegex = new RegExp(`(?:export\\s+)?class\\s+${escaped}(?=\\s|\\{)`, "m");
854
- const classMatch = classRegex.exec(source);
855
- if (classMatch && classMatch.index !== void 0) {
856
- const braceOpen = source.indexOf("{", classMatch.index);
857
- if (braceOpen !== -1) {
858
- const braceClose = findMatchingBlockEnd(source, braceOpen);
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
- matches.sort((left, right) => left.start - right.start);
872
- return matches[0];
663
+ return buildDefaultImport(clause)?.code ?? null;
873
664
  }
874
- function createStructuredReplacement(kind, name, code) {
875
- if (!shouldUseDeclarationSource(code)) {
876
- return `const ${name} = ${toInitializerSource(code)};`;
665
+ function rewriteExportLine(line, namedExports, markDefaultExport) {
666
+ const trimmed = stripOptionalLineTerminator(line);
667
+ if (!trimmed.startsWith("export ")) {
668
+ return null;
877
669
  }
878
- const source = code.toString();
879
- return kind === "functionDecl" ? normalizeFunctionDeclaration(name, source) : normalizeClassDeclaration(name, source);
880
- }
881
- function createDeclarationSnippet(name, code) {
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
- if (typeof code === "string") {
893
- const trimmed = code.trim();
894
- if (looksLikeDeclarationSnippet(trimmed)) {
895
- return trimmed;
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
- return `export const ${name} = ${toInitializerSource(code)};`;
899
- }
900
- function save(dbName, code, options) {
901
- const DIR = options?.dir || import_node_path.default.join(process.cwd(), "databases");
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
- let src = import_node_fs.default.readFileSync(dbPath, "utf8");
917
- const originalSrc = src;
918
- const declaration = findDeclaration(src, fnName);
919
- if (declaration) {
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
- import_node_fs.default.writeFileSync(dbPath, src, "utf8");
937
- if (src === originalSrc) {
938
- return `Saved ${fnName} to database ${dbName}.`;
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
- return `Updated ${dbName} with ${fnName}.`;
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 valueToCode(val, depth = 0) {
943
- const indentUnit = " ";
944
- const indent = indentUnit.repeat(depth);
945
- const indentInner = indentUnit.repeat(depth + 1);
946
- if (val === null) return "null";
947
- const t = typeof val;
948
- if (t === "string") return JSON.stringify(val);
949
- if (t === "number" || t === "boolean") return String(val);
950
- if (t === "function") return val.toString();
951
- if (Array.isArray(val)) {
952
- if (val.length === 0) return "[]";
953
- const items = val.map((v) => valueToCode(v, depth + 1));
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
- if (t === "object") {
957
- const keys = Object.keys(val);
958
- if (keys.length === 0) return "{}";
959
- const entries = keys.map((k) => {
960
- const keyPart = isIdentifier(k) ? k : JSON.stringify(k);
961
- const v = valueToCode(val[k], depth + 1);
962
- return indentInner + keyPart + ": " + v;
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
- return String(val);
967
- }
968
- function isIdentifier(key) {
969
- return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key);
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
  }