@scriptdb/vm 1.1.0 → 1.1.2

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.
@@ -0,0 +1,28 @@
1
+ import vm from 'node:vm';
2
+
3
+ interface VMOptions {
4
+ language?: 'ts' | 'js';
5
+ registerModules?: {
6
+ [key: string]: any;
7
+ };
8
+ }
9
+ declare class VM {
10
+ private transpiler;
11
+ private ctx;
12
+ private registerModules;
13
+ private DATABASE_DIR;
14
+ private SCRIPTDB_DIR;
15
+ private pkgScriptDB;
16
+ constructor(options?: VMOptions);
17
+ register(context: {
18
+ [key: string]: any;
19
+ }): void;
20
+ resolvePath(fileList: any[], query: string): any;
21
+ moduleLinker(specifier: any, referencingModule: any): Promise<vm.SyntheticModule>;
22
+ run(code: string, options?: vm.RunningCodeOptions | string): Promise<{
23
+ namespace: Object;
24
+ logs: any[];
25
+ }>;
26
+ }
27
+
28
+ export { VM, VM as default };
@@ -0,0 +1,28 @@
1
+ import vm from 'node:vm';
2
+
3
+ interface VMOptions {
4
+ language?: 'ts' | 'js';
5
+ registerModules?: {
6
+ [key: string]: any;
7
+ };
8
+ }
9
+ declare class VM {
10
+ private transpiler;
11
+ private ctx;
12
+ private registerModules;
13
+ private DATABASE_DIR;
14
+ private SCRIPTDB_DIR;
15
+ private pkgScriptDB;
16
+ constructor(options?: VMOptions);
17
+ register(context: {
18
+ [key: string]: any;
19
+ }): void;
20
+ resolvePath(fileList: any[], query: string): any;
21
+ moduleLinker(specifier: any, referencingModule: any): Promise<vm.SyntheticModule>;
22
+ run(code: string, options?: vm.RunningCodeOptions | string): Promise<{
23
+ namespace: Object;
24
+ logs: any[];
25
+ }>;
26
+ }
27
+
28
+ export { VM, VM as default };
package/dist/index.js CHANGED
@@ -1,38 +1,68 @@
1
- // @bun
2
- // src/index.ts
3
- var Bun = globalThis.Bun;
4
- import vm from "vm";
5
- import fs from "fs";
6
- import path from "path";
7
- import os from "os";
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
8
29
 
9
- class VM {
10
- transpiler;
11
- ctx;
12
- registerModules;
13
- DATABASE_DIR = path.join(os.homedir(), ".scriptdb", "databases");
14
- SCRIPTDB_DIR = path.join(os.homedir(), ".scriptdb");
15
- pkgScriptDB = {};
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ VM: () => VM,
34
+ default: () => index_default
35
+ });
36
+ module.exports = __toCommonJS(index_exports);
37
+ var import_bun = __toESM(require("bun"));
38
+ var import_node_vm = __toESM(require("vm"));
39
+ var import_node_fs = __toESM(require("fs"));
40
+ var import_node_path = __toESM(require("path"));
41
+ var import_node_os = __toESM(require("os"));
42
+ var VM = class {
16
43
  constructor(options) {
17
- if (!fs.existsSync(this.DATABASE_DIR)) {
18
- fs.mkdirSync(this.DATABASE_DIR, { recursive: true });
44
+ this.DATABASE_DIR = import_node_path.default.join(import_node_os.default.homedir(), ".scriptdb", "databases");
45
+ this.SCRIPTDB_DIR = import_node_path.default.join(import_node_os.default.homedir(), ".scriptdb");
46
+ this.pkgScriptDB = {};
47
+ if (!import_node_fs.default.existsSync(this.DATABASE_DIR)) {
48
+ import_node_fs.default.mkdirSync(this.DATABASE_DIR, { recursive: true });
19
49
  }
20
- if (!fs.existsSync(this.SCRIPTDB_DIR)) {
21
- fs.mkdirSync(this.SCRIPTDB_DIR, { recursive: true });
50
+ if (!import_node_fs.default.existsSync(this.SCRIPTDB_DIR)) {
51
+ import_node_fs.default.mkdirSync(this.SCRIPTDB_DIR, { recursive: true });
22
52
  }
23
- const pkgPath = path.join(this.SCRIPTDB_DIR, "package.json");
24
- if (fs.existsSync(pkgPath)) {
25
- this.pkgScriptDB = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
53
+ const pkgPath = import_node_path.default.join(this.SCRIPTDB_DIR, "package.json");
54
+ if (import_node_fs.default.existsSync(pkgPath)) {
55
+ this.pkgScriptDB = JSON.parse(import_node_fs.default.readFileSync(pkgPath, "utf8"));
26
56
  }
27
- this.transpiler = new Bun.Transpiler({
57
+ this.transpiler = new import_bun.default.Transpiler({
28
58
  loader: options?.language || "ts"
29
59
  });
30
60
  this.registerModules = options?.registerModules || {};
31
- this.ctx = vm.createContext(this.registerModules);
61
+ this.ctx = import_node_vm.default.createContext(this.registerModules);
32
62
  }
33
63
  register(context) {
34
64
  this.registerModules = { ...this.registerModules, ...context };
35
- this.ctx = vm.createContext(this.registerModules);
65
+ this.ctx = import_node_vm.default.createContext(this.registerModules);
36
66
  }
37
67
  resolvePath(fileList, query) {
38
68
  const aliases = { "@db": this.DATABASE_DIR };
@@ -43,25 +73,29 @@ class VM {
43
73
  break;
44
74
  }
45
75
  }
46
- resolvedPath = path.normalize(resolvedPath);
76
+ resolvedPath = import_node_path.default.normalize(resolvedPath);
47
77
  return fileList.find((file) => {
48
- const normalizedFile = path.normalize(file);
78
+ const normalizedFile = import_node_path.default.normalize(file);
49
79
  const fileWithoutExt = normalizedFile.replace(/\.[^/.]+$/, "");
50
80
  return normalizedFile === resolvedPath || fileWithoutExt === resolvedPath || normalizedFile === resolvedPath + ".ts" || normalizedFile === resolvedPath + ".js";
51
81
  });
52
82
  }
53
83
  async moduleLinker(specifier, referencingModule) {
54
- const dbFiles = fs.readdirSync(this.DATABASE_DIR).filter((f) => f.endsWith(".ts")).map((f) => path.join(this.DATABASE_DIR, f));
84
+ const dbFiles = import_node_fs.default.readdirSync(this.DATABASE_DIR).filter((f) => f.endsWith(".ts")).map((f) => import_node_path.default.join(this.DATABASE_DIR, f));
55
85
  const dbResult = this.resolvePath(dbFiles, specifier);
56
86
  if (dbResult) {
57
87
  try {
58
88
  const actualModule = await import(dbResult);
59
89
  const exportNames = Object.keys(actualModule);
60
- return new vm.SyntheticModule(exportNames, function() {
61
- exportNames.forEach((key) => {
62
- this.setExport(key, actualModule[key]);
63
- });
64
- }, { identifier: specifier, context: referencingModule.context });
90
+ return new import_node_vm.default.SyntheticModule(
91
+ exportNames,
92
+ function() {
93
+ exportNames.forEach((key) => {
94
+ this.setExport(key, actualModule[key]);
95
+ });
96
+ },
97
+ { identifier: specifier, context: referencingModule.context }
98
+ );
65
99
  } catch (err) {
66
100
  console.error(`Failed to load database module ${specifier}:`, err);
67
101
  throw err;
@@ -70,14 +104,18 @@ class VM {
70
104
  const allowedPackages = Object.keys(this.pkgScriptDB.dependencies || {});
71
105
  if (allowedPackages.includes(specifier)) {
72
106
  try {
73
- const modulePath = path.join(this.SCRIPTDB_DIR, "node_modules", specifier);
107
+ const modulePath = import_node_path.default.join(this.SCRIPTDB_DIR, "node_modules", specifier);
74
108
  const actualModule = await import(modulePath);
75
109
  const exportNames = Object.keys(actualModule);
76
- return new vm.SyntheticModule(exportNames, function() {
77
- exportNames.forEach((key) => {
78
- this.setExport(key, actualModule[key]);
79
- });
80
- }, { identifier: specifier, context: referencingModule.context });
110
+ return new import_node_vm.default.SyntheticModule(
111
+ exportNames,
112
+ function() {
113
+ exportNames.forEach((key) => {
114
+ this.setExport(key, actualModule[key]);
115
+ });
116
+ },
117
+ { identifier: specifier, context: referencingModule.context }
118
+ );
81
119
  } catch (err) {
82
120
  console.error(`Failed to load workspace module ${specifier}:`, err);
83
121
  throw err;
@@ -95,7 +133,7 @@ class VM {
95
133
  console: customConsole
96
134
  });
97
135
  const js = this.transpiler.transformSync(code);
98
- const mod = new vm.SourceTextModule(js, { context: this.ctx, identifier: path.join(this.SCRIPTDB_DIR, "virtual-entry.js") });
136
+ const mod = new import_node_vm.default.SourceTextModule(js, { context: this.ctx, identifier: import_node_path.default.join(this.SCRIPTDB_DIR, "virtual-entry.js") });
99
137
  await mod.link(this.moduleLinker.bind(this));
100
138
  await mod.evaluate();
101
139
  return {
@@ -103,9 +141,10 @@ class VM {
103
141
  logs
104
142
  };
105
143
  }
106
- }
107
- var src_default = VM;
108
- export {
109
- src_default as default,
110
- VM
111
144
  };
145
+ var index_default = VM;
146
+ // Annotate the CommonJS export names for ESM import in node:
147
+ 0 && (module.exports = {
148
+ VM
149
+ });
150
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import Bun from \"bun\";\nimport vm from \"node:vm\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport os from \"node:os\";\ninterface VMOptions {\n language?: 'ts' | 'js';\n registerModules?: { [key: string]: any };\n}\n\nexport class VM {\n private transpiler: Bun.Transpiler;\n private ctx: vm.Context;\n private registerModules: { [key: string]: any };\n private DATABASE_DIR = path.join(os.homedir(), '.scriptdb', 'databases');\n private SCRIPTDB_DIR = path.join(os.homedir(), '.scriptdb');\n private pkgScriptDB: { dependencies?: Record<string, string> } = {};\n constructor(options?: VMOptions) {\n // Ensure directories exist\n if (!fs.existsSync(this.DATABASE_DIR)) {\n fs.mkdirSync(this.DATABASE_DIR, { recursive: true });\n }\n if (!fs.existsSync(this.SCRIPTDB_DIR)) {\n fs.mkdirSync(this.SCRIPTDB_DIR, { recursive: true });\n }\n\n // Load scriptdb workspace package.json if it exists\n const pkgPath = path.join(this.SCRIPTDB_DIR, 'package.json');\n if (fs.existsSync(pkgPath)) {\n this.pkgScriptDB = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));\n }\n this.transpiler = new Bun.Transpiler({\n loader: options?.language || 'ts',\n });\n\n\n\n this.registerModules = options?.registerModules || {};\n\n this.ctx = vm.createContext(this.registerModules);\n\n\n }\n\n register(context: { [key: string]: any }) {\n this.registerModules = { ...this.registerModules, ...context };\n // Register any custom modules or plugins here if needed\n this.ctx = vm.createContext(this.registerModules);\n }\n\n resolvePath(fileList: any[], query: string) {\n const aliases = { '@db': this.DATABASE_DIR };\n \n let resolvedPath = query;\n for (const [alias, target] of Object.entries(aliases)) {\n if (resolvedPath.startsWith(alias + '/')) {\n resolvedPath = resolvedPath.replace(alias, target);\n break;\n }\n }\n\n // Normalize path separators for cross-platform compatibility\n resolvedPath = path.normalize(resolvedPath);\n\n return fileList.find(file => {\n const normalizedFile = path.normalize(file);\n const fileWithoutExt = normalizedFile.replace(/\\.[^/.]+$/, \"\");\n return normalizedFile === resolvedPath || \n fileWithoutExt === resolvedPath || \n normalizedFile === resolvedPath + '.ts' || \n normalizedFile === resolvedPath + '.js';\n });\n }\n\n async moduleLinker(specifier: any, referencingModule: any) {\n // Try database files first\n const dbFiles = fs.readdirSync(this.DATABASE_DIR)\n .filter(f => f.endsWith(\".ts\"))\n .map(f => path.join(this.DATABASE_DIR, f));\n\n const dbResult = this.resolvePath(dbFiles, specifier);\n if (dbResult) {\n try {\n const actualModule = await import(dbResult);\n const exportNames = Object.keys(actualModule);\n return new vm.SyntheticModule(\n exportNames,\n function () {\n exportNames.forEach(key => {\n this.setExport(key, actualModule[key]);\n });\n },\n { identifier: specifier, context: referencingModule.context }\n );\n } catch (err) {\n console.error(`Failed to load database module ${specifier}:`, err);\n throw err;\n }\n }\n\n // Try workspace packages\n const allowedPackages = Object.keys(this.pkgScriptDB.dependencies || {});\n if (allowedPackages.includes(specifier)) {\n try {\n // Import from scriptdb workspace node_modules\n const modulePath = path.join(this.SCRIPTDB_DIR, 'node_modules', specifier);\n const actualModule = await import(modulePath);\n const exportNames = Object.keys(actualModule);\n return new vm.SyntheticModule(\n exportNames,\n function () {\n exportNames.forEach(key => {\n this.setExport(key, actualModule[key]);\n });\n },\n { identifier: specifier, context: referencingModule.context }\n );\n } catch (err) {\n console.error(`Failed to load workspace module ${specifier}:`, err);\n throw err;\n }\n }\n\n throw new Error(`Module ${specifier} is not allowed or not found.`);\n }\n\n async run(code: string, options?: vm.RunningCodeOptions | string) {\n // Remove import statements since modules are already registered in context\n // import { testdb } from 'testdb' -> testdb is already available in this.ctx\n // const importRegex = /^\\s*import\\s+\\{?\\s*([^}]+?)\\s*\\}?\\s+from\\s+['\"]([^'\"]+)['\"]\\s*;?\\s*$/gm;\n // const importMatches = code.match(importRegex);\n // const importCode = importMatches ? importMatches.join('\\n') : '';\n\n\n // const codeWithoutImports = code.replace(importRegex, '').trim();\n\n // // Wrap code in async function\n // const wrappedCode = `(async () => {\\n${codeWithoutImports}\\n})()`;\n\n const logs: any[] = [];\n\n const customConsole = ['log', 'error', 'warn', 'info', 'debug', 'trace'].reduce((acc: any, type: any) => {\n acc[type] = (...args: any[]) => logs.push({ type, args });\n return acc;\n }, {});\n\n this.register({\n console: customConsole\n });\n\n\n const js = this.transpiler.transformSync(code);\n const mod = new vm.SourceTextModule(js, { context: this.ctx, identifier: path.join(this.SCRIPTDB_DIR, 'virtual-entry.js') });\n await mod.link(this.moduleLinker.bind(this));\n await mod.evaluate();\n\n return {\n namespace: mod.namespace,\n logs: logs\n }\n }\n}\n\n\nexport default VM;"],"mappings":"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","names":["path","os","fs","Bun","vm"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,115 @@
1
+ // src/index.ts
2
+ import Bun from "bun";
3
+ import vm from "vm";
4
+ import fs from "fs";
5
+ import path from "path";
6
+ import os from "os";
7
+ var VM = class {
8
+ constructor(options) {
9
+ this.DATABASE_DIR = path.join(os.homedir(), ".scriptdb", "databases");
10
+ this.SCRIPTDB_DIR = path.join(os.homedir(), ".scriptdb");
11
+ this.pkgScriptDB = {};
12
+ if (!fs.existsSync(this.DATABASE_DIR)) {
13
+ fs.mkdirSync(this.DATABASE_DIR, { recursive: true });
14
+ }
15
+ if (!fs.existsSync(this.SCRIPTDB_DIR)) {
16
+ fs.mkdirSync(this.SCRIPTDB_DIR, { recursive: true });
17
+ }
18
+ const pkgPath = path.join(this.SCRIPTDB_DIR, "package.json");
19
+ if (fs.existsSync(pkgPath)) {
20
+ this.pkgScriptDB = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
21
+ }
22
+ this.transpiler = new Bun.Transpiler({
23
+ loader: options?.language || "ts"
24
+ });
25
+ this.registerModules = options?.registerModules || {};
26
+ this.ctx = vm.createContext(this.registerModules);
27
+ }
28
+ register(context) {
29
+ this.registerModules = { ...this.registerModules, ...context };
30
+ this.ctx = vm.createContext(this.registerModules);
31
+ }
32
+ resolvePath(fileList, query) {
33
+ const aliases = { "@db": this.DATABASE_DIR };
34
+ let resolvedPath = query;
35
+ for (const [alias, target] of Object.entries(aliases)) {
36
+ if (resolvedPath.startsWith(alias + "/")) {
37
+ resolvedPath = resolvedPath.replace(alias, target);
38
+ break;
39
+ }
40
+ }
41
+ resolvedPath = path.normalize(resolvedPath);
42
+ return fileList.find((file) => {
43
+ const normalizedFile = path.normalize(file);
44
+ const fileWithoutExt = normalizedFile.replace(/\.[^/.]+$/, "");
45
+ return normalizedFile === resolvedPath || fileWithoutExt === resolvedPath || normalizedFile === resolvedPath + ".ts" || normalizedFile === resolvedPath + ".js";
46
+ });
47
+ }
48
+ async moduleLinker(specifier, referencingModule) {
49
+ const dbFiles = fs.readdirSync(this.DATABASE_DIR).filter((f) => f.endsWith(".ts")).map((f) => path.join(this.DATABASE_DIR, f));
50
+ const dbResult = this.resolvePath(dbFiles, specifier);
51
+ if (dbResult) {
52
+ try {
53
+ const actualModule = await import(dbResult);
54
+ const exportNames = Object.keys(actualModule);
55
+ return new vm.SyntheticModule(
56
+ exportNames,
57
+ function() {
58
+ exportNames.forEach((key) => {
59
+ this.setExport(key, actualModule[key]);
60
+ });
61
+ },
62
+ { identifier: specifier, context: referencingModule.context }
63
+ );
64
+ } catch (err) {
65
+ console.error(`Failed to load database module ${specifier}:`, err);
66
+ throw err;
67
+ }
68
+ }
69
+ const allowedPackages = Object.keys(this.pkgScriptDB.dependencies || {});
70
+ if (allowedPackages.includes(specifier)) {
71
+ try {
72
+ const modulePath = path.join(this.SCRIPTDB_DIR, "node_modules", specifier);
73
+ const actualModule = await import(modulePath);
74
+ const exportNames = Object.keys(actualModule);
75
+ return new vm.SyntheticModule(
76
+ exportNames,
77
+ function() {
78
+ exportNames.forEach((key) => {
79
+ this.setExport(key, actualModule[key]);
80
+ });
81
+ },
82
+ { identifier: specifier, context: referencingModule.context }
83
+ );
84
+ } catch (err) {
85
+ console.error(`Failed to load workspace module ${specifier}:`, err);
86
+ throw err;
87
+ }
88
+ }
89
+ throw new Error(`Module ${specifier} is not allowed or not found.`);
90
+ }
91
+ async run(code, options) {
92
+ const logs = [];
93
+ const customConsole = ["log", "error", "warn", "info", "debug", "trace"].reduce((acc, type) => {
94
+ acc[type] = (...args) => logs.push({ type, args });
95
+ return acc;
96
+ }, {});
97
+ this.register({
98
+ console: customConsole
99
+ });
100
+ const js = this.transpiler.transformSync(code);
101
+ const mod = new vm.SourceTextModule(js, { context: this.ctx, identifier: path.join(this.SCRIPTDB_DIR, "virtual-entry.js") });
102
+ await mod.link(this.moduleLinker.bind(this));
103
+ await mod.evaluate();
104
+ return {
105
+ namespace: mod.namespace,
106
+ logs
107
+ };
108
+ }
109
+ };
110
+ var index_default = VM;
111
+ export {
112
+ VM,
113
+ index_default as default
114
+ };
115
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import Bun from \"bun\";\nimport vm from \"node:vm\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport os from \"node:os\";\ninterface VMOptions {\n language?: 'ts' | 'js';\n registerModules?: { [key: string]: any };\n}\n\nexport class VM {\n private transpiler: Bun.Transpiler;\n private ctx: vm.Context;\n private registerModules: { [key: string]: any };\n private DATABASE_DIR = path.join(os.homedir(), '.scriptdb', 'databases');\n private SCRIPTDB_DIR = path.join(os.homedir(), '.scriptdb');\n private pkgScriptDB: { dependencies?: Record<string, string> } = {};\n constructor(options?: VMOptions) {\n // Ensure directories exist\n if (!fs.existsSync(this.DATABASE_DIR)) {\n fs.mkdirSync(this.DATABASE_DIR, { recursive: true });\n }\n if (!fs.existsSync(this.SCRIPTDB_DIR)) {\n fs.mkdirSync(this.SCRIPTDB_DIR, { recursive: true });\n }\n\n // Load scriptdb workspace package.json if it exists\n const pkgPath = path.join(this.SCRIPTDB_DIR, 'package.json');\n if (fs.existsSync(pkgPath)) {\n this.pkgScriptDB = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));\n }\n this.transpiler = new Bun.Transpiler({\n loader: options?.language || 'ts',\n });\n\n\n\n this.registerModules = options?.registerModules || {};\n\n this.ctx = vm.createContext(this.registerModules);\n\n\n }\n\n register(context: { [key: string]: any }) {\n this.registerModules = { ...this.registerModules, ...context };\n // Register any custom modules or plugins here if needed\n this.ctx = vm.createContext(this.registerModules);\n }\n\n resolvePath(fileList: any[], query: string) {\n const aliases = { '@db': this.DATABASE_DIR };\n \n let resolvedPath = query;\n for (const [alias, target] of Object.entries(aliases)) {\n if (resolvedPath.startsWith(alias + '/')) {\n resolvedPath = resolvedPath.replace(alias, target);\n break;\n }\n }\n\n // Normalize path separators for cross-platform compatibility\n resolvedPath = path.normalize(resolvedPath);\n\n return fileList.find(file => {\n const normalizedFile = path.normalize(file);\n const fileWithoutExt = normalizedFile.replace(/\\.[^/.]+$/, \"\");\n return normalizedFile === resolvedPath || \n fileWithoutExt === resolvedPath || \n normalizedFile === resolvedPath + '.ts' || \n normalizedFile === resolvedPath + '.js';\n });\n }\n\n async moduleLinker(specifier: any, referencingModule: any) {\n // Try database files first\n const dbFiles = fs.readdirSync(this.DATABASE_DIR)\n .filter(f => f.endsWith(\".ts\"))\n .map(f => path.join(this.DATABASE_DIR, f));\n\n const dbResult = this.resolvePath(dbFiles, specifier);\n if (dbResult) {\n try {\n const actualModule = await import(dbResult);\n const exportNames = Object.keys(actualModule);\n return new vm.SyntheticModule(\n exportNames,\n function () {\n exportNames.forEach(key => {\n this.setExport(key, actualModule[key]);\n });\n },\n { identifier: specifier, context: referencingModule.context }\n );\n } catch (err) {\n console.error(`Failed to load database module ${specifier}:`, err);\n throw err;\n }\n }\n\n // Try workspace packages\n const allowedPackages = Object.keys(this.pkgScriptDB.dependencies || {});\n if (allowedPackages.includes(specifier)) {\n try {\n // Import from scriptdb workspace node_modules\n const modulePath = path.join(this.SCRIPTDB_DIR, 'node_modules', specifier);\n const actualModule = await import(modulePath);\n const exportNames = Object.keys(actualModule);\n return new vm.SyntheticModule(\n exportNames,\n function () {\n exportNames.forEach(key => {\n this.setExport(key, actualModule[key]);\n });\n },\n { identifier: specifier, context: referencingModule.context }\n );\n } catch (err) {\n console.error(`Failed to load workspace module ${specifier}:`, err);\n throw err;\n }\n }\n\n throw new Error(`Module ${specifier} is not allowed or not found.`);\n }\n\n async run(code: string, options?: vm.RunningCodeOptions | string) {\n // Remove import statements since modules are already registered in context\n // import { testdb } from 'testdb' -> testdb is already available in this.ctx\n // const importRegex = /^\\s*import\\s+\\{?\\s*([^}]+?)\\s*\\}?\\s+from\\s+['\"]([^'\"]+)['\"]\\s*;?\\s*$/gm;\n // const importMatches = code.match(importRegex);\n // const importCode = importMatches ? importMatches.join('\\n') : '';\n\n\n // const codeWithoutImports = code.replace(importRegex, '').trim();\n\n // // Wrap code in async function\n // const wrappedCode = `(async () => {\\n${codeWithoutImports}\\n})()`;\n\n const logs: any[] = [];\n\n const customConsole = ['log', 'error', 'warn', 'info', 'debug', 'trace'].reduce((acc: any, type: any) => {\n acc[type] = (...args: any[]) => logs.push({ type, args });\n return acc;\n }, {});\n\n this.register({\n console: customConsole\n });\n\n\n const js = this.transpiler.transformSync(code);\n const mod = new vm.SourceTextModule(js, { context: this.ctx, identifier: path.join(this.SCRIPTDB_DIR, 'virtual-entry.js') });\n await mod.link(this.moduleLinker.bind(this));\n await mod.evaluate();\n\n return {\n namespace: mod.namespace,\n logs: logs\n }\n }\n}\n\n\nexport default VM;"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scriptdb/vm",
3
- "version": "1.1.0",
3
+ "version": "1.1.2",
4
4
  "description": "Virtual machine package for script database",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -17,10 +17,7 @@
17
17
  ],
18
18
  "scripts": {
19
19
  "dev": "bun --watch src/index.ts",
20
- "build": "bun build src/index.ts --outdir dist --target bun --format esm --splitting",
21
- "build:cjs": "bun build src/index.ts --outdir dist --target bun --format cjs --outfile dist/index.js",
22
- "build:types": "tsc --emitDeclarationOnly --project tsconfig.build.json",
23
- "build:all": "bun run build && bun run build:cjs && bun run build:types",
20
+ "build": "tsup",
24
21
  "test": "bun test",
25
22
  "lint": "bun run lint:src",
26
23
  "lint:src": "eslint src --ext .ts,.tsx",