vmlive 1.0.7 → 1.0.8

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.
package/README.md CHANGED
@@ -33,11 +33,7 @@ Starts the local emulation environment.
33
33
  - Provides local proxy bindings for your SQL Database (`env.DB`), Global KV (`env.KV`), and Object Storage (`env.BUCKET`) using the `.vmlive/` directory for persistent storage.
34
34
  - Supports hot-reloading for `.js` and `.ts` files.
35
35
 
36
- ### `npx vmlive test`
37
- Executes your Vitest suites against a strictly ephemeral **in-memory** engine.
38
- - Spins up `VirtualMachine` in memory-only mode without touching `.vmlive/` disk databases.
39
- - Runs `npx vitest run` and gracefully destroys the engine upon exit.
40
- - Allows test suites to deeply mutate state predictably without sandbox bleeding.
36
+
41
37
 
42
38
  ### `npx vmlive deploy`
43
39
  Uploads the local code to the vm.live edge platform.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vmlive",
3
- "version": "1.0.7",
3
+ "version": "1.0.8",
4
4
  "description": "Local development VM for custom Serverless PaaS",
5
5
  "type": "module",
6
6
  "bin": {
package/src/cli.js CHANGED
@@ -40,8 +40,9 @@ const buildProxyDispatcher = (functions, workspaceId, projectId, includeDashboar
40
40
  return new Response(null, { status: 204 });
41
41
  }
42
42
 
43
+ const explicitTarget = request.headers.get("x-vm-target");
43
44
  const hostHeader = request.headers.get("Host") || url.hostname;
44
- let targetName = hostHeader.split('.')[0];
45
+ let targetName = explicitTarget || hostHeader.split('.')[0];
45
46
 
46
47
  let res;
47
48
 
@@ -526,100 +527,6 @@ const runDev = async () => {
526
527
  });
527
528
  };
528
529
 
529
- const runTest = async () => {
530
- if (!fs.existsSync(CONFIG_PATH)) {
531
- throw new Error("Missing vm.json in project root. Run 'vm init' to scaffold a new project workspace.");
532
- }
533
-
534
- const testArgs = process.argv.slice(3);
535
- console.log('\x1b[36mInitializing Ephemeral Target Engine for Integration Tests...\x1b[0m');
536
-
537
- const config = JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf-8'));
538
- if (!fs.existsSync(WORK_DIR)) fs.mkdirSync(WORK_DIR, { recursive: true });
539
-
540
- const sharedBindings = fs.existsSync(path.resolve('.env'))
541
- ? dotenv.parse(fs.readFileSync(path.resolve('.env')))
542
- : {};
543
-
544
- const resourcesConfig = buildResourcesConfig();
545
-
546
- const entryPoints = config.functions.reduce((acc, fn) => {
547
- acc[`${fn.name}-out`] = path.resolve(fn.entry);
548
- return acc;
549
- }, {});
550
-
551
- const workspaceId = config.workspaceId || "ws_local";
552
- const projectId = config.projectId || "prj_local";
553
-
554
- config.functions.forEach(fn => {
555
- const relativeTarget = `./${fn.name}-out.mjs`;
556
- fs.writeFileSync(path.join(WORK_DIR, `${fn.name}-shim.mjs`), generateShim(relativeTarget, workspaceId, projectId, fn.name));
557
- });
558
-
559
- const builder = await esbuild.context({
560
- entryPoints,
561
- bundle: true,
562
- format: 'esm',
563
- outdir: WORK_DIR,
564
- outExtension: { '.js': '.mjs' },
565
- external: ['cloudflare:*'],
566
- logLevel: 'silent'
567
- });
568
-
569
- await builder.rebuild();
570
-
571
- const shadowSource = fs.readFileSync(path.join(__dirname, 'shadow-dos.js'), 'utf-8');
572
- fs.writeFileSync(path.join(WORK_DIR, 'shadow-dos.mjs'), shadowSource);
573
-
574
- const mfPort = process.env.PORT ? parseInt(process.env.PORT) : 8787;
575
-
576
- // Exact parity workers but omitting the Dashboard intentionally
577
- const miniflareWorkers = [
578
- buildProxyDispatcher(config.functions, workspaceId, projectId, false),
579
- {
580
- name: "vm-shadow-worker",
581
- modules: true,
582
- scriptPath: path.join(WORK_DIR, 'shadow-dos.mjs'),
583
- bindings: { PORT: mfPort },
584
- durableObjects: { LocalTaskManagerDO: "LocalTaskManagerDO", LocalChannelRoomDO: "LocalChannelRoomDO" }
585
- },
586
- ...config.functions.map(fn => ({
587
- name: fn.name,
588
- modules: true,
589
- scriptPath: path.join(WORK_DIR, `${fn.name}-shim.mjs`),
590
- bindings: sharedBindings,
591
- ...resourcesConfig,
592
- durableObjects: {
593
- TASK_DO: { className: "LocalTaskManagerDO", scriptName: "vm-shadow-worker" },
594
- CHANNEL_DO: { className: "LocalChannelRoomDO", scriptName: "vm-shadow-worker" }
595
- }
596
- }))
597
- ];
598
-
599
- // IN-MEMORY EMULATOR (NO PERSIST PATHS)
600
- const mf = new Emulator({
601
- workers: miniflareWorkers,
602
- port: mfPort
603
- });
604
-
605
- await mf.ready;
606
- console.log('\x1b[32m✔ Ephemeral environment completely provisioned and bound.\x1b[0m\\n');
607
-
608
- const { spawn } = await import('child_process');
609
-
610
- const testProcess = spawn('npx', ['vitest', 'run', ...testArgs], {
611
- stdio: 'inherit',
612
- env: { ...process.env, VMLIVE_TESTING: "true" }
613
- });
614
-
615
- testProcess.on('exit', async (code) => {
616
- console.log('\\n\x1b[36mTerminating ephemeral engine execution context...\x1b[0m');
617
- await builder.dispose();
618
- await mf.dispose();
619
- process.exit(code || 0);
620
- });
621
- };
622
-
623
530
  const runDeploy = async () => {
624
531
  console.log('\x1b[36mDeploying...\x1b[0m');
625
532
 
@@ -778,8 +685,6 @@ const main = async () => {
778
685
  await runAdd();
779
686
  } else if (command === 'dev') {
780
687
  await runDev();
781
- } else if (command === 'test') {
782
- await runTest();
783
688
  } else if (command === 'login') {
784
689
  await runLogin();
785
690
  } else if (command === 'deploy') {
@@ -789,7 +694,7 @@ const main = async () => {
789
694
  console.log(`vmlive CLI v${pkg.version}`);
790
695
  } else {
791
696
  console.error(`\x1b[31m❌ Unknown command: ${command || 'missing'}\x1b[0m`);
792
- console.log('Usage: vm init | vm add | vm dev | vm test | vm login | vm deploy | vm which');
697
+ console.log('Usage: vm init | vm add | vm dev | vm login | vm deploy | vm which');
793
698
  process.exit(1);
794
699
  }
795
700
  };
package/src/shadow-dos.js CHANGED
@@ -49,7 +49,7 @@ export class LocalTaskManagerDO extends DurableObject {
49
49
  const res = await fetch(invokeUrl, {
50
50
  method: 'POST',
51
51
  headers: {
52
- 'Host': `${task.function_slug}.localhost`,
52
+ 'x-vm-target': `${task.workspace_id}-${task.project_id}-${task.function_slug}`,
53
53
  'Content-Type': 'application/json',
54
54
  'x-vm-system-signature': 'local-bypass'
55
55
  },