@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/bin.js
CHANGED
|
@@ -210,12 +210,16 @@ function handshakeEmail(value, cached) {
|
|
|
210
210
|
}
|
|
211
211
|
return email;
|
|
212
212
|
}
|
|
213
|
-
function approvalBrowser(options) {
|
|
213
|
+
function approvalBrowser(options, host = {}) {
|
|
214
214
|
if (options.open === true) return { open: true, mode: "forced" };
|
|
215
215
|
if (options.open === false) return { open: false, reason: "disabled by --no-open" };
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
if (
|
|
216
|
+
const env = host.env ?? process3.env;
|
|
217
|
+
if (env.CI) return { open: false, reason: "CI environment" };
|
|
218
|
+
if (env.SSH_CONNECTION || env.SSH_TTY) return { open: false, reason: "SSH session; pass --open to force" };
|
|
219
|
+
const platform = host.platform ?? process3.platform;
|
|
220
|
+
if (platform !== "darwin" && platform !== "win32" && !env.DISPLAY && !env.WAYLAND_DISPLAY) {
|
|
221
|
+
return { open: false, reason: "no graphical display; pass --open to force" };
|
|
222
|
+
}
|
|
219
223
|
return { open: true, mode: "auto" };
|
|
220
224
|
}
|
|
221
225
|
function handshakeUrl(platformUrl, userCode) {
|
|
@@ -286,8 +290,9 @@ async function scopedToken(platform, scope, options, doFetch, out) {
|
|
|
286
290
|
onCode: async ({ userCode, expiresIn, verificationUriComplete }) => {
|
|
287
291
|
const approvalUrl = verificationUriComplete ?? handshakeUrl(audience, userCode);
|
|
288
292
|
out.log(`Review, then approve scoped request ${userCode} at ${approvalUrl} within ${Math.floor(expiresIn / 60)}m.`);
|
|
289
|
-
|
|
290
|
-
|
|
293
|
+
if (approvalBrowser({ open: options.open }).open) {
|
|
294
|
+
await (options.openApprovalUrl ?? openUrl)(approvalUrl).catch(() => void 0);
|
|
295
|
+
}
|
|
291
296
|
}
|
|
292
297
|
});
|
|
293
298
|
const tokens = cache?.platform === audience ? { ...cache.tokens ?? {} } : {};
|
|
@@ -940,6 +945,28 @@ function looksSecret(value) {
|
|
|
940
945
|
return redactSecrets(value) !== value || value.includes("-----BEGIN");
|
|
941
946
|
}
|
|
942
947
|
|
|
948
|
+
// src/calendar-errors.ts
|
|
949
|
+
var PLATFORM_NOT_READY_CODES = /* @__PURE__ */ new Set([
|
|
950
|
+
"calendar_google_oauth_not_configured",
|
|
951
|
+
"calendar_token_vault_not_configured",
|
|
952
|
+
"calendar_db_ingress_not_configured"
|
|
953
|
+
]);
|
|
954
|
+
var CalendarRequestError = class extends Error {
|
|
955
|
+
/** HTTP status returned by the registry. */
|
|
956
|
+
status;
|
|
957
|
+
/** Machine-readable `error.code` from the response body, when present. */
|
|
958
|
+
code;
|
|
959
|
+
constructor(message, status, code) {
|
|
960
|
+
super(message);
|
|
961
|
+
this.name = "CalendarRequestError";
|
|
962
|
+
this.status = status;
|
|
963
|
+
if (code !== void 0) this.code = code;
|
|
964
|
+
}
|
|
965
|
+
};
|
|
966
|
+
function isCalendarPlatformNotReady(error) {
|
|
967
|
+
return error instanceof CalendarRequestError && error.code !== void 0 && PLATFORM_NOT_READY_CODES.has(error.code);
|
|
968
|
+
}
|
|
969
|
+
|
|
943
970
|
// src/calendar-http.ts
|
|
944
971
|
var CALENDAR_STATES = [
|
|
945
972
|
"not_connected",
|
|
@@ -1086,7 +1113,8 @@ async function calendarJson(ctx, suffix, init) {
|
|
|
1086
1113
|
if (!response.ok) {
|
|
1087
1114
|
const code = textField(body.error?.code, 128);
|
|
1088
1115
|
const message = textField(body.error?.message, 500);
|
|
1089
|
-
|
|
1116
|
+
const detail = `${code ? ` ${code}` : ""}${message ? `: ${message}` : ""}`;
|
|
1117
|
+
throw new CalendarRequestError(redactSecrets(`calendar request failed (${response.status})${detail}`), response.status, code);
|
|
1090
1118
|
}
|
|
1091
1119
|
return body;
|
|
1092
1120
|
}
|
|
@@ -1226,7 +1254,6 @@ async function lifecycleContext(options) {
|
|
|
1226
1254
|
token: options.token,
|
|
1227
1255
|
email: options.email,
|
|
1228
1256
|
open: options.open,
|
|
1229
|
-
interactive: options.interactive,
|
|
1230
1257
|
openApprovalUrl: options.openConsentUrl
|
|
1231
1258
|
},
|
|
1232
1259
|
doFetch,
|
|
@@ -1235,7 +1262,7 @@ async function lifecycleContext(options) {
|
|
|
1235
1262
|
return { cfg, ctx: { platform: cfg.platformUrl, appId: cfg.app.id, env, token, fetch: doFetch }, out };
|
|
1236
1263
|
}
|
|
1237
1264
|
function connectionOptions(options, out) {
|
|
1238
|
-
const browser = approvalBrowser({
|
|
1265
|
+
const browser = approvalBrowser({ open: options.open });
|
|
1239
1266
|
return {
|
|
1240
1267
|
out,
|
|
1241
1268
|
open: browser.open,
|
|
@@ -2032,17 +2059,6 @@ async function provision(options) {
|
|
|
2032
2059
|
if (cfg.services.includes("calendar")) {
|
|
2033
2060
|
const calendarCtx = { platform: cfg.platformUrl, appId: cfg.app.id, env, token, fetch: doFetch };
|
|
2034
2061
|
await applyCalendarBookingPage(calendarCtx, calendarBookingPageUrl(cfg, env), out);
|
|
2035
|
-
await ensureCalendarConnected(
|
|
2036
|
-
calendarCtx,
|
|
2037
|
-
{
|
|
2038
|
-
open: options.open,
|
|
2039
|
-
interactive: options.interactive,
|
|
2040
|
-
openConsentUrl: options.openApprovalUrl,
|
|
2041
|
-
wait: options.calendarPollWait,
|
|
2042
|
-
pollTimeoutMs: options.calendarPollTimeoutMs,
|
|
2043
|
-
stdout: out
|
|
2044
|
-
}
|
|
2045
|
-
);
|
|
2046
2062
|
}
|
|
2047
2063
|
}
|
|
2048
2064
|
for (const env of cfg.envs) {
|
|
@@ -2106,6 +2122,25 @@ ${env}: credentials are already saved; retry "odla-ai secrets push --env ${env}$
|
|
|
2106
2122
|
writeDevVars(devVarsTarget, credentials, env, o11yDevVars(cfg));
|
|
2107
2123
|
out.log(`dev vars: wrote ${displayPath(devVarsTarget, cfg.rootDir)} for ${env}`);
|
|
2108
2124
|
}
|
|
2125
|
+
if (cfg.services.includes("calendar")) {
|
|
2126
|
+
for (const env of cfg.envs) {
|
|
2127
|
+
try {
|
|
2128
|
+
await ensureCalendarConnected(
|
|
2129
|
+
{ platform: cfg.platformUrl, appId: cfg.app.id, env, token, fetch: doFetch },
|
|
2130
|
+
{
|
|
2131
|
+
open: options.open,
|
|
2132
|
+
openConsentUrl: options.openApprovalUrl,
|
|
2133
|
+
wait: options.calendarPollWait,
|
|
2134
|
+
pollTimeoutMs: options.calendarPollTimeoutMs,
|
|
2135
|
+
stdout: out
|
|
2136
|
+
}
|
|
2137
|
+
);
|
|
2138
|
+
} catch (error) {
|
|
2139
|
+
if (!isCalendarPlatformNotReady(error)) throw error;
|
|
2140
|
+
out.log(`${env}: calendar consent skipped (${error.code}); resume with "odla-ai calendar connect --env ${env}" once the platform is configured`);
|
|
2141
|
+
}
|
|
2142
|
+
}
|
|
2143
|
+
}
|
|
2109
2144
|
}
|
|
2110
2145
|
function serviceRank(service) {
|
|
2111
2146
|
if (service === "db") return 0;
|
|
@@ -2987,7 +3022,6 @@ async function smoke(options) {
|
|
|
2987
3022
|
token: options.token,
|
|
2988
3023
|
email: options.email,
|
|
2989
3024
|
open: options.open,
|
|
2990
|
-
interactive: options.interactive,
|
|
2991
3025
|
openApprovalUrl: options.openApprovalUrl
|
|
2992
3026
|
},
|
|
2993
3027
|
doFetch,
|
|
@@ -3275,8 +3309,9 @@ Safety:
|
|
|
3275
3309
|
Provision caches the approved developer token and service credentials under
|
|
3276
3310
|
.odla/ with mode 0600, and init adds those paths to .gitignore. Secret push
|
|
3277
3311
|
preflights Wrangler before any shown-once issuance or destructive rotation.
|
|
3278
|
-
Provision opens the approval page automatically
|
|
3279
|
-
|
|
3312
|
+
Provision opens the approval page in your browser automatically whenever the
|
|
3313
|
+
machine can show one, including agent-driven runs; only CI, SSH, and
|
|
3314
|
+
display-less hosts skip it. Use --open to force or --no-open to suppress.
|
|
3280
3315
|
A fresh device handshake requires --email <odla-account> or ODLA_USER_EMAIL.
|
|
3281
3316
|
The email is a non-secret identity hint: never provide a password or session
|
|
3282
3317
|
token. The matching account must already exist, be signed in, explicitly
|
|
@@ -3982,4 +4017,4 @@ export {
|
|
|
3982
4017
|
smoke,
|
|
3983
4018
|
runCli
|
|
3984
4019
|
};
|
|
3985
|
-
//# sourceMappingURL=chunk-
|
|
4020
|
+
//# sourceMappingURL=chunk-DC4MIB4X.js.map
|