octwin-cli 0.1.3 → 0.1.4
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/index.js +78 -7
- package/package.json +1 -1
- package/templates/starter/commands.yaml +1 -1
package/dist/index.js
CHANGED
|
@@ -210,17 +210,91 @@ async function cmdWhoami(flags) {
|
|
|
210
210
|
: await res.text();
|
|
211
211
|
die(`token check failed for '${tenant}' (HTTP ${res.status}) — ${why}`);
|
|
212
212
|
}
|
|
213
|
+
/**
|
|
214
|
+
* Read the deploy SSE stream, printing each progress frame's message live, and
|
|
215
|
+
* return the terminal `done`/`error` event (or null if the stream ended without
|
|
216
|
+
* one). The platform emits `data: {json}\n\n` frames — install + seed progress,
|
|
217
|
+
* with per-record / per-image lines during a `--seed` (image generation is slow).
|
|
218
|
+
*/
|
|
219
|
+
async function readDeployProgress(body) {
|
|
220
|
+
const reader = body.getReader();
|
|
221
|
+
const decoder = new TextDecoder();
|
|
222
|
+
let buf = '';
|
|
223
|
+
let terminal = null;
|
|
224
|
+
for (;;) {
|
|
225
|
+
const { done, value } = await reader.read();
|
|
226
|
+
if (done)
|
|
227
|
+
break;
|
|
228
|
+
buf += decoder.decode(value, { stream: true });
|
|
229
|
+
let idx;
|
|
230
|
+
while ((idx = buf.indexOf('\n\n')) >= 0) {
|
|
231
|
+
const frame = buf.slice(0, idx);
|
|
232
|
+
buf = buf.slice(idx + 2);
|
|
233
|
+
const dataLine = frame.split('\n').find((l) => l.startsWith('data:'));
|
|
234
|
+
if (!dataLine)
|
|
235
|
+
continue;
|
|
236
|
+
let ev;
|
|
237
|
+
try {
|
|
238
|
+
ev = JSON.parse(dataLine.slice(5).trim());
|
|
239
|
+
}
|
|
240
|
+
catch {
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
if (ev.stage === 'done' || ev.stage === 'error') {
|
|
244
|
+
terminal = ev;
|
|
245
|
+
continue;
|
|
246
|
+
}
|
|
247
|
+
if (ev.message)
|
|
248
|
+
console.log(` ${ev.status === 'error' ? '⚠' : '·'} ${ev.message}`);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return terminal;
|
|
252
|
+
}
|
|
253
|
+
function printDeploySuccess(id, version, tenant, project, r) {
|
|
254
|
+
console.log(`✓ Deployed ${id}@${version} and installed onto ${tenant}/${project}`);
|
|
255
|
+
if (r?.warning)
|
|
256
|
+
console.log(` ⚠ ${r.warning}`);
|
|
257
|
+
const s = r?.summary;
|
|
258
|
+
if (s) {
|
|
259
|
+
const parts = [];
|
|
260
|
+
if (s.records != null)
|
|
261
|
+
parts.push(`${s.records} record(s) created`);
|
|
262
|
+
if (s.updated)
|
|
263
|
+
parts.push(`${s.updated} updated`);
|
|
264
|
+
if (s.images)
|
|
265
|
+
parts.push(`${s.images} image(s) generated`);
|
|
266
|
+
if (s.rules)
|
|
267
|
+
parts.push(`${s.rules} availability rule(s)`);
|
|
268
|
+
if (parts.length)
|
|
269
|
+
console.log(` Seeded: ${parts.join(', ')}`);
|
|
270
|
+
}
|
|
271
|
+
console.log(`\nChat with it on your tenant (web widget / console test page for ${tenant}/${project}).`);
|
|
272
|
+
}
|
|
213
273
|
async function cmdDeploy(flags) {
|
|
214
274
|
const packDir = resolve(flags.dir ?? '.');
|
|
215
275
|
const { url, tenant, project, token } = resolveTarget(flags, packDir);
|
|
216
276
|
const { id, version, files } = localValidate(packDir);
|
|
217
277
|
const endpoint = `${url}/api/admin/tenants/${tenant}/projects/${project}/packs/deploy`;
|
|
218
|
-
|
|
278
|
+
const seed = flags.seed === true;
|
|
279
|
+
console.log(`→ Deploying ${id}@${version} (${Object.keys(files).length} files) to ${tenant}/${project}${seed ? ' — with demo seed' : ''} …`);
|
|
219
280
|
const res = await fetch(endpoint, {
|
|
220
281
|
method: 'POST',
|
|
221
|
-
|
|
222
|
-
|
|
282
|
+
// Ask for a progress stream; the platform falls back to plain JSON if it
|
|
283
|
+
// (or an error before any progress) can't stream — handled below.
|
|
284
|
+
headers: { 'content-type': 'application/json', accept: 'text/event-stream', authorization: `Bearer ${token}` },
|
|
285
|
+
body: JSON.stringify({ files, seed }),
|
|
223
286
|
});
|
|
287
|
+
// Streaming path — live install + seed progress (image generation can take a
|
|
288
|
+
// while, so `--seed` prints per-record / per-image lines as they happen).
|
|
289
|
+
if (res.ok && (res.headers.get('content-type') ?? '').includes('text/event-stream') && res.body) {
|
|
290
|
+
const final = await readDeployProgress(res.body);
|
|
291
|
+
if (!final || final.stage === 'error')
|
|
292
|
+
die(`deploy failed${final?.message ? `: ${final.message}` : ' (stream ended early)'}`);
|
|
293
|
+
printDeploySuccess(id, version, tenant, project, final);
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
// Non-streaming path — plain JSON (older platform, or an error thrown before
|
|
297
|
+
// any progress frame, which the platform returns as clean JSON).
|
|
224
298
|
const text = await res.text();
|
|
225
299
|
let json;
|
|
226
300
|
try {
|
|
@@ -234,10 +308,7 @@ async function cmdDeploy(flags) {
|
|
|
234
308
|
console.error(typeof json === 'string' ? json : JSON.stringify(json, null, 2));
|
|
235
309
|
process.exit(1);
|
|
236
310
|
}
|
|
237
|
-
|
|
238
|
-
if (json?.warning)
|
|
239
|
-
console.log(` ⚠ ${json.warning}`);
|
|
240
|
-
console.log(`\nChat with it on your tenant (web widget / console test page for ${tenant}/${project}).`);
|
|
311
|
+
printDeploySuccess(id, version, tenant, project, json);
|
|
241
312
|
}
|
|
242
313
|
async function cmdStatus(flags) {
|
|
243
314
|
const packDir = resolve(flags.dir ?? '.');
|
package/package.json
CHANGED