@celsian/vura-cli 0.5.2 → 0.5.3

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.
@@ -263,7 +263,7 @@ export async function startStandaloneServer(manifest, opts) {
263
263
  catch { /* not installed — keep default */ }
264
264
  const result = await esbuild({
265
265
  stdin: {
266
- contents: generateClientPageEntry(`./${basename(absPath)}`, page.mode),
266
+ contents: generateClientPageEntry(`./${basename(absPath)}`, page.mode, { dev: true }),
267
267
  resolveDir: dirname(absPath),
268
268
  sourcefile: '__vura-client-entry__.js',
269
269
  loader: 'js',
@@ -1,5 +1,5 @@
1
1
  import type { ApiRoute, PageRoute, RouteManifest } from '@celsian/vura-core';
2
- export type RuntimeProfile = 'static' | 'cold' | 'hot' | 'task-cold' | 'cron-cold' | 'task-hot' | 'cron-hot';
2
+ export type RuntimeProfile = 'static' | 'cold' | 'hot' | 'streaming-hot' | 'task-cold' | 'cron-cold' | 'task-hot' | 'cron-hot';
3
3
  export interface RuntimeRouteInspection {
4
4
  type: 'api' | 'page';
5
5
  pattern: string;
@@ -6,19 +6,24 @@ function configNumber(config, key) {
6
6
  const value = config[key];
7
7
  return typeof value === 'number' && Number.isFinite(value) ? value : undefined;
8
8
  }
9
+ function prefersHotTask(config) {
10
+ return ['runtime', 'placement', 'target'].some((key) => configString(config, key) === 'hot')
11
+ || config.hot === true;
12
+ }
9
13
  export function taskNameFromPattern(urlPattern) {
10
14
  return urlPattern.replace(/^\/api\//, '').replace(/\//g, '.');
11
15
  }
12
16
  export function profileForApiRoute(route) {
13
17
  if (route.kind === 'hot')
14
- return 'hot';
18
+ return route.hasWebsocket ? 'streaming-hot' : 'hot';
15
19
  if (route.kind === 'task')
16
- return 'task-cold';
20
+ return prefersHotTask(route.config) ? 'task-hot' : 'task-cold';
17
21
  return 'cold';
18
22
  }
19
23
  export function cronProfileForApiRoute(route) {
20
- if (route.kind === 'task' && configString(route.config, 'schedule'))
21
- return 'cron-cold';
24
+ if (route.kind === 'task' && configString(route.config, 'schedule')) {
25
+ return profileForApiRoute(route) === 'task-hot' ? 'cron-hot' : 'cron-cold';
26
+ }
22
27
  return null;
23
28
  }
24
29
  export function profileForPageRoute(page) {
@@ -27,9 +32,12 @@ export function profileForPageRoute(page) {
27
32
  return 'static';
28
33
  }
29
34
  function backingTargetForApiRoute(route) {
30
- if (route.kind === 'hot')
35
+ const profile = profileForApiRoute(route);
36
+ if (profile === 'hot' || profile === 'streaming-hot')
31
37
  return 'hot server';
32
- if (route.kind === 'task')
38
+ if (profile === 'task-hot')
39
+ return 'hot task runtime';
40
+ if (profile === 'task-cold')
33
41
  return 'serverless task function';
34
42
  return 'serverless function';
35
43
  }
@@ -71,7 +79,9 @@ function inspectApiRoute(route) {
71
79
  filePath: route.filePath,
72
80
  sourceIntent: `schedule:${schedule}`,
73
81
  effectiveProfile: cronProfile,
74
- backingTarget: 'control-plane scheduler to task function',
82
+ backingTarget: cronProfile === 'cron-hot'
83
+ ? 'control-plane scheduler to hot task runtime'
84
+ : 'control-plane scheduler to task function',
75
85
  methods: route.methods,
76
86
  schedule,
77
87
  hasWebsocket: false,
@@ -100,6 +110,7 @@ export function inspectRuntime(manifest) {
100
110
  static: 0,
101
111
  cold: 0,
102
112
  hot: 0,
113
+ 'streaming-hot': 0,
103
114
  'task-cold': 0,
104
115
  'cron-cold': 0,
105
116
  'task-hot': 0,
@@ -134,37 +145,43 @@ export function adviseRuntime(manifest) {
134
145
  pattern: route.urlPattern,
135
146
  type: 'api',
136
147
  currentProfile,
137
- recommendation: 'hot',
148
+ recommendation: 'streaming-hot',
138
149
  severity: route.kind === 'hot' ? 'info' : 'warn',
139
150
  reason: route.kind === 'hot'
140
- ? 'WebSocket route is correctly placed on hot runtime.'
141
- : 'WebSocket exports require hot runtime to handle upgrades.',
151
+ ? 'WebSocket route is correctly placed on streaming-hot runtime.'
152
+ : 'WebSocket exports require streaming-hot runtime to handle upgrades.',
142
153
  });
143
154
  }
144
155
  if (route.kind === 'task') {
156
+ const taskProfile = profileForApiRoute(route);
145
157
  advice.push({
146
158
  pattern: route.urlPattern,
147
159
  type: 'api',
148
160
  currentProfile,
149
- recommendation: 'task-cold',
161
+ recommendation: taskProfile,
150
162
  severity: 'info',
151
- reason: schedule
152
- ? 'Scheduled task is a task-cold worker with cron-cold dispatch.'
153
- : 'Task route is a task-cold worker for manual or API-triggered jobs.',
163
+ reason: taskProfile === 'task-hot'
164
+ ? 'Task route is pinned to hot task runtime for long-running or stateful work.'
165
+ : schedule
166
+ ? 'Scheduled task is a task-cold worker with cron-cold dispatch.'
167
+ : 'Task route is a task-cold worker for manual or API-triggered jobs.',
154
168
  nextCommand: `vura tasks run ${taskNameFromPattern(route.urlPattern)}`,
155
169
  });
156
170
  if (schedule) {
171
+ const cronProfile = cronProfileForApiRoute(route) ?? 'cron-cold';
157
172
  advice.push({
158
173
  pattern: route.urlPattern,
159
174
  type: 'api',
160
- currentProfile: 'cron-cold',
161
- recommendation: 'cron-cold',
175
+ currentProfile: cronProfile,
176
+ recommendation: cronProfile,
162
177
  severity: 'info',
163
- reason: `Cron schedule ${schedule} dispatches to the task-cold target.`,
178
+ reason: cronProfile === 'cron-hot'
179
+ ? `Cron schedule ${schedule} dispatches to the hot task target.`
180
+ : `Cron schedule ${schedule} dispatches to the task-cold target.`,
164
181
  nextCommand: 'vura tasks list',
165
182
  });
166
183
  }
167
- if (typeof timeout === 'number' && timeout > 60_000) {
184
+ if (typeof timeout === 'number' && timeout > 60_000 && taskProfile !== 'task-hot') {
168
185
  advice.push({
169
186
  pattern: route.urlPattern,
170
187
  type: 'api',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@celsian/vura-cli",
3
- "version": "0.5.2",
3
+ "version": "0.5.3",
4
4
  "description": "Vura CLI — build and deploy full-stack apps",
5
5
  "type": "module",
6
6
  "bin": {
@@ -15,12 +15,12 @@
15
15
  "!dist/**/*.map"
16
16
  ],
17
17
  "dependencies": {
18
- "@celsian/vura-core": "0.5.2",
18
+ "@celsian/vura-core": "0.5.3",
19
19
  "esbuild": "^0.28.1",
20
20
  "what-framework": "^0.11.1"
21
21
  },
22
22
  "peerDependencies": {
23
- "@celsian/vura-adapter-vura": "0.5.2",
23
+ "@celsian/vura-adapter-vura": "0.5.3",
24
24
  "ws": "^8.0.0"
25
25
  },
26
26
  "peerDependenciesMeta": {
@@ -32,7 +32,7 @@
32
32
  }
33
33
  },
34
34
  "devDependencies": {
35
- "@celsian/vura-adapter-vura": "0.5.2",
35
+ "@celsian/vura-adapter-vura": "0.5.3",
36
36
  "@types/ws": "^8.18.1",
37
37
  "ws": "^8.21.0"
38
38
  },