elit 3.6.5 → 3.6.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. package/Cargo.lock +1 -1
  2. package/Cargo.toml +1 -1
  3. package/README.md +6 -0
  4. package/dist/build.cjs +421 -331
  5. package/dist/build.d.ts +1 -16
  6. package/dist/build.js +420 -330
  7. package/dist/build.mjs +420 -330
  8. package/dist/chokidar.cjs +219 -182
  9. package/dist/chokidar.d.ts +25 -10
  10. package/dist/chokidar.js +217 -182
  11. package/dist/chokidar.mjs +218 -183
  12. package/dist/cli.cjs +21608 -20241
  13. package/dist/cli.d.ts +19 -37
  14. package/dist/cli.mjs +21262 -19910
  15. package/dist/config.cjs +357 -350
  16. package/dist/config.d.ts +19 -240
  17. package/dist/config.js +520 -515
  18. package/dist/config.mjs +346 -341
  19. package/dist/contracts-BeW9k0yZ.d.ts +54 -0
  20. package/dist/contracts-D7KIS-TK.d.ts +36 -0
  21. package/dist/coverage.cjs +448 -485
  22. package/dist/coverage.d.ts +13 -59
  23. package/dist/coverage.js +447 -484
  24. package/dist/coverage.mjs +447 -484
  25. package/dist/database.cjs +819 -828
  26. package/dist/database.d.ts +8 -24
  27. package/dist/database.js +818 -829
  28. package/dist/database.mjs +818 -829
  29. package/dist/desktop-auto-render.cjs +1700 -1522
  30. package/dist/desktop-auto-render.d.ts +4 -9
  31. package/dist/desktop-auto-render.js +1695 -1517
  32. package/dist/desktop-auto-render.mjs +1696 -1518
  33. package/dist/desktop.cjs +3 -1
  34. package/dist/desktop.d.ts +4 -1
  35. package/dist/desktop.js +1 -1
  36. package/dist/desktop.mjs +1 -1
  37. package/dist/dev-build.cjs +830 -0
  38. package/dist/dev-build.d.ts +53 -0
  39. package/dist/dev-build.js +3318 -0
  40. package/dist/dev-build.mjs +797 -0
  41. package/dist/dom.cjs +717 -590
  42. package/dist/dom.d.ts +2 -15
  43. package/dist/dom.js +714 -587
  44. package/dist/dom.mjs +716 -589
  45. package/dist/el.cjs +62 -52
  46. package/dist/el.d.ts +5 -10
  47. package/dist/el.js +60 -52
  48. package/dist/el.mjs +60 -52
  49. package/dist/fs.cjs +72 -63
  50. package/dist/fs.d.ts +22 -19
  51. package/dist/fs.js +71 -62
  52. package/dist/fs.mjs +71 -62
  53. package/dist/hmr.cjs +40 -14
  54. package/dist/hmr.d.ts +11 -23
  55. package/dist/hmr.js +38 -14
  56. package/dist/hmr.mjs +38 -14
  57. package/dist/http.cjs +251 -99
  58. package/dist/http.d.ts +38 -104
  59. package/dist/http.js +249 -99
  60. package/dist/http.mjs +249 -99
  61. package/dist/https.cjs +524 -228
  62. package/dist/https.d.ts +44 -36
  63. package/dist/https.js +520 -226
  64. package/dist/https.mjs +522 -228
  65. package/dist/index.cjs +7502 -7690
  66. package/dist/index.d.ts +8 -3
  67. package/dist/index.js +7486 -7676
  68. package/dist/index.mjs +7497 -7686
  69. package/dist/mime-types.cjs +10 -4
  70. package/dist/mime-types.d.ts +8 -11
  71. package/dist/mime-types.js +9 -3
  72. package/dist/mime-types.mjs +9 -3
  73. package/dist/native.cjs +8616 -8869
  74. package/dist/native.d.ts +7 -8
  75. package/dist/native.js +8682 -8935
  76. package/dist/native.mjs +8615 -8868
  77. package/dist/path.cjs +83 -77
  78. package/dist/path.d.ts +29 -29
  79. package/dist/path.js +82 -76
  80. package/dist/path.mjs +82 -76
  81. package/dist/pm.cjs +3300 -0
  82. package/dist/pm.d.ts +256 -0
  83. package/dist/pm.js +5638 -0
  84. package/dist/pm.mjs +3196 -0
  85. package/dist/preview-build.cjs +712 -0
  86. package/dist/preview-build.d.ts +59 -0
  87. package/dist/preview-build.js +3194 -0
  88. package/dist/preview-build.mjs +676 -0
  89. package/dist/render-context.cjs +13 -2
  90. package/dist/render-context.d.ts +9 -31
  91. package/dist/render-context.js +11 -2
  92. package/dist/render-context.mjs +11 -2
  93. package/dist/router.cjs +787 -645
  94. package/dist/router.d.ts +8 -12
  95. package/dist/router.js +786 -644
  96. package/dist/router.mjs +786 -644
  97. package/dist/runtime.cjs +1 -1
  98. package/dist/runtime.js +1 -1
  99. package/dist/runtime.mjs +1 -1
  100. package/dist/server.cjs +3315 -2603
  101. package/dist/server.d.ts +49 -4
  102. package/dist/server.js +7611 -2834
  103. package/dist/server.mjs +3317 -2607
  104. package/dist/smtp-server.cjs +128 -0
  105. package/dist/smtp-server.d.ts +27 -0
  106. package/dist/smtp-server.js +4199 -0
  107. package/dist/smtp-server.mjs +100 -0
  108. package/dist/state-DvEkDehk.d.ts +195 -0
  109. package/dist/state.cjs +768 -658
  110. package/dist/state.d.ts +11 -69
  111. package/dist/state.js +760 -650
  112. package/dist/state.mjs +767 -657
  113. package/dist/style.cjs +1011 -968
  114. package/dist/style.d.ts +13 -127
  115. package/dist/style.js +1009 -970
  116. package/dist/style.mjs +1011 -971
  117. package/dist/test-reporter.cjs +332 -316
  118. package/dist/test-reporter.d.ts +28 -33
  119. package/dist/test-reporter.js +328 -312
  120. package/dist/test-reporter.mjs +328 -312
  121. package/dist/test-runtime.cjs +927 -968
  122. package/dist/test-runtime.d.ts +24 -99
  123. package/dist/test-runtime.js +922 -965
  124. package/dist/test-runtime.mjs +922 -965
  125. package/dist/test.cjs +4428 -4273
  126. package/dist/test.d.ts +2 -8
  127. package/dist/test.js +4307 -4154
  128. package/dist/test.mjs +4419 -4267
  129. package/dist/types-BONVzPtp.d.ts +59 -0
  130. package/dist/types-BR4wMiVx.d.ts +32 -0
  131. package/dist/types-C4gKykuG.d.ts +23 -0
  132. package/dist/types-CIhpN1-K.d.ts +64 -0
  133. package/dist/types-Ckj8md_j.d.ts +84 -0
  134. package/dist/types-CpjQTAkX.d.ts +24 -0
  135. package/dist/types-D0LjrYjS.d.ts +14 -0
  136. package/dist/types-DAisuVr5.d.ts +75 -0
  137. package/dist/types-tJn88E1N.d.ts +242 -0
  138. package/dist/types.d.ts +71 -226
  139. package/dist/universal.cjs +1 -1
  140. package/dist/universal.d.ts +1 -5
  141. package/dist/universal.js +1 -1
  142. package/dist/universal.mjs +1 -1
  143. package/dist/websocket-XfyK23zD.d.ts +119 -0
  144. package/dist/ws.cjs +129 -108
  145. package/dist/ws.d.ts +21 -131
  146. package/dist/ws.js +128 -109
  147. package/dist/ws.mjs +128 -109
  148. package/dist/wss.cjs +757 -479
  149. package/dist/wss.d.ts +31 -28
  150. package/dist/wss.js +755 -479
  151. package/dist/wss.mjs +758 -482
  152. package/package.json +16 -1
  153. package/vendor/epaint-0.31.1/src/image.rs +418 -0
  154. package/dist/server-CcBFc2F5.d.ts +0 -449
package/dist/database.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
  }