@walkeros/cli 4.8.1-next-1792019907609 → 4.8.2
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/CHANGELOG.md +62 -6
- package/dist/cli.js +3663 -3665
- package/dist/examples/event.json +1 -1
- package/dist/examples/flow-complete.json +89 -127
- package/dist/examples/flow-complete.md +7 -7
- package/dist/examples/flow-order-complete.json +1 -1
- package/dist/examples/flow.json +1 -1
- package/dist/examples/index.d.ts +34 -4
- package/dist/examples/index.js +108 -134
- package/dist/examples/index.js.map +1 -1
- package/dist/index.d.ts +22 -182
- package/dist/index.js +418 -865
- package/dist/index.js.map +1 -1
- package/dist/validate.d.ts +1 -1
- package/dist/validate.js +80 -79
- package/dist/validate.js.map +1 -1
- package/examples/event.json +1 -1
- package/examples/flow-complete.json +89 -127
- package/examples/flow-complete.md +7 -7
- package/examples/flow-order-complete.json +1 -1
- package/examples/flow.json +1 -1
- package/package.json +30 -30
- package/src/telemetry/flow.json +42 -34
package/dist/index.js
CHANGED
|
@@ -350,479 +350,10 @@ async function readStdinToTempFile(label) {
|
|
|
350
350
|
return tmpPath;
|
|
351
351
|
}
|
|
352
352
|
|
|
353
|
-
// src/lib/config-file.ts
|
|
354
|
-
import {
|
|
355
|
-
readFileSync,
|
|
356
|
-
writeFileSync,
|
|
357
|
-
mkdirSync,
|
|
358
|
-
unlinkSync,
|
|
359
|
-
existsSync,
|
|
360
|
-
chmodSync,
|
|
361
|
-
renameSync
|
|
362
|
-
} from "fs";
|
|
363
|
-
import { randomBytes } from "crypto";
|
|
364
|
-
import { join } from "path";
|
|
365
|
-
import { homedir } from "os";
|
|
366
|
-
function getConfigDir() {
|
|
367
|
-
const xdgConfig = process.env.XDG_CONFIG_HOME;
|
|
368
|
-
const base = xdgConfig || join(homedir(), ".config");
|
|
369
|
-
return join(base, "walkeros");
|
|
370
|
-
}
|
|
371
|
-
function getConfigPath() {
|
|
372
|
-
return join(getConfigDir(), "config.json");
|
|
373
|
-
}
|
|
374
|
-
function readConfig() {
|
|
375
|
-
const configPath = getConfigPath();
|
|
376
|
-
try {
|
|
377
|
-
const content = readFileSync(configPath, "utf-8");
|
|
378
|
-
return JSON.parse(content);
|
|
379
|
-
} catch {
|
|
380
|
-
return null;
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
function replaceConfigFile(config) {
|
|
384
|
-
const dir = getConfigDir();
|
|
385
|
-
mkdirSync(dir, { recursive: true, mode: 448 });
|
|
386
|
-
const configPath = getConfigPath();
|
|
387
|
-
const tempPath = `${configPath}.${process.pid}.${randomBytes(6).toString("hex")}.tmp`;
|
|
388
|
-
try {
|
|
389
|
-
writeFileSync(tempPath, JSON.stringify(config, null, 2), { mode: 384 });
|
|
390
|
-
chmodSync(tempPath, 384);
|
|
391
|
-
renameSync(tempPath, configPath);
|
|
392
|
-
} catch (error) {
|
|
393
|
-
try {
|
|
394
|
-
unlinkSync(tempPath);
|
|
395
|
-
} catch {
|
|
396
|
-
}
|
|
397
|
-
throw error;
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
function writeConfig(config) {
|
|
401
|
-
replaceConfigFile({ ...readConfig() ?? {}, ...config });
|
|
402
|
-
}
|
|
403
|
-
function clearAuthFields() {
|
|
404
|
-
const config = readConfig();
|
|
405
|
-
if (!config) return;
|
|
406
|
-
const {
|
|
407
|
-
token: _token,
|
|
408
|
-
accessToken: _accessToken,
|
|
409
|
-
accessTokenExpiresAt: _accessTokenExpiresAt,
|
|
410
|
-
refreshToken: _refreshToken,
|
|
411
|
-
email: _email,
|
|
412
|
-
...rest
|
|
413
|
-
} = config;
|
|
414
|
-
replaceConfigFile(rest);
|
|
415
|
-
}
|
|
416
|
-
function writeTelemetryOnlyConfig(partial) {
|
|
417
|
-
writeConfig(partial);
|
|
418
|
-
}
|
|
419
|
-
function deleteConfig() {
|
|
420
|
-
const configPath = getConfigPath();
|
|
421
|
-
if (existsSync(configPath)) {
|
|
422
|
-
unlinkSync(configPath);
|
|
423
|
-
return true;
|
|
424
|
-
}
|
|
425
|
-
return false;
|
|
426
|
-
}
|
|
427
|
-
function hasStoredCredential(config) {
|
|
428
|
-
return Boolean(config?.token || config?.accessToken);
|
|
429
|
-
}
|
|
430
|
-
function resolveToken() {
|
|
431
|
-
const envToken = process.env.WALKEROS_TOKEN;
|
|
432
|
-
if (envToken) return { token: envToken, source: "env" };
|
|
433
|
-
const config = readConfig();
|
|
434
|
-
if (config?.token) return { token: config.token, source: "config" };
|
|
435
|
-
return null;
|
|
436
|
-
}
|
|
437
|
-
function resolveAppUrl() {
|
|
438
|
-
const envUrl = process.env.WALKEROS_APP_URL;
|
|
439
|
-
if (envUrl) return envUrl;
|
|
440
|
-
const config = readConfig();
|
|
441
|
-
if (config?.appUrl) return config.appUrl;
|
|
442
|
-
return "https://app.walkeros.io";
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
// src/lib/config-lock.ts
|
|
446
|
-
import { closeSync, mkdirSync as mkdirSync2, openSync, statSync, unlinkSync as unlinkSync2 } from "fs";
|
|
447
|
-
var STALE_MS = 15e3;
|
|
448
|
-
var RETRY_MS = 100;
|
|
449
|
-
var TIMEOUT_MS = 1e4;
|
|
450
|
-
function getConfigLockPath() {
|
|
451
|
-
return `${getConfigPath()}.lock`;
|
|
452
|
-
}
|
|
453
|
-
function hasCode(value) {
|
|
454
|
-
return typeof value === "object" && value !== null && "code" in value;
|
|
455
|
-
}
|
|
456
|
-
function isAlreadyLocked(error) {
|
|
457
|
-
return hasCode(error) && error.code === "EEXIST";
|
|
458
|
-
}
|
|
459
|
-
function delay(ms) {
|
|
460
|
-
return new Promise((resolve5) => setTimeout(resolve5, ms));
|
|
461
|
-
}
|
|
462
|
-
function breakIfStale(lockPath) {
|
|
463
|
-
try {
|
|
464
|
-
const age = Date.now() - statSync(lockPath).mtimeMs;
|
|
465
|
-
if (age < STALE_MS) return false;
|
|
466
|
-
unlinkSync2(lockPath);
|
|
467
|
-
return true;
|
|
468
|
-
} catch {
|
|
469
|
-
return false;
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
async function withConfigLock(fn) {
|
|
473
|
-
const lockPath = getConfigLockPath();
|
|
474
|
-
mkdirSync2(getConfigDir(), { recursive: true, mode: 448 });
|
|
475
|
-
const deadline = Date.now() + TIMEOUT_MS;
|
|
476
|
-
for (; ; ) {
|
|
477
|
-
let handle;
|
|
478
|
-
try {
|
|
479
|
-
handle = openSync(lockPath, "wx", 384);
|
|
480
|
-
} catch (error) {
|
|
481
|
-
if (!isAlreadyLocked(error)) throw error;
|
|
482
|
-
if (breakIfStale(lockPath)) continue;
|
|
483
|
-
if (Date.now() >= deadline) {
|
|
484
|
-
throw new Error(
|
|
485
|
-
`Timed out waiting for the walkerOS config lock at ${lockPath}. Remove the file if no other walkeros process is running.`
|
|
486
|
-
);
|
|
487
|
-
}
|
|
488
|
-
await delay(RETRY_MS);
|
|
489
|
-
continue;
|
|
490
|
-
}
|
|
491
|
-
closeSync(handle);
|
|
492
|
-
try {
|
|
493
|
-
return await fn();
|
|
494
|
-
} finally {
|
|
495
|
-
try {
|
|
496
|
-
unlinkSync2(lockPath);
|
|
497
|
-
} catch {
|
|
498
|
-
}
|
|
499
|
-
}
|
|
500
|
-
}
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
// src/core/oauth-client.ts
|
|
504
|
-
import { z as z2 } from "zod";
|
|
505
|
-
|
|
506
|
-
// src/lib/secure-url.ts
|
|
507
|
-
function isLoopback(hostname) {
|
|
508
|
-
return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "[::1]";
|
|
509
|
-
}
|
|
510
|
-
function requireSecureUrl(url) {
|
|
511
|
-
let parsed;
|
|
512
|
-
try {
|
|
513
|
-
parsed = new URL(url);
|
|
514
|
-
} catch {
|
|
515
|
-
return url;
|
|
516
|
-
}
|
|
517
|
-
if (parsed.protocol !== "http:" || isLoopback(parsed.hostname)) return url;
|
|
518
|
-
throw new Error(
|
|
519
|
-
`Refusing to send walkerOS credentials over plain http to ${url}. Use https, or localhost / 127.0.0.1 / [::1] for local development.`
|
|
520
|
-
);
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
// src/core/app-fetch.ts
|
|
524
|
-
import { z } from "zod";
|
|
525
|
-
|
|
526
|
-
// src/core/client-context.ts
|
|
527
|
-
var context;
|
|
528
|
-
function setClientContext(input) {
|
|
529
|
-
const envType = process.env.WALKEROS_CLIENT_TYPE;
|
|
530
|
-
const type = envType ?? input.type ?? "cli";
|
|
531
|
-
context = { type, version: input.version };
|
|
532
|
-
}
|
|
533
|
-
function getClientContext() {
|
|
534
|
-
return context;
|
|
535
|
-
}
|
|
536
|
-
function resetClientContext() {
|
|
537
|
-
context = void 0;
|
|
538
|
-
}
|
|
539
|
-
function clientContextHeaders() {
|
|
540
|
-
if (!context) return {};
|
|
541
|
-
return {
|
|
542
|
-
"User-Agent": `walkeros-${context.type}/${context.version}`,
|
|
543
|
-
"X-WalkerOS-Client": context.type,
|
|
544
|
-
"X-WalkerOS-Client-Version": context.version
|
|
545
|
-
};
|
|
546
|
-
}
|
|
547
|
-
|
|
548
|
-
// src/core/app-fetch.ts
|
|
549
|
-
var AppErrorSchema = z.object({
|
|
550
|
-
error: z.object({ message: z.string().min(1) })
|
|
551
|
-
});
|
|
552
|
-
function appErrorMessage(body) {
|
|
553
|
-
const parsed = AppErrorSchema.safeParse(body);
|
|
554
|
-
return parsed.success ? parsed.data.error.message : void 0;
|
|
555
|
-
}
|
|
556
|
-
async function appFetch(path23, init = {}) {
|
|
557
|
-
const url = `${(init.baseUrl ?? resolveAppUrl()).replace(/\/+$/, "")}${path23}`;
|
|
558
|
-
const headers = new Headers(clientContextHeaders());
|
|
559
|
-
for (const [name, value] of Object.entries(init.headers ?? {}))
|
|
560
|
-
headers.set(name, value);
|
|
561
|
-
if (init.token && !headers.has("Authorization"))
|
|
562
|
-
headers.set("Authorization", `Bearer ${init.token}`);
|
|
563
|
-
if (headers.has("Authorization")) requireSecureUrl(url);
|
|
564
|
-
const request = { headers };
|
|
565
|
-
if (init.method && init.method !== "GET") request.method = init.method;
|
|
566
|
-
if (init.body !== void 0) request.body = init.body;
|
|
567
|
-
if (init.signal) request.signal = init.signal;
|
|
568
|
-
if (init.redirect) request.redirect = init.redirect;
|
|
569
|
-
return (init.fetch ?? fetch)(url, request);
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
// src/core/app-paths.ts
|
|
573
|
-
var APP_PATHS = {
|
|
574
|
-
deviceAuthorization: "/api/oauth/device_authorization",
|
|
575
|
-
token: "/api/oauth/token",
|
|
576
|
-
revoke: "/api/oauth/revoke",
|
|
577
|
-
whoami: "/api/auth/whoami",
|
|
578
|
-
health: "/api/health",
|
|
579
|
-
telemetry: "/api/telemetry",
|
|
580
|
-
openapi: "/api/openapi.json"
|
|
581
|
-
};
|
|
582
|
-
|
|
583
|
-
// src/core/oauth-client.ts
|
|
584
|
-
var CLI_CLIENT_ID = "walkeros-cli";
|
|
585
|
-
var CLI_SCOPE = "read write offline_access";
|
|
586
|
-
var DEVICE_CODE_GRANT = "urn:ietf:params:oauth:grant-type:device_code";
|
|
587
|
-
var REFRESH_TIMEOUT_MS = 1e4;
|
|
588
|
-
var REVOKE_TIMEOUT_MS = 5e3;
|
|
589
|
-
var DEVICE_AUTHORIZATION_TIMEOUT_MS = 1e4;
|
|
590
|
-
var DeviceAuthorizationSchema = z2.object({
|
|
591
|
-
device_code: z2.string().min(1),
|
|
592
|
-
user_code: z2.string().min(1),
|
|
593
|
-
verification_uri: z2.string().min(1),
|
|
594
|
-
verification_uri_complete: z2.string().min(1).optional(),
|
|
595
|
-
expires_in: z2.number().int().nonnegative(),
|
|
596
|
-
interval: z2.number().int().nonnegative()
|
|
597
|
-
});
|
|
598
|
-
var TokenSchema = z2.object({
|
|
599
|
-
access_token: z2.string().min(1),
|
|
600
|
-
expires_in: z2.number().int().nonnegative(),
|
|
601
|
-
refresh_token: z2.string().min(1).optional()
|
|
602
|
-
});
|
|
603
|
-
var ErrorSchema = z2.object({
|
|
604
|
-
error: z2.string().min(1),
|
|
605
|
-
error_description: z2.string().optional()
|
|
606
|
-
});
|
|
607
|
-
async function readJson(response) {
|
|
608
|
-
try {
|
|
609
|
-
return await response.json();
|
|
610
|
-
} catch {
|
|
611
|
-
return null;
|
|
612
|
-
}
|
|
613
|
-
}
|
|
614
|
-
function errorCode(body) {
|
|
615
|
-
const parsed = ErrorSchema.safeParse(body);
|
|
616
|
-
return parsed.success ? parsed.data.error : null;
|
|
617
|
-
}
|
|
618
|
-
function describe(response, body) {
|
|
619
|
-
const parsed = ErrorSchema.safeParse(body);
|
|
620
|
-
if (parsed.success) {
|
|
621
|
-
return parsed.data.error_description ? `${parsed.data.error}: ${parsed.data.error_description}` : parsed.data.error;
|
|
622
|
-
}
|
|
623
|
-
return appErrorMessage(body) ?? `HTTP ${response.status}`;
|
|
624
|
-
}
|
|
625
|
-
function postForm(appUrl, path23, form, fetchFn, signal) {
|
|
626
|
-
return appFetch(path23, {
|
|
627
|
-
method: "POST",
|
|
628
|
-
baseUrl: requireSecureUrl(appUrl),
|
|
629
|
-
headers: {
|
|
630
|
-
Accept: "application/json",
|
|
631
|
-
"Content-Type": "application/x-www-form-urlencoded"
|
|
632
|
-
},
|
|
633
|
-
body: new URLSearchParams(form).toString(),
|
|
634
|
-
redirect: "error",
|
|
635
|
-
fetch: fetchFn,
|
|
636
|
-
signal
|
|
637
|
-
});
|
|
638
|
-
}
|
|
639
|
-
function toTokenSet(body) {
|
|
640
|
-
const parsed = TokenSchema.safeParse(body);
|
|
641
|
-
if (!parsed.success) throw new Error("Malformed token response");
|
|
642
|
-
return {
|
|
643
|
-
accessToken: parsed.data.access_token,
|
|
644
|
-
accessTokenExpiresAt: new Date(
|
|
645
|
-
Date.now() + parsed.data.expires_in * 1e3
|
|
646
|
-
).toISOString(),
|
|
647
|
-
refreshToken: parsed.data.refresh_token ?? null
|
|
648
|
-
};
|
|
649
|
-
}
|
|
650
|
-
async function startDeviceAuthorization(appUrl, fetchFn = globalThis.fetch) {
|
|
651
|
-
const response = await postForm(
|
|
652
|
-
appUrl,
|
|
653
|
-
APP_PATHS.deviceAuthorization,
|
|
654
|
-
{
|
|
655
|
-
client_id: CLI_CLIENT_ID,
|
|
656
|
-
scope: CLI_SCOPE,
|
|
657
|
-
// RFC 8707. The token comes back bound to the API, so a leaked CLI token
|
|
658
|
-
// cannot be replayed against the MCP resource.
|
|
659
|
-
resource: `${appUrl}/api`
|
|
660
|
-
},
|
|
661
|
-
fetchFn,
|
|
662
|
-
AbortSignal.timeout(DEVICE_AUTHORIZATION_TIMEOUT_MS)
|
|
663
|
-
);
|
|
664
|
-
const body = await readJson(response);
|
|
665
|
-
if (!response.ok) throw new Error(describe(response, body));
|
|
666
|
-
const parsed = DeviceAuthorizationSchema.safeParse(body);
|
|
667
|
-
if (!parsed.success)
|
|
668
|
-
throw new Error("Malformed device authorization response");
|
|
669
|
-
return {
|
|
670
|
-
deviceCode: parsed.data.device_code,
|
|
671
|
-
userCode: parsed.data.user_code,
|
|
672
|
-
verificationUri: parsed.data.verification_uri,
|
|
673
|
-
verificationUriComplete: parsed.data.verification_uri_complete ?? parsed.data.verification_uri,
|
|
674
|
-
expiresIn: parsed.data.expires_in,
|
|
675
|
-
interval: parsed.data.interval
|
|
676
|
-
};
|
|
677
|
-
}
|
|
678
|
-
async function pollDeviceToken(appUrl, deviceCode, fetchFn = globalThis.fetch, signal) {
|
|
679
|
-
let response;
|
|
680
|
-
try {
|
|
681
|
-
response = await postForm(
|
|
682
|
-
appUrl,
|
|
683
|
-
APP_PATHS.token,
|
|
684
|
-
{
|
|
685
|
-
grant_type: DEVICE_CODE_GRANT,
|
|
686
|
-
device_code: deviceCode,
|
|
687
|
-
client_id: CLI_CLIENT_ID
|
|
688
|
-
},
|
|
689
|
-
fetchFn,
|
|
690
|
-
signal
|
|
691
|
-
);
|
|
692
|
-
} catch (error) {
|
|
693
|
-
if (signal?.aborted) return { status: "pending" };
|
|
694
|
-
throw error;
|
|
695
|
-
}
|
|
696
|
-
const body = await readJson(response);
|
|
697
|
-
if (response.ok) {
|
|
698
|
-
try {
|
|
699
|
-
return { status: "ok", tokens: toTokenSet(body) };
|
|
700
|
-
} catch (error) {
|
|
701
|
-
return {
|
|
702
|
-
status: "error",
|
|
703
|
-
error: error instanceof Error ? error.message : String(error)
|
|
704
|
-
};
|
|
705
|
-
}
|
|
706
|
-
}
|
|
707
|
-
switch (errorCode(body)) {
|
|
708
|
-
case "authorization_pending":
|
|
709
|
-
return { status: "pending" };
|
|
710
|
-
case "slow_down":
|
|
711
|
-
return { status: "slow_down" };
|
|
712
|
-
case "access_denied":
|
|
713
|
-
return { status: "denied" };
|
|
714
|
-
case "expired_token":
|
|
715
|
-
return { status: "expired" };
|
|
716
|
-
default:
|
|
717
|
-
return { status: "error", error: describe(response, body) };
|
|
718
|
-
}
|
|
719
|
-
}
|
|
720
|
-
async function refreshTokens(appUrl, refreshToken, fetchFn = globalThis.fetch) {
|
|
721
|
-
const response = await postForm(
|
|
722
|
-
appUrl,
|
|
723
|
-
APP_PATHS.token,
|
|
724
|
-
{
|
|
725
|
-
grant_type: "refresh_token",
|
|
726
|
-
refresh_token: refreshToken,
|
|
727
|
-
client_id: CLI_CLIENT_ID
|
|
728
|
-
},
|
|
729
|
-
fetchFn,
|
|
730
|
-
AbortSignal.timeout(REFRESH_TIMEOUT_MS)
|
|
731
|
-
);
|
|
732
|
-
const body = await readJson(response);
|
|
733
|
-
if (!response.ok) {
|
|
734
|
-
if (errorCode(body) === "invalid_grant") return null;
|
|
735
|
-
throw new Error(describe(response, body));
|
|
736
|
-
}
|
|
737
|
-
return toTokenSet(body);
|
|
738
|
-
}
|
|
739
|
-
async function revokeRefreshToken(appUrl, refreshToken, fetchFn = globalThis.fetch) {
|
|
740
|
-
try {
|
|
741
|
-
await postForm(
|
|
742
|
-
appUrl,
|
|
743
|
-
APP_PATHS.revoke,
|
|
744
|
-
{
|
|
745
|
-
token: refreshToken,
|
|
746
|
-
token_type_hint: "refresh_token",
|
|
747
|
-
client_id: CLI_CLIENT_ID
|
|
748
|
-
},
|
|
749
|
-
fetchFn,
|
|
750
|
-
AbortSignal.timeout(REVOKE_TIMEOUT_MS)
|
|
751
|
-
);
|
|
752
|
-
} catch {
|
|
753
|
-
}
|
|
754
|
-
}
|
|
755
|
-
|
|
756
353
|
// src/core/auth.ts
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
if (legacyNoticeShown) return;
|
|
761
|
-
legacyNoticeShown = true;
|
|
762
|
-
process.stderr.write(
|
|
763
|
-
"walkerOS: using a static token from your config. Run `walkeros auth login` to switch to a session that refreshes automatically.\n"
|
|
764
|
-
);
|
|
765
|
-
}
|
|
766
|
-
function isFresh(config, nowMs) {
|
|
767
|
-
if (!config.accessToken || !config.accessTokenExpiresAt) return false;
|
|
768
|
-
const expiresAt = Date.parse(config.accessTokenExpiresAt);
|
|
769
|
-
if (Number.isNaN(expiresAt)) return false;
|
|
770
|
-
return expiresAt - nowMs > REFRESH_SKEW_MS;
|
|
771
|
-
}
|
|
772
|
-
async function resolveAccessToken(opts) {
|
|
773
|
-
const envToken = process.env.WALKEROS_TOKEN;
|
|
774
|
-
if (envToken) return envToken;
|
|
775
|
-
const now = opts?.now ?? Date.now;
|
|
776
|
-
const config = readConfig();
|
|
777
|
-
if (!config) return null;
|
|
778
|
-
if (config.token) {
|
|
779
|
-
noticeLegacyToken();
|
|
780
|
-
return config.token;
|
|
781
|
-
}
|
|
782
|
-
if (!config.refreshToken) {
|
|
783
|
-
return isFresh(config, now()) ? config.accessToken ?? null : null;
|
|
784
|
-
}
|
|
785
|
-
if (isFresh(config, now())) return config.accessToken ?? null;
|
|
786
|
-
return withConfigLock(async () => {
|
|
787
|
-
const current = readConfig();
|
|
788
|
-
if (!current?.refreshToken) return current?.accessToken ?? null;
|
|
789
|
-
if (isFresh(current, now())) return current.accessToken ?? null;
|
|
790
|
-
let rotated;
|
|
791
|
-
try {
|
|
792
|
-
rotated = await refreshTokens(
|
|
793
|
-
resolveAppUrl(),
|
|
794
|
-
current.refreshToken,
|
|
795
|
-
opts?.fetch
|
|
796
|
-
);
|
|
797
|
-
} catch (error) {
|
|
798
|
-
const reason = error instanceof Error ? error.message : String(error);
|
|
799
|
-
throw new Error(
|
|
800
|
-
`Could not reach ${resolveAppUrl()} to refresh your session: ${reason}. Your saved session was kept, so try again once the connection is back.`
|
|
801
|
-
);
|
|
802
|
-
}
|
|
803
|
-
if (rotated === null) {
|
|
804
|
-
clearAuthFields();
|
|
805
|
-
return null;
|
|
806
|
-
}
|
|
807
|
-
writeConfig({
|
|
808
|
-
accessToken: rotated.accessToken,
|
|
809
|
-
accessTokenExpiresAt: rotated.accessTokenExpiresAt,
|
|
810
|
-
// A server that rotates no new refresh token leaves the current one in
|
|
811
|
-
// force; overwriting it with null would end the session on the next call.
|
|
812
|
-
refreshToken: rotated.refreshToken ?? current.refreshToken
|
|
813
|
-
});
|
|
814
|
-
return rotated.accessToken;
|
|
815
|
-
});
|
|
816
|
-
}
|
|
817
|
-
async function getAuthHeaders() {
|
|
818
|
-
const token = await resolveAccessToken();
|
|
819
|
-
if (!token) return {};
|
|
820
|
-
return { Authorization: `Bearer ${token}` };
|
|
821
|
-
}
|
|
822
|
-
function credentialSource() {
|
|
823
|
-
if (process.env.WALKEROS_TOKEN) return "env";
|
|
824
|
-
if (hasStoredCredential(readConfig())) return "config";
|
|
825
|
-
return null;
|
|
354
|
+
function resolveAccessToken() {
|
|
355
|
+
const token = process.env.WALKEROS_TOKEN;
|
|
356
|
+
return token ? token : null;
|
|
826
357
|
}
|
|
827
358
|
|
|
828
359
|
// src/core/event-validation.ts
|
|
@@ -1017,6 +548,7 @@ function getDefaultOutput(platform) {
|
|
|
1017
548
|
import path8 from "path";
|
|
1018
549
|
import fs8 from "fs-extra";
|
|
1019
550
|
import { getFlowSettings, getPlatform } from "@walkeros/core";
|
|
551
|
+
import { validateFlowStructure } from "@walkeros/core/dev";
|
|
1020
552
|
|
|
1021
553
|
// src/core/content-digest.ts
|
|
1022
554
|
import { createHash } from "crypto";
|
|
@@ -1095,11 +627,22 @@ function assertWindowCollector(value, source = {}) {
|
|
|
1095
627
|
|
|
1096
628
|
// src/config/loader.ts
|
|
1097
629
|
var DEFAULT_INCLUDE_FOLDER = "./shared";
|
|
630
|
+
function assertFlowStructure(config, flowName) {
|
|
631
|
+
const { errors } = validateFlowStructure({
|
|
632
|
+
...config,
|
|
633
|
+
flows: { [flowName]: config.flows[flowName] }
|
|
634
|
+
});
|
|
635
|
+
if (errors.length === 0) return;
|
|
636
|
+
const lines = errors.map((error) => ` - ${error.path}: ${error.message}`);
|
|
637
|
+
throw new Error(`Invalid configuration:
|
|
638
|
+
${lines.join("\n")}`);
|
|
639
|
+
}
|
|
1098
640
|
function loadBundleConfig(rawConfig, options) {
|
|
1099
641
|
const sanitized = stripLegacyBundleExternal(rawConfig, options.logger);
|
|
1100
642
|
const config = validateFlowConfig(sanitized);
|
|
1101
643
|
const availableFlows = getAvailableFlows(config);
|
|
1102
644
|
const flowName = resolveFlow(config, options.flowName, availableFlows);
|
|
645
|
+
assertFlowStructure(config, flowName);
|
|
1103
646
|
assertLiteralBuildEnv(config, flowName);
|
|
1104
647
|
let flowSettings = getFlowSettings(config, flowName, { deferred: true });
|
|
1105
648
|
const platform = getPlatform(flowSettings);
|
|
@@ -1255,10 +798,12 @@ import path14 from "path";
|
|
|
1255
798
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
1256
799
|
import fs14 from "fs-extra";
|
|
1257
800
|
import {
|
|
801
|
+
getPlatform as getPlatform2,
|
|
1258
802
|
packageNameToVariable as packageNameToVariable2,
|
|
1259
803
|
getStepRuntimeProps,
|
|
1260
804
|
ENV_MARKER_PREFIX,
|
|
1261
805
|
SECRET_MARKER_PREFIX as SECRET_MARKER_PREFIX2,
|
|
806
|
+
STEP_FUNCTION_KEYS,
|
|
1262
807
|
isPathStepEntry,
|
|
1263
808
|
isObject as isObject3
|
|
1264
809
|
} from "@walkeros/core";
|
|
@@ -1473,7 +1018,7 @@ function tempSibling(dest) {
|
|
|
1473
1018
|
).join("");
|
|
1474
1019
|
return `${dest}${TMP_INFIX}${rand}`;
|
|
1475
1020
|
}
|
|
1476
|
-
function
|
|
1021
|
+
function errorCode(error) {
|
|
1477
1022
|
if (typeof error === "object" && error !== null && "code" in error) {
|
|
1478
1023
|
const code = error.code;
|
|
1479
1024
|
return typeof code === "string" ? code : void 0;
|
|
@@ -1481,7 +1026,7 @@ function errorCode2(error) {
|
|
|
1481
1026
|
return void 0;
|
|
1482
1027
|
}
|
|
1483
1028
|
function isOccupied(error) {
|
|
1484
|
-
const code =
|
|
1029
|
+
const code = errorCode(error);
|
|
1485
1030
|
return code === "EEXIST" || code === "ENOTEMPTY";
|
|
1486
1031
|
}
|
|
1487
1032
|
function isCacheTempName(name) {
|
|
@@ -1520,7 +1065,7 @@ async function replaceIncomplete(tmp, dest) {
|
|
|
1520
1065
|
await fs9.rename(dest, aside);
|
|
1521
1066
|
moved = true;
|
|
1522
1067
|
} catch (error) {
|
|
1523
|
-
if (
|
|
1068
|
+
if (errorCode(error) !== "ENOENT") throw error;
|
|
1524
1069
|
}
|
|
1525
1070
|
const restore = moved && await isCacheDirComplete(aside);
|
|
1526
1071
|
const winner = restore ? aside : tmp;
|
|
@@ -1698,7 +1243,7 @@ function backoffForAttempt(index) {
|
|
|
1698
1243
|
const spread = base * JITTER;
|
|
1699
1244
|
return base + (Math.random() * 2 - 1) * spread;
|
|
1700
1245
|
}
|
|
1701
|
-
function
|
|
1246
|
+
function delay(ms) {
|
|
1702
1247
|
return new Promise((resolve5) => {
|
|
1703
1248
|
setTimeout(resolve5, ms);
|
|
1704
1249
|
});
|
|
@@ -1740,7 +1285,7 @@ async function withPacoteRetry(fn, label, options = {}) {
|
|
|
1740
1285
|
maxTotalMs - (Date.now() - start)
|
|
1741
1286
|
);
|
|
1742
1287
|
if (sleepMs <= 0) break;
|
|
1743
|
-
await
|
|
1288
|
+
await delay(sleepMs);
|
|
1744
1289
|
}
|
|
1745
1290
|
throw new Error(
|
|
1746
1291
|
`Failed ${label} after ${made} attempts: ${describeError(lastError)}`
|
|
@@ -2567,21 +2112,21 @@ async function ensureCodeOnDisk(codeContent, compiledCode, tmpDir, inputs) {
|
|
|
2567
2112
|
}
|
|
2568
2113
|
|
|
2569
2114
|
// src/version.ts
|
|
2570
|
-
import { readFileSync
|
|
2115
|
+
import { readFileSync } from "fs";
|
|
2571
2116
|
import { fileURLToPath } from "url";
|
|
2572
|
-
import { dirname as dirname3, join as
|
|
2117
|
+
import { dirname as dirname3, join as join3 } from "path";
|
|
2573
2118
|
var versionFilename = fileURLToPath(import.meta.url);
|
|
2574
2119
|
var versionDirname = dirname3(versionFilename);
|
|
2575
2120
|
function findPackageJson() {
|
|
2576
2121
|
const paths = [
|
|
2577
|
-
|
|
2122
|
+
join3(versionDirname, "../package.json"),
|
|
2578
2123
|
// dist/ or src/
|
|
2579
|
-
|
|
2124
|
+
join3(versionDirname, "../../package.json")
|
|
2580
2125
|
// src/core/ (not used, but safe)
|
|
2581
2126
|
];
|
|
2582
2127
|
for (const p of paths) {
|
|
2583
2128
|
try {
|
|
2584
|
-
return
|
|
2129
|
+
return readFileSync(p, "utf-8");
|
|
2585
2130
|
} catch {
|
|
2586
2131
|
}
|
|
2587
2132
|
}
|
|
@@ -2597,9 +2142,11 @@ function hasCodeReference(code) {
|
|
|
2597
2142
|
return isInlineCode(code) || typeof code === "string";
|
|
2598
2143
|
}
|
|
2599
2144
|
function generateInlineCode(inline, runtimeProps, isDestination) {
|
|
2600
|
-
const pushFn = inline.push.replace("$code:", "");
|
|
2601
|
-
const initFn = inline.init ? inline.init.replace("$code:", "") : void 0;
|
|
2602
2145
|
const typeLine = inline.type ? `type: '${inline.type}',` : "";
|
|
2146
|
+
const functionLines = STEP_FUNCTION_KEYS.flatMap((key) => {
|
|
2147
|
+
const fn = inline[key];
|
|
2148
|
+
return fn ? [`${key}: ${fn.replace("$code:", "")}`] : [];
|
|
2149
|
+
}).join(",\n ");
|
|
2603
2150
|
const props = {
|
|
2604
2151
|
config: {},
|
|
2605
2152
|
env: {},
|
|
@@ -2611,8 +2158,7 @@ function generateInlineCode(inline, runtimeProps, isDestination) {
|
|
|
2611
2158
|
code: {
|
|
2612
2159
|
${typeLine}
|
|
2613
2160
|
config: ${processConfigValue(props.config)},
|
|
2614
|
-
${
|
|
2615
|
-
push: ${pushFn}
|
|
2161
|
+
${functionLines}
|
|
2616
2162
|
},
|
|
2617
2163
|
${propLines}
|
|
2618
2164
|
}`;
|
|
@@ -2621,8 +2167,7 @@ function generateInlineCode(inline, runtimeProps, isDestination) {
|
|
|
2621
2167
|
code: async (context) => ({
|
|
2622
2168
|
${typeLine}
|
|
2623
2169
|
config: context.config,
|
|
2624
|
-
${
|
|
2625
|
-
push: ${pushFn}
|
|
2170
|
+
${functionLines}
|
|
2626
2171
|
}),
|
|
2627
2172
|
${propLines}
|
|
2628
2173
|
}`;
|
|
@@ -2768,6 +2313,7 @@ async function bundleCore(flowSettings, buildOptions, logger, showStats = false,
|
|
|
2768
2313
|
packagePaths
|
|
2769
2314
|
);
|
|
2770
2315
|
const versionsHash = await getHashServer3(sortedVersions.join("\n"), 12);
|
|
2316
|
+
applyCollectorDefaults(flowSettings);
|
|
2771
2317
|
if (provenance) {
|
|
2772
2318
|
applyCollectorProvenance(
|
|
2773
2319
|
flowSettings,
|
|
@@ -2939,7 +2485,7 @@ ${dataDeclaration}${needs}`;
|
|
|
2939
2485
|
};
|
|
2940
2486
|
if (buildOptions.platform === "browser") {
|
|
2941
2487
|
stage2Options.format = "iife";
|
|
2942
|
-
stage2Options.plugins = [
|
|
2488
|
+
stage2Options.plugins = [cliPackagesPlugin()];
|
|
2943
2489
|
stage2Options.define = {
|
|
2944
2490
|
"process.env.NODE_ENV": '"production"',
|
|
2945
2491
|
global: "globalThis",
|
|
@@ -3107,22 +2653,25 @@ function getNodeExternals() {
|
|
|
3107
2653
|
}
|
|
3108
2654
|
return externals;
|
|
3109
2655
|
}
|
|
3110
|
-
var
|
|
3111
|
-
function
|
|
2656
|
+
var CLI_PACKAGES = "walkeros-cli-packages";
|
|
2657
|
+
function cliPackagesPlugin() {
|
|
3112
2658
|
const resolveDir = path14.dirname(fileURLToPath2(import.meta.url));
|
|
3113
2659
|
return {
|
|
3114
|
-
name:
|
|
2660
|
+
name: CLI_PACKAGES,
|
|
3115
2661
|
setup(build2) {
|
|
3116
|
-
build2.onResolve(
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
2662
|
+
build2.onResolve(
|
|
2663
|
+
{ filter: /^@walkeros\/(core|web-core)$/ },
|
|
2664
|
+
async (args) => {
|
|
2665
|
+
if (args.pluginData === CLI_PACKAGES) return void 0;
|
|
2666
|
+
const resolved = await build2.resolve(args.path, {
|
|
2667
|
+
kind: args.kind,
|
|
2668
|
+
resolveDir,
|
|
2669
|
+
pluginData: CLI_PACKAGES
|
|
2670
|
+
});
|
|
2671
|
+
if (resolved.errors.length > 0) return { errors: resolved.errors };
|
|
2672
|
+
return { path: resolved.path, sideEffects: resolved.sideEffects };
|
|
2673
|
+
}
|
|
2674
|
+
);
|
|
3126
2675
|
}
|
|
3127
2676
|
};
|
|
3128
2677
|
}
|
|
@@ -3439,6 +2988,12 @@ ${firstError.text}`
|
|
|
3439
2988
|
function buildDataPayload(flowSettings) {
|
|
3440
2989
|
return buildSplitConfigObject(flowSettings, detectNamedImports(flowSettings)).dataPayloadObj;
|
|
3441
2990
|
}
|
|
2991
|
+
function applyCollectorDefaults(flowSettings) {
|
|
2992
|
+
if (getPlatform2(flowSettings) !== "server") return;
|
|
2993
|
+
const collector = flowSettings.collector ?? {};
|
|
2994
|
+
collector.consentDenied ??= "skip";
|
|
2995
|
+
flowSettings.collector = collector;
|
|
2996
|
+
}
|
|
3442
2997
|
function applyCollectorProvenance(flowSettings, flowName, release2, fallback) {
|
|
3443
2998
|
const collector = flowSettings.collector ?? {};
|
|
3444
2999
|
collector.name ??= flowName;
|
|
@@ -3557,6 +3112,34 @@ export function wireConfig(__data) {
|
|
|
3557
3112
|
|
|
3558
3113
|
export { startFlow };`;
|
|
3559
3114
|
}
|
|
3115
|
+
var HOST_LOGGER_MERGE = ` // The host's logger (masking, its error ring) joins the flow's own: the
|
|
3116
|
+
// flow's level and format win, unless the host forces a level (--verbose);
|
|
3117
|
+
// the flow's handler runs first, then the host's, once per line, always.
|
|
3118
|
+
// The flow handler's originalHandler does nothing, so no line prints a
|
|
3119
|
+
// second time unmasked. The host learns the flow's settings before the
|
|
3120
|
+
// collector starts, so every line, the first included, has its format.
|
|
3121
|
+
if (context.logger) {
|
|
3122
|
+
const own = config.logger || {};
|
|
3123
|
+
const host = context.logger;
|
|
3124
|
+
if (context.onLogger) context.onLogger({ level: own.level, format: own.format });
|
|
3125
|
+
const level = context.logLevel ?? own.level ?? host.level;
|
|
3126
|
+
const printedByHost = () => {};
|
|
3127
|
+
const handler = own.handler && host.handler
|
|
3128
|
+
? (lvl, message, ctx, scope) => {
|
|
3129
|
+
try {
|
|
3130
|
+
own.handler(lvl, message, ctx, scope, printedByHost);
|
|
3131
|
+
} finally {
|
|
3132
|
+
host.handler(lvl, message, ctx, scope, printedByHost);
|
|
3133
|
+
}
|
|
3134
|
+
}
|
|
3135
|
+
: host.handler || own.handler;
|
|
3136
|
+
config.logger = {
|
|
3137
|
+
...host,
|
|
3138
|
+
...(level !== undefined ? { level } : {}),
|
|
3139
|
+
...(own.format ? { format: own.format } : {}),
|
|
3140
|
+
...(handler ? { handler } : {}),
|
|
3141
|
+
};
|
|
3142
|
+
}`;
|
|
3560
3143
|
function generateServerEntry(stage1Path, dataPayload) {
|
|
3561
3144
|
const stage1Specifier = toFileImportSpecifier(stage1Path);
|
|
3562
3145
|
return `import { startFlow, wireConfig } from '${stage1Specifier}';
|
|
@@ -3566,7 +3149,7 @@ const __configData = ${dataPayload};
|
|
|
3566
3149
|
export default async function(context = {}) {
|
|
3567
3150
|
const config = wireConfig(__configData);
|
|
3568
3151
|
|
|
3569
|
-
|
|
3152
|
+
${HOST_LOGGER_MERGE}
|
|
3570
3153
|
|
|
3571
3154
|
if (context.sourceSettings && config.sources) {
|
|
3572
3155
|
for (const src of Object.values(config.sources)) {
|
|
@@ -3626,6 +3209,7 @@ function readObserveConnect(flowSettings, logger) {
|
|
|
3626
3209
|
);
|
|
3627
3210
|
return void 0;
|
|
3628
3211
|
}
|
|
3212
|
+
var OBSERVE_SLOT_IMPORT = "import { pageObserveSlot } from '@walkeros/web-core';\n";
|
|
3629
3213
|
function emitObserveAssignment(observe) {
|
|
3630
3214
|
const literal = {
|
|
3631
3215
|
url: observe.url,
|
|
@@ -3635,9 +3219,9 @@ function emitObserveAssignment(observe) {
|
|
|
3635
3219
|
...observe.sample !== void 0 ? { sample: observe.sample } : {}
|
|
3636
3220
|
};
|
|
3637
3221
|
return `
|
|
3638
|
-
config.observe =
|
|
3222
|
+
config.observe = { ...${JSON.stringify(literal)}, slot: pageObserveSlot() };`;
|
|
3639
3223
|
}
|
|
3640
|
-
var MOIN_IMPORT = "import { moin } from '@walkeros/core';\n";
|
|
3224
|
+
var MOIN_IMPORT = "import { moin } from '@walkeros/web-core';\n";
|
|
3641
3225
|
function emitMoinCall(target) {
|
|
3642
3226
|
if (!target)
|
|
3643
3227
|
return `
|
|
@@ -3685,10 +3269,11 @@ function generateWebEntry(stage1Path, dataPayload, options = {}) {
|
|
|
3685
3269
|
}
|
|
3686
3270
|
}` : "";
|
|
3687
3271
|
const stage1Specifier = toFileImportSpecifier(stage1Path);
|
|
3272
|
+
const observeImport = options.observe ? OBSERVE_SLOT_IMPORT : "";
|
|
3688
3273
|
const observeBlock = options.observe ? emitObserveAssignment(options.observe) : "";
|
|
3689
3274
|
const loaderImport = platform === "browser" ? MOIN_IMPORT : "";
|
|
3690
3275
|
const loaderCall = platform === "browser" ? emitMoinCall() : "";
|
|
3691
|
-
return `${loaderImport}import { startFlow, wireConfig } from '${stage1Specifier}';
|
|
3276
|
+
return `${loaderImport}${observeImport}import { startFlow, wireConfig } from '${stage1Specifier}';
|
|
3692
3277
|
|
|
3693
3278
|
const __configData = ${dataPayload};
|
|
3694
3279
|
|
|
@@ -3712,7 +3297,7 @@ function generateWrapEntry(stage1Path, options = {}) {
|
|
|
3712
3297
|
}
|
|
3713
3298
|
const preview = options.preview;
|
|
3714
3299
|
const previewEnabled = !!preview?.enabled;
|
|
3715
|
-
const previewImport = previewEnabled ? `import { browserSwapActivator } from '@walkeros/core';
|
|
3300
|
+
const previewImport = previewEnabled ? `import { browserSwapActivator } from '@walkeros/web-core';
|
|
3716
3301
|
` : "";
|
|
3717
3302
|
const grantTargets = options.previewGrantTargets ?? [];
|
|
3718
3303
|
const previewGrantBlock = grantTargets.length > 0 ? `
|
|
@@ -3762,10 +3347,11 @@ ${grantTargets.map((key) => {
|
|
|
3762
3347
|
}
|
|
3763
3348
|
}` : "";
|
|
3764
3349
|
const stage1Specifier = toFileImportSpecifier(stage1Path);
|
|
3350
|
+
const observeImport = options.observe ? OBSERVE_SLOT_IMPORT : "";
|
|
3765
3351
|
const observeBlock = options.observe ? emitObserveAssignment(options.observe) : "";
|
|
3766
3352
|
const loaderImport = platform === "browser" ? MOIN_IMPORT : "";
|
|
3767
3353
|
const loaderCall = platform === "browser" ? emitMoinCall(options.moin) : "";
|
|
3768
|
-
return `${loaderImport}${previewImport}import { startFlow, wireConfig, __configData } from '${stage1Specifier}';
|
|
3354
|
+
return `${loaderImport}${previewImport}${observeImport}import { startFlow, wireConfig, __configData } from '${stage1Specifier}';
|
|
3769
3355
|
|
|
3770
3356
|
(async () => {${loaderCall}${previewBlock}
|
|
3771
3357
|
const config = wireConfig(__configData);${envBlock}${previewGrantBlock}${observeBlock}
|
|
@@ -3782,7 +3368,7 @@ function generateWrapEntryServer(stage1Path) {
|
|
|
3782
3368
|
export default async function(context = {}) {
|
|
3783
3369
|
const config = wireConfig(__configData);
|
|
3784
3370
|
|
|
3785
|
-
|
|
3371
|
+
${HOST_LOGGER_MERGE}
|
|
3786
3372
|
|
|
3787
3373
|
if (context.sourceSettings && config.sources) {
|
|
3788
3374
|
for (const src of Object.values(config.sources)) {
|
|
@@ -4268,7 +3854,7 @@ async function bundle(configOrPath, options = {}) {
|
|
|
4268
3854
|
// src/commands/push/index.ts
|
|
4269
3855
|
import path18 from "path";
|
|
4270
3856
|
import fs18 from "fs-extra";
|
|
4271
|
-
import { createIngest, getPlatform as
|
|
3857
|
+
import { createIngest, getPlatform as getPlatform4, stepId } from "@walkeros/core";
|
|
4272
3858
|
import {
|
|
4273
3859
|
enrichEvent,
|
|
4274
3860
|
transformerInit,
|
|
@@ -4497,13 +4083,13 @@ function installTimerInterception(options = {}) {
|
|
|
4497
4083
|
setInterval: Reflect.get(target, "setInterval"),
|
|
4498
4084
|
clearInterval: Reflect.get(target, "clearInterval")
|
|
4499
4085
|
});
|
|
4500
|
-
const trackedSetTimeout = (callback,
|
|
4086
|
+
const trackedSetTimeout = (callback, delay2, ...args) => {
|
|
4501
4087
|
if (typeof callback !== "function") return 0;
|
|
4502
4088
|
const id = nextId++;
|
|
4503
4089
|
pending.set(id, {
|
|
4504
4090
|
id,
|
|
4505
4091
|
callback,
|
|
4506
|
-
delay:
|
|
4092
|
+
delay: delay2 ?? 0,
|
|
4507
4093
|
type: "timeout",
|
|
4508
4094
|
args,
|
|
4509
4095
|
cleared: false
|
|
@@ -4516,13 +4102,13 @@ function installTimerInterception(options = {}) {
|
|
|
4516
4102
|
const entry = pending.get(numId);
|
|
4517
4103
|
if (entry) entry.cleared = true;
|
|
4518
4104
|
};
|
|
4519
|
-
const trackedSetInterval = (callback,
|
|
4105
|
+
const trackedSetInterval = (callback, delay2, ...args) => {
|
|
4520
4106
|
if (typeof callback !== "function") return 0;
|
|
4521
4107
|
const id = nextId++;
|
|
4522
4108
|
pending.set(id, {
|
|
4523
4109
|
id,
|
|
4524
4110
|
callback,
|
|
4525
|
-
delay:
|
|
4111
|
+
delay: delay2 ?? 0,
|
|
4526
4112
|
type: "interval",
|
|
4527
4113
|
args,
|
|
4528
4114
|
cleared: false
|
|
@@ -4962,7 +4548,7 @@ function buildSimulationResult(args) {
|
|
|
4962
4548
|
// src/commands/push/prepare.ts
|
|
4963
4549
|
import path17 from "path";
|
|
4964
4550
|
import fs17 from "fs-extra";
|
|
4965
|
-
import { getPlatform as
|
|
4551
|
+
import { getPlatform as getPlatform3 } from "@walkeros/core";
|
|
4966
4552
|
|
|
4967
4553
|
// src/core/known-secrets.ts
|
|
4968
4554
|
import { REF_SECRET } from "@walkeros/core";
|
|
@@ -5004,7 +4590,7 @@ async function prepareFlow(input) {
|
|
|
5004
4590
|
configPath: process.cwd(),
|
|
5005
4591
|
flowName: input.flow
|
|
5006
4592
|
});
|
|
5007
|
-
const platform =
|
|
4593
|
+
const platform = getPlatform3(flowSettings);
|
|
5008
4594
|
const overrides = buildOverrides(
|
|
5009
4595
|
{ simulate: input.simulate, mock: input.mock },
|
|
5010
4596
|
flowSettings
|
|
@@ -5580,7 +5166,7 @@ async function executeConfigPush(options, validatedEvent, logger, setTempDir, lo
|
|
|
5580
5166
|
logger,
|
|
5581
5167
|
raw: loaded.raw
|
|
5582
5168
|
});
|
|
5583
|
-
const platform =
|
|
5169
|
+
const platform = getPlatform4(flowSettings);
|
|
5584
5170
|
const overrides = buildOverrides({ mock: options.mock }, flowSettings);
|
|
5585
5171
|
logger.debug("Bundling flow configuration");
|
|
5586
5172
|
const tempDir = await tmpRunDir("push");
|
|
@@ -6451,16 +6037,9 @@ import chalk2 from "chalk";
|
|
|
6451
6037
|
import { isObject as isObject10 } from "@walkeros/core";
|
|
6452
6038
|
|
|
6453
6039
|
// src/commands/validate/validators/contract.ts
|
|
6454
|
-
import { isObject as isObject5 } from "@walkeros/core";
|
|
6040
|
+
import { CONTRACT_RULE_KEYS, isObject as isObject5 } from "@walkeros/core";
|
|
6041
|
+
var KNOWN_KEYS = new Set(CONTRACT_RULE_KEYS);
|
|
6455
6042
|
var SECTION_KEYS = ["globals", "context", "custom", "user", "consent"];
|
|
6456
|
-
var KNOWN_KEYS = /* @__PURE__ */ new Set([
|
|
6457
|
-
"extend",
|
|
6458
|
-
"tagging",
|
|
6459
|
-
"description",
|
|
6460
|
-
"events",
|
|
6461
|
-
"schema",
|
|
6462
|
-
...SECTION_KEYS
|
|
6463
|
-
]);
|
|
6464
6043
|
function validateContract(input) {
|
|
6465
6044
|
const errors = [];
|
|
6466
6045
|
const warnings = [];
|
|
@@ -6501,7 +6080,9 @@ function validateContract(input) {
|
|
|
6501
6080
|
const keys = Object.keys(obj);
|
|
6502
6081
|
const unknownKeys = keys.filter((k) => !KNOWN_KEYS.has(k));
|
|
6503
6082
|
const hasKnownKey = keys.some((k) => KNOWN_KEYS.has(k));
|
|
6504
|
-
const objectValuedUnknown = unknownKeys.filter(
|
|
6083
|
+
const objectValuedUnknown = unknownKeys.filter(
|
|
6084
|
+
(k) => isObject5(obj[k]) && !SECTION_KEYS.includes(k)
|
|
6085
|
+
);
|
|
6505
6086
|
if (!hasKnownKey && objectValuedUnknown.length > 0) {
|
|
6506
6087
|
errors.push({
|
|
6507
6088
|
path: name,
|
|
@@ -6511,9 +6092,9 @@ function validateContract(input) {
|
|
|
6511
6092
|
continue;
|
|
6512
6093
|
}
|
|
6513
6094
|
for (const key of unknownKeys) {
|
|
6514
|
-
|
|
6095
|
+
errors.push({
|
|
6515
6096
|
path: `${name}.${key}`,
|
|
6516
|
-
message: `Unknown contract key "${key}" is
|
|
6097
|
+
message: SECTION_KEYS.includes(key) ? `Contract section "${key}" is not enforced: the validate transformer reads only "events" and "schema". Put the rule into "schema" (a JSON Schema for the whole event), for example "schema": { "properties": { "${key}": { ... } } }.` : `Unknown contract key "${key}" is not supported. Known keys: ${[...KNOWN_KEYS].join(", ")}.`,
|
|
6517
6098
|
code: "UNKNOWN_CONTRACT_KEY"
|
|
6518
6099
|
});
|
|
6519
6100
|
}
|
|
@@ -6547,18 +6128,6 @@ function validateContract(input) {
|
|
|
6547
6128
|
});
|
|
6548
6129
|
}
|
|
6549
6130
|
}
|
|
6550
|
-
for (const key of SECTION_KEYS) {
|
|
6551
|
-
if (key in obj) {
|
|
6552
|
-
if (typeof obj[key] !== "object" || obj[key] === null) {
|
|
6553
|
-
errors.push({
|
|
6554
|
-
path: `${name}.${key}`,
|
|
6555
|
-
message: `Section "${key}" must be a JSON Schema object`,
|
|
6556
|
-
value: obj[key],
|
|
6557
|
-
code: "INVALID_SECTION"
|
|
6558
|
-
});
|
|
6559
|
-
}
|
|
6560
|
-
}
|
|
6561
|
-
}
|
|
6562
6131
|
if (obj.events !== void 0) {
|
|
6563
6132
|
if (typeof obj.events !== "object" || obj.events === null) {
|
|
6564
6133
|
errors.push({
|
|
@@ -6670,9 +6239,14 @@ import {
|
|
|
6670
6239
|
isObject as isObject8,
|
|
6671
6240
|
REF_CONTRACT,
|
|
6672
6241
|
resolveContracts,
|
|
6242
|
+
SECRET_MARKER_PREFIX as SECRET_MARKER_PREFIX4,
|
|
6673
6243
|
validateStepEntry
|
|
6674
6244
|
} from "@walkeros/core";
|
|
6675
|
-
import {
|
|
6245
|
+
import {
|
|
6246
|
+
checkStepKeys,
|
|
6247
|
+
schemas as schemas4,
|
|
6248
|
+
validateFlowStructure as validateFlowStructure2
|
|
6249
|
+
} from "@walkeros/core/dev";
|
|
6676
6250
|
import {
|
|
6677
6251
|
validateEventAgainstContract
|
|
6678
6252
|
} from "@walkeros/transformer-validate";
|
|
@@ -6873,7 +6447,7 @@ import {
|
|
|
6873
6447
|
REF_STORE,
|
|
6874
6448
|
SECRET_MARKER_PREFIX as SECRET_MARKER_PREFIX3
|
|
6875
6449
|
} from "@walkeros/core";
|
|
6876
|
-
var CLIENT_HEADER = "walkeros-cli/4.8.
|
|
6450
|
+
var CLIENT_HEADER = "walkeros-cli/4.8.2";
|
|
6877
6451
|
function createSettingsContext(configDir) {
|
|
6878
6452
|
return { configDir, cache: /* @__PURE__ */ new Map(), compiled: /* @__PURE__ */ new Map() };
|
|
6879
6453
|
}
|
|
@@ -6991,7 +6565,7 @@ function packageSource(spec, rawFlow) {
|
|
|
6991
6565
|
const pinned = pin.version ?? version;
|
|
6992
6566
|
return pinned ? { name, version: pinned } : { name };
|
|
6993
6567
|
}
|
|
6994
|
-
function
|
|
6568
|
+
function readJson(file) {
|
|
6995
6569
|
return JSON.parse(fs19.readFileSync(file, "utf-8"));
|
|
6996
6570
|
}
|
|
6997
6571
|
function readLocalSchema(source, configDir) {
|
|
@@ -7002,9 +6576,9 @@ function readLocalSchema(source, configDir) {
|
|
|
7002
6576
|
path19.join(root, "walkerOS.json")
|
|
7003
6577
|
].find((candidate) => fs19.existsSync(candidate));
|
|
7004
6578
|
if (!file) throw new Error(`no walkerOS.json under ${root}`);
|
|
7005
|
-
const meta =
|
|
6579
|
+
const meta = readJson(file);
|
|
7006
6580
|
const pkgFile = path19.join(root, "package.json");
|
|
7007
|
-
const pkg = fs19.existsSync(pkgFile) ?
|
|
6581
|
+
const pkg = fs19.existsSync(pkgFile) ? readJson(pkgFile) : void 0;
|
|
7008
6582
|
const schemas6 = isObject7(meta) ? meta.schemas : void 0;
|
|
7009
6583
|
const exportSchemas = isObject7(meta) ? meta.exportSchemas : void 0;
|
|
7010
6584
|
const declared = isObject7(meta) && isObject7(meta.$meta) ? meta.$meta.exports : void 0;
|
|
@@ -7188,7 +6762,9 @@ var { validateFlowConfig: validateFlowConfig2 } = schemas4;
|
|
|
7188
6762
|
var DEPRECATED_PACKAGES = {
|
|
7189
6763
|
"@walkeros/store-memory": "has been removed. Use the built-in cache by omitting cache.store, or remove the store declaration if it was only used as a cache target."
|
|
7190
6764
|
};
|
|
7191
|
-
var
|
|
6765
|
+
var STEP_KINDS2 = [
|
|
6766
|
+
["sources", "Source"],
|
|
6767
|
+
["transformers", "Transformer"],
|
|
7192
6768
|
["destinations", "Destination"],
|
|
7193
6769
|
["stores", "Store"]
|
|
7194
6770
|
];
|
|
@@ -7237,7 +6813,11 @@ async function validateFlowWithPackages(input, options = {}) {
|
|
|
7237
6813
|
}
|
|
7238
6814
|
}
|
|
7239
6815
|
for (const outcome of await Promise.all(pending)) {
|
|
7240
|
-
|
|
6816
|
+
for (const finding of outcome.findings) {
|
|
6817
|
+
if (finding.keyword === "additionalProperties")
|
|
6818
|
+
result.errors.push(finding);
|
|
6819
|
+
else result.warnings.push(finding);
|
|
6820
|
+
}
|
|
7241
6821
|
run.skipped.push(...outcome.skipped);
|
|
7242
6822
|
deferred.push(...outcome.deferred);
|
|
7243
6823
|
if (outcome.checked) packages.push(outcome.checked);
|
|
@@ -7245,6 +6825,7 @@ async function validateFlowWithPackages(input, options = {}) {
|
|
|
7245
6825
|
result.details.scope = describeScope(scope, run.checks);
|
|
7246
6826
|
result.details.deferred = [...result.details.deferred ?? [], ...deferred];
|
|
7247
6827
|
if (packages.length > 0) result.details.packages = packages;
|
|
6828
|
+
result.valid = result.errors.length === 0;
|
|
7248
6829
|
return result;
|
|
7249
6830
|
}
|
|
7250
6831
|
function runFlowChecks(input, options) {
|
|
@@ -7303,8 +6884,13 @@ function runFlowChecks(input, options) {
|
|
|
7303
6884
|
for (const issue of coreResult.errors) {
|
|
7304
6885
|
const path23 = issue.path || "root";
|
|
7305
6886
|
if (!inScope(path23)) continue;
|
|
7306
|
-
if (path23 === "contract" && contractErrors > 0)
|
|
7307
|
-
|
|
6887
|
+
if ((path23 === "contract" || path23.startsWith("contract.")) && contractErrors > 0)
|
|
6888
|
+
continue;
|
|
6889
|
+
errors.push({
|
|
6890
|
+
path: path23,
|
|
6891
|
+
message: issue.message,
|
|
6892
|
+
code: issue.code ?? "SCHEMA_VALIDATION"
|
|
6893
|
+
});
|
|
7308
6894
|
}
|
|
7309
6895
|
for (const issue of coreResult.warnings) {
|
|
7310
6896
|
const path23 = issue.path || "root";
|
|
@@ -7338,20 +6924,13 @@ function runFlowChecks(input, options) {
|
|
|
7338
6924
|
}
|
|
7339
6925
|
}
|
|
7340
6926
|
}
|
|
7341
|
-
for (const [section, kind] of
|
|
6927
|
+
for (const [section, kind] of STEP_KINDS2) {
|
|
7342
6928
|
const steps = flowValue[section];
|
|
7343
6929
|
if (!isObject8(steps)) continue;
|
|
7344
6930
|
for (const [name, step] of Object.entries(steps)) {
|
|
7345
6931
|
if (!isObject8(step)) continue;
|
|
7346
6932
|
const at = `flows.${flowName}.${section}.${name}`;
|
|
7347
|
-
|
|
7348
|
-
warnings.push({
|
|
7349
|
-
path: `${at}.${key}`,
|
|
7350
|
-
message: `Unknown key "${key}" on ${kind} is ignored by the runtime`,
|
|
7351
|
-
suggestion: "Remove the key, or move it to where it belongs.",
|
|
7352
|
-
code: "UNKNOWN_KEY"
|
|
7353
|
-
});
|
|
7354
|
-
}
|
|
6933
|
+
errors.push(...checkStepKeys(step, kind, at));
|
|
7355
6934
|
const pkg = step.package;
|
|
7356
6935
|
if (typeof pkg === "string" && pkg in DEPRECATED_PACKAGES) {
|
|
7357
6936
|
warnings.push({
|
|
@@ -7362,6 +6941,7 @@ function runFlowChecks(input, options) {
|
|
|
7362
6941
|
}
|
|
7363
6942
|
}
|
|
7364
6943
|
}
|
|
6944
|
+
checkWebLoggerFormat(flowName, flowValue, errors);
|
|
7365
6945
|
}
|
|
7366
6946
|
if (flows) {
|
|
7367
6947
|
details.flowNames = allFlows;
|
|
@@ -7425,7 +7005,7 @@ function runFlowChecks(input, options) {
|
|
|
7425
7005
|
}
|
|
7426
7006
|
};
|
|
7427
7007
|
perFlow(["flow:structure"], (name, flow, file) => {
|
|
7428
|
-
const structure =
|
|
7008
|
+
const structure = validateFlowStructure2({
|
|
7429
7009
|
...file,
|
|
7430
7010
|
flows: { [name]: flow }
|
|
7431
7011
|
});
|
|
@@ -7533,16 +7113,31 @@ function checkResolvedWindowCollector(name, raw, flow, errors, deferred) {
|
|
|
7533
7113
|
code: "SCHEMA_VALIDATION"
|
|
7534
7114
|
});
|
|
7535
7115
|
}
|
|
7536
|
-
function
|
|
7537
|
-
|
|
7538
|
-
const
|
|
7539
|
-
|
|
7540
|
-
|
|
7541
|
-
|
|
7542
|
-
|
|
7543
|
-
|
|
7116
|
+
function checkWebLoggerFormat(flowName, flow, errors) {
|
|
7117
|
+
if (!isObject8(flow.config) || flow.config.platform !== "web") return;
|
|
7118
|
+
const at = `flows.${flowName}`;
|
|
7119
|
+
const loggers = [];
|
|
7120
|
+
if (isObject8(flow.collector))
|
|
7121
|
+
loggers.push([`${at}.collector.logger`, flow.collector.logger]);
|
|
7122
|
+
for (const [section] of STEP_KINDS2) {
|
|
7123
|
+
const steps = flow[section];
|
|
7124
|
+
if (!isObject8(steps)) continue;
|
|
7125
|
+
for (const [name, step] of Object.entries(steps)) {
|
|
7126
|
+
if (isObject8(step) && isObject8(step.config))
|
|
7127
|
+
loggers.push([
|
|
7128
|
+
`${at}.${section}.${name}.config.logger`,
|
|
7129
|
+
step.config.logger
|
|
7130
|
+
]);
|
|
7131
|
+
}
|
|
7132
|
+
}
|
|
7133
|
+
for (const [path23, logger] of loggers) {
|
|
7134
|
+
if (!isObject8(logger) || logger.format === void 0) continue;
|
|
7135
|
+
errors.push({
|
|
7136
|
+
path: `${path23}.format`,
|
|
7137
|
+
message: "logger.format applies to server flows only: a web flow logs to the browser console, which has no output format. Remove it.",
|
|
7138
|
+
code: "WEB_LOGGER_FORMAT"
|
|
7139
|
+
});
|
|
7544
7140
|
}
|
|
7545
|
-
return unknown;
|
|
7546
7141
|
}
|
|
7547
7142
|
function routeTargets(spec) {
|
|
7548
7143
|
if (spec === void 0) return [];
|
|
@@ -7770,6 +7365,12 @@ function lintRoute(spec, position, known, errors, warnings) {
|
|
|
7770
7365
|
}
|
|
7771
7366
|
}
|
|
7772
7367
|
}
|
|
7368
|
+
function hasRuntimeValue(value) {
|
|
7369
|
+
if (typeof value === "string")
|
|
7370
|
+
return value.includes(ENV_MARKER_PREFIX3) || value.startsWith(SECRET_MARKER_PREFIX4) || /\$(?:env|secret)\./.test(value);
|
|
7371
|
+
if (Array.isArray(value)) return value.some(hasRuntimeValue);
|
|
7372
|
+
return isObject8(value) && Object.values(value).some(hasRuntimeValue);
|
|
7373
|
+
}
|
|
7773
7374
|
var VALIDATE_PACKAGE = "@walkeros/transformer-validate";
|
|
7774
7375
|
function isValidateStep(step) {
|
|
7775
7376
|
return step.package === VALIDATE_PACKAGE;
|
|
@@ -7840,6 +7441,15 @@ function checkValidateStepExamples(stepPath, step, contract, errors, warnings, s
|
|
|
7840
7441
|
}
|
|
7841
7442
|
if (!step.examples) return;
|
|
7842
7443
|
const contracts = resolution.sources;
|
|
7444
|
+
if (contracts.some(hasRuntimeValue)) {
|
|
7445
|
+
skipped?.push({
|
|
7446
|
+
path: stepPath,
|
|
7447
|
+
check: "flow:contract-examples",
|
|
7448
|
+
reason: "the contract uses a $env or $secret value, known only when the bundle builds or runs, so the examples cannot be judged statically",
|
|
7449
|
+
code: "CONTRACT_NOT_STATIC"
|
|
7450
|
+
});
|
|
7451
|
+
return;
|
|
7452
|
+
}
|
|
7843
7453
|
const mode = settings.mode === "strict" ? "strict" : "pass";
|
|
7844
7454
|
const format = settings.format === true;
|
|
7845
7455
|
const output = isObject8(settings.output) ? settings.output : {};
|
|
@@ -8046,6 +7656,7 @@ var VALIDATE_CODES = [
|
|
|
8046
7656
|
"CONTRACT_VIOLATION",
|
|
8047
7657
|
"MAPPING_DOT_KEY",
|
|
8048
7658
|
"FLOW_REF_WARNING",
|
|
7659
|
+
"WEB_LOGGER_FORMAT",
|
|
8049
7660
|
"FLOW_CYCLE",
|
|
8050
7661
|
"VAR_CYCLE",
|
|
8051
7662
|
// Structure (the bundler's own preflight, validateFlowStructure)
|
|
@@ -8054,7 +7665,11 @@ var VALIDATE_CODES = [
|
|
|
8054
7665
|
"STORE_REFERENCE_NOT_FOUND",
|
|
8055
7666
|
"STATE_STORE_UNKNOWN",
|
|
8056
7667
|
"STATE_STORE_FILE",
|
|
8057
|
-
"
|
|
7668
|
+
"MAPPING_NO_OP",
|
|
7669
|
+
"MAPPING_VALUE_NO_OPERATOR",
|
|
7670
|
+
"MAPPING_VALUE_PRODUCERS",
|
|
7671
|
+
"BATCH_WITHOUT_PUSH_BATCH",
|
|
7672
|
+
"MALFORMED_REFERENCE",
|
|
8058
7673
|
// Resolution (getFlowSettings, as the bundler resolves the flow)
|
|
8059
7674
|
"UNRESOLVED_REFERENCE",
|
|
8060
7675
|
"MISSING_ENV",
|
|
@@ -8071,7 +7686,6 @@ var VALIDATE_CODES = [
|
|
|
8071
7686
|
"INVALID_TAGGING",
|
|
8072
7687
|
"INVALID_SCHEMA",
|
|
8073
7688
|
"INVALID_EXTENDS",
|
|
8074
|
-
"INVALID_SECTION",
|
|
8075
7689
|
"INVALID_EVENTS",
|
|
8076
7690
|
"CIRCULAR_EXTENDS",
|
|
8077
7691
|
"INVALID_ENTITY_KEY",
|
|
@@ -8346,191 +7960,8 @@ function exitCodeOf(result, strict) {
|
|
|
8346
7960
|
return result.valid ? 0 : 1;
|
|
8347
7961
|
}
|
|
8348
7962
|
|
|
8349
|
-
// src/commands/login/index.ts
|
|
8350
|
-
import { z as z3 } from "zod";
|
|
8351
|
-
var POLL_TIMEOUT_BUFFER_MS = 5e3;
|
|
8352
|
-
var DEFAULT_POLL_INTERVAL_MS = 5e3;
|
|
8353
|
-
var MIN_SERVER_POLL_INTERVAL_MS = 1e3;
|
|
8354
|
-
var DEFAULT_POLL_TIMEOUT_MS = 9e5;
|
|
8355
|
-
var SLOW_DOWN_STEP_MS = 5e3;
|
|
8356
|
-
var WHOAMI_TIMEOUT_MS = 1e4;
|
|
8357
|
-
var TIMED_OUT = "Authorization timed out. Please try again.";
|
|
8358
|
-
var WhoamiSchema = z3.object({ email: z3.string().min(1) });
|
|
8359
|
-
async function openInBrowser(url) {
|
|
8360
|
-
const { default: open } = await import("open");
|
|
8361
|
-
await open(url);
|
|
8362
|
-
}
|
|
8363
|
-
function delay3(ms) {
|
|
8364
|
-
return new Promise((resolve5) => setTimeout(resolve5, ms));
|
|
8365
|
-
}
|
|
8366
|
-
async function loginCommand(options) {
|
|
8367
|
-
const logger = createCLILogger(options);
|
|
8368
|
-
try {
|
|
8369
|
-
const result = await login({ url: options.url });
|
|
8370
|
-
if (options.json) {
|
|
8371
|
-
logger.json(result);
|
|
8372
|
-
} else if (result.success) {
|
|
8373
|
-
if (result.email) logger.info(`Logged in as ${result.email}`);
|
|
8374
|
-
else logger.info("Logged in.");
|
|
8375
|
-
logger.info(`Session stored in ${result.configPath}`);
|
|
8376
|
-
} else if (result.error) {
|
|
8377
|
-
logger.error(result.error);
|
|
8378
|
-
}
|
|
8379
|
-
process.exit(result.success ? 0 : 1);
|
|
8380
|
-
} catch (error) {
|
|
8381
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
8382
|
-
if (options.json) {
|
|
8383
|
-
logger.json({ success: false, error: message });
|
|
8384
|
-
} else {
|
|
8385
|
-
logger.error(message);
|
|
8386
|
-
}
|
|
8387
|
-
process.exit(1);
|
|
8388
|
-
}
|
|
8389
|
-
}
|
|
8390
|
-
async function fetchEmail(appUrl, accessToken, fetchFn) {
|
|
8391
|
-
try {
|
|
8392
|
-
const response = await appFetch(APP_PATHS.whoami, {
|
|
8393
|
-
baseUrl: appUrl,
|
|
8394
|
-
token: accessToken,
|
|
8395
|
-
fetch: fetchFn,
|
|
8396
|
-
signal: AbortSignal.timeout(WHOAMI_TIMEOUT_MS)
|
|
8397
|
-
});
|
|
8398
|
-
if (!response.ok) return void 0;
|
|
8399
|
-
const parsed = WhoamiSchema.safeParse(await response.json());
|
|
8400
|
-
return parsed.success ? parsed.data.email : void 0;
|
|
8401
|
-
} catch {
|
|
8402
|
-
return void 0;
|
|
8403
|
-
}
|
|
8404
|
-
}
|
|
8405
|
-
async function persistSession(appUrl, tokens, fetchFn) {
|
|
8406
|
-
writeConfig({
|
|
8407
|
-
accessToken: tokens.accessToken,
|
|
8408
|
-
accessTokenExpiresAt: tokens.accessTokenExpiresAt,
|
|
8409
|
-
refreshToken: tokens.refreshToken ?? void 0,
|
|
8410
|
-
appUrl,
|
|
8411
|
-
// Drop the static token this session replaces, so the deprecated path
|
|
8412
|
-
// cannot outlive the login that retired it.
|
|
8413
|
-
token: void 0
|
|
8414
|
-
});
|
|
8415
|
-
const email = await fetchEmail(appUrl, tokens.accessToken, fetchFn);
|
|
8416
|
-
writeConfig({ email });
|
|
8417
|
-
}
|
|
8418
|
-
async function completeDeviceLogin(deviceCode, options = {}) {
|
|
8419
|
-
const fetchFn = options.fetch ?? globalThis.fetch;
|
|
8420
|
-
const appUrl = requireSecureUrl(options.url || resolveAppUrl());
|
|
8421
|
-
const deadline = Date.now() + (options.timeoutMs ?? DEFAULT_POLL_TIMEOUT_MS);
|
|
8422
|
-
let intervalMs = options.intervalMs ?? DEFAULT_POLL_INTERVAL_MS;
|
|
8423
|
-
let attempts = 0;
|
|
8424
|
-
let waiting = "pending";
|
|
8425
|
-
while (Date.now() + intervalMs <= deadline) {
|
|
8426
|
-
if (options.maxPollAttempts !== void 0 && attempts >= options.maxPollAttempts)
|
|
8427
|
-
break;
|
|
8428
|
-
attempts += 1;
|
|
8429
|
-
await delay3(intervalMs);
|
|
8430
|
-
const signal = AbortSignal.timeout(Math.max(1, deadline - Date.now()));
|
|
8431
|
-
const poll = await pollDeviceToken(appUrl, deviceCode, fetchFn, signal);
|
|
8432
|
-
if (poll.status === "pending") {
|
|
8433
|
-
waiting = "pending";
|
|
8434
|
-
if (signal.aborted) break;
|
|
8435
|
-
continue;
|
|
8436
|
-
}
|
|
8437
|
-
if (poll.status === "slow_down") {
|
|
8438
|
-
waiting = "slow_down";
|
|
8439
|
-
intervalMs += SLOW_DOWN_STEP_MS;
|
|
8440
|
-
continue;
|
|
8441
|
-
}
|
|
8442
|
-
if (poll.status !== "ok") return poll;
|
|
8443
|
-
await persistSession(appUrl, poll.tokens, fetchFn);
|
|
8444
|
-
return { status: "ok" };
|
|
8445
|
-
}
|
|
8446
|
-
return { status: waiting };
|
|
8447
|
-
}
|
|
8448
|
-
async function login(options = {}) {
|
|
8449
|
-
const fetchFn = options.fetch ?? globalThis.fetch;
|
|
8450
|
-
const appUrl = requireSecureUrl(options.url || resolveAppUrl());
|
|
8451
|
-
let authorization;
|
|
8452
|
-
try {
|
|
8453
|
-
authorization = await startDeviceAuthorization(appUrl, fetchFn);
|
|
8454
|
-
} catch {
|
|
8455
|
-
return { success: false, error: "Failed to request device code" };
|
|
8456
|
-
}
|
|
8457
|
-
const target = authorization.verificationUriComplete;
|
|
8458
|
-
const prompt = (message) => process.stderr.write(message + "\n");
|
|
8459
|
-
prompt(`
|
|
8460
|
-
! Your one-time code: ${authorization.userCode}`);
|
|
8461
|
-
prompt(` Authorize here: ${target}
|
|
8462
|
-
`);
|
|
8463
|
-
const opener = options.openUrl ?? openInBrowser;
|
|
8464
|
-
try {
|
|
8465
|
-
await opener(target);
|
|
8466
|
-
prompt(" Opening browser...");
|
|
8467
|
-
} catch {
|
|
8468
|
-
prompt(" Could not open browser. Visit the URL manually.");
|
|
8469
|
-
}
|
|
8470
|
-
prompt(" Waiting for authorization... (press Ctrl+C to cancel)\n");
|
|
8471
|
-
const outcome = await completeDeviceLogin(authorization.deviceCode, {
|
|
8472
|
-
url: appUrl,
|
|
8473
|
-
fetch: fetchFn,
|
|
8474
|
-
timeoutMs: authorization.expiresIn * 1e3 + POLL_TIMEOUT_BUFFER_MS,
|
|
8475
|
-
// Clamped here, at the one place a server's number enters the loop. The
|
|
8476
|
-
// helper takes its caller's interval as stated, which is what keeps a
|
|
8477
|
-
// stated 0 from becoming a poll flood without making the helper's own
|
|
8478
|
-
// option untestably slow.
|
|
8479
|
-
intervalMs: options.pollIntervalMs ?? Math.max(MIN_SERVER_POLL_INTERVAL_MS, authorization.interval * 1e3),
|
|
8480
|
-
...options.maxPollAttempts !== void 0 ? { maxPollAttempts: options.maxPollAttempts } : {}
|
|
8481
|
-
});
|
|
8482
|
-
switch (outcome.status) {
|
|
8483
|
-
case "ok": {
|
|
8484
|
-
const email = readConfig()?.email;
|
|
8485
|
-
return {
|
|
8486
|
-
success: true,
|
|
8487
|
-
...email ? { email } : {},
|
|
8488
|
-
configPath: getConfigPath()
|
|
8489
|
-
};
|
|
8490
|
-
}
|
|
8491
|
-
case "denied":
|
|
8492
|
-
return { success: false, error: "Authorization was denied." };
|
|
8493
|
-
case "error":
|
|
8494
|
-
return { success: false, error: outcome.error };
|
|
8495
|
-
default:
|
|
8496
|
-
return { success: false, error: TIMED_OUT };
|
|
8497
|
-
}
|
|
8498
|
-
}
|
|
8499
|
-
|
|
8500
|
-
// src/commands/logout/index.ts
|
|
8501
|
-
async function logoutCommand(options) {
|
|
8502
|
-
const logger = createCLILogger(options);
|
|
8503
|
-
const { deleted, superseded } = await logout();
|
|
8504
|
-
const configPath = getConfigPath();
|
|
8505
|
-
if (options.json) {
|
|
8506
|
-
logger.json({ success: true, deleted, superseded });
|
|
8507
|
-
} else if (superseded) {
|
|
8508
|
-
logger.info(
|
|
8509
|
-
"A newer session was stored while logging out, and was kept. Run `walkeros auth logout` again to remove it."
|
|
8510
|
-
);
|
|
8511
|
-
} else if (deleted) {
|
|
8512
|
-
logger.info(`Logged out. Session removed from ${configPath}`);
|
|
8513
|
-
} else {
|
|
8514
|
-
logger.info("No stored credentials found.");
|
|
8515
|
-
}
|
|
8516
|
-
process.exit(0);
|
|
8517
|
-
}
|
|
8518
|
-
function sameSession(before, after) {
|
|
8519
|
-
return before?.accessToken === after.accessToken && before?.refreshToken === after.refreshToken && before?.token === after.token;
|
|
8520
|
-
}
|
|
8521
|
-
async function logout() {
|
|
8522
|
-
const before = readConfig();
|
|
8523
|
-
if (before?.refreshToken) {
|
|
8524
|
-
await revokeRefreshToken(resolveAppUrl(), before.refreshToken);
|
|
8525
|
-
}
|
|
8526
|
-
const after = readConfig();
|
|
8527
|
-
if (after && !sameSession(before, after))
|
|
8528
|
-
return { deleted: false, superseded: true };
|
|
8529
|
-
return { deleted: deleteConfig(), superseded: false };
|
|
8530
|
-
}
|
|
8531
|
-
|
|
8532
7963
|
// src/commands/auth/index.ts
|
|
8533
|
-
import { z as
|
|
7964
|
+
import { z as z3 } from "zod";
|
|
8534
7965
|
|
|
8535
7966
|
// src/core/api-error.ts
|
|
8536
7967
|
var EXIT_RETRYABLE = 75;
|
|
@@ -8588,31 +8019,166 @@ ${err.message}
|
|
|
8588
8019
|
process.exit(1);
|
|
8589
8020
|
}
|
|
8590
8021
|
|
|
8022
|
+
// src/core/app-fetch.ts
|
|
8023
|
+
import { z } from "zod";
|
|
8024
|
+
|
|
8025
|
+
// src/lib/config-file.ts
|
|
8026
|
+
import {
|
|
8027
|
+
readFileSync as readFileSync3,
|
|
8028
|
+
writeFileSync,
|
|
8029
|
+
mkdirSync,
|
|
8030
|
+
unlinkSync,
|
|
8031
|
+
chmodSync,
|
|
8032
|
+
renameSync
|
|
8033
|
+
} from "fs";
|
|
8034
|
+
import { randomBytes } from "crypto";
|
|
8035
|
+
import { join as join5 } from "path";
|
|
8036
|
+
import { homedir } from "os";
|
|
8037
|
+
function getConfigDir() {
|
|
8038
|
+
const xdgConfig = process.env.XDG_CONFIG_HOME;
|
|
8039
|
+
const base = xdgConfig || join5(homedir(), ".config");
|
|
8040
|
+
return join5(base, "walkeros");
|
|
8041
|
+
}
|
|
8042
|
+
function getConfigPath() {
|
|
8043
|
+
return join5(getConfigDir(), "config.json");
|
|
8044
|
+
}
|
|
8045
|
+
function readConfig() {
|
|
8046
|
+
const configPath = getConfigPath();
|
|
8047
|
+
try {
|
|
8048
|
+
const content = readFileSync3(configPath, "utf-8");
|
|
8049
|
+
return JSON.parse(content);
|
|
8050
|
+
} catch {
|
|
8051
|
+
return null;
|
|
8052
|
+
}
|
|
8053
|
+
}
|
|
8054
|
+
function replaceConfigFile(config) {
|
|
8055
|
+
const dir = getConfigDir();
|
|
8056
|
+
mkdirSync(dir, { recursive: true, mode: 448 });
|
|
8057
|
+
const configPath = getConfigPath();
|
|
8058
|
+
const tempPath = `${configPath}.${process.pid}.${randomBytes(6).toString("hex")}.tmp`;
|
|
8059
|
+
try {
|
|
8060
|
+
writeFileSync(tempPath, JSON.stringify(config, null, 2), { mode: 384 });
|
|
8061
|
+
chmodSync(tempPath, 384);
|
|
8062
|
+
renameSync(tempPath, configPath);
|
|
8063
|
+
} catch (error) {
|
|
8064
|
+
try {
|
|
8065
|
+
unlinkSync(tempPath);
|
|
8066
|
+
} catch {
|
|
8067
|
+
}
|
|
8068
|
+
throw error;
|
|
8069
|
+
}
|
|
8070
|
+
}
|
|
8071
|
+
function writeConfig(config) {
|
|
8072
|
+
replaceConfigFile({ ...readConfig() ?? {}, ...config });
|
|
8073
|
+
}
|
|
8074
|
+
function writeTelemetryOnlyConfig(partial) {
|
|
8075
|
+
writeConfig(partial);
|
|
8076
|
+
}
|
|
8077
|
+
function resolveAppUrl() {
|
|
8078
|
+
const envUrl = process.env.WALKEROS_APP_URL;
|
|
8079
|
+
if (envUrl) return envUrl;
|
|
8080
|
+
const config = readConfig();
|
|
8081
|
+
if (config?.appUrl) return config.appUrl;
|
|
8082
|
+
return "https://app.walkeros.io";
|
|
8083
|
+
}
|
|
8084
|
+
|
|
8085
|
+
// src/lib/secure-url.ts
|
|
8086
|
+
function isLoopback(hostname) {
|
|
8087
|
+
return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "[::1]";
|
|
8088
|
+
}
|
|
8089
|
+
function requireSecureUrl(url) {
|
|
8090
|
+
let parsed;
|
|
8091
|
+
try {
|
|
8092
|
+
parsed = new URL(url);
|
|
8093
|
+
} catch {
|
|
8094
|
+
return url;
|
|
8095
|
+
}
|
|
8096
|
+
if (parsed.protocol !== "http:" || isLoopback(parsed.hostname)) return url;
|
|
8097
|
+
throw new Error(
|
|
8098
|
+
`Refusing to send walkerOS credentials over plain http to ${url}. Use https, or localhost / 127.0.0.1 / [::1] for local development.`
|
|
8099
|
+
);
|
|
8100
|
+
}
|
|
8101
|
+
|
|
8102
|
+
// src/core/client-context.ts
|
|
8103
|
+
var context;
|
|
8104
|
+
function setClientContext(input) {
|
|
8105
|
+
const envType = process.env.WALKEROS_CLIENT_TYPE;
|
|
8106
|
+
const type = envType ?? input.type ?? "cli";
|
|
8107
|
+
context = { type, version: input.version };
|
|
8108
|
+
}
|
|
8109
|
+
function getClientContext() {
|
|
8110
|
+
return context;
|
|
8111
|
+
}
|
|
8112
|
+
function resetClientContext() {
|
|
8113
|
+
context = void 0;
|
|
8114
|
+
}
|
|
8115
|
+
function clientContextHeaders() {
|
|
8116
|
+
if (!context) return {};
|
|
8117
|
+
return {
|
|
8118
|
+
"User-Agent": `walkeros-${context.type}/${context.version}`,
|
|
8119
|
+
"X-WalkerOS-Client": context.type,
|
|
8120
|
+
"X-WalkerOS-Client-Version": context.version
|
|
8121
|
+
};
|
|
8122
|
+
}
|
|
8123
|
+
|
|
8124
|
+
// src/core/app-fetch.ts
|
|
8125
|
+
var AppErrorSchema = z.object({
|
|
8126
|
+
error: z.object({ message: z.string().min(1) })
|
|
8127
|
+
});
|
|
8128
|
+
function appErrorMessage(body) {
|
|
8129
|
+
const parsed = AppErrorSchema.safeParse(body);
|
|
8130
|
+
return parsed.success ? parsed.data.error.message : void 0;
|
|
8131
|
+
}
|
|
8132
|
+
async function appFetch(path23, init = {}) {
|
|
8133
|
+
const url = `${(init.baseUrl ?? resolveAppUrl()).replace(/\/+$/, "")}${path23}`;
|
|
8134
|
+
const headers = new Headers(clientContextHeaders());
|
|
8135
|
+
for (const [name, value] of Object.entries(init.headers ?? {}))
|
|
8136
|
+
headers.set(name, value);
|
|
8137
|
+
if (init.token && !headers.has("Authorization"))
|
|
8138
|
+
headers.set("Authorization", `Bearer ${init.token}`);
|
|
8139
|
+
if (headers.has("Authorization")) requireSecureUrl(url);
|
|
8140
|
+
const request = { headers };
|
|
8141
|
+
if (init.method && init.method !== "GET") request.method = init.method;
|
|
8142
|
+
if (init.body !== void 0) request.body = init.body;
|
|
8143
|
+
if (init.signal) request.signal = init.signal;
|
|
8144
|
+
if (init.redirect) request.redirect = init.redirect;
|
|
8145
|
+
return (init.fetch ?? fetch)(url, request);
|
|
8146
|
+
}
|
|
8147
|
+
|
|
8148
|
+
// src/core/app-paths.ts
|
|
8149
|
+
var APP_PATHS = {
|
|
8150
|
+
whoami: "/api/auth/whoami",
|
|
8151
|
+
health: "/api/health",
|
|
8152
|
+
telemetry: "/api/telemetry",
|
|
8153
|
+
openapi: "/api/openapi.json"
|
|
8154
|
+
};
|
|
8155
|
+
|
|
8591
8156
|
// src/commands/api/index.ts
|
|
8592
8157
|
import { once } from "events";
|
|
8593
8158
|
import { readFile as readFile2 } from "fs/promises";
|
|
8594
|
-
import { z as
|
|
8159
|
+
import { z as z2 } from "zod";
|
|
8160
|
+
var NOT_SIGNED_IN = "no token: set WALKEROS_TOKEN to a token from Account > Automation tokens in the walkerOS app";
|
|
8595
8161
|
var ERROR_BODY_LIMIT = 64 * 1024;
|
|
8596
|
-
var DocumentSchema =
|
|
8597
|
-
paths:
|
|
8598
|
-
components:
|
|
8162
|
+
var DocumentSchema = z2.object({
|
|
8163
|
+
paths: z2.record(z2.string(), z2.record(z2.string(), z2.unknown())),
|
|
8164
|
+
components: z2.record(z2.string(), z2.record(z2.string(), z2.unknown())).optional()
|
|
8599
8165
|
});
|
|
8600
|
-
var OperationSchema =
|
|
8601
|
-
summary:
|
|
8602
|
-
description:
|
|
8603
|
-
parameters:
|
|
8604
|
-
requestBody:
|
|
8605
|
-
responses:
|
|
8166
|
+
var OperationSchema = z2.object({
|
|
8167
|
+
summary: z2.string().optional(),
|
|
8168
|
+
description: z2.string().optional(),
|
|
8169
|
+
parameters: z2.array(z2.unknown()).optional(),
|
|
8170
|
+
requestBody: z2.unknown().optional(),
|
|
8171
|
+
responses: z2.record(z2.string(), z2.unknown()).optional()
|
|
8606
8172
|
});
|
|
8607
|
-
var OptionsSchema =
|
|
8608
|
-
data:
|
|
8609
|
-
header:
|
|
8610
|
-
project:
|
|
8611
|
-
yes:
|
|
8173
|
+
var OptionsSchema = z2.object({
|
|
8174
|
+
data: z2.string().optional(),
|
|
8175
|
+
header: z2.array(z2.string()).default([]),
|
|
8176
|
+
project: z2.string().optional(),
|
|
8177
|
+
yes: z2.boolean().optional()
|
|
8612
8178
|
});
|
|
8613
8179
|
|
|
8614
8180
|
// src/commands/auth/index.ts
|
|
8615
|
-
async function
|
|
8181
|
+
async function readJson2(response) {
|
|
8616
8182
|
try {
|
|
8617
8183
|
return await response.json();
|
|
8618
8184
|
} catch {
|
|
@@ -8620,19 +8186,17 @@ async function readJson3(response) {
|
|
|
8620
8186
|
}
|
|
8621
8187
|
}
|
|
8622
8188
|
async function whoami() {
|
|
8623
|
-
const token =
|
|
8624
|
-
if (!token)
|
|
8625
|
-
throw new Error("Not authenticated. Run `walkeros auth login` first.");
|
|
8189
|
+
const token = resolveAccessToken();
|
|
8190
|
+
if (!token) throw new Error(NOT_SIGNED_IN);
|
|
8626
8191
|
const response = await appFetch(APP_PATHS.whoami, { token });
|
|
8627
|
-
const body = await
|
|
8192
|
+
const body = await readJson2(response);
|
|
8628
8193
|
if (!response.ok)
|
|
8629
8194
|
throw new Error(appErrorMessage(body) ?? `HTTP ${response.status}`);
|
|
8630
8195
|
return body;
|
|
8631
8196
|
}
|
|
8632
|
-
var IdentitySchema =
|
|
8633
|
-
email:
|
|
8634
|
-
userId:
|
|
8635
|
-
projectId: z5.string().nullish()
|
|
8197
|
+
var IdentitySchema = z3.object({
|
|
8198
|
+
email: z3.string().optional(),
|
|
8199
|
+
userId: z3.string().optional()
|
|
8636
8200
|
});
|
|
8637
8201
|
async function whoamiCommand(options) {
|
|
8638
8202
|
const logger = createCLILogger(options);
|
|
@@ -8649,7 +8213,6 @@ async function whoamiCommand(options) {
|
|
|
8649
8213
|
const data = identity.data;
|
|
8650
8214
|
if (data.email) logger.info(data.email);
|
|
8651
8215
|
if (data.userId) logger.info(`User: ${data.userId}`);
|
|
8652
|
-
if (data.projectId) logger.info(`Project: ${data.projectId}`);
|
|
8653
8216
|
}
|
|
8654
8217
|
} catch (error) {
|
|
8655
8218
|
handleCliError(error);
|
|
@@ -8724,7 +8287,7 @@ function telemetryDisableCommand() {
|
|
|
8724
8287
|
}
|
|
8725
8288
|
|
|
8726
8289
|
// src/index.ts
|
|
8727
|
-
import { validateFlowStructure as
|
|
8290
|
+
import { validateFlowStructure as validateFlowStructure3 } from "@walkeros/core/dev";
|
|
8728
8291
|
|
|
8729
8292
|
// src/commands/bundle/wrap.ts
|
|
8730
8293
|
import * as path21 from "path";
|
|
@@ -8800,11 +8363,12 @@ async function wrapSkeleton(options) {
|
|
|
8800
8363
|
format: "esm",
|
|
8801
8364
|
platform,
|
|
8802
8365
|
outfile: outputPath,
|
|
8803
|
-
// Resolve `@walkeros/core` (
|
|
8804
|
-
// package's own dependency tree and the
|
|
8805
|
-
// esbuild looks under the temp entryDir
|
|
8806
|
-
// The wrap step always runs from inside the
|
|
8807
|
-
// CLI's local node_modules and the workspace root
|
|
8366
|
+
// Resolve `@walkeros/web-core` (the Tag Mode loader and the preview
|
|
8367
|
+
// activator) from the CLI package's own dependency tree and the
|
|
8368
|
+
// workspace root. Without this, esbuild looks under the temp entryDir
|
|
8369
|
+
// which has no node_modules. The wrap step always runs from inside the
|
|
8370
|
+
// CLI process; both the CLI's local node_modules and the workspace root
|
|
8371
|
+
// are safe anchors.
|
|
8808
8372
|
nodePaths: getNodeResolutionPaths(),
|
|
8809
8373
|
treeShaking: true,
|
|
8810
8374
|
logLevel: "error",
|
|
@@ -8819,7 +8383,7 @@ async function wrapSkeleton(options) {
|
|
|
8819
8383
|
};
|
|
8820
8384
|
if (platform === "browser") {
|
|
8821
8385
|
esbuildOptions.format = "iife";
|
|
8822
|
-
esbuildOptions.plugins = [
|
|
8386
|
+
esbuildOptions.plugins = [cliPackagesPlugin()];
|
|
8823
8387
|
const needs = readNeedsMarker(skeletonText);
|
|
8824
8388
|
esbuildOptions.define = {
|
|
8825
8389
|
"process.env.NODE_ENV": '"production"',
|
|
@@ -8854,10 +8418,10 @@ import fs22 from "fs-extra";
|
|
|
8854
8418
|
import { FlowReferenceError as FlowReferenceError2 } from "@walkeros/core";
|
|
8855
8419
|
|
|
8856
8420
|
// src/schemas/build-manifest.ts
|
|
8857
|
-
import { z as
|
|
8421
|
+
import { z as z4 } from "@walkeros/core/dev";
|
|
8858
8422
|
var BUILD_MANIFEST_VERSION = 1;
|
|
8859
|
-
var HttpUrlSchema =
|
|
8860
|
-
var OutputNameSchema =
|
|
8423
|
+
var HttpUrlSchema = z4.url({ protocol: /^https?$/ });
|
|
8424
|
+
var OutputNameSchema = z4.string().regex(/^[A-Za-z0-9][A-Za-z0-9._-]*$/, "Must be a bare file name").describe("Output file name; its extension picks the format (.tar.gz packs)");
|
|
8861
8425
|
var BUNDLE_TARGET_NAMES = [
|
|
8862
8426
|
"cdn",
|
|
8863
8427
|
"cdn-skeleton",
|
|
@@ -8873,8 +8437,8 @@ var RESERVED_HEADERS = /* @__PURE__ */ new Set([
|
|
|
8873
8437
|
var OutputFields = {
|
|
8874
8438
|
outputName: OutputNameSchema,
|
|
8875
8439
|
putUrl: HttpUrlSchema.describe("Presigned PUT for exactly this output"),
|
|
8876
|
-
contentType:
|
|
8877
|
-
headers:
|
|
8440
|
+
contentType: z4.string().min(1).optional().describe("Content-Type sent with the PUT (must match a signed header)"),
|
|
8441
|
+
headers: z4.record(z4.string().min(1), z4.string()).refine(
|
|
8878
8442
|
(headers) => Object.keys(headers).every(
|
|
8879
8443
|
(name) => !RESERVED_HEADERS.has(name.toLowerCase())
|
|
8880
8444
|
),
|
|
@@ -8883,68 +8447,68 @@ var OutputFields = {
|
|
|
8883
8447
|
"Extra headers sent with the PUT (for headers a presign signs); never logged"
|
|
8884
8448
|
)
|
|
8885
8449
|
};
|
|
8886
|
-
var BuildBundleArtifactSchema =
|
|
8887
|
-
target:
|
|
8450
|
+
var BuildBundleArtifactSchema = z4.object({
|
|
8451
|
+
target: z4.enum(BUNDLE_TARGET_NAMES).describe("Named bundle target"),
|
|
8888
8452
|
...OutputFields
|
|
8889
8453
|
}).strict();
|
|
8890
|
-
var BuildWrapOptionsSchema =
|
|
8891
|
-
windowCollector:
|
|
8892
|
-
windowElb:
|
|
8893
|
-
preview:
|
|
8894
|
-
enabled:
|
|
8895
|
-
keyring:
|
|
8896
|
-
|
|
8454
|
+
var BuildWrapOptionsSchema = z4.object({
|
|
8455
|
+
windowCollector: z4.string().min(1).optional(),
|
|
8456
|
+
windowElb: z4.string().min(1).optional(),
|
|
8457
|
+
preview: z4.object({
|
|
8458
|
+
enabled: z4.boolean(),
|
|
8459
|
+
keyring: z4.array(
|
|
8460
|
+
z4.object({ kid: z4.string(), spki: z4.string() }).strict()
|
|
8897
8461
|
),
|
|
8898
|
-
iss:
|
|
8899
|
-
pb:
|
|
8900
|
-
acceptForeign:
|
|
8901
|
-
demoAllowlist:
|
|
8902
|
-
previewOrigin:
|
|
8462
|
+
iss: z4.string(),
|
|
8463
|
+
pb: z4.string().optional(),
|
|
8464
|
+
acceptForeign: z4.boolean().optional(),
|
|
8465
|
+
demoAllowlist: z4.array(z4.string()).optional(),
|
|
8466
|
+
previewOrigin: z4.string()
|
|
8903
8467
|
}).strict().optional(),
|
|
8904
|
-
previewGrantTargets:
|
|
8905
|
-
observe:
|
|
8906
|
-
url:
|
|
8907
|
-
binding:
|
|
8908
|
-
flowId:
|
|
8909
|
-
level:
|
|
8910
|
-
sample:
|
|
8468
|
+
previewGrantTargets: z4.array(z4.string()).optional(),
|
|
8469
|
+
observe: z4.object({
|
|
8470
|
+
url: z4.string(),
|
|
8471
|
+
binding: z4.string(),
|
|
8472
|
+
flowId: z4.string().optional(),
|
|
8473
|
+
level: z4.enum(["off", "standard", "trace"]).optional(),
|
|
8474
|
+
sample: z4.number().min(0).max(1).optional()
|
|
8911
8475
|
}).strict().optional(),
|
|
8912
|
-
moin:
|
|
8913
|
-
minify:
|
|
8914
|
-
minifyOptions:
|
|
8915
|
-
identifiers:
|
|
8916
|
-
syntax:
|
|
8917
|
-
whitespace:
|
|
8918
|
-
keepNames:
|
|
8919
|
-
legalComments:
|
|
8476
|
+
moin: z4.object({ app: z4.string(), base: z4.string() }).strict().optional().describe("Tag Mode loader target; absent, the production app"),
|
|
8477
|
+
minify: z4.boolean().optional(),
|
|
8478
|
+
minifyOptions: z4.object({
|
|
8479
|
+
identifiers: z4.boolean().optional(),
|
|
8480
|
+
syntax: z4.boolean().optional(),
|
|
8481
|
+
whitespace: z4.boolean().optional(),
|
|
8482
|
+
keepNames: z4.boolean().optional(),
|
|
8483
|
+
legalComments: z4.enum(["none", "inline", "eof", "linked", "external"]).optional()
|
|
8920
8484
|
}).strict().optional(),
|
|
8921
|
-
target:
|
|
8485
|
+
target: z4.string().min(1).optional().describe("esbuild target")
|
|
8922
8486
|
}).strict().describe("Options forwarded to wrapSkeleton");
|
|
8923
|
-
var BuildWrapArtifactSchema =
|
|
8924
|
-
target:
|
|
8925
|
-
platform:
|
|
8926
|
-
skeleton:
|
|
8927
|
-
|
|
8928
|
-
|
|
8487
|
+
var BuildWrapArtifactSchema = z4.object({
|
|
8488
|
+
target: z4.literal("wrap"),
|
|
8489
|
+
platform: z4.enum(["browser", "node"]),
|
|
8490
|
+
skeleton: z4.union([
|
|
8491
|
+
z4.object({ url: HttpUrlSchema }).strict(),
|
|
8492
|
+
z4.object({ artifact: OutputNameSchema }).strict()
|
|
8929
8493
|
]).describe(
|
|
8930
8494
|
"The skeleton to wrap: a GET URL, or the outputName of an earlier bundle artifact in this manifest"
|
|
8931
8495
|
),
|
|
8932
8496
|
options: BuildWrapOptionsSchema.optional(),
|
|
8933
8497
|
...OutputFields
|
|
8934
8498
|
}).strict();
|
|
8935
|
-
var BuildArtifactSchema =
|
|
8499
|
+
var BuildArtifactSchema = z4.union([
|
|
8936
8500
|
BuildBundleArtifactSchema,
|
|
8937
8501
|
BuildWrapArtifactSchema
|
|
8938
8502
|
]);
|
|
8939
|
-
var BuildManifestSchema =
|
|
8940
|
-
version:
|
|
8941
|
-
toolchain:
|
|
8942
|
-
flowConfig:
|
|
8943
|
-
flowName:
|
|
8944
|
-
buildEnv:
|
|
8503
|
+
var BuildManifestSchema = z4.object({
|
|
8504
|
+
version: z4.literal(BUILD_MANIFEST_VERSION),
|
|
8505
|
+
toolchain: z4.string().min(1).describe("Exact @walkeros/cli version; any other version refuses"),
|
|
8506
|
+
flowConfig: z4.record(z4.string(), z4.unknown()).optional().describe("Flow.Json to bundle; required when any bundle artifact is"),
|
|
8507
|
+
flowName: z4.string().min(1).optional(),
|
|
8508
|
+
buildEnv: z4.record(z4.string(), z4.string()).optional().describe(
|
|
8945
8509
|
"Base env for web $env, beneath config.bundle.env. Never the CLI process's own env"
|
|
8946
8510
|
),
|
|
8947
|
-
artifacts:
|
|
8511
|
+
artifacts: z4.array(BuildArtifactSchema).min(1),
|
|
8948
8512
|
resultPutUrl: HttpUrlSchema.describe("Presigned PUT for the result JSON")
|
|
8949
8513
|
}).loose().superRefine((manifest, ctx) => {
|
|
8950
8514
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -8987,21 +8551,21 @@ var BUILD_ERROR_CODES = [
|
|
|
8987
8551
|
"BUILD_FAILED",
|
|
8988
8552
|
"UPLOAD_FAILED"
|
|
8989
8553
|
];
|
|
8990
|
-
var BuildResultSchema =
|
|
8991
|
-
ok:
|
|
8992
|
-
toolchain:
|
|
8993
|
-
artifacts:
|
|
8994
|
-
|
|
8995
|
-
target:
|
|
8996
|
-
outputName:
|
|
8997
|
-
bytes:
|
|
8998
|
-
sha256:
|
|
8554
|
+
var BuildResultSchema = z4.object({
|
|
8555
|
+
ok: z4.boolean(),
|
|
8556
|
+
toolchain: z4.string().describe("The CLI version that ran the build"),
|
|
8557
|
+
artifacts: z4.array(
|
|
8558
|
+
z4.object({
|
|
8559
|
+
target: z4.string(),
|
|
8560
|
+
outputName: z4.string(),
|
|
8561
|
+
bytes: z4.number().int().nonnegative(),
|
|
8562
|
+
sha256: z4.string()
|
|
8999
8563
|
})
|
|
9000
8564
|
).describe("Outputs PUT successfully, in manifest order"),
|
|
9001
|
-
error:
|
|
9002
|
-
code:
|
|
9003
|
-
message:
|
|
9004
|
-
outputName:
|
|
8565
|
+
error: z4.object({
|
|
8566
|
+
code: z4.enum(BUILD_ERROR_CODES),
|
|
8567
|
+
message: z4.string(),
|
|
8568
|
+
outputName: z4.string().optional().describe("The artifact being built when the error occurred")
|
|
9005
8569
|
}).optional()
|
|
9006
8570
|
}).meta({ id: "BuildResult", title: "walkeros bundle --manifest result" });
|
|
9007
8571
|
|
|
@@ -9052,16 +8616,16 @@ async function fetchWithRetry(url, init, options) {
|
|
|
9052
8616
|
if (failure instanceof Response && !isTransientStatus(failure.status)) {
|
|
9053
8617
|
throw new Error(`${label} failed: ${reason}`);
|
|
9054
8618
|
}
|
|
9055
|
-
const
|
|
9056
|
-
if (
|
|
8619
|
+
const delay2 = BACKOFF_MS[attempt - 1];
|
|
8620
|
+
if (delay2 === void 0) {
|
|
9057
8621
|
throw new Error(
|
|
9058
8622
|
`${label} failed after ${maxAttempts} attempts: ${reason}`
|
|
9059
8623
|
);
|
|
9060
8624
|
}
|
|
9061
8625
|
warn?.(
|
|
9062
|
-
`${label} attempt ${attempt}/${maxAttempts} failed: ${reason}, retrying in ${
|
|
8626
|
+
`${label} attempt ${attempt}/${maxAttempts} failed: ${reason}, retrying in ${delay2 / 1e3}s`
|
|
9063
8627
|
);
|
|
9064
|
-
await sleep(
|
|
8628
|
+
await sleep(delay2);
|
|
9065
8629
|
}
|
|
9066
8630
|
}
|
|
9067
8631
|
|
|
@@ -9549,22 +9113,13 @@ export {
|
|
|
9549
9113
|
bundle,
|
|
9550
9114
|
bundleCommand,
|
|
9551
9115
|
classifyStepProperties,
|
|
9552
|
-
clearAuthFields,
|
|
9553
9116
|
clientContextHeaders,
|
|
9554
9117
|
collectKnownSecrets,
|
|
9555
|
-
completeDeviceLogin,
|
|
9556
9118
|
containsCodeMarkers,
|
|
9557
|
-
credentialSource,
|
|
9558
|
-
deleteConfig,
|
|
9559
9119
|
formatPushResult,
|
|
9560
|
-
getAuthHeaders,
|
|
9561
9120
|
getClientContext,
|
|
9562
9121
|
loadConfig,
|
|
9563
9122
|
loadJsonConfig,
|
|
9564
|
-
login,
|
|
9565
|
-
loginCommand,
|
|
9566
|
-
logout,
|
|
9567
|
-
logoutCommand,
|
|
9568
9123
|
push,
|
|
9569
9124
|
pushCommand,
|
|
9570
9125
|
readConfig,
|
|
@@ -9573,7 +9128,6 @@ export {
|
|
|
9573
9128
|
resolveAppUrl,
|
|
9574
9129
|
resolveExportName,
|
|
9575
9130
|
resolveManifestSource,
|
|
9576
|
-
resolveToken,
|
|
9577
9131
|
runBuildManifest,
|
|
9578
9132
|
selectDevExamples,
|
|
9579
9133
|
setClientContext,
|
|
@@ -9581,14 +9135,13 @@ export {
|
|
|
9581
9135
|
simulateDestination,
|
|
9582
9136
|
simulateSource,
|
|
9583
9137
|
simulateTransformer,
|
|
9584
|
-
startDeviceAuthorization,
|
|
9585
9138
|
telemetry_exports as telemetry,
|
|
9586
9139
|
telemetryDisableCommand,
|
|
9587
9140
|
telemetryEnableCommand,
|
|
9588
9141
|
telemetryStatusCommand,
|
|
9589
9142
|
validate,
|
|
9590
9143
|
validateCommand,
|
|
9591
|
-
|
|
9144
|
+
validateFlowStructure3 as validateFlowStructure,
|
|
9592
9145
|
whoami,
|
|
9593
9146
|
whoamiCommand,
|
|
9594
9147
|
wrapSkeleton,
|