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