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 +1 -5
- package/package.json +1 -1
- package/src/cli.js +3 -98
- package/src/shadow-dos.js +1 -1
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
|
-
|
|
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
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
|
|
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
|
-
'
|
|
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
|
},
|