@celsian/vura-cli 0.5.4 → 0.5.6
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/dist/commands/dev.js +66 -6
- package/dist/commands/tasks.js +39 -3
- package/package.json +4 -4
package/dist/commands/dev.js
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
*/
|
|
15
15
|
import { renderToString as builtinRenderToString } from 'what-framework/server';
|
|
16
16
|
import { importRouteModule } from './shared.js';
|
|
17
|
-
import { buildManifest, compilePageRoutes, matchPageRoute, compileRoutes, matchApiPath, getLogger, wrapDocument, escapeHtml, parseNodeBody, reportError, getMimeType, createApiApp, createWsUpgradeHandler, createNoServerWebSocketServer, GLOBAL_HOOKS_FILENAMES, nodeToWebRequest, writeWebResponse, generateClientPageEntry, } from '@celsian/vura-core';
|
|
17
|
+
import { buildManifest, compilePageRoutes, matchPageRoute, compileRoutes, matchApiPath, getLogger, wrapDocument, escapeHtml, parseNodeBody, reportError, getMimeType, runTaskOnce, buildTaskEnvelope, createApiApp, createWsUpgradeHandler, createNoServerWebSocketServer, GLOBAL_HOOKS_FILENAMES, nodeToWebRequest, writeWebResponse, generateClientPageEntry, } from '@celsian/vura-core';
|
|
18
18
|
export function parseDevOptions(args, projectRoot = process.cwd()) {
|
|
19
19
|
const portArg = args.find((_, i) => args[i - 1] === '--port');
|
|
20
20
|
const hostArg = args.find((_, i) => args[i - 1] === '--host');
|
|
@@ -375,14 +375,74 @@ export async function startStandaloneServer(manifest, opts) {
|
|
|
375
375
|
}
|
|
376
376
|
try {
|
|
377
377
|
const mod = await loadHandler(taskRoute.filePath);
|
|
378
|
+
if (typeof mod.POST !== 'function') {
|
|
379
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
380
|
+
res.end(JSON.stringify({ error: 'Task must export POST handler' }));
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
378
383
|
const body = await parseNodeBody(req);
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
384
|
+
// Accept both `{ input: ... }` (legacy admin convention + the platform's
|
|
385
|
+
// `{ taskId, input, attempt, runId?, steps? }` wrapper) and a raw payload
|
|
386
|
+
// posted directly as the body (enqueue()'s local fallback).
|
|
387
|
+
const isWrapper = body && typeof body === 'object' && 'input' in body;
|
|
388
|
+
const input = isWrapper ? body.input : body;
|
|
389
|
+
// Platform cron/synthetic dispatches (X-Vura-Cron: true) skip input
|
|
390
|
+
// validation, mirroring the standalone server + in-process cron.
|
|
391
|
+
const isCronDispatch = String(req.headers['x-vura-cron'] ?? '').toLowerCase() === 'true';
|
|
392
|
+
const isPlatformDispatch = String(req.headers['x-vura-task-id'] ?? '') !== '';
|
|
393
|
+
// Dispatch body v2 (Phase 2): tolerate-absent runId + steps.
|
|
394
|
+
const runId = isWrapper && typeof body.runId === 'string'
|
|
395
|
+
? body.runId
|
|
396
|
+
: undefined;
|
|
397
|
+
const dispatchSteps = isWrapper && body.steps && typeof body.steps === 'object'
|
|
398
|
+
? body.steps
|
|
399
|
+
: {};
|
|
400
|
+
// Off-platform child dispatcher so `step.waitForTask` resolves the child
|
|
401
|
+
// in-process during `vura dev` (no durable platform → waits run locally).
|
|
402
|
+
const localChildDispatch = async (childName, childPayload) => {
|
|
403
|
+
const childRoute = manifest.api.find((r) => r.kind === 'task' &&
|
|
404
|
+
r.urlPattern.replace(/^\/api\//, '').replace(/\//g, '.') === childName);
|
|
405
|
+
if (!childRoute)
|
|
406
|
+
return { ok: false, error: `Task not found: ${childName}` };
|
|
407
|
+
const childMod = await loadHandlerCached(childRoute.filePath);
|
|
408
|
+
if (typeof childMod.POST !== 'function')
|
|
409
|
+
return { ok: false, error: 'Task must export POST handler' };
|
|
410
|
+
const childRes = await runTaskOnce({
|
|
411
|
+
name: childName,
|
|
412
|
+
config: {
|
|
413
|
+
retries: typeof childRoute.config.retries === 'number' ? childRoute.config.retries : 0,
|
|
414
|
+
timeout: typeof childRoute.config.timeout === 'number' ? childRoute.config.timeout : 30_000,
|
|
415
|
+
},
|
|
416
|
+
handler: childMod.POST,
|
|
417
|
+
}, { input: childPayload, hasPlatform: false, localChildDispatch });
|
|
418
|
+
return childRes.status === 'completed'
|
|
419
|
+
? { ok: true, result: childRes.result }
|
|
420
|
+
: { ok: false, error: childRes.error };
|
|
421
|
+
};
|
|
422
|
+
const runResult = await runTaskOnce({
|
|
423
|
+
name: taskName,
|
|
424
|
+
config: {
|
|
425
|
+
retries: typeof taskRoute.config.retries === 'number' ? taskRoute.config.retries : 0,
|
|
426
|
+
timeout: typeof taskRoute.config.timeout === 'number' ? taskRoute.config.timeout : 30_000,
|
|
427
|
+
},
|
|
428
|
+
handler: mod.POST,
|
|
429
|
+
inputSchema: isCronDispatch ? undefined : mod.input,
|
|
430
|
+
}, {
|
|
431
|
+
input,
|
|
432
|
+
runId,
|
|
433
|
+
steps: dispatchSteps,
|
|
434
|
+
hasPlatform: isPlatformDispatch ? true : undefined,
|
|
435
|
+
localChildDispatch,
|
|
383
436
|
});
|
|
437
|
+
if (runResult.validationError) {
|
|
438
|
+
res.writeHead(runResult.validationError.statusCode, { 'Content-Type': 'application/json' });
|
|
439
|
+
res.end(JSON.stringify(runResult.validationError.body));
|
|
440
|
+
return;
|
|
441
|
+
}
|
|
442
|
+
// Additive envelope + legacy status/result for backward compatibility.
|
|
443
|
+
const envelope = buildTaskEnvelope(taskName, runResult);
|
|
384
444
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
385
|
-
res.end(JSON.stringify({ status:
|
|
445
|
+
res.end(JSON.stringify({ ...envelope, status: runResult.status, ...(runResult.error !== undefined ? { error: runResult.error } : {}) }));
|
|
386
446
|
}
|
|
387
447
|
catch (err) {
|
|
388
448
|
reportError(err instanceof Error ? err : new Error(String(err.message)), { method, path: url.pathname, requestId: reqCtx.requestId }, logger);
|
package/dist/commands/tasks.js
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* process.exit() directly. This lets vitest keep running while still signalling
|
|
11
11
|
* the right exit code to the shell via the CLI entry point.
|
|
12
12
|
*/
|
|
13
|
-
import { buildManifest, runTaskOnce } from '@celsian/vura-core';
|
|
13
|
+
import { buildManifest, runTaskOnce, buildTaskEnvelope } from '@celsian/vura-core';
|
|
14
14
|
import { importRouteModule } from './shared.js';
|
|
15
15
|
// ─── Name helpers ────────────────────────────────────────────────────────────
|
|
16
16
|
/**
|
|
@@ -75,6 +75,27 @@ async function runTask(projectRoot, taskName, rawInput) {
|
|
|
75
75
|
process.exitCode = 1;
|
|
76
76
|
return;
|
|
77
77
|
}
|
|
78
|
+
// Off-platform child dispatcher so `step.waitForTask` resolves the child
|
|
79
|
+
// in-process when running a task from the CLI (no durable platform).
|
|
80
|
+
const localChildDispatch = async (childName, childPayload) => {
|
|
81
|
+
const childRoute = taskRoutes.find((r) => taskNameFromPattern(r.urlPattern) === childName);
|
|
82
|
+
if (!childRoute)
|
|
83
|
+
return { ok: false, error: `Task not found: ${childName}` };
|
|
84
|
+
const childMod = await importRouteModule(projectRoot, childRoute.filePath);
|
|
85
|
+
if (typeof childMod.POST !== 'function')
|
|
86
|
+
return { ok: false, error: 'Task must export POST handler' };
|
|
87
|
+
const childRes = await runTaskOnce({
|
|
88
|
+
name: childName,
|
|
89
|
+
config: {
|
|
90
|
+
retries: typeof childRoute.config.retries === 'number' ? childRoute.config.retries : 0,
|
|
91
|
+
timeout: typeof childRoute.config.timeout === 'number' ? childRoute.config.timeout : 30_000,
|
|
92
|
+
},
|
|
93
|
+
handler: childMod.POST,
|
|
94
|
+
}, { input: childPayload, hasPlatform: false, localChildDispatch });
|
|
95
|
+
return childRes.status === 'completed'
|
|
96
|
+
? { ok: true, result: childRes.result }
|
|
97
|
+
: { ok: false, error: childRes.error };
|
|
98
|
+
};
|
|
78
99
|
const result = await runTaskOnce({
|
|
79
100
|
name: taskName,
|
|
80
101
|
config: {
|
|
@@ -82,8 +103,23 @@ async function runTask(projectRoot, taskName, rawInput) {
|
|
|
82
103
|
timeout: typeof route.config.timeout === 'number' ? route.config.timeout : 30_000,
|
|
83
104
|
},
|
|
84
105
|
handler: mod.POST,
|
|
85
|
-
|
|
86
|
-
|
|
106
|
+
// Phase 1: validate --input against the task's optional `input` schema.
|
|
107
|
+
inputSchema: mod.input,
|
|
108
|
+
}, { input, hasPlatform: false, localChildDispatch });
|
|
109
|
+
// A schema validation failure never ran the handler — print the standard
|
|
110
|
+
// validation error body and exit 1.
|
|
111
|
+
if (result.validationError) {
|
|
112
|
+
console.error(JSON.stringify(result.validationError.body, null, 2));
|
|
113
|
+
process.exitCode = 1;
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
// Print the additive run envelope ({ ok, taskName, attempts, result? }) plus
|
|
117
|
+
// the legacy status/error fields so existing consumers keep working.
|
|
118
|
+
const envelope = buildTaskEnvelope(taskName, result);
|
|
119
|
+
const output = { ...envelope, status: result.status };
|
|
120
|
+
if (result.error !== undefined)
|
|
121
|
+
output.error = result.error;
|
|
122
|
+
console.log(JSON.stringify(output, null, 2));
|
|
87
123
|
if (result.status === 'failed') {
|
|
88
124
|
process.exitCode = 1;
|
|
89
125
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@celsian/vura-cli",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.6",
|
|
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.6",
|
|
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.6",
|
|
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.6",
|
|
36
36
|
"@types/ws": "^8.18.1",
|
|
37
37
|
"ws": "^8.21.0"
|
|
38
38
|
},
|