vmlive 1.0.3 → 1.0.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vmlive",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "description": "Local development VM for custom Serverless PaaS",
5
5
  "type": "module",
6
6
  "bin": {
package/src/cli.js CHANGED
@@ -28,7 +28,7 @@ const buildResourcesConfig = () => {
28
28
  };
29
29
  };
30
30
 
31
- const buildProxyDispatcher = (functions, workspaceId, projectId) => ({
31
+ const buildProxyDispatcher = (functions, workspaceId, projectId, includeDashboard = true) => ({
32
32
  name: "vm-gateway-proxy",
33
33
  modules: true,
34
34
  script: `
@@ -43,18 +43,26 @@ const buildProxyDispatcher = (functions, workspaceId, projectId) => ({
43
43
  const hostHeader = request.headers.get("Host") || url.hostname;
44
44
  let targetName = hostHeader.split('.')[0];
45
45
 
46
+ let res;
47
+
46
48
  if (targetName === 'dashboard' && env.DASHBOARD) {
47
- return env.DASHBOARD.fetch(request);
49
+ res = await env.DASHBOARD.fetch(request);
50
+ } else if (targetName && env[targetName]) {
51
+ res = await env[targetName].fetch(request);
52
+ } else {
53
+ res = new Response(
54
+ \`Function Not Found: \${targetName}.\\n\\nExpected format: http://${workspaceId}-${projectId}-<function_name>.localhost\`,
55
+ { status: 404 }
56
+ );
48
57
  }
49
58
 
50
- if (targetName && env[targetName]) {
51
- return env[targetName].fetch(request);
52
- }
59
+ const method = request.method;
60
+ const path = url.pathname;
61
+ const status = res.status;
62
+ const color = status >= 500 ? "\\x1b[31m" : status >= 400 ? "\\x1b[33m" : "\\x1b[32m";
53
63
 
54
- return new Response(
55
- \`Function Not Found: \${targetName}.\\n\\nExpected format: http://${workspaceId}-${projectId}-<function_name>.localhost\`,
56
- { status: 404 }
57
- );
64
+ console.log(\`\\x1b[90m[\${targetName}]\\x1b[0m \${method} \${path} \${color}\${status}\\x1b[0m\`);
65
+ return res;
58
66
  }
59
67
  }
60
68
  `,
@@ -63,7 +71,7 @@ const buildProxyDispatcher = (functions, workspaceId, projectId) => ({
63
71
  acc[`${workspaceId}-${projectId}-${fn.name}`] = fn.name;
64
72
  return acc;
65
73
  }, {}),
66
- DASHBOARD: "vm-dashboard-worker"
74
+ ...(includeDashboard ? { DASHBOARD: "vm-dashboard-worker" } : {})
67
75
  }
68
76
  });
69
77
 
@@ -462,11 +470,12 @@ const runDev = async () => {
462
470
  console.log('\nLocal endpoints available:');
463
471
 
464
472
  const dashboardUrl = `http://dashboard.localhost:${mfPort}`;
465
- console.log(` \x1b]8;;${dashboardUrl}\x1b\\${dashboardUrl}\x1b]8;;\x1b\\ \x1b[32m[Dashboard]\x1b[0m`);
473
+ console.log(` \x1b]8;;${dashboardUrl}\x1b\\\x1b[32m[dashboard]\x1b[0m\x1b]8;;\x1b\\ ${dashboardUrl}`);
466
474
 
467
475
  config.functions.forEach(fn => {
468
476
  const endpointUrl = `http://${workspaceId}-${projectId}-${fn.name}.localhost:${mfPort}`;
469
- console.log(` \x1b]8;;${endpointUrl}\x1b\\${endpointUrl}\x1b]8;;\x1b\\`);
477
+ const padName = `[${fn.name}]`.padEnd(13, ' ');
478
+ console.log(` \x1b]8;;${endpointUrl}\x1b\\\x1b[36m${padName}\x1b[0m\x1b]8;;\x1b\\ ${endpointUrl}`);
470
479
  });
471
480
 
472
481
  setInterval(() => {
@@ -566,7 +575,7 @@ const runTest = async () => {
566
575
 
567
576
  // Exact parity workers but omitting the Dashboard intentionally
568
577
  const miniflareWorkers = [
569
- buildProxyDispatcher(config.functions, workspaceId, projectId),
578
+ buildProxyDispatcher(config.functions, workspaceId, projectId, false),
570
579
  {
571
580
  name: "vm-shadow-worker",
572
581
  modules: true,
@@ -146,4 +146,4 @@ export default {
146
146
  // Default to the Editor UI Payload
147
147
  return new Response(UI_HTML, { headers: { 'Content-Type': 'text/html; charset=utf-8' }});
148
148
  }
149
- };`
149
+ };
@@ -3,8 +3,8 @@ import * as UserCode from '${outFileUrl}';
3
3
 
4
4
  export default {
5
5
  async fetch(req, env, ctx) {
6
- // Isolate the global KV
7
- const { __RAW_KV, ...safeEnv } = env;
6
+ // Isolate the global KV and Storage
7
+ const { __RAW_KV, R2, ...safeEnv } = env;
8
8
  const KV_PREFIX = \`${workspaceId}:${projectId}:\`;
9
9
 
10
10
  // 1. Air-Gapped Virtual KV Multiplexer
@@ -80,9 +80,12 @@ export default {
80
80
  const Channels = {
81
81
  accept: async (roomName, metadata) => {
82
82
  console.log(\`\\x1b[36m[\${env.PROJECT_ID || '${projectId}'}]\\x1b[0m 🔌 Channels.accept: [\${roomName}]\`, metadata);
83
- const req = new Request("http://platform/.internal", { headers: { Upgrade: "websocket" }});
83
+ if (req.headers.get("Upgrade") !== "websocket") {
84
+ return new Response("Upgrade Required: Endpoint expects a WebSocket connection.", { status: 426 });
85
+ }
86
+ const doReq = new Request("http://platform/.internal", { headers: req.headers });
84
87
  const stub = env.CHANNEL_DO.idFromName(roomName);
85
- return await env.CHANNEL_DO.get(stub).fetch(req);
88
+ return await env.CHANNEL_DO.get(stub).fetch(doReq);
86
89
  },
87
90
  broadcast: async (roomName, payload) => {
88
91
  console.log(\`\\x1b[36m[\${env.PROJECT_ID || '${projectId}'}]\\x1b[0m 📡 Channels.broadcast: [\${roomName}]\`, payload);
@@ -110,6 +113,7 @@ export default {
110
113
  const customEnv = {
111
114
  ...safeEnv,
112
115
  KV: virtualKV,
116
+ BUCKET: R2,
113
117
  Tasks,
114
118
  Channels,
115
119
  Discord,