@odla-ai/cli 0.10.2 → 0.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -4
- package/dist/bin.cjs +58 -23
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +1 -1
- package/dist/{chunk-MWVKOIGR.js → chunk-DC4MIB4X.js} +59 -24
- package/dist/chunk-DC4MIB4X.js.map +1 -0
- package/dist/index.cjs +58 -23
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -10
- package/dist/index.d.ts +10 -10
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-MWVKOIGR.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -286,12 +286,16 @@ function handshakeEmail(value, cached) {
|
|
|
286
286
|
}
|
|
287
287
|
return email;
|
|
288
288
|
}
|
|
289
|
-
function approvalBrowser(options) {
|
|
289
|
+
function approvalBrowser(options, host = {}) {
|
|
290
290
|
if (options.open === true) return { open: true, mode: "forced" };
|
|
291
291
|
if (options.open === false) return { open: false, reason: "disabled by --no-open" };
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
if (
|
|
292
|
+
const env = host.env ?? import_node_process2.default.env;
|
|
293
|
+
if (env.CI) return { open: false, reason: "CI environment" };
|
|
294
|
+
if (env.SSH_CONNECTION || env.SSH_TTY) return { open: false, reason: "SSH session; pass --open to force" };
|
|
295
|
+
const platform = host.platform ?? import_node_process2.default.platform;
|
|
296
|
+
if (platform !== "darwin" && platform !== "win32" && !env.DISPLAY && !env.WAYLAND_DISPLAY) {
|
|
297
|
+
return { open: false, reason: "no graphical display; pass --open to force" };
|
|
298
|
+
}
|
|
295
299
|
return { open: true, mode: "auto" };
|
|
296
300
|
}
|
|
297
301
|
function handshakeUrl(platformUrl, userCode) {
|
|
@@ -388,8 +392,9 @@ async function scopedToken(platform, scope, options, doFetch, out) {
|
|
|
388
392
|
onCode: async ({ userCode, expiresIn, verificationUriComplete }) => {
|
|
389
393
|
const approvalUrl = verificationUriComplete ?? handshakeUrl(audience, userCode);
|
|
390
394
|
out.log(`Review, then approve scoped request ${userCode} at ${approvalUrl} within ${Math.floor(expiresIn / 60)}m.`);
|
|
391
|
-
|
|
392
|
-
|
|
395
|
+
if (approvalBrowser({ open: options.open }).open) {
|
|
396
|
+
await (options.openApprovalUrl ?? openUrl)(approvalUrl).catch(() => void 0);
|
|
397
|
+
}
|
|
393
398
|
}
|
|
394
399
|
});
|
|
395
400
|
const tokens = cache?.platform === audience ? { ...cache.tokens ?? {} } : {};
|
|
@@ -1133,6 +1138,28 @@ function unique(values) {
|
|
|
1133
1138
|
return [...new Set(values.filter(Boolean))];
|
|
1134
1139
|
}
|
|
1135
1140
|
|
|
1141
|
+
// src/calendar-errors.ts
|
|
1142
|
+
var PLATFORM_NOT_READY_CODES = /* @__PURE__ */ new Set([
|
|
1143
|
+
"calendar_google_oauth_not_configured",
|
|
1144
|
+
"calendar_token_vault_not_configured",
|
|
1145
|
+
"calendar_db_ingress_not_configured"
|
|
1146
|
+
]);
|
|
1147
|
+
var CalendarRequestError = class extends Error {
|
|
1148
|
+
/** HTTP status returned by the registry. */
|
|
1149
|
+
status;
|
|
1150
|
+
/** Machine-readable `error.code` from the response body, when present. */
|
|
1151
|
+
code;
|
|
1152
|
+
constructor(message, status, code) {
|
|
1153
|
+
super(message);
|
|
1154
|
+
this.name = "CalendarRequestError";
|
|
1155
|
+
this.status = status;
|
|
1156
|
+
if (code !== void 0) this.code = code;
|
|
1157
|
+
}
|
|
1158
|
+
};
|
|
1159
|
+
function isCalendarPlatformNotReady(error) {
|
|
1160
|
+
return error instanceof CalendarRequestError && error.code !== void 0 && PLATFORM_NOT_READY_CODES.has(error.code);
|
|
1161
|
+
}
|
|
1162
|
+
|
|
1136
1163
|
// src/redact.ts
|
|
1137
1164
|
var REPLACEMENTS = [
|
|
1138
1165
|
[/odla_(sk|dev)_[A-Za-z0-9._-]+/g, "odla_$1_[redacted]"],
|
|
@@ -1298,7 +1325,8 @@ async function calendarJson(ctx, suffix, init) {
|
|
|
1298
1325
|
if (!response.ok) {
|
|
1299
1326
|
const code = textField(body.error?.code, 128);
|
|
1300
1327
|
const message = textField(body.error?.message, 500);
|
|
1301
|
-
|
|
1328
|
+
const detail = `${code ? ` ${code}` : ""}${message ? `: ${message}` : ""}`;
|
|
1329
|
+
throw new CalendarRequestError(redactSecrets(`calendar request failed (${response.status})${detail}`), response.status, code);
|
|
1302
1330
|
}
|
|
1303
1331
|
return body;
|
|
1304
1332
|
}
|
|
@@ -1438,7 +1466,6 @@ async function lifecycleContext(options) {
|
|
|
1438
1466
|
token: options.token,
|
|
1439
1467
|
email: options.email,
|
|
1440
1468
|
open: options.open,
|
|
1441
|
-
interactive: options.interactive,
|
|
1442
1469
|
openApprovalUrl: options.openConsentUrl
|
|
1443
1470
|
},
|
|
1444
1471
|
doFetch,
|
|
@@ -1447,7 +1474,7 @@ async function lifecycleContext(options) {
|
|
|
1447
1474
|
return { cfg, ctx: { platform: cfg.platformUrl, appId: cfg.app.id, env, token, fetch: doFetch }, out };
|
|
1448
1475
|
}
|
|
1449
1476
|
function connectionOptions(options, out) {
|
|
1450
|
-
const browser = approvalBrowser({
|
|
1477
|
+
const browser = approvalBrowser({ open: options.open });
|
|
1451
1478
|
return {
|
|
1452
1479
|
out,
|
|
1453
1480
|
open: browser.open,
|
|
@@ -1908,8 +1935,9 @@ Safety:
|
|
|
1908
1935
|
Provision caches the approved developer token and service credentials under
|
|
1909
1936
|
.odla/ with mode 0600, and init adds those paths to .gitignore. Secret push
|
|
1910
1937
|
preflights Wrangler before any shown-once issuance or destructive rotation.
|
|
1911
|
-
Provision opens the approval page automatically
|
|
1912
|
-
|
|
1938
|
+
Provision opens the approval page in your browser automatically whenever the
|
|
1939
|
+
machine can show one, including agent-driven runs; only CI, SSH, and
|
|
1940
|
+
display-less hosts skip it. Use --open to force or --no-open to suppress.
|
|
1913
1941
|
A fresh device handshake requires --email <odla-account> or ODLA_USER_EMAIL.
|
|
1914
1942
|
The email is a non-secret identity hint: never provide a password or session
|
|
1915
1943
|
token. The matching account must already exist, be signed in, explicitly
|
|
@@ -2349,17 +2377,6 @@ async function provision(options) {
|
|
|
2349
2377
|
if (cfg.services.includes("calendar")) {
|
|
2350
2378
|
const calendarCtx = { platform: cfg.platformUrl, appId: cfg.app.id, env, token, fetch: doFetch };
|
|
2351
2379
|
await applyCalendarBookingPage(calendarCtx, calendarBookingPageUrl(cfg, env), out);
|
|
2352
|
-
await ensureCalendarConnected(
|
|
2353
|
-
calendarCtx,
|
|
2354
|
-
{
|
|
2355
|
-
open: options.open,
|
|
2356
|
-
interactive: options.interactive,
|
|
2357
|
-
openConsentUrl: options.openApprovalUrl,
|
|
2358
|
-
wait: options.calendarPollWait,
|
|
2359
|
-
pollTimeoutMs: options.calendarPollTimeoutMs,
|
|
2360
|
-
stdout: out
|
|
2361
|
-
}
|
|
2362
|
-
);
|
|
2363
2380
|
}
|
|
2364
2381
|
}
|
|
2365
2382
|
for (const env of cfg.envs) {
|
|
@@ -2423,6 +2440,25 @@ ${env}: credentials are already saved; retry "odla-ai secrets push --env ${env}$
|
|
|
2423
2440
|
writeDevVars(devVarsTarget, credentials, env, o11yDevVars(cfg));
|
|
2424
2441
|
out.log(`dev vars: wrote ${displayPath(devVarsTarget, cfg.rootDir)} for ${env}`);
|
|
2425
2442
|
}
|
|
2443
|
+
if (cfg.services.includes("calendar")) {
|
|
2444
|
+
for (const env of cfg.envs) {
|
|
2445
|
+
try {
|
|
2446
|
+
await ensureCalendarConnected(
|
|
2447
|
+
{ platform: cfg.platformUrl, appId: cfg.app.id, env, token, fetch: doFetch },
|
|
2448
|
+
{
|
|
2449
|
+
open: options.open,
|
|
2450
|
+
openConsentUrl: options.openApprovalUrl,
|
|
2451
|
+
wait: options.calendarPollWait,
|
|
2452
|
+
pollTimeoutMs: options.calendarPollTimeoutMs,
|
|
2453
|
+
stdout: out
|
|
2454
|
+
}
|
|
2455
|
+
);
|
|
2456
|
+
} catch (error) {
|
|
2457
|
+
if (!isCalendarPlatformNotReady(error)) throw error;
|
|
2458
|
+
out.log(`${env}: calendar consent skipped (${error.code}); resume with "odla-ai calendar connect --env ${env}" once the platform is configured`);
|
|
2459
|
+
}
|
|
2460
|
+
}
|
|
2461
|
+
}
|
|
2426
2462
|
}
|
|
2427
2463
|
function serviceRank(service) {
|
|
2428
2464
|
if (service === "db") return 0;
|
|
@@ -3732,7 +3768,6 @@ async function smoke(options) {
|
|
|
3732
3768
|
token: options.token,
|
|
3733
3769
|
email: options.email,
|
|
3734
3770
|
open: options.open,
|
|
3735
|
-
interactive: options.interactive,
|
|
3736
3771
|
openApprovalUrl: options.openApprovalUrl
|
|
3737
3772
|
},
|
|
3738
3773
|
doFetch,
|