@celsian/vura-cli 0.5.6 → 0.5.9
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
|
@@ -6,7 +6,7 @@ CLI for [Vura](https://vura.io) — develop, build, and run tasks for Vura appli
|
|
|
6
6
|
|
|
7
7
|
## What it does
|
|
8
8
|
|
|
9
|
-
`@celsian/vura-cli` provides the `vura` command for developing and
|
|
9
|
+
`@celsian/vura-cli` provides the `vura` command for developing, building, inspecting, and deploying Vura projects. It reports effective Function/Dedicated placement and pending Edge requests, including memory, CPU, timeout, provider recommendation, confidence, and reasons. `create-vura` installs the managed deployment adapter, so `vura deploy` works without a follow-up package install. Self-hosted builds can use the Lambda or Cloudflare adapters. The package was historically named `then`/`thenjs`; the only installed bin is `vura`.
|
|
10
10
|
|
|
11
11
|
## Install
|
|
12
12
|
|
|
@@ -44,6 +44,10 @@ vura routes inspect --json
|
|
|
44
44
|
vura runtime advise --json
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
+
An Edge declaration is a request, not an override. The CLI reports it as
|
|
48
|
+
pending while the route continues on 1 GiB Function compute; only measured
|
|
49
|
+
platform eligibility can promote it to the fixed 128 MiB Edge runtime.
|
|
50
|
+
|
|
47
51
|
(`then` is a shell reserved word — use `vura` in all scripts.)
|
|
48
52
|
|
|
49
53
|
## Documentation
|
package/dist/commands/deploy.js
CHANGED
|
@@ -100,7 +100,7 @@ export async function deployCommand(args) {
|
|
|
100
100
|
});
|
|
101
101
|
console.log('');
|
|
102
102
|
console.log(` ${flags.production ? 'Production' : 'Preview'} deployment ready.`);
|
|
103
|
-
console.log(` URL:
|
|
103
|
+
console.log(` URL: ${result.url}`);
|
|
104
104
|
}
|
|
105
105
|
catch (err) {
|
|
106
106
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ApiRoute, PageRoute, RouteManifest } from '@celsian/vura-core';
|
|
1
|
+
import type { ApiRoute, ComputeClass, PageRoute, RouteManifest } from '@celsian/vura-core';
|
|
2
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';
|
|
@@ -10,6 +10,15 @@ export interface RuntimeRouteInspection {
|
|
|
10
10
|
methods?: string[];
|
|
11
11
|
schedule?: string;
|
|
12
12
|
hasWebsocket?: boolean;
|
|
13
|
+
effectiveComputeClass?: 'function' | 'dedicated';
|
|
14
|
+
requestedComputeClass?: ComputeClass;
|
|
15
|
+
edgeEligibility?: 'pending';
|
|
16
|
+
memory?: string | number;
|
|
17
|
+
cpu?: number;
|
|
18
|
+
timeout?: number;
|
|
19
|
+
providerRecommendation?: 'elastic-function-provider' | 'dedicated-fly-machine' | 'cloudflare-workers-for-platforms';
|
|
20
|
+
confidence?: 'high' | 'medium';
|
|
21
|
+
reasons?: string[];
|
|
13
22
|
warnings: string[];
|
|
14
23
|
nextCommand?: string;
|
|
15
24
|
}
|
|
@@ -6,8 +6,74 @@ 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 configObject(config, key) {
|
|
10
|
+
const value = config[key];
|
|
11
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value)
|
|
12
|
+
? value
|
|
13
|
+
: undefined;
|
|
14
|
+
}
|
|
15
|
+
function computeForRoute(route) {
|
|
16
|
+
return configObject(route.config, 'compute') ?? { class: route.kind === 'hot' ? 'dedicated' : 'function', memory: '1gb' };
|
|
17
|
+
}
|
|
18
|
+
function computeDetails(route) {
|
|
19
|
+
const compute = computeForRoute(route);
|
|
20
|
+
const effectiveComputeClass = compute.effectiveClass === 'dedicated' || compute.class === 'dedicated'
|
|
21
|
+
? 'dedicated'
|
|
22
|
+
: 'function';
|
|
23
|
+
const requestedComputeClass = compute.class === 'edge' || compute.requestedClass === 'edge'
|
|
24
|
+
? 'edge'
|
|
25
|
+
: effectiveComputeClass;
|
|
26
|
+
const effectiveMemory = compute.effectiveMemory ?? compute.memory;
|
|
27
|
+
const memory = typeof effectiveMemory === 'string' || typeof effectiveMemory === 'number'
|
|
28
|
+
? effectiveMemory
|
|
29
|
+
: undefined;
|
|
30
|
+
const cpu = typeof compute.cpu === 'number' ? compute.cpu : undefined;
|
|
31
|
+
const timeout = configNumber(route.config, 'timeout');
|
|
32
|
+
const edgeEligibility = compute.edgeEligibility === 'pending' ? 'pending' : undefined;
|
|
33
|
+
if (requestedComputeClass === 'edge') {
|
|
34
|
+
return {
|
|
35
|
+
effectiveComputeClass,
|
|
36
|
+
requestedComputeClass,
|
|
37
|
+
edgeEligibility,
|
|
38
|
+
memory,
|
|
39
|
+
cpu,
|
|
40
|
+
timeout,
|
|
41
|
+
providerRecommendation: 'cloudflare-workers-for-platforms',
|
|
42
|
+
confidence: 'high',
|
|
43
|
+
reasons: [
|
|
44
|
+
'Edge is an optimization request and remains on Function until the platform marks this endpoint eligible from observed memory/runtime telemetry.',
|
|
45
|
+
'Edge has a fixed 128mb isolate ceiling; the safe fallback is Function at 1gb.',
|
|
46
|
+
],
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
if (effectiveComputeClass === 'dedicated') {
|
|
50
|
+
return {
|
|
51
|
+
effectiveComputeClass,
|
|
52
|
+
requestedComputeClass,
|
|
53
|
+
memory,
|
|
54
|
+
cpu,
|
|
55
|
+
timeout,
|
|
56
|
+
providerRecommendation: 'dedicated-fly-machine',
|
|
57
|
+
confidence: 'high',
|
|
58
|
+
reasons: [route.hasWebsocket
|
|
59
|
+
? 'WebSocket upgrades require persistent Dedicated compute.'
|
|
60
|
+
: 'The route explicitly requests persistent Dedicated compute.'],
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
effectiveComputeClass,
|
|
65
|
+
requestedComputeClass,
|
|
66
|
+
memory,
|
|
67
|
+
cpu,
|
|
68
|
+
timeout,
|
|
69
|
+
providerRecommendation: 'elastic-function-provider',
|
|
70
|
+
confidence: 'medium',
|
|
71
|
+
reasons: ['Stateless endpoints and tasks default to scale-to-zero Function compute at 1gb.'],
|
|
72
|
+
};
|
|
73
|
+
}
|
|
9
74
|
function prefersHotTask(config) {
|
|
10
|
-
return
|
|
75
|
+
return configObject(config, 'compute')?.class === 'dedicated'
|
|
76
|
+
|| ['runtime', 'placement', 'target'].some((key) => configString(config, key) === 'hot')
|
|
11
77
|
|| config.hot === true;
|
|
12
78
|
}
|
|
13
79
|
export function taskNameFromPattern(urlPattern) {
|
|
@@ -53,6 +119,10 @@ function inspectApiRoute(route) {
|
|
|
53
119
|
if (route.hasWebsocket && route.kind !== 'hot') {
|
|
54
120
|
warnings.push('WebSocket exports require kind: hot to be reachable.');
|
|
55
121
|
}
|
|
122
|
+
const details = computeDetails(route);
|
|
123
|
+
if (details.requestedComputeClass === 'edge' && details.edgeEligibility === 'pending') {
|
|
124
|
+
warnings.push('Edge request is pending platform eligibility; effective runtime remains Function at 1gb.');
|
|
125
|
+
}
|
|
56
126
|
const base = {
|
|
57
127
|
type: 'api',
|
|
58
128
|
pattern: route.urlPattern,
|
|
@@ -63,6 +133,7 @@ function inspectApiRoute(route) {
|
|
|
63
133
|
methods: route.methods,
|
|
64
134
|
schedule,
|
|
65
135
|
hasWebsocket: Boolean(route.hasWebsocket),
|
|
136
|
+
...details,
|
|
66
137
|
warnings,
|
|
67
138
|
nextCommand: route.kind === 'task'
|
|
68
139
|
? `vura tasks run ${taskNameFromPattern(route.urlPattern)}`
|
|
@@ -85,6 +156,7 @@ function inspectApiRoute(route) {
|
|
|
85
156
|
methods: route.methods,
|
|
86
157
|
schedule,
|
|
87
158
|
hasWebsocket: false,
|
|
159
|
+
...details,
|
|
88
160
|
warnings: [],
|
|
89
161
|
nextCommand: 'vura tasks list',
|
|
90
162
|
},
|
|
@@ -140,6 +212,17 @@ export function adviseRuntime(manifest) {
|
|
|
140
212
|
const currentProfile = profileForApiRoute(route);
|
|
141
213
|
const schedule = configString(route.config, 'schedule');
|
|
142
214
|
const timeout = configNumber(route.config, 'timeout');
|
|
215
|
+
const details = computeDetails(route);
|
|
216
|
+
if (details.requestedComputeClass === 'edge') {
|
|
217
|
+
advice.push({
|
|
218
|
+
pattern: route.urlPattern,
|
|
219
|
+
type: 'api',
|
|
220
|
+
currentProfile,
|
|
221
|
+
recommendation: currentProfile,
|
|
222
|
+
severity: 'warn',
|
|
223
|
+
reason: 'Edge request is pending measured platform eligibility; deploys continue on Function at 1gb until approved.',
|
|
224
|
+
});
|
|
225
|
+
}
|
|
143
226
|
if (route.hasWebsocket) {
|
|
144
227
|
advice.push({
|
|
145
228
|
pattern: route.urlPattern,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@celsian/vura-cli",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.9",
|
|
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.
|
|
18
|
+
"@celsian/vura-core": "0.5.9",
|
|
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.
|
|
23
|
+
"@celsian/vura-adapter-vura": "0.5.9",
|
|
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.
|
|
35
|
+
"@celsian/vura-adapter-vura": "0.5.9",
|
|
36
36
|
"@types/ws": "^8.18.1",
|
|
37
37
|
"ws": "^8.21.0"
|
|
38
38
|
},
|