@kizenapps/cli 0.8.0 → 0.9.0
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 +308 -78
- package/dist/index.js.map +1 -1
- package/dist/nwjs/shell/icon.png +0 -0
- package/dist/nwjs/shell/index.html +200 -0
- package/dist/nwjs/shell/package.json +16 -0
- package/dist/viewer/assets/fa-core-DAYjf9Yn.js +558 -0
- package/dist/viewer/assets/fa-core-Ff8SZmm_.js +558 -0
- package/dist/viewer/assets/index-47Vh9MH0.js +17 -0
- package/dist/viewer/assets/index-6uunWX8M.js +17 -0
- package/dist/viewer/assets/index-B48OpZHg.js +17 -0
- package/dist/viewer/assets/index-BFfw7eD7.js +17 -0
- package/dist/viewer/assets/index-BFyUUb06.js +17 -0
- package/dist/viewer/assets/index-BL-Yu7Bf.js +17 -0
- package/dist/viewer/assets/index-BUmv8vz7.js +17 -0
- package/dist/viewer/assets/index-BZ4HmEz8.js +17 -0
- package/dist/viewer/assets/index-BZIXccTd.js +17 -0
- package/dist/viewer/assets/index-Bk9hnfnO.js +17 -0
- package/dist/viewer/assets/index-C0SIHm9A.js +17 -0
- package/dist/viewer/assets/index-CDd-WK6Y.js +17 -0
- package/dist/viewer/assets/index-CDxQqP40.js +17 -0
- package/dist/viewer/assets/{index-C_gRcfsL.js → index-CGJzvpL5.js} +7 -7
- package/dist/viewer/assets/index-CIarX3Lt.js +17 -0
- package/dist/viewer/assets/index-CIfVP45E.js +17 -0
- package/dist/viewer/assets/index-CJeb7uFu.css +2 -0
- package/dist/viewer/assets/index-CbwLb2S_.js +17 -0
- package/dist/viewer/assets/index-CsfWgoID.js +17 -0
- package/dist/viewer/assets/index-CvWmkIY5.js +17 -0
- package/dist/viewer/assets/index-Cy-weKfG.css +2 -0
- package/dist/viewer/assets/index-Cym12l2M.js +17 -0
- package/dist/viewer/assets/index-D0W0oANg.js +17 -0
- package/dist/viewer/assets/index-DCPtqd3W.js +17 -0
- package/dist/viewer/assets/index-DF_zYdLw.js +17 -0
- package/dist/viewer/assets/index-DGqxQcUx.js +17 -0
- package/dist/viewer/assets/index-DK0OVb7V.js +17 -0
- package/dist/viewer/assets/index-DKjVFdzw.js +17 -0
- package/dist/viewer/assets/index-DLhj0I_2.js +17 -0
- package/dist/viewer/assets/index-DPS_ZjbM.js +17 -0
- package/dist/viewer/assets/index-DSbHkhcS.js +17 -0
- package/dist/viewer/assets/index-DTbmNtEU.js +17 -0
- package/dist/viewer/assets/index-DUYd6RpI.js +17 -0
- package/dist/viewer/assets/index-DZwYe1wZ.css +2 -0
- package/dist/viewer/assets/index-DkRokbYc.js +17 -0
- package/dist/viewer/assets/index-DtOWzkR5.js +17 -0
- package/dist/viewer/assets/index-DuvXujkm.js +17 -0
- package/dist/viewer/assets/index-Dv0mX-oM.js +17 -0
- package/dist/viewer/assets/index-DyXisBY9.css +2 -0
- package/dist/viewer/assets/index-Nm1xKWTO.js +17 -0
- package/dist/viewer/assets/index-ZBdAq6dF.js +17 -0
- package/dist/viewer/assets/index-ZOxL_JJZ.js +17 -0
- package/dist/viewer/assets/index-kMMOwjlY.js +17 -0
- package/dist/viewer/assets/{index-_K33TupM.js → index-ov2oU6RI.js} +7 -7
- package/dist/viewer/assets/index-uF6u0kT8.js +17 -0
- package/dist/viewer/assets/index-xbDHMSaa.css +2 -0
- package/dist/viewer/assets/react-D7PmSb6e.js +9 -0
- package/dist/viewer/assets/react-DIjeYlvh.js +9 -0
- package/dist/viewer/index.html +4 -4
- package/package.json +4 -4
- package/dist/viewer/assets/index-B09qenTV.js +0 -17
- package/dist/viewer/assets/index-CVd4BLit.js +0 -17
- package/dist/viewer/assets/index-CcvbGL5I.js +0 -17
- package/dist/viewer/assets/index-Ci5up9QD.js +0 -17
- package/dist/viewer/assets/index-DOiSISo1.css +0 -2
- package/dist/viewer/assets/index-DSJAwx9Y.js +0 -17
- package/dist/viewer/assets/index-DUgUEouL.css +0 -2
- package/dist/viewer/assets/index-WnCF0zx3.js +0 -17
- package/dist/viewer/assets/index-dPV4go8k.js +0 -17
- package/dist/viewer/assets/index-xFuxlPJA.js +0 -17
package/dist/index.js
CHANGED
|
@@ -229,14 +229,231 @@ import { render as render2 } from "ink";
|
|
|
229
229
|
// src/ui/DevUI.tsx
|
|
230
230
|
import { useCallback as useCallback2, useEffect as useEffect3, useRef, useState as useState3 } from "react";
|
|
231
231
|
import { Box as Box4, Text as Text4, useInput as useInput2 } from "ink";
|
|
232
|
-
import { spawn } from "child_process";
|
|
233
232
|
import { createReadStream, watch } from "fs";
|
|
234
|
-
import { access, readFile as
|
|
233
|
+
import { access, readFile as readFile5 } from "fs/promises";
|
|
235
234
|
import { createServer } from "http";
|
|
235
|
+
import { dirname as dirname3, extname, join as join7 } from "path";
|
|
236
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
237
|
+
import { WebSocketServer } from "ws";
|
|
238
|
+
|
|
239
|
+
// src/chrome/launcher.ts
|
|
240
|
+
import { launch } from "chrome-launcher";
|
|
236
241
|
import { createRequire } from "module";
|
|
237
|
-
import {
|
|
242
|
+
import { mkdirSync } from "fs";
|
|
243
|
+
import { readFile as readFile2 } from "fs/promises";
|
|
244
|
+
import { dirname, join as join4 } from "path";
|
|
238
245
|
import { fileURLToPath } from "url";
|
|
239
|
-
|
|
246
|
+
var CDP = createRequire(import.meta.url)("chrome-remote-interface");
|
|
247
|
+
var CSP_HEADERS = /* @__PURE__ */ new Set([
|
|
248
|
+
"content-security-policy",
|
|
249
|
+
"content-security-policy-report-only",
|
|
250
|
+
"x-frame-options"
|
|
251
|
+
]);
|
|
252
|
+
var KIZEN_DOMAINS = ["kizen.dev", "kizen.com"];
|
|
253
|
+
function isKizenUrl(url) {
|
|
254
|
+
try {
|
|
255
|
+
const { hostname } = new URL(url);
|
|
256
|
+
return KIZEN_DOMAINS.some((d) => hostname === d || hostname.endsWith("." + d));
|
|
257
|
+
} catch {
|
|
258
|
+
return false;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
function parseProp(prop) {
|
|
262
|
+
if (prop.type === "number") return Number(prop.value);
|
|
263
|
+
if (prop.type === "boolean") return prop.value === "true";
|
|
264
|
+
if (prop.type === "undefined") return void 0;
|
|
265
|
+
if (prop.type === "object" && prop.value === "null") return null;
|
|
266
|
+
if (prop.type === "object" && prop.valuePreview) {
|
|
267
|
+
const { valuePreview } = prop;
|
|
268
|
+
if (valuePreview.subtype === "array") {
|
|
269
|
+
return valuePreview.properties.filter((p) => /^\d+$/.test(p.name)).sort((a, b) => parseInt(a.name) - parseInt(b.name)).map(parseProp);
|
|
270
|
+
}
|
|
271
|
+
const obj = {};
|
|
272
|
+
for (const p of valuePreview.properties) obj[p.name] = parseProp(p);
|
|
273
|
+
return obj;
|
|
274
|
+
}
|
|
275
|
+
return prop.value ?? `[${prop.type}]`;
|
|
276
|
+
}
|
|
277
|
+
function serializeArg(arg) {
|
|
278
|
+
if (arg.value !== void 0) return arg.value;
|
|
279
|
+
if (arg.preview) {
|
|
280
|
+
const { preview } = arg;
|
|
281
|
+
if (preview.subtype === "array") {
|
|
282
|
+
return preview.properties.filter((p) => /^\d+$/.test(p.name)).sort((a, b) => parseInt(a.name) - parseInt(b.name)).map(parseProp);
|
|
283
|
+
}
|
|
284
|
+
const obj = {};
|
|
285
|
+
for (const prop of preview.properties) obj[prop.name] = parseProp(prop);
|
|
286
|
+
return obj;
|
|
287
|
+
}
|
|
288
|
+
return arg.description ?? `[${arg.type}]`;
|
|
289
|
+
}
|
|
290
|
+
async function serializeArgAsync(client, arg) {
|
|
291
|
+
if (arg.type === "object" && arg.objectId) {
|
|
292
|
+
try {
|
|
293
|
+
const result = await client.Runtime.callFunctionOn({
|
|
294
|
+
objectId: arg.objectId,
|
|
295
|
+
functionDeclaration: 'function() { const seen = new WeakSet(); return JSON.stringify(this, function(k,v) { if (typeof v === "object" && v !== null) { if (seen.has(v)) return "[Circular]"; seen.add(v); } return v; }); }',
|
|
296
|
+
returnByValue: true
|
|
297
|
+
});
|
|
298
|
+
const val = result.result.value;
|
|
299
|
+
if (typeof val === "string") return JSON.parse(val);
|
|
300
|
+
} catch {
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
return serializeArg(arg);
|
|
304
|
+
}
|
|
305
|
+
async function installDockIcon(client) {
|
|
306
|
+
try {
|
|
307
|
+
const iconPath = join4(dirname(fileURLToPath(import.meta.url)), "viewer", "icon.png");
|
|
308
|
+
const icon = await readFile2(iconPath);
|
|
309
|
+
await client.Browser.setDockTile({ image: icon.toString("base64") });
|
|
310
|
+
} catch {
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
async function launchChromeViewer(opts) {
|
|
314
|
+
mkdirSync(opts.userDataDir, { recursive: true });
|
|
315
|
+
const chrome = await launch({
|
|
316
|
+
startingUrl: `http://localhost:${opts.port}`,
|
|
317
|
+
chromeFlags: [
|
|
318
|
+
`--app=http://localhost:${opts.port}`,
|
|
319
|
+
"--no-first-run",
|
|
320
|
+
"--no-default-browser-check",
|
|
321
|
+
"--disable-extensions"
|
|
322
|
+
],
|
|
323
|
+
userDataDir: opts.userDataDir,
|
|
324
|
+
handleSIGINT: false,
|
|
325
|
+
logLevel: "silent"
|
|
326
|
+
});
|
|
327
|
+
let client = null;
|
|
328
|
+
let cookieTimer = null;
|
|
329
|
+
let cdpPort = chrome.port;
|
|
330
|
+
for (let attempt = 0; attempt < 10; attempt++) {
|
|
331
|
+
await new Promise((r) => setTimeout(r, 300));
|
|
332
|
+
try {
|
|
333
|
+
client = await CDP({ port: cdpPort });
|
|
334
|
+
break;
|
|
335
|
+
} catch {
|
|
336
|
+
if (attempt === 9) {
|
|
337
|
+
return {
|
|
338
|
+
kill: () => chrome.kill()
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
if (!client) {
|
|
344
|
+
return {
|
|
345
|
+
kill: () => chrome.kill()
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
const c = client;
|
|
349
|
+
await installDockIcon(c);
|
|
350
|
+
await c.Fetch.enable({
|
|
351
|
+
patterns: KIZEN_DOMAINS.flatMap((d) => [
|
|
352
|
+
{ urlPattern: `*://${d}/*`, requestStage: "Response" },
|
|
353
|
+
{ urlPattern: `*://*.${d}/*`, requestStage: "Response" }
|
|
354
|
+
])
|
|
355
|
+
});
|
|
356
|
+
c.on("Fetch.requestPaused", (rawParams) => {
|
|
357
|
+
void (async () => {
|
|
358
|
+
const params = rawParams;
|
|
359
|
+
const { requestId, request, responseHeaders, responseStatusCode } = params;
|
|
360
|
+
const url = request?.url ?? "";
|
|
361
|
+
const filtered = [];
|
|
362
|
+
for (const h of responseHeaders ?? []) {
|
|
363
|
+
if (CSP_HEADERS.has(h.name.toLowerCase())) continue;
|
|
364
|
+
if (h.name.toLowerCase() === "set-cookie" && isKizenUrl(url)) {
|
|
365
|
+
const patched = h.value.split("\n").map((cookie) => {
|
|
366
|
+
if (!/SameSite=/i.test(cookie)) return cookie + "; SameSite=None; Secure";
|
|
367
|
+
return cookie.replace(/SameSite=\w+/i, "SameSite=None");
|
|
368
|
+
}).join("\n");
|
|
369
|
+
filtered.push({ name: h.name, value: patched });
|
|
370
|
+
} else {
|
|
371
|
+
filtered.push(h);
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
try {
|
|
375
|
+
const { body, base64Encoded } = await c.Fetch.getResponseBody({ requestId });
|
|
376
|
+
await c.Fetch.fulfillRequest({
|
|
377
|
+
requestId,
|
|
378
|
+
responseCode: responseStatusCode ?? 200,
|
|
379
|
+
responseHeaders: filtered,
|
|
380
|
+
body,
|
|
381
|
+
...base64Encoded && { base64Encoded: true }
|
|
382
|
+
});
|
|
383
|
+
} catch {
|
|
384
|
+
try {
|
|
385
|
+
await c.Fetch.continueRequest({ requestId });
|
|
386
|
+
} catch {
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
})();
|
|
390
|
+
});
|
|
391
|
+
cookieTimer = setInterval(() => {
|
|
392
|
+
void (async () => {
|
|
393
|
+
try {
|
|
394
|
+
const { cookies } = await c.Network.getAllCookies();
|
|
395
|
+
for (const cookie of cookies) {
|
|
396
|
+
if (!isKizenUrl(`https://${cookie.domain ?? ""}`)) continue;
|
|
397
|
+
if (cookie.sameSite === "None") continue;
|
|
398
|
+
const raw = cookie.domain ?? "";
|
|
399
|
+
const bare = raw.startsWith(".") ? raw.slice(1) : raw;
|
|
400
|
+
await c.Network.setCookie({
|
|
401
|
+
url: `https://${bare}`,
|
|
402
|
+
name: cookie.name,
|
|
403
|
+
value: cookie.value,
|
|
404
|
+
domain: raw,
|
|
405
|
+
path: cookie.path ?? "/",
|
|
406
|
+
secure: true,
|
|
407
|
+
...cookie.httpOnly !== void 0 && { httpOnly: cookie.httpOnly },
|
|
408
|
+
...cookie.expirationDate !== void 0 && {
|
|
409
|
+
expires: cookie.expirationDate
|
|
410
|
+
},
|
|
411
|
+
sameSite: "None"
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
} catch {
|
|
415
|
+
}
|
|
416
|
+
})();
|
|
417
|
+
}, 2e3);
|
|
418
|
+
await c.send("Runtime.enable", { generatePreview: true });
|
|
419
|
+
c.on("Target.attachedToTarget", (rawParams) => {
|
|
420
|
+
const { sessionId } = rawParams;
|
|
421
|
+
void c.send("Runtime.enable", { generatePreview: true }, sessionId).catch(() => {
|
|
422
|
+
});
|
|
423
|
+
});
|
|
424
|
+
await c.Target.setAutoAttach({
|
|
425
|
+
autoAttach: true,
|
|
426
|
+
waitForDebuggerOnStart: false,
|
|
427
|
+
flatten: true
|
|
428
|
+
});
|
|
429
|
+
await c.Target.setDiscoverTargets({ discover: true });
|
|
430
|
+
c.on("Target.targetCreated", (rawParams) => {
|
|
431
|
+
const { targetInfo } = rawParams;
|
|
432
|
+
if (targetInfo.type === "page" && targetInfo.url === "chrome://newtab/") {
|
|
433
|
+
void c.Target.closeTarget({ targetId: targetInfo.targetId }).catch(() => {
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
});
|
|
437
|
+
c.on("Runtime.consoleAPICalled", (rawParams) => {
|
|
438
|
+
void (async () => {
|
|
439
|
+
const { type, args } = rawParams;
|
|
440
|
+
if (args[0]?.type === "string" && String(args[0].value).includes("Chrome Security")) return;
|
|
441
|
+
const level = type === "warning" ? "warn" : ["log", "warn", "error", "info"].includes(type) ? type : "log";
|
|
442
|
+
const serialized = await Promise.all(args.map((arg) => serializeArgAsync(c, arg)));
|
|
443
|
+
opts.broadcast({ type: "console-message", level, args: serialized });
|
|
444
|
+
})().catch(() => {
|
|
445
|
+
});
|
|
446
|
+
});
|
|
447
|
+
const kill = () => {
|
|
448
|
+
if (cookieTimer !== null) clearInterval(cookieTimer);
|
|
449
|
+
try {
|
|
450
|
+
void c.close();
|
|
451
|
+
} catch {
|
|
452
|
+
}
|
|
453
|
+
chrome.kill();
|
|
454
|
+
};
|
|
455
|
+
return { kill };
|
|
456
|
+
}
|
|
240
457
|
|
|
241
458
|
// src/lib/proxyCache.ts
|
|
242
459
|
function createProxyCache() {
|
|
@@ -270,12 +487,12 @@ function createProxyCache() {
|
|
|
270
487
|
}
|
|
271
488
|
|
|
272
489
|
// src/lib/credentials.ts
|
|
273
|
-
import { mkdir as mkdir2, readFile as
|
|
490
|
+
import { mkdir as mkdir2, readFile as readFile3, readdir as readdir2, writeFile as writeFile2 } from "fs/promises";
|
|
274
491
|
import { homedir } from "os";
|
|
275
|
-
import { dirname, join as
|
|
492
|
+
import { dirname as dirname2, join as join5 } from "path";
|
|
276
493
|
var ENVIRONMENTS = ["go", "fmo", "staging", "integration", "test1"];
|
|
277
|
-
var GLOBAL_CREDENTIALS_DIR =
|
|
278
|
-
var GLOBAL_CREDENTIALS_PATH =
|
|
494
|
+
var GLOBAL_CREDENTIALS_DIR = join5(homedir(), ".kizenappbuilder");
|
|
495
|
+
var GLOBAL_CREDENTIALS_PATH = join5(GLOBAL_CREDENTIALS_DIR, "credentials.json");
|
|
279
496
|
var DEFAULT_PROFILE_NAME = "credentials";
|
|
280
497
|
function isValidEnvironment(value) {
|
|
281
498
|
return ENVIRONMENTS.includes(value);
|
|
@@ -294,7 +511,7 @@ function parseCredentials(raw) {
|
|
|
294
511
|
};
|
|
295
512
|
}
|
|
296
513
|
async function loadCredentialsFromFile(filePath) {
|
|
297
|
-
const content = await
|
|
514
|
+
const content = await readFile3(filePath, "utf-8");
|
|
298
515
|
return parseCredentials(JSON.parse(content));
|
|
299
516
|
}
|
|
300
517
|
async function loadGlobalCredentials() {
|
|
@@ -305,11 +522,11 @@ async function loadGlobalCredentials() {
|
|
|
305
522
|
}
|
|
306
523
|
}
|
|
307
524
|
async function saveGlobalCredentials(credentials) {
|
|
308
|
-
await mkdir2(
|
|
525
|
+
await mkdir2(dirname2(GLOBAL_CREDENTIALS_PATH), { recursive: true });
|
|
309
526
|
await writeFile2(GLOBAL_CREDENTIALS_PATH, JSON.stringify(credentials, null, 2), "utf-8");
|
|
310
527
|
}
|
|
311
528
|
function getProfilePath(name) {
|
|
312
|
-
return
|
|
529
|
+
return join5(GLOBAL_CREDENTIALS_DIR, `${name}.json`);
|
|
313
530
|
}
|
|
314
531
|
async function listCredentialProfiles() {
|
|
315
532
|
const profiles = [
|
|
@@ -318,10 +535,14 @@ async function listCredentialProfiles() {
|
|
|
318
535
|
try {
|
|
319
536
|
const entries = await readdir2(GLOBAL_CREDENTIALS_DIR);
|
|
320
537
|
for (const entry of entries) {
|
|
321
|
-
if (!entry.endsWith(".json"))
|
|
538
|
+
if (!entry.endsWith(".json")) {
|
|
539
|
+
continue;
|
|
540
|
+
}
|
|
322
541
|
const name = entry.slice(0, -5);
|
|
323
|
-
if (name === DEFAULT_PROFILE_NAME)
|
|
324
|
-
|
|
542
|
+
if (name === DEFAULT_PROFILE_NAME) {
|
|
543
|
+
continue;
|
|
544
|
+
}
|
|
545
|
+
profiles.push({ name, path: join5(GLOBAL_CREDENTIALS_DIR, entry), isDefault: false });
|
|
325
546
|
}
|
|
326
547
|
} catch {
|
|
327
548
|
}
|
|
@@ -344,11 +565,11 @@ async function loadCredentialProfile(name) {
|
|
|
344
565
|
}
|
|
345
566
|
|
|
346
567
|
// src/lib/config.ts
|
|
347
|
-
import { mkdir as mkdir3, readFile as
|
|
348
|
-
import { join as
|
|
568
|
+
import { mkdir as mkdir3, readFile as readFile4, writeFile as writeFile3 } from "fs/promises";
|
|
569
|
+
import { join as join6 } from "path";
|
|
349
570
|
async function loadConfig(outputDir) {
|
|
350
571
|
try {
|
|
351
|
-
const content = await
|
|
572
|
+
const content = await readFile4(join6(outputDir, "config.json"), "utf-8");
|
|
352
573
|
return JSON.parse(content);
|
|
353
574
|
} catch {
|
|
354
575
|
return {};
|
|
@@ -356,7 +577,7 @@ async function loadConfig(outputDir) {
|
|
|
356
577
|
}
|
|
357
578
|
async function saveConfig(outputDir, config) {
|
|
358
579
|
await mkdir3(outputDir, { recursive: true });
|
|
359
|
-
await writeFile3(
|
|
580
|
+
await writeFile3(join6(outputDir, "config.json"), JSON.stringify(config, null, 2), "utf-8");
|
|
360
581
|
}
|
|
361
582
|
|
|
362
583
|
// src/ui/CredentialSetupUI.tsx
|
|
@@ -383,7 +604,7 @@ var CredentialSetupUI = ({
|
|
|
383
604
|
const [error, setError] = useState2(null);
|
|
384
605
|
const [activeProfileName, setActiveProfileName] = useState2(void 0);
|
|
385
606
|
const handleModeChosen = useCallback(
|
|
386
|
-
|
|
607
|
+
(mode) => {
|
|
387
608
|
if (mode === "local") {
|
|
388
609
|
onComplete({ mode: "local", credentials: null });
|
|
389
610
|
return;
|
|
@@ -452,7 +673,7 @@ var CredentialSetupUI = ({
|
|
|
452
673
|
setPhase({ type: "mode-select", cursor: 1 });
|
|
453
674
|
} else if (key.return) {
|
|
454
675
|
const mode = phase.cursor === 0 ? "global" : "local";
|
|
455
|
-
|
|
676
|
+
handleModeChosen(mode);
|
|
456
677
|
}
|
|
457
678
|
return;
|
|
458
679
|
}
|
|
@@ -468,13 +689,16 @@ var CredentialSetupUI = ({
|
|
|
468
689
|
if (cursor === addNewIdx) {
|
|
469
690
|
setPhase({ type: "name-entry", nameBuffer: "", existingProfiles: profiles });
|
|
470
691
|
} else {
|
|
471
|
-
|
|
692
|
+
const selected = profiles[cursor] ?? profiles[0];
|
|
693
|
+
if (selected) {
|
|
694
|
+
void handleProfileChosen(selected);
|
|
695
|
+
}
|
|
472
696
|
}
|
|
473
697
|
}
|
|
474
698
|
return;
|
|
475
699
|
}
|
|
476
700
|
if (phase.type === "name-entry") {
|
|
477
|
-
const { nameBuffer,
|
|
701
|
+
const { nameBuffer, existingProfiles } = phase;
|
|
478
702
|
if (key.backspace || key.delete) {
|
|
479
703
|
setPhase({ type: "name-entry", nameBuffer: nameBuffer.slice(0, -1), existingProfiles });
|
|
480
704
|
} else if (key.return) {
|
|
@@ -619,7 +843,14 @@ var CredentialSetupUI = ({
|
|
|
619
843
|
}),
|
|
620
844
|
/* @__PURE__ */ jsxs2(Box3, { gap: 2, children: [
|
|
621
845
|
/* @__PURE__ */ jsx3(Text3, { ...cursor === addNewIdx && { color: "cyan" }, children: cursor === addNewIdx ? "\u276F" : " " }),
|
|
622
|
-
/* @__PURE__ */ jsx3(
|
|
846
|
+
/* @__PURE__ */ jsx3(
|
|
847
|
+
Text3,
|
|
848
|
+
{
|
|
849
|
+
bold: cursor === addNewIdx,
|
|
850
|
+
...cursor === addNewIdx && { color: "cyan" },
|
|
851
|
+
children: "+ Add new profile"
|
|
852
|
+
}
|
|
853
|
+
)
|
|
623
854
|
] })
|
|
624
855
|
] }),
|
|
625
856
|
/* @__PURE__ */ jsx3(Hint, { text: "\u2191\u2193 to move \xB7 Enter to select \xB7 Esc to cancel" })
|
|
@@ -649,7 +880,7 @@ var CredentialSetupUI = ({
|
|
|
649
880
|
}
|
|
650
881
|
const { field: activeField, values, envCursor } = phase;
|
|
651
882
|
const isEnvField = activeField === FIELDS.length;
|
|
652
|
-
const profileLabel = activeProfileName
|
|
883
|
+
const profileLabel = activeProfileName ?? DEFAULT_PROFILE_NAME;
|
|
653
884
|
return /* @__PURE__ */ jsxs2(Box3, { flexDirection: "column", paddingY: 1, paddingX: 2, gap: 1, children: [
|
|
654
885
|
/* @__PURE__ */ jsx3(Logo, {}),
|
|
655
886
|
/* @__PURE__ */ jsxs2(Box3, { flexDirection: "column", marginTop: 1, children: [
|
|
@@ -659,7 +890,8 @@ var CredentialSetupUI = ({
|
|
|
659
890
|
/* @__PURE__ */ jsxs2(Box3, { flexDirection: "column", gap: 0, children: [
|
|
660
891
|
/* @__PURE__ */ jsx3(Text3, { bold: true, children: activeProfileName !== void 0 ? `Profile: ${activeProfileName}` : "Global credentials" }),
|
|
661
892
|
/* @__PURE__ */ jsxs2(Text3, { dimColor: true, children: [
|
|
662
|
-
"Saved to:
|
|
893
|
+
"Saved to:",
|
|
894
|
+
" ",
|
|
663
895
|
activeProfileName !== void 0 ? `~/.kizenappbuilder/${activeProfileName}.json` : GLOBAL_CREDENTIALS_PATH
|
|
664
896
|
] })
|
|
665
897
|
] }),
|
|
@@ -739,12 +971,8 @@ var Spinner2 = () => {
|
|
|
739
971
|
return /* @__PURE__ */ jsx4(Text4, { color: "cyan", children: SPINNER_FRAMES2[frame] ?? "\u280B" });
|
|
740
972
|
};
|
|
741
973
|
function getViewerPath() {
|
|
742
|
-
const filename =
|
|
743
|
-
return
|
|
744
|
-
}
|
|
745
|
-
function getElectronMainPath() {
|
|
746
|
-
const filename = fileURLToPath(import.meta.url);
|
|
747
|
-
return join6(dirname2(filename), "electron", "main.js");
|
|
974
|
+
const filename = fileURLToPath2(import.meta.url);
|
|
975
|
+
return join7(dirname3(filename), "viewer");
|
|
748
976
|
}
|
|
749
977
|
async function fileExists(filePath) {
|
|
750
978
|
try {
|
|
@@ -782,7 +1010,7 @@ function createRequestHandler(viewerPath, createServerLog, createProxyLog, crede
|
|
|
782
1010
|
const creds = profileName === void 0 || profileName === "" ? await loadGlobalCredentials() : await loadCredentialProfile(profileName);
|
|
783
1011
|
if (creds !== null) {
|
|
784
1012
|
credentialsRef.current = creds;
|
|
785
|
-
activeProfileRef.current = profileName
|
|
1013
|
+
activeProfileRef.current = profileName ?? void 0;
|
|
786
1014
|
const active = activeProfileRef.current;
|
|
787
1015
|
await saveConfig(outputDir, {
|
|
788
1016
|
credentialMode: "global",
|
|
@@ -795,9 +1023,9 @@ function createRequestHandler(viewerPath, createServerLog, createProxyLog, crede
|
|
|
795
1023
|
return;
|
|
796
1024
|
}
|
|
797
1025
|
if (url === "/api/bundle") {
|
|
798
|
-
const bundlePath =
|
|
1026
|
+
const bundlePath = join7(process.cwd(), ".kizenapp", "bundle.json");
|
|
799
1027
|
try {
|
|
800
|
-
const content = await
|
|
1028
|
+
const content = await readFile5(bundlePath, "utf-8");
|
|
801
1029
|
res.writeHead(200, { "Content-Type": "application/json; charset=utf-8" });
|
|
802
1030
|
res.end(content);
|
|
803
1031
|
} catch {
|
|
@@ -870,8 +1098,8 @@ function createRequestHandler(viewerPath, createServerLog, createProxyLog, crede
|
|
|
870
1098
|
return;
|
|
871
1099
|
}
|
|
872
1100
|
const rawPath = url === "/" ? "/index.html" : url;
|
|
873
|
-
const filePath =
|
|
874
|
-
const resolvedPath = await fileExists(filePath) ? filePath :
|
|
1101
|
+
const filePath = join7(viewerPath, rawPath);
|
|
1102
|
+
const resolvedPath = await fileExists(filePath) ? filePath : join7(viewerPath, "index.html");
|
|
875
1103
|
const ext = extname(resolvedPath);
|
|
876
1104
|
const mimeType = MIME_TYPES[ext] ?? "application/octet-stream";
|
|
877
1105
|
res.writeHead(200, { "Content-Type": mimeType });
|
|
@@ -923,10 +1151,40 @@ var DevUI = ({
|
|
|
923
1151
|
const [lastBuilt, setLastBuilt] = useState3(null);
|
|
924
1152
|
const [wsClientCount, setWsClientCount] = useState3(0);
|
|
925
1153
|
const buildingRef = useRef(false);
|
|
926
|
-
const
|
|
1154
|
+
const viewerLaunchedRef = useRef(false);
|
|
1155
|
+
const chromeHandleRef = useRef(null);
|
|
927
1156
|
const debounceTimerRef = useRef(null);
|
|
928
1157
|
const wsClientsRef = useRef(/* @__PURE__ */ new Set());
|
|
929
1158
|
const pendingMessagesRef = useRef([]);
|
|
1159
|
+
const broadcast = useCallback2((msg) => {
|
|
1160
|
+
const json = JSON.stringify(msg);
|
|
1161
|
+
if (wsClientsRef.current.size === 0) {
|
|
1162
|
+
pendingMessagesRef.current = [...pendingMessagesRef.current, json].slice(-LOG_LIMIT);
|
|
1163
|
+
return;
|
|
1164
|
+
}
|
|
1165
|
+
for (const client of wsClientsRef.current) {
|
|
1166
|
+
if (client.readyState === 1) {
|
|
1167
|
+
client.send(json);
|
|
1168
|
+
}
|
|
1169
|
+
}
|
|
1170
|
+
}, []);
|
|
1171
|
+
const createServerLog = useCallback2((message) => {
|
|
1172
|
+
setServerLogHistory(
|
|
1173
|
+
(h) => [...h, `${(/* @__PURE__ */ new Date()).toLocaleTimeString()}: ${message}`].slice(-LOG_LIMIT)
|
|
1174
|
+
);
|
|
1175
|
+
}, []);
|
|
1176
|
+
const launchChromeViewerCb = useCallback2(() => {
|
|
1177
|
+
chromeHandleRef.current?.kill();
|
|
1178
|
+
chromeHandleRef.current = null;
|
|
1179
|
+
void launchChromeViewer({
|
|
1180
|
+
port,
|
|
1181
|
+
userDataDir: join7(outputDir, ".chrome"),
|
|
1182
|
+
broadcast
|
|
1183
|
+
}).then((handle) => {
|
|
1184
|
+
chromeHandleRef.current = handle;
|
|
1185
|
+
process.on("exit", () => handle.kill());
|
|
1186
|
+
});
|
|
1187
|
+
}, [port, outputDir, broadcast]);
|
|
930
1188
|
useInput2(
|
|
931
1189
|
(input, key) => {
|
|
932
1190
|
if (input === "q" || key.ctrl && input === "c") {
|
|
@@ -935,50 +1193,19 @@ var DevUI = ({
|
|
|
935
1193
|
if (input === "c") {
|
|
936
1194
|
setCredMode("editing");
|
|
937
1195
|
}
|
|
938
|
-
if (input === "
|
|
939
|
-
|
|
1196
|
+
if (input === "v") {
|
|
1197
|
+
launchChromeViewerCb();
|
|
940
1198
|
}
|
|
941
1199
|
},
|
|
942
1200
|
{ isActive: credMode === "main" }
|
|
943
1201
|
);
|
|
944
1202
|
useEffect3(() => {
|
|
945
|
-
if (status !== "running" ||
|
|
946
|
-
return;
|
|
947
|
-
}
|
|
948
|
-
electronLaunchedRef.current = true;
|
|
949
|
-
const _require = createRequire(import.meta.url);
|
|
950
|
-
const electronBin = _require("electron");
|
|
951
|
-
const electronMain = getElectronMainPath();
|
|
952
|
-
const userDataDir = join6(outputDir, ".electron");
|
|
953
|
-
const proc = spawn(
|
|
954
|
-
electronBin,
|
|
955
|
-
[electronMain, `--port=${String(port)}`, `--user-data-dir=${userDataDir}`],
|
|
956
|
-
{
|
|
957
|
-
stdio: "ignore"
|
|
958
|
-
}
|
|
959
|
-
);
|
|
960
|
-
proc.unref();
|
|
961
|
-
process.on("exit", () => {
|
|
962
|
-
proc.kill();
|
|
963
|
-
});
|
|
964
|
-
}, [status, port, outputDir]);
|
|
965
|
-
const createServerLog = useCallback2((message) => {
|
|
966
|
-
setServerLogHistory(
|
|
967
|
-
(h) => [...h, `${(/* @__PURE__ */ new Date()).toLocaleTimeString()}: ${message}`].slice(-LOG_LIMIT)
|
|
968
|
-
);
|
|
969
|
-
}, []);
|
|
970
|
-
const broadcast = useCallback2((msg) => {
|
|
971
|
-
const json = JSON.stringify(msg);
|
|
972
|
-
if (wsClientsRef.current.size === 0) {
|
|
973
|
-
pendingMessagesRef.current = [...pendingMessagesRef.current, json].slice(-LOG_LIMIT);
|
|
1203
|
+
if (status !== "running" || viewerLaunchedRef.current) {
|
|
974
1204
|
return;
|
|
975
1205
|
}
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
}
|
|
980
|
-
}
|
|
981
|
-
}, []);
|
|
1206
|
+
viewerLaunchedRef.current = true;
|
|
1207
|
+
launchChromeViewerCb();
|
|
1208
|
+
}, [status, launchChromeViewerCb]);
|
|
982
1209
|
const handleCredentialsDone = useCallback2(
|
|
983
1210
|
(result) => {
|
|
984
1211
|
credentialsRef.current = result.credentials;
|
|
@@ -1065,7 +1292,7 @@ var DevUI = ({
|
|
|
1065
1292
|
}, [pluginDir, triggerBuild, createBuildLog]);
|
|
1066
1293
|
useEffect3(() => {
|
|
1067
1294
|
const viewerPath = getViewerPath();
|
|
1068
|
-
void fileExists(
|
|
1295
|
+
void fileExists(join7(viewerPath, "index.html")).then((viewerBuilt) => {
|
|
1069
1296
|
if (!viewerBuilt) {
|
|
1070
1297
|
setErrorMessage("Viewer not built. Run 'pnpm build:viewer' first.");
|
|
1071
1298
|
setStatus("error");
|
|
@@ -1110,7 +1337,7 @@ var DevUI = ({
|
|
|
1110
1337
|
server.close();
|
|
1111
1338
|
};
|
|
1112
1339
|
});
|
|
1113
|
-
}, [port, createServerLog, createProxyLog]);
|
|
1340
|
+
}, [port, createServerLog, createProxyLog, broadcast, outputDir]);
|
|
1114
1341
|
if (credMode === "editing") {
|
|
1115
1342
|
return /* @__PURE__ */ jsx4(
|
|
1116
1343
|
CredentialSetupUI,
|
|
@@ -1218,8 +1445,11 @@ var DevUI = ({
|
|
|
1218
1445
|
/* @__PURE__ */ jsx4(Text4, { dimColor: true, children: "] quit [" }),
|
|
1219
1446
|
/* @__PURE__ */ jsx4(Text4, { children: "c" }),
|
|
1220
1447
|
/* @__PURE__ */ jsx4(Text4, { dimColor: true, children: "] credentials [" }),
|
|
1221
|
-
/* @__PURE__ */ jsx4(Text4, { children: "
|
|
1222
|
-
/* @__PURE__ */
|
|
1448
|
+
/* @__PURE__ */ jsx4(Text4, { children: "v" }),
|
|
1449
|
+
/* @__PURE__ */ jsxs3(Text4, { dimColor: true, children: [
|
|
1450
|
+
"] ",
|
|
1451
|
+
wsClientCount === 0 ? "open viewer" : "relaunch viewer"
|
|
1452
|
+
] })
|
|
1223
1453
|
] })
|
|
1224
1454
|
] });
|
|
1225
1455
|
};
|