@tailor-platform/sdk 1.67.1 → 1.69.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +98 -1
- package/dist/application-Br48NXBD.mjs +4 -0
- package/dist/application-Cr-limKC.mjs +6192 -0
- package/dist/application-Cr-limKC.mjs.map +1 -0
- package/dist/cli/index.mjs +147 -34
- package/dist/cli/index.mjs.map +1 -1
- package/dist/cli/lib.d.mts +297 -157
- package/dist/cli/lib.mjs +4 -4
- package/dist/cli/lib.mjs.map +1 -1
- package/dist/cli/skills.mjs +1 -1
- package/dist/completion/zsh-worker.zsh +127 -48
- package/dist/configure/index.d.mts +2 -2
- package/dist/configure/index.mjs +4 -0
- package/dist/configure/index.mjs.map +1 -1
- package/dist/{crashreport-u9y2npiy.mjs → crashreport-BqyvFk-_.mjs} +2 -2
- package/dist/{crashreport-u9y2npiy.mjs.map → crashreport-BqyvFk-_.mjs.map} +1 -1
- package/dist/{crashreport-6jpCceOF.mjs → crashreport-BwF8cHF0.mjs} +1 -1
- package/dist/enum-constants-C7DaWeQo.mjs.map +1 -1
- package/dist/field-C4zdJLW5.mjs.map +1 -1
- package/dist/file-utils-BHPxPXmn.mjs.map +1 -1
- package/dist/{idp-BlBPtXJ-.d.mts → idp-BmYwCXnJ.d.mts} +30 -3
- package/dist/{idp-BZPqpcYY.mjs → idp-ynUfzwpz.mjs} +9 -1
- package/dist/idp-ynUfzwpz.mjs.map +1 -0
- package/dist/{index-DvEUb3pX.d.mts → index-B7VbJm0_.d.mts} +25 -16
- package/dist/{index-DRhMpdnA.d.mts → index-dKNk8hjo.d.mts} +2 -2
- package/dist/job-BpsFXPbi.mjs.map +1 -1
- package/dist/{kysely-type-D1e0Vwkd.mjs → kysely-type-CSoZxVKN.mjs} +2 -2
- package/dist/{kysely-type-D1e0Vwkd.mjs.map → kysely-type-CSoZxVKN.mjs.map} +1 -1
- package/dist/{logger-DpJyJvNz.mjs → logger-DKF-JsAK.mjs} +3 -3
- package/dist/{logger-DpJyJvNz.mjs.map → logger-DKF-JsAK.mjs.map} +1 -1
- package/dist/{mock-DMgIygjE.mjs → mock-wf5qeZLi.mjs} +19 -9
- package/dist/mock-wf5qeZLi.mjs.map +1 -0
- package/dist/plugin/builtin/kysely-type/index.mjs +1 -1
- package/dist/plugin/index.mjs.map +1 -1
- package/dist/registry-D0uB0OrK.mjs.map +1 -1
- package/dist/{repl-editor-CJG3sz7A.mjs → repl-editor-DD5YP5mt.mjs} +4 -4
- package/dist/{repl-editor-CJG3sz7A.mjs.map → repl-editor-DD5YP5mt.mjs.map} +1 -1
- package/dist/runtime/globals.d.mts +3 -2
- package/dist/runtime/idp.d.mts +2 -2
- package/dist/runtime/idp.mjs +1 -1
- package/dist/runtime/index.d.mts +2 -2
- package/dist/runtime/index.mjs +1 -1
- package/dist/{runtime-BU6KtCvk.mjs → runtime-jowoN6qC.mjs} +803 -226
- package/dist/runtime-jowoN6qC.mjs.map +1 -0
- package/dist/schema-1msIhXwA.mjs.map +1 -1
- package/dist/seed-YAbtMy65.mjs.map +1 -1
- package/dist/{service-wI3Hvrgx.mjs → service-B2Jd9CxS.mjs} +2 -2
- package/dist/service-B2Jd9CxS.mjs.map +1 -0
- package/dist/service-CRaa4Joe.mjs +4 -0
- package/dist/{service-DMohAx8a.mjs → service-DDWgZL_L2.mjs} +2 -2
- package/dist/service-DDWgZL_L2.mjs.map +1 -0
- package/dist/service_pb-DGSmn-aF.mjs +4 -0
- package/dist/{application-WpWwTyk9.mjs → service_pb-DSNjrcbW.mjs} +22 -6176
- package/dist/service_pb-DSNjrcbW.mjs.map +1 -0
- package/dist/telemetry-BQbbVo2t.mjs.map +1 -1
- package/dist/types-CmzfQP_m.mjs.map +1 -1
- package/dist/utils/test/index.d.mts +2 -2
- package/dist/utils/test/index.mjs.map +1 -1
- package/dist/vitest/environment.mjs +1 -1
- package/dist/vitest/environment.mjs.map +1 -1
- package/dist/vitest/index.mjs +4 -4
- package/dist/vitest/index.mjs.map +1 -1
- package/dist/vitest/setup.mjs +1 -1
- package/dist/{workflow.generated-1S50BhEb.d.mts → workflow.generated-Br9bmLdX.d.mts} +98 -3
- package/docs/cli/application.md +5 -202
- package/docs/cli/auth.md +12 -256
- package/docs/cli/completion.md +0 -24
- package/docs/cli/crashreport.md +0 -58
- package/docs/cli/executor.md +53 -164
- package/docs/cli/function.md +2 -118
- package/docs/cli/organization.md +1 -211
- package/docs/cli/query.md +0 -20
- package/docs/cli/secret.md +70 -250
- package/docs/cli/setup.md +21 -59
- package/docs/cli/skills.md +0 -39
- package/docs/cli/staticwebsite.md +24 -172
- package/docs/cli/tailordb.md +5 -255
- package/docs/cli/upgrade.md +0 -20
- package/docs/cli/user.md +32 -247
- package/docs/cli/workflow.md +139 -161
- package/docs/cli/workspace.md +158 -537
- package/docs/cli-reference.md +59 -40
- package/docs/configuration.md +7 -1
- package/docs/github-actions.md +27 -14
- package/docs/services/idp.md +55 -2
- package/docs/services/staticwebsite.md +7 -1
- package/package.json +23 -18
- package/dist/application-Djeezk3m.mjs +0 -4
- package/dist/application-WpWwTyk9.mjs.map +0 -1
- package/dist/idp-BZPqpcYY.mjs.map +0 -1
- package/dist/mock-DMgIygjE.mjs.map +0 -1
- package/dist/runtime-BU6KtCvk.mjs.map +0 -1
- package/dist/service-BHQIerYh.mjs +0 -4
- package/dist/service-DMohAx8a.mjs.map +0 -1
- package/dist/service-wI3Hvrgx.mjs.map +0 -1
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
|
|
2
2
|
import { t as db } from "./schema-1msIhXwA.mjs";
|
|
3
|
-
import { $ as
|
|
3
|
+
import { $ as CreateUserProfileConfigRequestSchema, A as UpdatePipelineServiceRequestSchema, At as PageDirection, B as UpdateExecutorExecutorRequestSchema, Ct as GetApplicationSchemaHealthResponse_ApplicationSchemaHealthStatus, D as CreatePipelineResolverRequestSchema, Dt as ConditionSchema, E as UpdateSecretManagerSecretRequestSchema, Et as Subgraph_ServiceType, F as IdPPermissionOperator, G as CreateAuthHookRequestSchema, H as ExecutorTargetType, I as IdPPermissionPermit, J as CreateAuthOAuth2ClientRequestSchema, K as CreateAuthIDPConfigRequestSchema, L as FunctionExecution_Status, M as CreateIdPServiceRequestSchema, N as UpdateIdPServiceRequestSchema, O as CreatePipelineServiceRequestSchema, Ot as Condition_Operator, P as IdPLang, Q as CreateTenantConfigRequestSchema, S as UpdateStaticWebsiteRequestSchema, St as CreateApplicationRequestSchema, T as CreateSecretManagerVaultRequestSchema, Tt as ApplicationSchemaUpdateAttemptStatus, U as ExecutorTriggerType, V as ExecutorJobStatus, W as CreateAuthConnectionRequestSchema, X as CreateAuthSCIMResourceRequestSchema, Y as CreateAuthSCIMConfigRequestSchema, Z as CreateAuthServiceRequestSchema, _ as TailorDBType_Permission_Operator, _t as AuthSCIMAttribute_Uniqueness, a as WorkspacePlatformUserRole, at as UpdateAuthSCIMResourceRequestSchema, b as AddCustomDomainRequestSchema, bt as TenantProviderConfig_TenantProviderType, c as UpdateWorkflowRequestSchema, ct as UpdateUserProfileConfigRequestSchema, d as CreateTailorDBServiceRequestSchema, dt as AuthIDPConfig_AuthType, et as UpdateAuthHookRequestSchema, f as CreateTailorDBTypeRequestSchema, ft as AuthInvokerSchema, g as TailorDBGQLPermission_Permit, gt as AuthSCIMAttribute_Type, h as TailorDBGQLPermission_Operator, ht as AuthSCIMAttribute_Mutability, it as UpdateAuthSCIMConfigRequestSchema, j as PipelineResolver_OperationType, k as UpdatePipelineResolverRequestSchema, kt as FilterSchema, l as WorkflowExecution_Status, lt as AuthConnection_Type, m as TailorDBGQLPermission_Action, mt as AuthOAuth2Client_GrantType, nt as UpdateAuthMachineUserRequestSchema, o as CreateWorkflowJobFunctionRequestSchema, ot as UpdateAuthServiceRequestSchema, p as UpdateTailorDBTypeRequestSchema, pt as AuthOAuth2Client_ClientType, q as CreateAuthMachineUserRequestSchema, rt as UpdateAuthOAuth2ClientRequestSchema, s as CreateWorkflowRequestSchema, st as UpdateTenantConfigRequestSchema, t as OperatorService, tt as UpdateAuthIDPConfigRequestSchema, u as WorkflowJobExecution_Status, ut as AuthHookPoint, v as TailorDBType_Permission_Permit, vt as AuthSCIMConfig_AuthorizationType, w as CreateSecretManagerSecretRequestSchema, wt as UpdateApplicationRequestSchema, x as CreateStaticWebsiteRequestSchema, xt as UserProfileProviderConfig_UserProfileProviderType, y as TailorDBType_PermitAction, z as CreateExecutorExecutorRequestSchema } from "./service_pb-DSNjrcbW.mjs";
|
|
4
4
|
import { t as assertDefined } from "./assert-CKfwrmCV.mjs";
|
|
5
|
-
import { a as parseBoolean, i as symbols, n as logger, r as styles, t as CIPromptError } from "./logger-
|
|
6
|
-
import {
|
|
5
|
+
import { a as parseBoolean, i as symbols, n as logger, r as styles, t as CIPromptError } from "./logger-DKF-JsAK.mjs";
|
|
6
|
+
import { A as loadMachineUserName, F as writePlatformConfig, G as resolveStaticWebsiteUrls, K as byName, L as fetchAll, M as readPlatformConfig, O as loadAccessToken, R as fetchMachineUserToken, S as getDistDir, T as loadConfig, U as initOperatorClient, W as platformBaseUrl, b as hasGenerationHooks, d as assertUniqueLocalTailorDBTypeNames, f as assertUniqueTailorDBTypeNamesWithExternal, h as platformBundleDefinePlugin, j as loadWorkspaceId, k as loadConfigPath, l as buildExecutorArgsExpr, m as stringifyFunction, n as generatePluginFilesIfNeeded, p as TailorDBTypeSchema, r as loadApplication, s as HTTP_METHODS, t as defineApplication, u as buildResolverOperationHookExpr, w as hashFile, x as createBundleCache, y as getPluginGenerationDependencies, z as fetchPaged } from "./application-Cr-limKC.mjs";
|
|
7
|
+
import { o as loadFilesWithIgnores, t as createExecutorService } from "./service-B2Jd9CxS.mjs";
|
|
7
8
|
import { t as multiline } from "./multiline-Cf9ODpr1.mjs";
|
|
8
9
|
import { t as readPackageJson } from "./package-json-DcQApfPQ.mjs";
|
|
9
10
|
import { i as userAgent } from "./secret-file-eB3R3Fil.mjs";
|
|
@@ -39,6 +40,7 @@ import * as inflection from "inflection";
|
|
|
39
40
|
import { pathToString } from "@bufbuild/protobuf/reflect";
|
|
40
41
|
import { createValidator } from "@bufbuild/protovalidate";
|
|
41
42
|
import { setTimeout as setTimeout$1 } from "timers/promises";
|
|
43
|
+
import { setTimeout as setTimeout$2 } from "node:timers/promises";
|
|
42
44
|
import { spawn } from "node:child_process";
|
|
43
45
|
import { watch } from "chokidar";
|
|
44
46
|
import * as madgeModule from "madge";
|
|
@@ -384,7 +386,7 @@ function nestedMessage(field) {
|
|
|
384
386
|
function isWellKnownType(message) {
|
|
385
387
|
return message.typeName.startsWith("google.protobuf.");
|
|
386
388
|
}
|
|
387
|
-
const UNREPRESENTABLE_WELL_KNOWN_TYPES = new Set([
|
|
389
|
+
const UNREPRESENTABLE_WELL_KNOWN_TYPES = /* @__PURE__ */ new Set([
|
|
388
390
|
"google.protobuf.Struct",
|
|
389
391
|
"google.protobuf.Value",
|
|
390
392
|
"google.protobuf.ListValue",
|
|
@@ -567,7 +569,7 @@ function fieldToJson(field, visited) {
|
|
|
567
569
|
return json;
|
|
568
570
|
}
|
|
569
571
|
function renderInspectJson(method) {
|
|
570
|
-
const visited = new Set([method.input]);
|
|
572
|
+
const visited = /* @__PURE__ */ new Set([method.input]);
|
|
571
573
|
return {
|
|
572
574
|
method: method.name,
|
|
573
575
|
input: {
|
|
@@ -598,7 +600,7 @@ function renderInspectText(method) {
|
|
|
598
600
|
const lines = [];
|
|
599
601
|
lines.push(`${method.name}`);
|
|
600
602
|
lines.push(` request: ${method.input.typeName}`);
|
|
601
|
-
const visited = new Set([method.input]);
|
|
603
|
+
const visited = /* @__PURE__ */ new Set([method.input]);
|
|
602
604
|
for (const f of method.input.fields) lines.push(...renderFieldText(f, " ", visited));
|
|
603
605
|
lines.push(` response: ${method.output.typeName}`);
|
|
604
606
|
return lines.join("\n");
|
|
@@ -749,7 +751,7 @@ function normalizeBodyFieldKeys(body, fields) {
|
|
|
749
751
|
}
|
|
750
752
|
return changed;
|
|
751
753
|
}
|
|
752
|
-
const FORBIDDEN_SEGMENTS = new Set([
|
|
754
|
+
const FORBIDDEN_SEGMENTS = /* @__PURE__ */ new Set([
|
|
753
755
|
"__proto__",
|
|
754
756
|
"constructor",
|
|
755
757
|
"prototype"
|
|
@@ -3161,7 +3163,8 @@ function normalizeIdPPermission(permission) {
|
|
|
3161
3163
|
read: permission.read.map((p) => normalizeIdPActionPermission(p)),
|
|
3162
3164
|
update: permission.update.map((p) => normalizeIdPActionPermission(p)),
|
|
3163
3165
|
delete: permission.delete.map((p) => normalizeIdPActionPermission(p)),
|
|
3164
|
-
sendPasswordResetEmail: permission.sendPasswordResetEmail.map((p) => normalizeIdPActionPermission(p))
|
|
3166
|
+
sendPasswordResetEmail: (permission.sendPasswordResetEmail ?? []).map((p) => normalizeIdPActionPermission(p)),
|
|
3167
|
+
unenrollMfa: (permission.unenrollMfa ?? []).map((p) => normalizeIdPActionPermission(p))
|
|
3165
3168
|
};
|
|
3166
3169
|
}
|
|
3167
3170
|
/**
|
|
@@ -3187,7 +3190,7 @@ function parseIdPPermission(rawPermission) {
|
|
|
3187
3190
|
function findOmittedPermitRules(permission) {
|
|
3188
3191
|
if (!permission) return [];
|
|
3189
3192
|
const locations = [];
|
|
3190
|
-
for (const action of Object.keys(permission)) permission[action]
|
|
3193
|
+
for (const action of Object.keys(permission)) permission[action]?.forEach((rule, index) => {
|
|
3191
3194
|
if (isObjectFormat(rule) && rule.permit === void 0) locations.push(`${String(action)}[${index}]`);
|
|
3192
3195
|
});
|
|
3193
3196
|
return locations;
|
|
@@ -3195,6 +3198,14 @@ function findOmittedPermitRules(permission) {
|
|
|
3195
3198
|
|
|
3196
3199
|
//#endregion
|
|
3197
3200
|
//#region src/cli/commands/deploy/idp.ts
|
|
3201
|
+
async function resolveServiceReturnOrigins(client, request) {
|
|
3202
|
+
const policy = request.userAuthPolicy;
|
|
3203
|
+
const originals = policy?.allowedReturnOrigins;
|
|
3204
|
+
if (!policy || !originals?.length) return;
|
|
3205
|
+
const resolved = await resolveStaticWebsiteUrls(client, assertDefined(request.workspaceId, "request missing workspaceId"), originals, `IdP service "${request.namespaceName ?? ""}" allowedReturnOrigins`);
|
|
3206
|
+
if (resolved.length !== originals.length) throw new Error(`IdP service "${request.namespaceName ?? ""}" allowedReturnOrigins: ${originals.length - resolved.length} of ${originals.length} entries could not be resolved. Check that each "<name>:url" entry refers to a deployed static website.`);
|
|
3207
|
+
policy.allowedReturnOrigins = resolved;
|
|
3208
|
+
}
|
|
3198
3209
|
/**
|
|
3199
3210
|
* Build the vault name for an IdP client.
|
|
3200
3211
|
* @param namespaceName - IdP namespace name
|
|
@@ -3224,9 +3235,11 @@ async function applyIdP(client, result, phase = "create-update") {
|
|
|
3224
3235
|
const { changeSet } = result;
|
|
3225
3236
|
if (phase === "create-update") {
|
|
3226
3237
|
await Promise.all([...changeSet.service.creates.map(async (create) => {
|
|
3238
|
+
await resolveServiceReturnOrigins(client, create.request);
|
|
3227
3239
|
await client.createIdPService(create.request);
|
|
3228
3240
|
await client.setMetadata(create.metaRequest);
|
|
3229
3241
|
}), ...changeSet.service.updates.map(async (update) => {
|
|
3242
|
+
await resolveServiceReturnOrigins(client, update.request);
|
|
3230
3243
|
await client.updateIdPService(update.request);
|
|
3231
3244
|
await client.setMetadata(update.metaRequest);
|
|
3232
3245
|
})]);
|
|
@@ -3285,7 +3298,8 @@ async function applyIdP(client, result, phase = "create-update") {
|
|
|
3285
3298
|
async function planIdP(context) {
|
|
3286
3299
|
const { client, workspaceId, application, forRemoval, forceApplyAll = false, idpUserTriggerTargets } = context;
|
|
3287
3300
|
const idps = forRemoval ? [] : application.idpServices;
|
|
3288
|
-
const
|
|
3301
|
+
const expectedLocalWebsites = new Set(application.staticWebsiteServices.map((website) => website.name));
|
|
3302
|
+
const { changeSet: serviceChangeSet, conflicts, unmanaged, resourceOwners } = await planServices$3(client, workspaceId, application.name, application.id, idps, idpUserTriggerTargets ?? /* @__PURE__ */ new Set(), expectedLocalWebsites);
|
|
3289
3303
|
return {
|
|
3290
3304
|
changeSet: {
|
|
3291
3305
|
service: serviceChangeSet,
|
|
@@ -3309,7 +3323,11 @@ function normalizeComparableUserAuthPolicy(policy) {
|
|
|
3309
3323
|
allowedEmailDomains: (policy?.allowedEmailDomains ?? []).toSorted(),
|
|
3310
3324
|
allowGoogleOauth: policy?.allowGoogleOauth ?? false,
|
|
3311
3325
|
disablePasswordAuth: policy?.disablePasswordAuth ?? false,
|
|
3312
|
-
allowMicrosoftOauth: policy?.allowMicrosoftOauth ?? false
|
|
3326
|
+
allowMicrosoftOauth: policy?.allowMicrosoftOauth ?? false,
|
|
3327
|
+
enableMfa: policy?.enableMfa ?? false,
|
|
3328
|
+
requireMfa: policy?.requireMfa ?? false,
|
|
3329
|
+
allowedReturnOrigins: (policy?.allowedReturnOrigins ?? []).toSorted(),
|
|
3330
|
+
mfaIssuer: policy?.mfaIssuer ?? ""
|
|
3313
3331
|
};
|
|
3314
3332
|
}
|
|
3315
3333
|
function normalizeComparableDisableGqlOperations(value) {
|
|
@@ -3318,7 +3336,9 @@ function normalizeComparableDisableGqlOperations(value) {
|
|
|
3318
3336
|
update: value?.update ?? false,
|
|
3319
3337
|
delete: value?.delete ?? false,
|
|
3320
3338
|
read: value?.read ?? false,
|
|
3321
|
-
sendPasswordResetEmail: value?.sendPasswordResetEmail ?? false
|
|
3339
|
+
sendPasswordResetEmail: value?.sendPasswordResetEmail ?? false,
|
|
3340
|
+
requestMfaSettingsUrl: value?.requestMfaSettingsUrl ?? false,
|
|
3341
|
+
unenrollMfa: value?.unenrollMfa ?? false
|
|
3322
3342
|
};
|
|
3323
3343
|
}
|
|
3324
3344
|
function normalizeComparableEmailConfig(value) {
|
|
@@ -3340,7 +3360,7 @@ function normalizeComparableIdPService(input) {
|
|
|
3340
3360
|
}
|
|
3341
3361
|
function normalizeComparablePermission(permission) {
|
|
3342
3362
|
if (!permission) return;
|
|
3343
|
-
if (permission.create.length === 0 && permission.read.length === 0 && permission.update.length === 0 && permission.delete.length === 0 && permission.sendPasswordResetEmail.length === 0) return;
|
|
3363
|
+
if (permission.create.length === 0 && permission.read.length === 0 && permission.update.length === 0 && permission.delete.length === 0 && permission.sendPasswordResetEmail.length === 0 && permission.unenrollMfa.length === 0) return;
|
|
3344
3364
|
const normalizePolicy = (policy) => ({
|
|
3345
3365
|
conditions: policy.conditions.map((c) => ({
|
|
3346
3366
|
left: c.left ? { kind: c.left.kind } : void 0,
|
|
@@ -3355,7 +3375,8 @@ function normalizeComparablePermission(permission) {
|
|
|
3355
3375
|
read: permission.read.map(normalizePolicy),
|
|
3356
3376
|
update: permission.update.map(normalizePolicy),
|
|
3357
3377
|
delete: permission.delete.map(normalizePolicy),
|
|
3358
|
-
sendPasswordResetEmail: permission.sendPasswordResetEmail.map(normalizePolicy)
|
|
3378
|
+
sendPasswordResetEmail: permission.sendPasswordResetEmail.map(normalizePolicy),
|
|
3379
|
+
unenrollMfa: permission.unenrollMfa.map(normalizePolicy)
|
|
3359
3380
|
};
|
|
3360
3381
|
}
|
|
3361
3382
|
function areIdPServicesEqual(existing, desired) {
|
|
@@ -3369,7 +3390,7 @@ function areIdPServicesEqual(existing, desired) {
|
|
|
3369
3390
|
permission: normalizeComparablePermission(existing.permission)
|
|
3370
3391
|
}), desired);
|
|
3371
3392
|
}
|
|
3372
|
-
async function planServices$3(client, workspaceId, appName, appId, idps, idpUserTriggerTargets) {
|
|
3393
|
+
async function planServices$3(client, workspaceId, appName, appId, idps, idpUserTriggerTargets, expectedLocalWebsites) {
|
|
3373
3394
|
const changeSet = createChangeSet("IdP services");
|
|
3374
3395
|
const conflicts = [];
|
|
3375
3396
|
const unmanaged = [];
|
|
@@ -3431,10 +3452,15 @@ async function planServices$3(client, workspaceId, appName, appId, idps, idpUser
|
|
|
3431
3452
|
if (omittedPermitLocations.length > 0) logger.warn(`IdP service "${namespaceName}" has permission rule(s) ${omittedPermitLocations.join(", ")} in object form without an explicit "permit"; they default to "deny". Set permit: true (allow) or permit: false (deny) to silence this warning.`);
|
|
3432
3453
|
const parsedPermission = parseIdPPermission(idp.permission);
|
|
3433
3454
|
const protoPermission = parsedPermission ? protoIdPPermission(parsedPermission) : void 0;
|
|
3455
|
+
const resolvedReturnOrigins = await resolveStaticWebsiteUrls(client, workspaceId, userAuthPolicy?.allowedReturnOrigins ? [...userAuthPolicy.allowedReturnOrigins] : [], `IdP service "${namespaceName}" allowedReturnOrigins`, { expectedLocalNames: expectedLocalWebsites });
|
|
3456
|
+
const userAuthPolicyForCompare = userAuthPolicy ? {
|
|
3457
|
+
...userAuthPolicy,
|
|
3458
|
+
allowedReturnOrigins: resolvedReturnOrigins
|
|
3459
|
+
} : userAuthPolicy;
|
|
3434
3460
|
const desired = normalizeComparableIdPService({
|
|
3435
3461
|
authorization,
|
|
3436
3462
|
lang,
|
|
3437
|
-
userAuthPolicy: normalizeComparableUserAuthPolicy(
|
|
3463
|
+
userAuthPolicy: normalizeComparableUserAuthPolicy(userAuthPolicyForCompare),
|
|
3438
3464
|
publishUserEvents,
|
|
3439
3465
|
disableGqlOperations: normalizeComparableDisableGqlOperations(convertGqlOperationsToDisable(idp.gqlOperations)),
|
|
3440
3466
|
emailConfig: normalizeComparableEmailConfig(emailConfig),
|
|
@@ -3576,7 +3602,9 @@ function convertGqlOperationsToDisable(gqlOperations) {
|
|
|
3576
3602
|
update: gqlOperations.update === false,
|
|
3577
3603
|
delete: gqlOperations.delete === false,
|
|
3578
3604
|
read: gqlOperations.read === false,
|
|
3579
|
-
sendPasswordResetEmail: gqlOperations.sendPasswordResetEmail === false
|
|
3605
|
+
sendPasswordResetEmail: gqlOperations.sendPasswordResetEmail === false,
|
|
3606
|
+
requestMfaSettingsUrl: gqlOperations.requestMfaSettingsUrl === false,
|
|
3607
|
+
unenrollMfa: gqlOperations.unenrollMfa === false
|
|
3580
3608
|
};
|
|
3581
3609
|
}
|
|
3582
3610
|
function protoIdPPermission(permission) {
|
|
@@ -3585,7 +3613,8 @@ function protoIdPPermission(permission) {
|
|
|
3585
3613
|
read: permission.read.map((p) => protoIdPPolicy(p)),
|
|
3586
3614
|
update: permission.update.map((p) => protoIdPPolicy(p)),
|
|
3587
3615
|
delete: permission.delete.map((p) => protoIdPPolicy(p)),
|
|
3588
|
-
sendPasswordResetEmail: permission.sendPasswordResetEmail.map((p) => protoIdPPolicy(p))
|
|
3616
|
+
sendPasswordResetEmail: permission.sendPasswordResetEmail.map((p) => protoIdPPolicy(p)),
|
|
3617
|
+
unenrollMfa: permission.unenrollMfa.map((p) => protoIdPPolicy(p))
|
|
3589
3618
|
};
|
|
3590
3619
|
}
|
|
3591
3620
|
function protoIdPPolicy(policy) {
|
|
@@ -3756,7 +3785,7 @@ async function planAuth(context) {
|
|
|
3756
3785
|
},
|
|
3757
3786
|
conflicts: [...conflicts, ...connectionResult.conflicts],
|
|
3758
3787
|
unmanaged: [...unmanaged, ...connectionResult.unmanaged],
|
|
3759
|
-
resourceOwners: new Set([...resourceOwners, ...connectionResult.resourceOwners])
|
|
3788
|
+
resourceOwners: /* @__PURE__ */ new Set([...resourceOwners, ...connectionResult.resourceOwners])
|
|
3760
3789
|
};
|
|
3761
3790
|
}
|
|
3762
3791
|
async function planServices$2(client, workspaceId, appName, appId, auths, forceApplyAll = false) {
|
|
@@ -4891,7 +4920,7 @@ async function readConfigId(configPath) {
|
|
|
4891
4920
|
async function assertConfigIdInCI(configPath) {
|
|
4892
4921
|
const result = await readConfigId(configPath);
|
|
4893
4922
|
if (result === null) return;
|
|
4894
|
-
if (!result.id) throw new Error("tailor.config.ts is missing an 'id'. CI does not auto-generate one (each run would be treated as a separate app and break resource ownership). Run 'tailor-sdk setup
|
|
4923
|
+
if (!result.id) throw new Error("tailor.config.ts is missing an 'id'. CI does not auto-generate one (each run would be treated as a separate app and break resource ownership). Run 'tailor-sdk setup' or 'tailor-sdk apply' locally and commit the injected id.");
|
|
4895
4924
|
if (!uuidRegex.test(result.id)) throw new Error(`'id' in ${configPath} must be a UUID. To use this config for a separate app, delete it.`);
|
|
4896
4925
|
}
|
|
4897
4926
|
/**
|
|
@@ -6975,7 +7004,7 @@ function createSnapshotFieldConfig(field) {
|
|
|
6975
7004
|
}
|
|
6976
7005
|
/**
|
|
6977
7006
|
* Create a snapshot field config from an OperatorFieldConfig (for nested fields)
|
|
6978
|
-
* @param {import("
|
|
7007
|
+
* @param {import("#/parser/service/tailordb/types").OperatorFieldConfig} fieldConfig - Field configuration
|
|
6979
7008
|
* @returns {SnapshotFieldConfig} Snapshot field configuration
|
|
6980
7009
|
*/
|
|
6981
7010
|
function createSnapshotFieldConfigFromOperatorConfig(fieldConfig) {
|
|
@@ -7825,7 +7854,7 @@ function validateMigrationFiles(migrationsDir) {
|
|
|
7825
7854
|
message: `Schema file found at migration ${formatMigrationNumber(num)}, but schema should only exist at ${formatMigrationNumber(0)}`,
|
|
7826
7855
|
migrationNumber: num
|
|
7827
7856
|
});
|
|
7828
|
-
const allNumbers = [
|
|
7857
|
+
const allNumbers = [.../* @__PURE__ */ new Set([...schemaFiles, ...diffFiles])].toSorted((a, b) => a - b);
|
|
7829
7858
|
if (allNumbers.length === 0) return errors;
|
|
7830
7859
|
for (const num of schemaFiles) if (num !== 0 && diffFiles.includes(num)) errors.push({
|
|
7831
7860
|
type: "duplicate",
|
|
@@ -7957,7 +7986,7 @@ function compareFields(typeName, fieldName, remoteField, snapshotField) {
|
|
|
7957
7986
|
/**
|
|
7958
7987
|
* System fields that are auto-generated and should be excluded from comparison
|
|
7959
7988
|
*/
|
|
7960
|
-
const SYSTEM_FIELDS = new Set(["id"]);
|
|
7989
|
+
const SYSTEM_FIELDS = /* @__PURE__ */ new Set(["id"]);
|
|
7961
7990
|
/**
|
|
7962
7991
|
* Compare remote TailorDB types with a local snapshot
|
|
7963
7992
|
* @param {ProtoTailorDBType[]} remoteTypes - Remote types from listParsedTailorDBTypes API
|
|
@@ -8485,7 +8514,7 @@ function protoGqlOperand(operand) {
|
|
|
8485
8514
|
/**
|
|
8486
8515
|
* Diff change kinds that require pre-migration schema adjustments.
|
|
8487
8516
|
*/
|
|
8488
|
-
const PRE_MIGRATION_FIELD_KINDS = new Set([
|
|
8517
|
+
const PRE_MIGRATION_FIELD_KINDS = /* @__PURE__ */ new Set([
|
|
8489
8518
|
"field_added",
|
|
8490
8519
|
"field_modified",
|
|
8491
8520
|
"field_removed"
|
|
@@ -8700,7 +8729,7 @@ const DEFAULT_POLL_INTERVAL = 1e3;
|
|
|
8700
8729
|
* @returns {Promise<ExecutionWaitResult>} Execution result
|
|
8701
8730
|
* @throws {Error} If execution is not found
|
|
8702
8731
|
*/
|
|
8703
|
-
async function waitForExecution
|
|
8732
|
+
async function waitForExecution(client, workspaceId, executionId, pollInterval = DEFAULT_POLL_INTERVAL) {
|
|
8704
8733
|
while (true) {
|
|
8705
8734
|
const { execution } = await client.getFunctionExecution({
|
|
8706
8735
|
workspaceId,
|
|
@@ -8735,7 +8764,7 @@ async function executeScript(options) {
|
|
|
8735
8764
|
invoker
|
|
8736
8765
|
});
|
|
8737
8766
|
const executionId = response.executionId;
|
|
8738
|
-
const result = await waitForExecution
|
|
8767
|
+
const result = await waitForExecution(client, workspaceId, executionId, pollInterval);
|
|
8739
8768
|
if (result.status === FunctionExecution_Status.SUCCESS) return {
|
|
8740
8769
|
success: true,
|
|
8741
8770
|
logs: result.logs,
|
|
@@ -9628,7 +9657,7 @@ async function rollbackSingleMigrationPrePhase(client, changeSet, migration, wor
|
|
|
9628
9657
|
const name = update.request.tailordbType?.name;
|
|
9629
9658
|
if (update.request.namespaceName === migration.namespace && name) namespaceTypes.add(name);
|
|
9630
9659
|
}
|
|
9631
|
-
const applied = new Set([...processedTypes.created, ...processedTypes.updated]);
|
|
9660
|
+
const applied = /* @__PURE__ */ new Set([...processedTypes.created, ...processedTypes.updated]);
|
|
9632
9661
|
const rollbackTypes = new Set([...namespaceTypes].filter((name) => applied.has(name)));
|
|
9633
9662
|
if (rollbackTypes.size === 0) return;
|
|
9634
9663
|
const priorSnapshot = reconstructSnapshotFromMigrations(migration.migrationsDir, migration.number - 1);
|
|
@@ -9949,7 +9978,7 @@ const tailordbCompareKnownDefaults = {
|
|
|
9949
9978
|
* Proto bigint-backed values can round-trip as numbers locally and strings remotely.
|
|
9950
9979
|
* Canonicalize them to strings at compare time.
|
|
9951
9980
|
*/
|
|
9952
|
-
numericStringPaths: new Set([
|
|
9981
|
+
numericStringPaths: /* @__PURE__ */ new Set([
|
|
9953
9982
|
"schema.fields.*.serial.start",
|
|
9954
9983
|
"schema.fields.*.serial.maxValue",
|
|
9955
9984
|
"schema.settings.defaultQueryLimitSize",
|
|
@@ -10529,8 +10558,13 @@ function validateItems(params) {
|
|
|
10529
10558
|
*
|
|
10530
10559
|
* Collections not validated: idp client, tailorDB gqlPermission, functionRegistry — no
|
|
10531
10560
|
* buf.validate annotations.
|
|
10532
|
-
* Application cors
|
|
10533
|
-
*
|
|
10561
|
+
* Application cors and IdP userAuthPolicy.allowedReturnOrigins receive special
|
|
10562
|
+
* handling: static-website URL placeholders are resolved at apply time, so the
|
|
10563
|
+
* relevant origin/URL constraints would false-positive on `<name>:url` entries
|
|
10564
|
+
* here. Application cors is dropped entirely (no other constraint to lose); IdP
|
|
10565
|
+
* `allowedReturnOrigins` substitutes placeholder entries with a dummy origin so
|
|
10566
|
+
* the per-item regex and the cross-field `enable_mfa requires ≥1 origin` rule
|
|
10567
|
+
* still get exercised on the rest of the payload.
|
|
10534
10568
|
* Workflow jobFunctions map excluded: versions are registered at apply time (registerJobFunctions)
|
|
10535
10569
|
* and the map field carries no min_items constraint. Job names are validated separately via
|
|
10536
10570
|
* CreateWorkflowJobFunctionRequestSchema using usedJobNames from the workflow change set.
|
|
@@ -10582,8 +10616,25 @@ async function validatePlan(input) {
|
|
|
10582
10616
|
creates(CreateStaticWebsiteRequestSchema, "StaticWebsite", staticWebsite.changeSet.creates);
|
|
10583
10617
|
updates(UpdateStaticWebsiteRequestSchema, "StaticWebsite", staticWebsite.changeSet.updates);
|
|
10584
10618
|
creates(AddCustomDomainRequestSchema, "StaticWebsite custom domain", staticWebsite.customDomainChangeSet.creates);
|
|
10585
|
-
|
|
10586
|
-
|
|
10619
|
+
const placeholderOriginReplacement = "https://placeholder.invalid";
|
|
10620
|
+
const substituteIdpReturnOrigins = (item) => {
|
|
10621
|
+
const request = item.request;
|
|
10622
|
+
const origins = request.userAuthPolicy?.allowedReturnOrigins;
|
|
10623
|
+
if (!Array.isArray(origins) || origins.length === 0) return item;
|
|
10624
|
+
const substituted = origins.map((origin) => typeof origin === "string" && /^[a-z0-9][a-z0-9-]{1,61}[a-z0-9]:url$/.test(origin) ? placeholderOriginReplacement : origin);
|
|
10625
|
+
return {
|
|
10626
|
+
...item,
|
|
10627
|
+
request: {
|
|
10628
|
+
...request,
|
|
10629
|
+
userAuthPolicy: {
|
|
10630
|
+
...request.userAuthPolicy,
|
|
10631
|
+
allowedReturnOrigins: substituted
|
|
10632
|
+
}
|
|
10633
|
+
}
|
|
10634
|
+
};
|
|
10635
|
+
};
|
|
10636
|
+
creates(CreateIdPServiceRequestSchema, "IdP service", idp.changeSet.service.creates.map(substituteIdpReturnOrigins));
|
|
10637
|
+
updates(UpdateIdPServiceRequestSchema, "IdP service", idp.changeSet.service.updates.map(substituteIdpReturnOrigins));
|
|
10587
10638
|
const idpClientVaultItems = [...idp.changeSet.client.creates.map((c) => ({
|
|
10588
10639
|
clientName: c.request.client?.name ?? "",
|
|
10589
10640
|
namespaceName: c.request.namespaceName ?? "",
|
|
@@ -11064,7 +11115,7 @@ async function deploy(options) {
|
|
|
11064
11115
|
await confirmImportantResourceDeletion(importantDeletions, yes);
|
|
11065
11116
|
const emptyApps = computeRenamedAppDeletions({
|
|
11066
11117
|
conflicts: allConflicts,
|
|
11067
|
-
resourceOwners: new Set([
|
|
11118
|
+
resourceOwners: /* @__PURE__ */ new Set([
|
|
11068
11119
|
...functionRegistry.resourceOwners,
|
|
11069
11120
|
...tailorDB.resourceOwners,
|
|
11070
11121
|
...staticWebsite.resourceOwners,
|
|
@@ -11178,7 +11229,42 @@ function colorizeExecutorJobStatus(status) {
|
|
|
11178
11229
|
* @returns True if status is terminal
|
|
11179
11230
|
*/
|
|
11180
11231
|
function isExecutorJobTerminalStatus(status) {
|
|
11181
|
-
return status
|
|
11232
|
+
return isExecutorJobSuccessStatus(status) || isExecutorJobFailureStatus(status);
|
|
11233
|
+
}
|
|
11234
|
+
/**
|
|
11235
|
+
* Check if executor job status is successful.
|
|
11236
|
+
* @param status - Executor job status enum value
|
|
11237
|
+
* @returns True if status is success
|
|
11238
|
+
*/
|
|
11239
|
+
function isExecutorJobSuccessStatus(status) {
|
|
11240
|
+
return status === ExecutorJobStatus.SUCCESS;
|
|
11241
|
+
}
|
|
11242
|
+
/**
|
|
11243
|
+
* Check if executor job status is a terminal failure.
|
|
11244
|
+
* @param status - Executor job status enum value
|
|
11245
|
+
* @returns True if status is failure
|
|
11246
|
+
*/
|
|
11247
|
+
function isExecutorJobFailureStatus(status) {
|
|
11248
|
+
return status === ExecutorJobStatus.FAILED || status === ExecutorJobStatus.CANCELED;
|
|
11249
|
+
}
|
|
11250
|
+
/**
|
|
11251
|
+
* Check if executor job status can still progress.
|
|
11252
|
+
* @param status - Executor job status enum value
|
|
11253
|
+
* @returns True if status is transient
|
|
11254
|
+
*/
|
|
11255
|
+
function isExecutorJobTransientStatus(status) {
|
|
11256
|
+
return status === ExecutorJobStatus.UNSPECIFIED || status === ExecutorJobStatus.PENDING || status === ExecutorJobStatus.RUNNING;
|
|
11257
|
+
}
|
|
11258
|
+
/**
|
|
11259
|
+
* Classify executor job status for waiter decisions.
|
|
11260
|
+
* @param status - Executor job status enum value
|
|
11261
|
+
* @returns Classified executor job status
|
|
11262
|
+
*/
|
|
11263
|
+
function classifyExecutorJobStatus(status) {
|
|
11264
|
+
if (isExecutorJobSuccessStatus(status)) return "success";
|
|
11265
|
+
if (isExecutorJobTerminalStatus(status)) return "failure";
|
|
11266
|
+
if (isExecutorJobTransientStatus(status)) return "transient";
|
|
11267
|
+
return "transient";
|
|
11182
11268
|
}
|
|
11183
11269
|
/**
|
|
11184
11270
|
* Parse executor job status string to enum.
|
|
@@ -11570,36 +11656,158 @@ function functionExecutionStatusToString(status) {
|
|
|
11570
11656
|
}
|
|
11571
11657
|
}
|
|
11572
11658
|
|
|
11659
|
+
//#endregion
|
|
11660
|
+
//#region src/cli/shared/wait-error.ts
|
|
11661
|
+
/**
|
|
11662
|
+
* Format a caught error into a string for diagnostics.
|
|
11663
|
+
* @param error - Error to format
|
|
11664
|
+
* @returns Error message string
|
|
11665
|
+
*/
|
|
11666
|
+
function formatWaitError(error) {
|
|
11667
|
+
return error instanceof Error ? error.message : String(error);
|
|
11668
|
+
}
|
|
11669
|
+
/**
|
|
11670
|
+
* Check whether a polling error is retryable (transient platform errors).
|
|
11671
|
+
* @param error - Error to check
|
|
11672
|
+
* @returns True if the error should be retried
|
|
11673
|
+
*/
|
|
11674
|
+
function isRetryableWaitError(error) {
|
|
11675
|
+
if (!(error instanceof ConnectError)) return false;
|
|
11676
|
+
return error.code === Code.Aborted || error.code === Code.ResourceExhausted || error.code === Code.Unavailable;
|
|
11677
|
+
}
|
|
11678
|
+
|
|
11573
11679
|
//#endregion
|
|
11574
11680
|
//#region src/cli/commands/workflow/args.ts
|
|
11681
|
+
const workflowWaitUntilArg = z.enum([
|
|
11682
|
+
"success",
|
|
11683
|
+
"suspended",
|
|
11684
|
+
"terminal"
|
|
11685
|
+
]);
|
|
11575
11686
|
const nameArgs = { name: arg(z.string(), {
|
|
11576
11687
|
positional: true,
|
|
11577
11688
|
description: "Workflow name"
|
|
11578
11689
|
}) };
|
|
11579
|
-
const
|
|
11580
|
-
wait: arg(z.boolean().default(false), {
|
|
11581
|
-
alias: "W",
|
|
11582
|
-
description: "Wait for execution to complete"
|
|
11583
|
-
}),
|
|
11690
|
+
const workflowWaitControlArgs = {
|
|
11584
11691
|
interval: arg(durationArg.default("3s"), {
|
|
11585
11692
|
alias: "i",
|
|
11586
|
-
description: "Polling interval when
|
|
11693
|
+
description: "Polling interval when waiting (e.g., '3s', '500ms', '1m')"
|
|
11694
|
+
}),
|
|
11695
|
+
timeout: arg(durationArg.default("10m"), {
|
|
11696
|
+
alias: "t",
|
|
11697
|
+
description: "Maximum time to wait (e.g., '30s', '10m')"
|
|
11698
|
+
}),
|
|
11699
|
+
until: arg(workflowWaitUntilArg.default("terminal"), {
|
|
11700
|
+
alias: "u",
|
|
11701
|
+
description: "Wait target (success, suspended, terminal)"
|
|
11587
11702
|
}),
|
|
11588
11703
|
logs: arg(z.boolean().default(false), {
|
|
11589
11704
|
alias: "l",
|
|
11590
|
-
description: "Display job execution logs after completion
|
|
11705
|
+
description: "Display job execution logs after completion"
|
|
11591
11706
|
})
|
|
11592
11707
|
};
|
|
11708
|
+
const waitArgs = {
|
|
11709
|
+
wait: arg(z.boolean().default(false), {
|
|
11710
|
+
alias: "W",
|
|
11711
|
+
description: "Wait for execution to complete"
|
|
11712
|
+
}),
|
|
11713
|
+
...workflowWaitControlArgs
|
|
11714
|
+
};
|
|
11593
11715
|
|
|
11594
11716
|
//#endregion
|
|
11595
11717
|
//#region src/cli/commands/workflow/status.ts
|
|
11596
11718
|
/**
|
|
11719
|
+
* Check if workflow execution status is successful.
|
|
11720
|
+
* @param status - Workflow execution status enum value
|
|
11721
|
+
* @returns True if status is success
|
|
11722
|
+
*/
|
|
11723
|
+
function isWorkflowExecutionSuccessStatus(status) {
|
|
11724
|
+
return status === WorkflowExecution_Status.SUCCESS;
|
|
11725
|
+
}
|
|
11726
|
+
/**
|
|
11727
|
+
* Check if workflow job execution status is suspended or waiting.
|
|
11728
|
+
* @param status - Workflow job execution status enum value
|
|
11729
|
+
* @returns True if status represents a wait point
|
|
11730
|
+
*/
|
|
11731
|
+
function isWorkflowJobExecutionSuspendedStatus(status) {
|
|
11732
|
+
return status === WorkflowJobExecution_Status.SUSPEND || status === WorkflowJobExecution_Status.WAITING;
|
|
11733
|
+
}
|
|
11734
|
+
/**
|
|
11735
|
+
* Check if workflow execution status is suspended or waiting.
|
|
11736
|
+
* @param status - Workflow execution status enum value
|
|
11737
|
+
* @returns True if status represents a suspended execution
|
|
11738
|
+
*/
|
|
11739
|
+
function isWorkflowExecutionSuspendedStatus(status) {
|
|
11740
|
+
return status === WorkflowExecution_Status.PENDING_RESUME || status === WorkflowExecution_Status.WAITING;
|
|
11741
|
+
}
|
|
11742
|
+
/**
|
|
11743
|
+
* Check if workflow execution status is a terminal failure.
|
|
11744
|
+
* @param status - Workflow execution status enum value
|
|
11745
|
+
* @returns True if status represents failure
|
|
11746
|
+
*/
|
|
11747
|
+
function isWorkflowExecutionFailureStatus(status) {
|
|
11748
|
+
return status === WorkflowExecution_Status.FAILED;
|
|
11749
|
+
}
|
|
11750
|
+
/**
|
|
11751
|
+
* Check if workflow execution status can still progress without user action.
|
|
11752
|
+
* @param status - Workflow execution status enum value
|
|
11753
|
+
* @returns True if status is transient
|
|
11754
|
+
*/
|
|
11755
|
+
function isWorkflowExecutionTransientStatus(status) {
|
|
11756
|
+
return status === WorkflowExecution_Status.UNSPECIFIED || status === WorkflowExecution_Status.PENDING || status === WorkflowExecution_Status.RUNNING || status === WorkflowExecution_Status.PENDING_RETRY;
|
|
11757
|
+
}
|
|
11758
|
+
/**
|
|
11597
11759
|
* Check if workflow execution status is terminal.
|
|
11598
11760
|
* @param status - Workflow execution status enum value
|
|
11599
11761
|
* @returns True if status is terminal
|
|
11600
11762
|
*/
|
|
11601
11763
|
function isWorkflowExecutionTerminalStatus(status) {
|
|
11602
|
-
return status
|
|
11764
|
+
return isWorkflowExecutionSuccessStatus(status) || isWorkflowExecutionFailureStatus(status) || isWorkflowExecutionSuspendedStatus(status);
|
|
11765
|
+
}
|
|
11766
|
+
/**
|
|
11767
|
+
* Classify workflow execution status for waiter decisions.
|
|
11768
|
+
* @param execution - Workflow execution to classify
|
|
11769
|
+
* @returns Classified workflow execution status
|
|
11770
|
+
*/
|
|
11771
|
+
function classifyWorkflowExecutionStatus(execution) {
|
|
11772
|
+
if (isWorkflowExecutionTerminalStatus(execution.status)) {
|
|
11773
|
+
if (isWorkflowExecutionSuccessStatus(execution.status)) return {
|
|
11774
|
+
statusClass: "success",
|
|
11775
|
+
status: execution.status
|
|
11776
|
+
};
|
|
11777
|
+
if (isWorkflowExecutionFailureStatus(execution.status)) return {
|
|
11778
|
+
statusClass: "failure",
|
|
11779
|
+
status: execution.status
|
|
11780
|
+
};
|
|
11781
|
+
return {
|
|
11782
|
+
statusClass: "suspended",
|
|
11783
|
+
status: execution.status
|
|
11784
|
+
};
|
|
11785
|
+
}
|
|
11786
|
+
if (execution.jobExecutions.some((job) => isWorkflowJobExecutionSuspendedStatus(job.status))) return {
|
|
11787
|
+
statusClass: "suspended",
|
|
11788
|
+
status: execution.status
|
|
11789
|
+
};
|
|
11790
|
+
if (isWorkflowExecutionTransientStatus(execution.status)) return {
|
|
11791
|
+
statusClass: "transient",
|
|
11792
|
+
status: execution.status
|
|
11793
|
+
};
|
|
11794
|
+
return {
|
|
11795
|
+
statusClass: "transient",
|
|
11796
|
+
status: execution.status
|
|
11797
|
+
};
|
|
11798
|
+
}
|
|
11799
|
+
/**
|
|
11800
|
+
* Check if a classified workflow execution has reached the requested waiter target.
|
|
11801
|
+
* @param classification - Workflow execution status classification
|
|
11802
|
+
* @param until - Requested wait target
|
|
11803
|
+
* @returns True if the wait target is reached
|
|
11804
|
+
*/
|
|
11805
|
+
function hasReachedWorkflowWaitTarget(classification, until) {
|
|
11806
|
+
switch (until) {
|
|
11807
|
+
case "success": return classification.statusClass === "success";
|
|
11808
|
+
case "suspended": return classification.statusClass === "suspended";
|
|
11809
|
+
case "terminal": return classification.statusClass === "success" || classification.statusClass === "failure" || classification.statusClass === "suspended";
|
|
11810
|
+
}
|
|
11603
11811
|
}
|
|
11604
11812
|
|
|
11605
11813
|
//#endregion
|
|
@@ -11616,6 +11824,8 @@ function workflowExecutionStatusToString(status) {
|
|
|
11616
11824
|
case WorkflowExecution_Status.RUNNING: return "RUNNING";
|
|
11617
11825
|
case WorkflowExecution_Status.SUCCESS: return "SUCCESS";
|
|
11618
11826
|
case WorkflowExecution_Status.FAILED: return "FAILED";
|
|
11827
|
+
case WorkflowExecution_Status.PENDING_RETRY: return "PENDING_RETRY";
|
|
11828
|
+
case WorkflowExecution_Status.WAITING: return "WAITING";
|
|
11619
11829
|
default: return "UNSPECIFIED";
|
|
11620
11830
|
}
|
|
11621
11831
|
}
|
|
@@ -11630,6 +11840,7 @@ function workflowJobExecutionStatusToString(status) {
|
|
|
11630
11840
|
case WorkflowJobExecution_Status.SUSPEND: return "SUSPEND";
|
|
11631
11841
|
case WorkflowJobExecution_Status.SUCCESS: return "SUCCESS";
|
|
11632
11842
|
case WorkflowJobExecution_Status.FAILED: return "FAILED";
|
|
11843
|
+
case WorkflowJobExecution_Status.WAITING: return "WAITING";
|
|
11633
11844
|
default: return "UNSPECIFIED";
|
|
11634
11845
|
}
|
|
11635
11846
|
}
|
|
@@ -11695,24 +11906,200 @@ function toWorkflowExecutionInfo(execution) {
|
|
|
11695
11906
|
}
|
|
11696
11907
|
|
|
11697
11908
|
//#endregion
|
|
11698
|
-
//#region src/cli/commands/workflow/
|
|
11699
|
-
|
|
11700
|
-
|
|
11701
|
-
}
|
|
11702
|
-
function formatTime$2(date) {
|
|
11909
|
+
//#region src/cli/commands/workflow/waiter.ts
|
|
11910
|
+
const DEFAULT_WORKFLOW_WAIT_INTERVAL_MS = 3e3;
|
|
11911
|
+
function formatTime$1(date) {
|
|
11703
11912
|
return date.toLocaleTimeString("en-US", { hour12: false });
|
|
11704
11913
|
}
|
|
11705
|
-
function colorizeStatus
|
|
11914
|
+
function colorizeStatus(status) {
|
|
11706
11915
|
const statusText = WorkflowExecution_Status[status];
|
|
11707
11916
|
switch (status) {
|
|
11708
|
-
case WorkflowExecution_Status.PENDING:
|
|
11709
|
-
case WorkflowExecution_Status.
|
|
11917
|
+
case WorkflowExecution_Status.PENDING:
|
|
11918
|
+
case WorkflowExecution_Status.UNSPECIFIED: return styles.dim(statusText);
|
|
11919
|
+
case WorkflowExecution_Status.PENDING_RESUME:
|
|
11920
|
+
case WorkflowExecution_Status.PENDING_RETRY:
|
|
11921
|
+
case WorkflowExecution_Status.WAITING: return styles.warning(statusText);
|
|
11710
11922
|
case WorkflowExecution_Status.RUNNING: return styles.info(statusText);
|
|
11711
11923
|
case WorkflowExecution_Status.SUCCESS: return styles.success(statusText);
|
|
11712
11924
|
case WorkflowExecution_Status.FAILED: return styles.error(statusText);
|
|
11713
11925
|
default: return statusText;
|
|
11714
11926
|
}
|
|
11715
11927
|
}
|
|
11928
|
+
function getActiveJobs(execution) {
|
|
11929
|
+
return execution.jobExecutions.filter((job) => job.status === WorkflowJobExecution_Status.RUNNING || job.status === WorkflowJobExecution_Status.SUSPEND || job.status === WorkflowJobExecution_Status.WAITING).map((job) => job.stackedJobName).join(", ");
|
|
11930
|
+
}
|
|
11931
|
+
function createWorkflowWaitResult(options) {
|
|
11932
|
+
const elapsedMs = Date.now() - options.startedAt;
|
|
11933
|
+
if (options.execution) {
|
|
11934
|
+
const classification = classifyWorkflowExecutionStatus(options.execution);
|
|
11935
|
+
return {
|
|
11936
|
+
...toWorkflowExecutionInfo(options.execution),
|
|
11937
|
+
statusClass: classification.statusClass,
|
|
11938
|
+
elapsedMs,
|
|
11939
|
+
attempts: options.attempts,
|
|
11940
|
+
timedOut: options.timedOut,
|
|
11941
|
+
lastError: options.lastError
|
|
11942
|
+
};
|
|
11943
|
+
}
|
|
11944
|
+
return {
|
|
11945
|
+
id: options.executionId,
|
|
11946
|
+
workflowName: "",
|
|
11947
|
+
status: "UNKNOWN",
|
|
11948
|
+
statusClass: "unknown",
|
|
11949
|
+
jobExecutions: 0,
|
|
11950
|
+
startedAt: null,
|
|
11951
|
+
finishedAt: null,
|
|
11952
|
+
elapsedMs,
|
|
11953
|
+
attempts: options.attempts,
|
|
11954
|
+
timedOut: options.timedOut,
|
|
11955
|
+
lastError: options.lastError
|
|
11956
|
+
};
|
|
11957
|
+
}
|
|
11958
|
+
/**
|
|
11959
|
+
* Wait for a workflow execution to reach the requested state.
|
|
11960
|
+
* @param options - Workflow waiter options
|
|
11961
|
+
* @returns Final or timed-out workflow wait result
|
|
11962
|
+
*/
|
|
11963
|
+
async function waitForWorkflowExecution(options) {
|
|
11964
|
+
const interval = options.interval ?? 3e3;
|
|
11965
|
+
const until = options.until ?? "terminal";
|
|
11966
|
+
const startedAt = Date.now();
|
|
11967
|
+
const sp = options.showProgress ? spinner({ indent: 2 }).start("Waiting for workflow to complete...") : null;
|
|
11968
|
+
let attempts = 0;
|
|
11969
|
+
let lastExecution;
|
|
11970
|
+
let lastError = null;
|
|
11971
|
+
let lastStatus;
|
|
11972
|
+
let lastActiveJobs;
|
|
11973
|
+
try {
|
|
11974
|
+
while (true) {
|
|
11975
|
+
const elapsedMs = Date.now() - startedAt;
|
|
11976
|
+
const remainingMs = options.timeout === void 0 ? void 0 : options.timeout - elapsedMs;
|
|
11977
|
+
if (remainingMs !== void 0 && remainingMs <= 0) {
|
|
11978
|
+
sp?.fail("Workflow wait timed out.");
|
|
11979
|
+
return createWorkflowWaitResult({
|
|
11980
|
+
executionId: options.executionId,
|
|
11981
|
+
execution: lastExecution,
|
|
11982
|
+
startedAt,
|
|
11983
|
+
attempts,
|
|
11984
|
+
timedOut: true,
|
|
11985
|
+
lastError
|
|
11986
|
+
});
|
|
11987
|
+
}
|
|
11988
|
+
try {
|
|
11989
|
+
attempts += 1;
|
|
11990
|
+
const { execution } = await options.client.getWorkflowExecution({
|
|
11991
|
+
workspaceId: options.workspaceId,
|
|
11992
|
+
executionId: options.executionId
|
|
11993
|
+
});
|
|
11994
|
+
if (!execution) {
|
|
11995
|
+
sp?.fail(`Execution '${options.executionId}' not found.`);
|
|
11996
|
+
throw new Error(`Execution '${options.executionId}' not found.`);
|
|
11997
|
+
}
|
|
11998
|
+
lastExecution = execution;
|
|
11999
|
+
lastError = null;
|
|
12000
|
+
const classification = classifyWorkflowExecutionStatus(execution);
|
|
12001
|
+
const coloredStatus = colorizeStatus(execution.status);
|
|
12002
|
+
if (execution.status !== lastStatus) {
|
|
12003
|
+
if (options.showProgress) {
|
|
12004
|
+
sp?.stop();
|
|
12005
|
+
logger.info(`Status: ${coloredStatus}`, {
|
|
12006
|
+
mode: "stream",
|
|
12007
|
+
indent: 2
|
|
12008
|
+
});
|
|
12009
|
+
sp?.start("Waiting for workflow to complete...");
|
|
12010
|
+
}
|
|
12011
|
+
lastStatus = execution.status;
|
|
12012
|
+
}
|
|
12013
|
+
if (options.trackJobs) {
|
|
12014
|
+
const activeJobs = getActiveJobs(execution);
|
|
12015
|
+
if (activeJobs && activeJobs !== lastActiveJobs) {
|
|
12016
|
+
if (options.showProgress) {
|
|
12017
|
+
sp?.stop();
|
|
12018
|
+
logger.info(`Job | ${activeJobs}: ${coloredStatus}`, {
|
|
12019
|
+
mode: "stream",
|
|
12020
|
+
indent: 2
|
|
12021
|
+
});
|
|
12022
|
+
sp?.start("Waiting for workflow to complete...");
|
|
12023
|
+
}
|
|
12024
|
+
lastActiveJobs = activeJobs;
|
|
12025
|
+
}
|
|
12026
|
+
}
|
|
12027
|
+
if (sp) sp.text = `Waiting for workflow to complete... (${formatTime$1(/* @__PURE__ */ new Date())})`;
|
|
12028
|
+
if (hasReachedWorkflowWaitTarget(classification, until) || classification.statusClass === "failure" || until === "suspended" && classification.statusClass === "success") {
|
|
12029
|
+
if (execution.status === WorkflowExecution_Status.SUCCESS) sp?.succeed(`Completed: ${coloredStatus}`);
|
|
12030
|
+
else if (isWorkflowExecutionFailureStatus(execution.status)) sp?.fail(`Completed: ${coloredStatus}`);
|
|
12031
|
+
else if (isWorkflowExecutionSuspendedStatus(execution.status)) sp?.warn(`Completed: ${coloredStatus}`);
|
|
12032
|
+
else sp?.succeed(`Completed: ${coloredStatus}`);
|
|
12033
|
+
return createWorkflowWaitResult({
|
|
12034
|
+
executionId: options.executionId,
|
|
12035
|
+
execution,
|
|
12036
|
+
startedAt,
|
|
12037
|
+
attempts,
|
|
12038
|
+
timedOut: false,
|
|
12039
|
+
lastError
|
|
12040
|
+
});
|
|
12041
|
+
}
|
|
12042
|
+
} catch (error) {
|
|
12043
|
+
if (!isRetryableWaitError(error)) throw error;
|
|
12044
|
+
lastError = formatWaitError(error);
|
|
12045
|
+
if (options.showProgress) {
|
|
12046
|
+
if (sp) sp.text = `Retrying workflow status poll... (${formatTime$1(/* @__PURE__ */ new Date())})`;
|
|
12047
|
+
}
|
|
12048
|
+
}
|
|
12049
|
+
const nextElapsedMs = Date.now() - startedAt;
|
|
12050
|
+
const nextRemainingMs = options.timeout === void 0 ? void 0 : options.timeout - nextElapsedMs;
|
|
12051
|
+
if (nextRemainingMs !== void 0 && nextRemainingMs <= 0) {
|
|
12052
|
+
sp?.fail("Workflow wait timed out.");
|
|
12053
|
+
return createWorkflowWaitResult({
|
|
12054
|
+
executionId: options.executionId,
|
|
12055
|
+
execution: lastExecution,
|
|
12056
|
+
startedAt,
|
|
12057
|
+
attempts,
|
|
12058
|
+
timedOut: true,
|
|
12059
|
+
lastError
|
|
12060
|
+
});
|
|
12061
|
+
}
|
|
12062
|
+
await setTimeout$2(nextRemainingMs === void 0 ? interval : Math.min(interval, nextRemainingMs));
|
|
12063
|
+
}
|
|
12064
|
+
} finally {
|
|
12065
|
+
sp?.stop();
|
|
12066
|
+
}
|
|
12067
|
+
}
|
|
12068
|
+
/**
|
|
12069
|
+
* Wait for an existing workflow execution by ID.
|
|
12070
|
+
* @param options - Workflow execution wait options
|
|
12071
|
+
* @returns Workflow wait result
|
|
12072
|
+
*/
|
|
12073
|
+
async function waitForWorkflowExecutionById(options) {
|
|
12074
|
+
return await waitForWorkflowExecution({
|
|
12075
|
+
client: await initOperatorClient(await loadAccessToken({ profile: options.profile })),
|
|
12076
|
+
workspaceId: await loadWorkspaceId({
|
|
12077
|
+
workspaceId: options.workspaceId,
|
|
12078
|
+
profile: options.profile
|
|
12079
|
+
}),
|
|
12080
|
+
executionId: options.executionId,
|
|
12081
|
+
interval: options.interval,
|
|
12082
|
+
timeout: options.timeout,
|
|
12083
|
+
until: options.until,
|
|
12084
|
+
showProgress: options.showProgress,
|
|
12085
|
+
trackJobs: options.trackJobs
|
|
12086
|
+
});
|
|
12087
|
+
}
|
|
12088
|
+
/**
|
|
12089
|
+
* Build a user-facing failure message for a workflow wait result.
|
|
12090
|
+
* @param result - Workflow wait result
|
|
12091
|
+
* @param until - Requested wait target
|
|
12092
|
+
* @returns Failure message, or undefined when the wait succeeded
|
|
12093
|
+
*/
|
|
12094
|
+
function getWorkflowWaitFailureMessage(result, until) {
|
|
12095
|
+
if (result.timedOut) return `Timed out waiting for workflow execution '${result.id}' to reach ${until}. Last status: ${result.status}.`;
|
|
12096
|
+
if (result.status === "FAILED") return `Workflow execution '${result.id}' failed.`;
|
|
12097
|
+
if (until === "success" && result.statusClass !== "success") return `Workflow execution '${result.id}' reached ${result.status} before success.`;
|
|
12098
|
+
if (until === "suspended" && result.statusClass !== "suspended") return `Workflow execution '${result.id}' reached ${result.status} before suspension.`;
|
|
12099
|
+
}
|
|
12100
|
+
|
|
12101
|
+
//#endregion
|
|
12102
|
+
//#region src/cli/commands/workflow/executions.ts
|
|
11716
12103
|
function parseStatus(status) {
|
|
11717
12104
|
switch (status.toUpperCase()) {
|
|
11718
12105
|
case "PENDING": return WorkflowExecution_Status.PENDING;
|
|
@@ -11720,7 +12107,10 @@ function parseStatus(status) {
|
|
|
11720
12107
|
case "RUNNING": return WorkflowExecution_Status.RUNNING;
|
|
11721
12108
|
case "SUCCESS": return WorkflowExecution_Status.SUCCESS;
|
|
11722
12109
|
case "FAILED": return WorkflowExecution_Status.FAILED;
|
|
11723
|
-
|
|
12110
|
+
case "PENDING_RETRY": return WorkflowExecution_Status.PENDING_RETRY;
|
|
12111
|
+
case "WAITING": return WorkflowExecution_Status.WAITING;
|
|
12112
|
+
case "UNSPECIFIED": return WorkflowExecution_Status.UNSPECIFIED;
|
|
12113
|
+
default: throw new Error(`Invalid status: ${status}. Valid values: UNSPECIFIED, PENDING, PENDING_RESUME, RUNNING, SUCCESS, FAILED, PENDING_RETRY, WAITING`);
|
|
11724
12114
|
}
|
|
11725
12115
|
}
|
|
11726
12116
|
async function listWorkflowExecutions(options) {
|
|
@@ -11809,37 +12199,28 @@ async function getWorkflowExecution(options) {
|
|
|
11809
12199
|
}
|
|
11810
12200
|
async function waitForCompletion() {
|
|
11811
12201
|
const interval = options.interval ?? 3e3;
|
|
11812
|
-
|
|
11813
|
-
|
|
11814
|
-
|
|
11815
|
-
|
|
11816
|
-
|
|
11817
|
-
|
|
11818
|
-
|
|
11819
|
-
|
|
11820
|
-
|
|
12202
|
+
const waitResult = await waitForWorkflowExecution({
|
|
12203
|
+
client,
|
|
12204
|
+
workspaceId,
|
|
12205
|
+
executionId: options.executionId,
|
|
12206
|
+
interval,
|
|
12207
|
+
timeout: options.timeout,
|
|
12208
|
+
until: options.until ?? "terminal"
|
|
12209
|
+
});
|
|
12210
|
+
return {
|
|
12211
|
+
...await fetchExecutionWithLogs(options.executionId, options.logs ?? false),
|
|
12212
|
+
statusClass: waitResult.statusClass,
|
|
12213
|
+
elapsedMs: waitResult.elapsedMs,
|
|
12214
|
+
attempts: waitResult.attempts,
|
|
12215
|
+
timedOut: waitResult.timedOut,
|
|
12216
|
+
lastError: waitResult.lastError
|
|
12217
|
+
};
|
|
11821
12218
|
}
|
|
11822
12219
|
return {
|
|
11823
12220
|
execution: await fetchExecutionWithLogs(options.executionId, options.logs ?? false),
|
|
11824
12221
|
wait: waitForCompletion
|
|
11825
12222
|
};
|
|
11826
12223
|
}
|
|
11827
|
-
async function waitWithSpinner(waitFn, interval, json) {
|
|
11828
|
-
const sp = !json ? spinner().start("Waiting for workflow to complete...") : null;
|
|
11829
|
-
const updateInterval = setInterval(() => {
|
|
11830
|
-
if (sp) sp.text = `Waiting for workflow to complete... (${formatTime$2(/* @__PURE__ */ new Date())})`;
|
|
11831
|
-
}, interval);
|
|
11832
|
-
try {
|
|
11833
|
-
const result = await waitFn();
|
|
11834
|
-
const coloredStatus = colorizeStatus$1(WorkflowExecution_Status[result.status]);
|
|
11835
|
-
if (result.status === "SUCCESS") sp?.succeed(`Completed: ${coloredStatus}`);
|
|
11836
|
-
else sp?.fail(`Completed: ${coloredStatus}`);
|
|
11837
|
-
return result;
|
|
11838
|
-
} finally {
|
|
11839
|
-
clearInterval(updateInterval);
|
|
11840
|
-
sp?.stop();
|
|
11841
|
-
}
|
|
11842
|
-
}
|
|
11843
12224
|
/**
|
|
11844
12225
|
* Print a workflow execution and its logs in a human-readable format.
|
|
11845
12226
|
* @param execution - Workflow execution detail info
|
|
@@ -11901,19 +12282,55 @@ const executionsCommand = defineAppCommand({
|
|
|
11901
12282
|
logs: arg(z.boolean().default(false), { description: "Display job execution logs (detail mode only)" })
|
|
11902
12283
|
}).strict(),
|
|
11903
12284
|
run: async (args) => {
|
|
12285
|
+
const jsonOutput = logger.jsonMode || args.json;
|
|
11904
12286
|
if (args.executionId) {
|
|
11905
12287
|
const interval = parseDuration(args.interval);
|
|
11906
|
-
|
|
12288
|
+
if (!jsonOutput) logger.info(`Execution ID: ${args.executionId}`, { mode: "stream" });
|
|
12289
|
+
if (args.wait) {
|
|
12290
|
+
const result = await waitForWorkflowExecutionById({
|
|
12291
|
+
executionId: args.executionId,
|
|
12292
|
+
workspaceId: args["workspace-id"],
|
|
12293
|
+
profile: args.profile,
|
|
12294
|
+
interval,
|
|
12295
|
+
timeout: parseDuration(args.timeout),
|
|
12296
|
+
until: args.until,
|
|
12297
|
+
showProgress: !jsonOutput,
|
|
12298
|
+
trackJobs: true
|
|
12299
|
+
});
|
|
12300
|
+
if (args.logs && !jsonOutput) {
|
|
12301
|
+
const { execution } = await getWorkflowExecution({
|
|
12302
|
+
executionId: args.executionId,
|
|
12303
|
+
workspaceId: args["workspace-id"],
|
|
12304
|
+
profile: args.profile,
|
|
12305
|
+
logs: true
|
|
12306
|
+
});
|
|
12307
|
+
printExecutionWithLogs(execution);
|
|
12308
|
+
} else if (args.logs) {
|
|
12309
|
+
const { execution } = await getWorkflowExecution({
|
|
12310
|
+
executionId: args.executionId,
|
|
12311
|
+
workspaceId: args["workspace-id"],
|
|
12312
|
+
profile: args.profile,
|
|
12313
|
+
logs: true
|
|
12314
|
+
});
|
|
12315
|
+
const output = {
|
|
12316
|
+
...result,
|
|
12317
|
+
jobDetails: execution.jobDetails
|
|
12318
|
+
};
|
|
12319
|
+
logger.out(output);
|
|
12320
|
+
} else logger.out(result);
|
|
12321
|
+
const failureMessage = getWorkflowWaitFailureMessage(result, args.until);
|
|
12322
|
+
if (failureMessage) throw new Error(failureMessage);
|
|
12323
|
+
return;
|
|
12324
|
+
}
|
|
12325
|
+
const { execution } = await getWorkflowExecution({
|
|
11907
12326
|
executionId: args.executionId,
|
|
11908
12327
|
workspaceId: args["workspace-id"],
|
|
11909
12328
|
profile: args.profile,
|
|
11910
12329
|
interval,
|
|
11911
12330
|
logs: args.logs
|
|
11912
12331
|
});
|
|
11913
|
-
if (
|
|
11914
|
-
|
|
11915
|
-
if (args.logs && !args.json) printExecutionWithLogs(result);
|
|
11916
|
-
else logger.out(result);
|
|
12332
|
+
if (args.logs && !jsonOutput) printExecutionWithLogs(execution);
|
|
12333
|
+
else logger.out(execution);
|
|
11917
12334
|
} else {
|
|
11918
12335
|
const executions = await listWorkflowExecutions({
|
|
11919
12336
|
workspaceId: args["workspace-id"],
|
|
@@ -11978,90 +12395,6 @@ const getCommand$5 = defineAppCommand({
|
|
|
11978
12395
|
|
|
11979
12396
|
//#endregion
|
|
11980
12397
|
//#region src/cli/commands/workflow/start.ts
|
|
11981
|
-
function sleep(ms) {
|
|
11982
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
11983
|
-
}
|
|
11984
|
-
function formatTime$1(date) {
|
|
11985
|
-
return date.toLocaleTimeString("en-US", { hour12: false });
|
|
11986
|
-
}
|
|
11987
|
-
function colorizeStatus(status) {
|
|
11988
|
-
const statusText = WorkflowExecution_Status[status];
|
|
11989
|
-
switch (status) {
|
|
11990
|
-
case WorkflowExecution_Status.PENDING: return styles.dim(statusText);
|
|
11991
|
-
case WorkflowExecution_Status.PENDING_RESUME: return styles.warning(statusText);
|
|
11992
|
-
case WorkflowExecution_Status.RUNNING: return styles.info(statusText);
|
|
11993
|
-
case WorkflowExecution_Status.SUCCESS: return styles.success(statusText);
|
|
11994
|
-
case WorkflowExecution_Status.FAILED: return styles.error(statusText);
|
|
11995
|
-
default: return statusText;
|
|
11996
|
-
}
|
|
11997
|
-
}
|
|
11998
|
-
/**
|
|
11999
|
-
* Wait for a workflow execution to reach a terminal state, optionally showing progress.
|
|
12000
|
-
* @param options - Wait options
|
|
12001
|
-
* @returns Final workflow execution info
|
|
12002
|
-
*/
|
|
12003
|
-
async function waitForExecution(options) {
|
|
12004
|
-
const { client, workspaceId, executionId, interval, showProgress, trackJobs } = options;
|
|
12005
|
-
let lastStatus;
|
|
12006
|
-
let lastRunningJobs;
|
|
12007
|
-
const sp = showProgress ? spinner({ indent: 2 }).start("Waiting for workflow to complete...") : null;
|
|
12008
|
-
try {
|
|
12009
|
-
while (true) {
|
|
12010
|
-
const { execution } = await client.getWorkflowExecution({
|
|
12011
|
-
workspaceId,
|
|
12012
|
-
executionId
|
|
12013
|
-
});
|
|
12014
|
-
if (!execution) {
|
|
12015
|
-
sp?.fail(`Execution '${executionId}' not found.`);
|
|
12016
|
-
throw new Error(`Execution '${executionId}' not found.`);
|
|
12017
|
-
}
|
|
12018
|
-
const now = formatTime$1(/* @__PURE__ */ new Date());
|
|
12019
|
-
const coloredStatus = colorizeStatus(execution.status);
|
|
12020
|
-
if (execution.status !== lastStatus) {
|
|
12021
|
-
if (showProgress) {
|
|
12022
|
-
sp?.stop();
|
|
12023
|
-
logger.info(`Status: ${coloredStatus}`, {
|
|
12024
|
-
mode: "stream",
|
|
12025
|
-
indent: 2
|
|
12026
|
-
});
|
|
12027
|
-
sp?.start(`Waiting for workflow to complete...`);
|
|
12028
|
-
}
|
|
12029
|
-
lastStatus = execution.status;
|
|
12030
|
-
}
|
|
12031
|
-
if (trackJobs && execution.status === WorkflowExecution_Status.RUNNING) {
|
|
12032
|
-
const runningJobs = getRunningJobs(execution);
|
|
12033
|
-
if (runningJobs && runningJobs !== lastRunningJobs) {
|
|
12034
|
-
if (showProgress) {
|
|
12035
|
-
sp?.stop();
|
|
12036
|
-
logger.info(`Job | ${runningJobs}: ${coloredStatus}`, {
|
|
12037
|
-
mode: "stream",
|
|
12038
|
-
indent: 2
|
|
12039
|
-
});
|
|
12040
|
-
sp?.start(`Waiting for workflow to complete...`);
|
|
12041
|
-
}
|
|
12042
|
-
lastRunningJobs = runningJobs;
|
|
12043
|
-
}
|
|
12044
|
-
}
|
|
12045
|
-
if (sp) sp.text = `Waiting for workflow to complete... (${now})`;
|
|
12046
|
-
if (isTerminalStatus(execution.status)) {
|
|
12047
|
-
if (execution.status === WorkflowExecution_Status.SUCCESS) sp?.succeed(`Completed: ${coloredStatus}`);
|
|
12048
|
-
else if (execution.status === WorkflowExecution_Status.FAILED) sp?.fail(`Completed: ${coloredStatus}`);
|
|
12049
|
-
else sp?.warn(`Completed: ${coloredStatus}`);
|
|
12050
|
-
return toWorkflowExecutionInfo(execution);
|
|
12051
|
-
}
|
|
12052
|
-
await sleep(interval);
|
|
12053
|
-
}
|
|
12054
|
-
} catch (error) {
|
|
12055
|
-
sp?.stop();
|
|
12056
|
-
throw error;
|
|
12057
|
-
}
|
|
12058
|
-
}
|
|
12059
|
-
function getRunningJobs(execution) {
|
|
12060
|
-
return execution.jobExecutions.filter((job) => job.status === WorkflowJobExecution_Status.RUNNING).map((job) => job.stackedJobName).join(", ");
|
|
12061
|
-
}
|
|
12062
|
-
function isTerminalStatus(status) {
|
|
12063
|
-
return status === WorkflowExecution_Status.SUCCESS || status === WorkflowExecution_Status.FAILED || status === WorkflowExecution_Status.PENDING_RESUME;
|
|
12064
|
-
}
|
|
12065
12398
|
async function startWorkflowCore(options) {
|
|
12066
12399
|
const { client, workspaceId, workflowName } = options;
|
|
12067
12400
|
try {
|
|
@@ -12076,11 +12409,13 @@ async function startWorkflowCore(options) {
|
|
|
12076
12409
|
});
|
|
12077
12410
|
return {
|
|
12078
12411
|
executionId,
|
|
12079
|
-
wait: (waitOptions) =>
|
|
12412
|
+
wait: (waitOptions) => waitForWorkflowExecution({
|
|
12080
12413
|
client,
|
|
12081
12414
|
workspaceId,
|
|
12082
12415
|
executionId,
|
|
12083
12416
|
interval: options.interval ?? 3e3,
|
|
12417
|
+
timeout: waitOptions?.timeout,
|
|
12418
|
+
until: waitOptions?.until,
|
|
12084
12419
|
showProgress: waitOptions?.showProgress,
|
|
12085
12420
|
trackJobs: true
|
|
12086
12421
|
})
|
|
@@ -12164,7 +12499,11 @@ const startCommand = defineAppCommand({
|
|
|
12164
12499
|
const jsonOutput = logger.jsonMode;
|
|
12165
12500
|
logger.info(`Execution ID: ${executionId}`, { mode: "stream" });
|
|
12166
12501
|
if (args.wait) {
|
|
12167
|
-
const result = await wait({
|
|
12502
|
+
const result = await wait({
|
|
12503
|
+
showProgress: !jsonOutput,
|
|
12504
|
+
timeout: parseDuration(args.timeout),
|
|
12505
|
+
until: args.until
|
|
12506
|
+
});
|
|
12168
12507
|
if (args.logs && !jsonOutput) {
|
|
12169
12508
|
const { execution } = await getWorkflowExecution({
|
|
12170
12509
|
executionId,
|
|
@@ -12173,7 +12512,20 @@ const startCommand = defineAppCommand({
|
|
|
12173
12512
|
logs: true
|
|
12174
12513
|
});
|
|
12175
12514
|
printExecutionWithLogs(execution);
|
|
12515
|
+
} else if (args.logs) {
|
|
12516
|
+
const { execution } = await getWorkflowExecution({
|
|
12517
|
+
executionId,
|
|
12518
|
+
workspaceId: args["workspace-id"],
|
|
12519
|
+
profile: args.profile,
|
|
12520
|
+
logs: true
|
|
12521
|
+
});
|
|
12522
|
+
logger.out({
|
|
12523
|
+
...result,
|
|
12524
|
+
jobDetails: execution.jobDetails
|
|
12525
|
+
});
|
|
12176
12526
|
} else logger.out(result);
|
|
12527
|
+
const failureMessage = getWorkflowWaitFailureMessage(result, args.until);
|
|
12528
|
+
if (failureMessage) throw new Error(failureMessage);
|
|
12177
12529
|
} else logger.out({ executionId });
|
|
12178
12530
|
}
|
|
12179
12531
|
});
|
|
@@ -12183,6 +12535,16 @@ const startCommand = defineAppCommand({
|
|
|
12183
12535
|
function formatTime(date) {
|
|
12184
12536
|
return date.toLocaleTimeString("en-US", { hour12: false });
|
|
12185
12537
|
}
|
|
12538
|
+
function createUnknownExecutorJob(executorName, jobId) {
|
|
12539
|
+
return {
|
|
12540
|
+
id: jobId,
|
|
12541
|
+
executorName,
|
|
12542
|
+
status: "UNKNOWN",
|
|
12543
|
+
scheduledAt: "N/A",
|
|
12544
|
+
createdAt: "N/A",
|
|
12545
|
+
updatedAt: "N/A"
|
|
12546
|
+
};
|
|
12547
|
+
}
|
|
12186
12548
|
async function listExecutorJobs(options) {
|
|
12187
12549
|
const executorName = "executorName" in options ? options.executorName : options.executor.name;
|
|
12188
12550
|
const client = await initOperatorClient(await loadAccessToken({ profile: options.profile }));
|
|
@@ -12266,7 +12628,27 @@ async function watchExecutorJob(options) {
|
|
|
12266
12628
|
profile: options.profile
|
|
12267
12629
|
});
|
|
12268
12630
|
const interval = options.interval ?? 3e3;
|
|
12269
|
-
const
|
|
12631
|
+
const timeout = options.timeout;
|
|
12632
|
+
const showProgress = options.showProgress ?? !logger.jsonMode;
|
|
12633
|
+
const startedAt = Date.now();
|
|
12634
|
+
const sp = showProgress ? spinner().start("Waiting for executor job to complete...") : null;
|
|
12635
|
+
let attempts = 0;
|
|
12636
|
+
let lastError = null;
|
|
12637
|
+
const remainingTimeout = () => {
|
|
12638
|
+
if (timeout === void 0) return;
|
|
12639
|
+
return timeout - (Date.now() - startedAt);
|
|
12640
|
+
};
|
|
12641
|
+
const withWaitMetadata = (result, timedOut) => ({
|
|
12642
|
+
...result,
|
|
12643
|
+
elapsedMs: Date.now() - startedAt,
|
|
12644
|
+
attempts,
|
|
12645
|
+
timedOut,
|
|
12646
|
+
lastError
|
|
12647
|
+
});
|
|
12648
|
+
const timeoutResult = (targetType, job) => withWaitMetadata({
|
|
12649
|
+
job: job ? toExecutorJobInfo(job) : createUnknownExecutorJob(executorName, options.jobId),
|
|
12650
|
+
targetType
|
|
12651
|
+
}, true);
|
|
12270
12652
|
try {
|
|
12271
12653
|
const { executor } = await client.getExecutorExecutor({
|
|
12272
12654
|
workspaceId,
|
|
@@ -12277,29 +12659,47 @@ async function watchExecutorJob(options) {
|
|
|
12277
12659
|
const targetTypeStr = executorTargetTypeToString(targetType);
|
|
12278
12660
|
let job;
|
|
12279
12661
|
while (true) {
|
|
12280
|
-
|
|
12281
|
-
|
|
12282
|
-
|
|
12283
|
-
|
|
12284
|
-
}
|
|
12285
|
-
|
|
12286
|
-
|
|
12287
|
-
|
|
12288
|
-
|
|
12662
|
+
const remainingMs = remainingTimeout();
|
|
12663
|
+
if (remainingMs !== void 0 && remainingMs <= 0) {
|
|
12664
|
+
sp?.fail("Executor job wait timed out.");
|
|
12665
|
+
return timeoutResult(targetTypeStr, job);
|
|
12666
|
+
}
|
|
12667
|
+
try {
|
|
12668
|
+
attempts += 1;
|
|
12669
|
+
job = (await client.getExecutorJob({
|
|
12670
|
+
workspaceId,
|
|
12671
|
+
executorName,
|
|
12672
|
+
jobId: options.jobId
|
|
12673
|
+
})).job;
|
|
12674
|
+
if (!job) throw new Error(`Job '${options.jobId}' not found.`);
|
|
12675
|
+
lastError = null;
|
|
12676
|
+
if (classifyExecutorJobStatus(job.status) !== "transient") break;
|
|
12677
|
+
} catch (error) {
|
|
12678
|
+
if (!isRetryableWaitError(error)) throw error;
|
|
12679
|
+
lastError = formatWaitError(error);
|
|
12680
|
+
if (sp) sp.text = `Retrying executor job poll... (${formatTime(/* @__PURE__ */ new Date())})`;
|
|
12681
|
+
}
|
|
12682
|
+
const nextRemainingMs = remainingTimeout();
|
|
12683
|
+
if (nextRemainingMs !== void 0 && nextRemainingMs <= 0) {
|
|
12684
|
+
sp?.fail("Executor job wait timed out.");
|
|
12685
|
+
return timeoutResult(targetTypeStr, job);
|
|
12686
|
+
}
|
|
12687
|
+
if (sp) sp.text = `Waiting for executor job... (${formatTime(/* @__PURE__ */ new Date())})`;
|
|
12688
|
+
await setTimeout$1(nextRemainingMs === void 0 ? interval : Math.min(interval, nextRemainingMs));
|
|
12289
12689
|
}
|
|
12290
12690
|
const jobInfo = toExecutorJobInfo(job);
|
|
12291
12691
|
const coloredStatus = colorizeExecutorJobStatus(jobInfo.status);
|
|
12292
|
-
if (job.status === ExecutorJobStatus.SUCCESS) sp
|
|
12293
|
-
else sp
|
|
12692
|
+
if (job.status === ExecutorJobStatus.SUCCESS) sp?.succeed(`Executor job completed: ${coloredStatus}`);
|
|
12693
|
+
else sp?.fail(`Executor job completed: ${coloredStatus}`);
|
|
12294
12694
|
const attemptInfos = (await fetchAll(async (pageToken, maxPageSize) => {
|
|
12295
|
-
const { attempts, nextPageToken } = await client.listExecutorJobAttempts({
|
|
12695
|
+
const { attempts: jobAttempts, nextPageToken } = await client.listExecutorJobAttempts({
|
|
12296
12696
|
workspaceId,
|
|
12297
12697
|
jobId: options.jobId,
|
|
12298
12698
|
pageToken,
|
|
12299
12699
|
pageSize: maxPageSize,
|
|
12300
12700
|
pageDirection: PageDirection.DESC
|
|
12301
12701
|
});
|
|
12302
|
-
return [
|
|
12702
|
+
return [jobAttempts, nextPageToken];
|
|
12303
12703
|
})).map(toExecutorJobAttemptInfo);
|
|
12304
12704
|
const jobDetail = {
|
|
12305
12705
|
...jobInfo,
|
|
@@ -12308,18 +12708,27 @@ async function watchExecutorJob(options) {
|
|
|
12308
12708
|
const operationReference = attemptInfos[0]?.operationReference;
|
|
12309
12709
|
if (operationReference) switch (targetType) {
|
|
12310
12710
|
case ExecutorTargetType.WORKFLOW:
|
|
12311
|
-
sp
|
|
12711
|
+
sp?.stop();
|
|
12312
12712
|
try {
|
|
12313
|
-
const
|
|
12713
|
+
const workflowTimeout = remainingTimeout();
|
|
12714
|
+
if (workflowTimeout !== void 0 && workflowTimeout <= 0) return withWaitMetadata({
|
|
12715
|
+
job: jobDetail,
|
|
12716
|
+
targetType: targetTypeStr,
|
|
12717
|
+
workflowExecutionId: operationReference
|
|
12718
|
+
}, true);
|
|
12719
|
+
const executionResult = await waitForWorkflowExecution({
|
|
12314
12720
|
client,
|
|
12315
12721
|
workspaceId,
|
|
12316
12722
|
executionId: operationReference,
|
|
12317
12723
|
interval,
|
|
12318
|
-
|
|
12724
|
+
timeout: workflowTimeout,
|
|
12725
|
+
showProgress,
|
|
12319
12726
|
trackJobs: true
|
|
12320
12727
|
});
|
|
12728
|
+
attempts += executionResult.attempts;
|
|
12729
|
+
lastError = executionResult.lastError;
|
|
12321
12730
|
let workflowJobLogs;
|
|
12322
|
-
if (options.logs) {
|
|
12731
|
+
if (options.logs) try {
|
|
12323
12732
|
const { execution: execWithLogs } = await getWorkflowExecution({
|
|
12324
12733
|
executionId: operationReference,
|
|
12325
12734
|
workspaceId: options.workspaceId,
|
|
@@ -12331,67 +12740,109 @@ async function watchExecutorJob(options) {
|
|
|
12331
12740
|
logs: job.logs,
|
|
12332
12741
|
result: job.result
|
|
12333
12742
|
}));
|
|
12743
|
+
} catch (error) {
|
|
12744
|
+
logger.warn(`Could not fetch workflow execution logs: ${error instanceof Error ? error.message : error}`);
|
|
12334
12745
|
}
|
|
12335
|
-
return {
|
|
12746
|
+
return withWaitMetadata({
|
|
12336
12747
|
job: jobDetail,
|
|
12337
12748
|
targetType: targetTypeStr,
|
|
12338
12749
|
workflowExecutionId: operationReference,
|
|
12339
12750
|
workflowStatus: executionResult.status,
|
|
12340
12751
|
workflowJobLogs
|
|
12341
|
-
};
|
|
12752
|
+
}, executionResult.timedOut);
|
|
12342
12753
|
} catch (error) {
|
|
12343
12754
|
logger.warn(`Could not track workflow execution: ${error instanceof Error ? error.message : error}`);
|
|
12344
|
-
return {
|
|
12755
|
+
return withWaitMetadata({
|
|
12345
12756
|
job: jobDetail,
|
|
12346
12757
|
targetType: targetTypeStr,
|
|
12347
12758
|
workflowExecutionId: operationReference
|
|
12348
|
-
};
|
|
12759
|
+
}, false);
|
|
12349
12760
|
}
|
|
12350
12761
|
case ExecutorTargetType.FUNCTION:
|
|
12351
12762
|
case ExecutorTargetType.JOB_FUNCTION:
|
|
12352
|
-
sp
|
|
12763
|
+
sp?.start(`Waiting for function execution ${operationReference}...`);
|
|
12353
12764
|
try {
|
|
12765
|
+
let functionStatus;
|
|
12354
12766
|
while (true) {
|
|
12355
|
-
const
|
|
12356
|
-
|
|
12357
|
-
|
|
12358
|
-
|
|
12359
|
-
if (!execution) throw new Error(`Function execution '${operationReference}' not found.`);
|
|
12360
|
-
if (isFunctionExecutionTerminalStatus(execution.status)) {
|
|
12361
|
-
const statusStr = functionExecutionStatusToString(execution.status);
|
|
12362
|
-
const coloredFnStatus = colorizeFunctionExecutionStatus(statusStr);
|
|
12363
|
-
if (execution.status === FunctionExecution_Status.SUCCESS) sp.succeed(`Function execution completed: ${coloredFnStatus}`);
|
|
12364
|
-
else sp.fail(`Function execution completed: ${coloredFnStatus}`);
|
|
12365
|
-
return {
|
|
12767
|
+
const functionTimeout = remainingTimeout();
|
|
12768
|
+
if (functionTimeout !== void 0 && functionTimeout <= 0) {
|
|
12769
|
+
sp?.fail("Function execution wait timed out.");
|
|
12770
|
+
return withWaitMetadata({
|
|
12366
12771
|
job: jobDetail,
|
|
12367
12772
|
targetType: targetTypeStr,
|
|
12368
12773
|
functionExecutionId: operationReference,
|
|
12369
|
-
functionStatus
|
|
12370
|
-
|
|
12371
|
-
};
|
|
12774
|
+
functionStatus
|
|
12775
|
+
}, true);
|
|
12372
12776
|
}
|
|
12373
|
-
|
|
12374
|
-
|
|
12777
|
+
try {
|
|
12778
|
+
attempts += 1;
|
|
12779
|
+
const { execution } = await client.getFunctionExecution({
|
|
12780
|
+
workspaceId,
|
|
12781
|
+
executionId: operationReference
|
|
12782
|
+
});
|
|
12783
|
+
if (!execution) throw new Error(`Function execution '${operationReference}' not found.`);
|
|
12784
|
+
lastError = null;
|
|
12785
|
+
functionStatus = functionExecutionStatusToString(execution.status);
|
|
12786
|
+
if (isFunctionExecutionTerminalStatus(execution.status)) {
|
|
12787
|
+
const coloredFnStatus = colorizeFunctionExecutionStatus(functionStatus);
|
|
12788
|
+
if (execution.status === FunctionExecution_Status.SUCCESS) sp?.succeed(`Function execution completed: ${coloredFnStatus}`);
|
|
12789
|
+
else sp?.fail(`Function execution completed: ${coloredFnStatus}`);
|
|
12790
|
+
return withWaitMetadata({
|
|
12791
|
+
job: jobDetail,
|
|
12792
|
+
targetType: targetTypeStr,
|
|
12793
|
+
functionExecutionId: operationReference,
|
|
12794
|
+
functionStatus,
|
|
12795
|
+
functionLogs: options.logs ? execution.logs || void 0 : void 0
|
|
12796
|
+
}, false);
|
|
12797
|
+
}
|
|
12798
|
+
} catch (error) {
|
|
12799
|
+
if (!isRetryableWaitError(error)) throw error;
|
|
12800
|
+
lastError = formatWaitError(error);
|
|
12801
|
+
if (sp) sp.text = `Retrying function execution poll... (${formatTime(/* @__PURE__ */ new Date())})`;
|
|
12802
|
+
}
|
|
12803
|
+
const nextFunctionTimeout = remainingTimeout();
|
|
12804
|
+
if (nextFunctionTimeout !== void 0 && nextFunctionTimeout <= 0) {
|
|
12805
|
+
sp?.fail("Function execution wait timed out.");
|
|
12806
|
+
return withWaitMetadata({
|
|
12807
|
+
job: jobDetail,
|
|
12808
|
+
targetType: targetTypeStr,
|
|
12809
|
+
functionExecutionId: operationReference,
|
|
12810
|
+
functionStatus
|
|
12811
|
+
}, true);
|
|
12812
|
+
}
|
|
12813
|
+
if (sp) sp.text = `Waiting for function execution... (${formatTime(/* @__PURE__ */ new Date())})`;
|
|
12814
|
+
await setTimeout$1(nextFunctionTimeout === void 0 ? interval : Math.min(interval, nextFunctionTimeout));
|
|
12375
12815
|
}
|
|
12376
12816
|
} catch (error) {
|
|
12377
|
-
sp
|
|
12378
|
-
return {
|
|
12817
|
+
sp?.warn(`Could not track function execution: ${error instanceof Error ? error.message : error}`);
|
|
12818
|
+
return withWaitMetadata({
|
|
12379
12819
|
job: jobDetail,
|
|
12380
12820
|
targetType: targetTypeStr,
|
|
12381
12821
|
functionExecutionId: operationReference
|
|
12382
|
-
};
|
|
12822
|
+
}, false);
|
|
12383
12823
|
}
|
|
12384
12824
|
break;
|
|
12385
12825
|
default: break;
|
|
12386
12826
|
}
|
|
12387
|
-
return {
|
|
12827
|
+
return withWaitMetadata({
|
|
12388
12828
|
job: jobDetail,
|
|
12389
12829
|
targetType: targetTypeStr
|
|
12390
|
-
};
|
|
12830
|
+
}, false);
|
|
12391
12831
|
} finally {
|
|
12392
|
-
sp
|
|
12832
|
+
sp?.stop();
|
|
12393
12833
|
}
|
|
12394
12834
|
}
|
|
12835
|
+
/**
|
|
12836
|
+
* Build a user-facing failure message for an executor job wait result.
|
|
12837
|
+
* @param result - Executor job wait result
|
|
12838
|
+
* @returns Failure message, or undefined when the wait succeeded
|
|
12839
|
+
*/
|
|
12840
|
+
function getExecutorWaitFailureMessage(result) {
|
|
12841
|
+
if (result.timedOut) return `Timed out waiting for executor job '${result.job.id}'. Last status: ${result.job.status}.`;
|
|
12842
|
+
if (result.job.status === "FAILED" || result.job.status === "CANCELED") return `Executor job '${result.job.id}' completed with status ${result.job.status}.`;
|
|
12843
|
+
if (result.workflowStatus === "FAILED") return `Workflow execution '${result.workflowExecutionId}' failed.`;
|
|
12844
|
+
if (result.functionStatus === "FAILED") return `Function execution '${result.functionExecutionId}' failed.`;
|
|
12845
|
+
}
|
|
12395
12846
|
function printJobWithAttempts(job) {
|
|
12396
12847
|
const summaryData = [
|
|
12397
12848
|
["id", job.id],
|
|
@@ -12473,6 +12924,10 @@ const jobsCommand = defineAppCommand({
|
|
|
12473
12924
|
alias: "i",
|
|
12474
12925
|
description: "Polling interval when using --wait (e.g., '3s', '500ms', '1m')"
|
|
12475
12926
|
}),
|
|
12927
|
+
timeout: arg(durationArg.default("5m"), {
|
|
12928
|
+
alias: "t",
|
|
12929
|
+
description: "Maximum time to wait when using --wait (e.g., '30s', '5m')"
|
|
12930
|
+
}),
|
|
12476
12931
|
...pagedLogArgs,
|
|
12477
12932
|
limit: arg(nonNegativeIntArg.default(50), { description: "Maximum number of jobs to list (0: unlimited, default: 50) (list mode only)" }),
|
|
12478
12933
|
logs: arg(z.boolean().default(false), {
|
|
@@ -12481,6 +12936,7 @@ const jobsCommand = defineAppCommand({
|
|
|
12481
12936
|
})
|
|
12482
12937
|
}).strict(),
|
|
12483
12938
|
run: async (args) => {
|
|
12939
|
+
const jsonOutput = logger.jsonMode || args.json;
|
|
12484
12940
|
if (args.jobId) {
|
|
12485
12941
|
if (args.wait) {
|
|
12486
12942
|
const result = await watchExecutorJob({
|
|
@@ -12489,9 +12945,11 @@ const jobsCommand = defineAppCommand({
|
|
|
12489
12945
|
workspaceId: args["workspace-id"],
|
|
12490
12946
|
profile: args.profile,
|
|
12491
12947
|
interval: parseDuration(args.interval),
|
|
12492
|
-
|
|
12948
|
+
timeout: parseDuration(args.timeout),
|
|
12949
|
+
logs: args.logs,
|
|
12950
|
+
showProgress: !jsonOutput
|
|
12493
12951
|
});
|
|
12494
|
-
if (!
|
|
12952
|
+
if (!jsonOutput) {
|
|
12495
12953
|
logger.log(styles.bold(`Target Type: ${result.targetType}\n`));
|
|
12496
12954
|
printJobWithAttempts(result.job);
|
|
12497
12955
|
if (result.workflowExecutionId) {
|
|
@@ -12526,6 +12984,8 @@ const jobsCommand = defineAppCommand({
|
|
|
12526
12984
|
}
|
|
12527
12985
|
}
|
|
12528
12986
|
} else logger.out(result);
|
|
12987
|
+
const failureMessage = getExecutorWaitFailureMessage(result);
|
|
12988
|
+
if (failureMessage) throw new Error(failureMessage);
|
|
12529
12989
|
return;
|
|
12530
12990
|
}
|
|
12531
12991
|
const job = await getExecutorJob({
|
|
@@ -12535,7 +12995,7 @@ const jobsCommand = defineAppCommand({
|
|
|
12535
12995
|
workspaceId: args["workspace-id"],
|
|
12536
12996
|
profile: args.profile
|
|
12537
12997
|
});
|
|
12538
|
-
if (args.attempts && !
|
|
12998
|
+
if (args.attempts && !jsonOutput) printJobWithAttempts(job);
|
|
12539
12999
|
else logger.out(job);
|
|
12540
13000
|
} else {
|
|
12541
13001
|
if (args.wait) logger.warn("--wait flag is ignored in list mode. Specify a job ID to wait.");
|
|
@@ -12722,12 +13182,17 @@ The \`--logs\` option displays logs from the downstream execution when available
|
|
|
12722
13182
|
alias: "i",
|
|
12723
13183
|
description: "Polling interval when using --wait (e.g., '3s', '500ms', '1m')"
|
|
12724
13184
|
}),
|
|
13185
|
+
timeout: arg(durationArg.default("5m"), {
|
|
13186
|
+
alias: "t",
|
|
13187
|
+
description: "Maximum time to wait when using --wait (e.g., '30s', '5m')"
|
|
13188
|
+
}),
|
|
12725
13189
|
logs: arg(z.boolean().default(false), {
|
|
12726
13190
|
alias: "l",
|
|
12727
13191
|
description: "Display function execution logs after completion (requires --wait)"
|
|
12728
13192
|
})
|
|
12729
13193
|
}).strict(),
|
|
12730
13194
|
run: async (args) => {
|
|
13195
|
+
const jsonOutput = logger.jsonMode || args.json;
|
|
12731
13196
|
await assertWritable({ profile: args.profile });
|
|
12732
13197
|
const client = await initOperatorClient(await loadAccessToken({ profile: args.profile }));
|
|
12733
13198
|
const workspaceId = await loadWorkspaceId({
|
|
@@ -12768,9 +13233,11 @@ The \`--logs\` option displays logs from the downstream execution when available
|
|
|
12768
13233
|
workspaceId: args["workspace-id"],
|
|
12769
13234
|
profile: args.profile,
|
|
12770
13235
|
interval: parseDuration(args.interval),
|
|
12771
|
-
|
|
13236
|
+
timeout: parseDuration(args.timeout),
|
|
13237
|
+
logs: args.logs,
|
|
13238
|
+
showProgress: !jsonOutput
|
|
12772
13239
|
});
|
|
12773
|
-
if (!
|
|
13240
|
+
if (!jsonOutput) {
|
|
12774
13241
|
logger.log(styles.bold(`\nTarget Type: ${watchResult.targetType}`));
|
|
12775
13242
|
logger.log(`Job Status: ${watchResult.job.status}`);
|
|
12776
13243
|
if (watchResult.workflowExecutionId) {
|
|
@@ -12805,6 +13272,8 @@ The \`--logs\` option displays logs from the downstream execution when available
|
|
|
12805
13272
|
}
|
|
12806
13273
|
}
|
|
12807
13274
|
} else logger.out(watchResult);
|
|
13275
|
+
const failureMessage = getExecutorWaitFailureMessage(watchResult);
|
|
13276
|
+
if (failureMessage) throw new Error(failureMessage);
|
|
12808
13277
|
}
|
|
12809
13278
|
}
|
|
12810
13279
|
});
|
|
@@ -15182,7 +15651,7 @@ function formatEnumUnion(values) {
|
|
|
15182
15651
|
return values.map((v) => `"${v}"`).join(" | ");
|
|
15183
15652
|
}
|
|
15184
15653
|
function generateEnumChangeColumnType(enumValueChange, config) {
|
|
15185
|
-
const selectType = formatEnumUnion([
|
|
15654
|
+
const selectType = formatEnumUnion([.../* @__PURE__ */ new Set([...enumValueChange.beforeValues, ...enumValueChange.afterValues])]);
|
|
15186
15655
|
const afterType = formatEnumUnion(enumValueChange.afterValues);
|
|
15187
15656
|
if (config.array && !config.required) return `ColumnType<(${selectType})[] | null, (${afterType})[] | null, (${afterType})[] | null>`;
|
|
15188
15657
|
if (config.array) return `ColumnType<(${selectType})[], (${afterType})[], (${afterType})[]>`;
|
|
@@ -15509,7 +15978,7 @@ async function generate(options) {
|
|
|
15509
15978
|
if (options.init) await handleInitOption(namespacesWithMigrations, options.yes);
|
|
15510
15979
|
let pluginManager;
|
|
15511
15980
|
if (plugins.length > 0) pluginManager = new PluginManager(plugins);
|
|
15512
|
-
const { defineApplication } = await import("./application-
|
|
15981
|
+
const { defineApplication } = await import("./application-Br48NXBD.mjs");
|
|
15513
15982
|
const application = defineApplication({
|
|
15514
15983
|
config,
|
|
15515
15984
|
pluginManager
|
|
@@ -15942,11 +16411,13 @@ async function resumeWorkflow(options) {
|
|
|
15942
16411
|
});
|
|
15943
16412
|
return {
|
|
15944
16413
|
executionId,
|
|
15945
|
-
wait: (waitOptions) =>
|
|
16414
|
+
wait: (waitOptions) => waitForWorkflowExecution({
|
|
15946
16415
|
client,
|
|
15947
16416
|
workspaceId,
|
|
15948
16417
|
executionId,
|
|
15949
16418
|
interval: options.interval ?? 3e3,
|
|
16419
|
+
timeout: waitOptions?.timeout,
|
|
16420
|
+
until: waitOptions?.until,
|
|
15950
16421
|
showProgress: waitOptions?.showProgress
|
|
15951
16422
|
})
|
|
15952
16423
|
};
|
|
@@ -15970,16 +16441,21 @@ const resumeCommand = defineAppCommand({
|
|
|
15970
16441
|
...waitArgs
|
|
15971
16442
|
}).strict(),
|
|
15972
16443
|
run: async (args) => {
|
|
16444
|
+
const jsonOutput = logger.jsonMode || args.json;
|
|
15973
16445
|
const { executionId, wait } = await resumeWorkflow({
|
|
15974
16446
|
executionId: args.executionId,
|
|
15975
16447
|
workspaceId: args["workspace-id"],
|
|
15976
16448
|
profile: args.profile,
|
|
15977
16449
|
interval: parseDuration(args.interval)
|
|
15978
16450
|
});
|
|
15979
|
-
if (!
|
|
16451
|
+
if (!jsonOutput) logger.info(`Execution ID: ${executionId}`, { mode: "stream" });
|
|
15980
16452
|
if (args.wait) {
|
|
15981
|
-
const result = await wait({
|
|
15982
|
-
|
|
16453
|
+
const result = await wait({
|
|
16454
|
+
showProgress: !jsonOutput,
|
|
16455
|
+
timeout: parseDuration(args.timeout),
|
|
16456
|
+
until: args.until
|
|
16457
|
+
});
|
|
16458
|
+
if (args.logs && !jsonOutput) {
|
|
15983
16459
|
const { execution } = await getWorkflowExecution({
|
|
15984
16460
|
executionId,
|
|
15985
16461
|
workspaceId: args["workspace-id"],
|
|
@@ -15987,11 +16463,112 @@ const resumeCommand = defineAppCommand({
|
|
|
15987
16463
|
logs: true
|
|
15988
16464
|
});
|
|
15989
16465
|
printExecutionWithLogs(execution);
|
|
16466
|
+
} else if (args.logs) {
|
|
16467
|
+
const { execution } = await getWorkflowExecution({
|
|
16468
|
+
executionId,
|
|
16469
|
+
workspaceId: args["workspace-id"],
|
|
16470
|
+
profile: args.profile,
|
|
16471
|
+
logs: true
|
|
16472
|
+
});
|
|
16473
|
+
logger.out({
|
|
16474
|
+
...result,
|
|
16475
|
+
jobDetails: execution.jobDetails
|
|
16476
|
+
});
|
|
15990
16477
|
} else logger.out(result);
|
|
16478
|
+
const failureMessage = getWorkflowWaitFailureMessage(result, args.until);
|
|
16479
|
+
if (failureMessage) throw new Error(failureMessage);
|
|
15991
16480
|
} else logger.out({ executionId });
|
|
15992
16481
|
}
|
|
15993
16482
|
});
|
|
15994
16483
|
|
|
16484
|
+
//#endregion
|
|
16485
|
+
//#region src/cli/commands/workflow/wait.ts
|
|
16486
|
+
/**
|
|
16487
|
+
* Wait for an existing workflow execution by ID.
|
|
16488
|
+
* @param options - Workflow wait options
|
|
16489
|
+
* @returns Workflow wait result
|
|
16490
|
+
*/
|
|
16491
|
+
async function waitWorkflowExecution(options) {
|
|
16492
|
+
return await waitForWorkflowExecutionById({
|
|
16493
|
+
...options,
|
|
16494
|
+
showProgress: options.showProgress ?? !logger.jsonMode,
|
|
16495
|
+
trackJobs: options.trackJobs ?? true
|
|
16496
|
+
});
|
|
16497
|
+
}
|
|
16498
|
+
/**
|
|
16499
|
+
* Attach workflow job logs to a wait result when requested.
|
|
16500
|
+
* @param result - Workflow wait result
|
|
16501
|
+
* @param options - Workflow wait options
|
|
16502
|
+
* @returns Workflow wait result with optional job details
|
|
16503
|
+
*/
|
|
16504
|
+
async function addWorkflowLogsToWaitResult(result, options) {
|
|
16505
|
+
const { execution } = await getWorkflowExecution({
|
|
16506
|
+
executionId: options.executionId,
|
|
16507
|
+
workspaceId: options.workspaceId,
|
|
16508
|
+
profile: options.profile,
|
|
16509
|
+
logs: true
|
|
16510
|
+
});
|
|
16511
|
+
return {
|
|
16512
|
+
...result,
|
|
16513
|
+
jobDetails: execution.jobDetails
|
|
16514
|
+
};
|
|
16515
|
+
}
|
|
16516
|
+
const waitCommand = defineAppCommand({
|
|
16517
|
+
name: "wait",
|
|
16518
|
+
description: "Wait for a workflow execution.",
|
|
16519
|
+
examples: [
|
|
16520
|
+
{
|
|
16521
|
+
cmd: "execution-id --until success --timeout 10m --json",
|
|
16522
|
+
desc: "Wait for workflow success"
|
|
16523
|
+
},
|
|
16524
|
+
{
|
|
16525
|
+
cmd: "execution-id --until suspended --timeout 6m --logs --json",
|
|
16526
|
+
desc: "Wait for a workflow wait point"
|
|
16527
|
+
},
|
|
16528
|
+
{
|
|
16529
|
+
cmd: "execution-id --until terminal",
|
|
16530
|
+
desc: "Wait for success, failure, or suspension"
|
|
16531
|
+
}
|
|
16532
|
+
],
|
|
16533
|
+
args: z.object({
|
|
16534
|
+
...workspaceArgs,
|
|
16535
|
+
"execution-id": arg(z.string(), {
|
|
16536
|
+
positional: true,
|
|
16537
|
+
description: "Execution ID"
|
|
16538
|
+
}),
|
|
16539
|
+
...workflowWaitControlArgs
|
|
16540
|
+
}).strict(),
|
|
16541
|
+
run: async (args) => {
|
|
16542
|
+
const jsonOutput = logger.jsonMode || args.json;
|
|
16543
|
+
const result = await waitWorkflowExecution({
|
|
16544
|
+
executionId: args.executionId,
|
|
16545
|
+
workspaceId: args["workspace-id"],
|
|
16546
|
+
profile: args.profile,
|
|
16547
|
+
interval: parseDuration(args.interval),
|
|
16548
|
+
timeout: parseDuration(args.timeout),
|
|
16549
|
+
until: args.until,
|
|
16550
|
+
showProgress: !jsonOutput
|
|
16551
|
+
});
|
|
16552
|
+
const output = args.logs ? await addWorkflowLogsToWaitResult(result, {
|
|
16553
|
+
executionId: args.executionId,
|
|
16554
|
+
workspaceId: args["workspace-id"],
|
|
16555
|
+
profile: args.profile
|
|
16556
|
+
}) : result;
|
|
16557
|
+
if (!jsonOutput && output.jobDetails) printExecutionWithLogs({
|
|
16558
|
+
id: output.id,
|
|
16559
|
+
workflowName: output.workflowName,
|
|
16560
|
+
status: output.status,
|
|
16561
|
+
jobExecutions: output.jobExecutions,
|
|
16562
|
+
startedAt: output.startedAt,
|
|
16563
|
+
finishedAt: output.finishedAt,
|
|
16564
|
+
jobDetails: output.jobDetails
|
|
16565
|
+
});
|
|
16566
|
+
else logger.out(output);
|
|
16567
|
+
const failureMessage = getWorkflowWaitFailureMessage(result, args.until);
|
|
16568
|
+
if (failureMessage) throw new Error(failureMessage);
|
|
16569
|
+
}
|
|
16570
|
+
});
|
|
16571
|
+
|
|
15995
16572
|
//#endregion
|
|
15996
16573
|
//#region src/cli/commands/workspace/app/transform.ts
|
|
15997
16574
|
const statusToString = (status) => {
|
|
@@ -17335,7 +17912,7 @@ async function runRepl(options) {
|
|
|
17335
17912
|
const execute = await prepareQueryExecutor(options);
|
|
17336
17913
|
const historyPath = getReplHistoryPath(options.engine, options.profile, options.workspaceId);
|
|
17337
17914
|
const validate = createReplValidator(options.engine);
|
|
17338
|
-
const { highlightSqlLine, highlightGraphqlLine, replTransform } = await import("./repl-editor-
|
|
17915
|
+
const { highlightSqlLine, highlightGraphqlLine, replTransform } = await import("./repl-editor-DD5YP5mt.mjs");
|
|
17339
17916
|
const highlight = options.engine === "sql" ? highlightSqlLine : highlightGraphqlLine;
|
|
17340
17917
|
const prompt = createPrompt({
|
|
17341
17918
|
prefix: "",
|
|
@@ -17669,5 +18246,5 @@ function isDeno() {
|
|
|
17669
18246
|
}
|
|
17670
18247
|
|
|
17671
18248
|
//#endregion
|
|
17672
|
-
export {
|
|
17673
|
-
//# sourceMappingURL=runtime-
|
|
18249
|
+
export { updateCommand$2 as $, protoGqlPermission as $t, listCommand$3 as A, apiCall as An, jobsCommand as At, show as B, toPageDirection as Bn, functionExecutionStatusToString as Bt, listCommand$2 as C, ensureConfigId as Cn, webhookCommand as Ct, waitWorkflowExecution as D, generateUserTypes as Dn, listExecutors as Dt, waitCommand as E, PluginManager as En, listCommand$9 as Et, generateCommand as F, confirmationArgs as Fn, getCommand$5 as Ft, updateCommand$1 as G, executeScript as Gt, logBetaWarning as H, getCommand$6 as Ht, generateMigrationScript as I, deploymentArgs as In, getWorkflow as It, treeCommand as J, MIGRATION_LABEL_KEY as Jt, updateOrganization as K, waitForExecution as Kt, writeDbTypesFile as L, isVerbose as Ln, executionsCommand as Lt, truncate as M, defineAppCommand as Mn, watchExecutorJob as Mt, truncateCommand as N, commonArgs as Nn, startCommand as Nt, resumeCommand as O, prompt as On, getExecutorJob as Ot, generate as P, configArg as Pn, startWorkflow as Pt, getOrganization as Q, generateAllTypeManifestsFromSnapshot as Qt, getConfiguredEditorCommand as R, pagedLogArgs as Rn, getWorkflowExecution as Rt, listApps as S, getNamespacesWithMigrations as Sn, listWebhookExecutors as St, healthCommand as T, sdkNameLabelKey as Tn, triggerExecutor as Tt, remove as U, getExecutor as Ut, showCommand as V, workspaceArgs as Vn, formatKeyValueTable as Vt, removeCommand$1 as W, deploy as Wt, listOrganizations as X, parseMigrationLabelNumber as Xt, listCommand$4 as Y, handleOptionalToRequiredError as Yt, getCommand$1 as Z, compareSnapshotWithRemote as Zt, getWorkspace as _, formatMigrationNumber as _n, generate$1 as _t, updateUser as a, assertValidMigrationFiles as an, deleteCommand$1 as at, createCommand as b, formatMigrationDiff as bn, getCommand$4 as bt, listCommand as c, createSnapshotFromLocalTypes as cn, createFolder as ct, inviteUser as d, getMigrationFilePath as dn, getCommand$3 as dt, DB_TYPES_FILE_NAME as en, updateFolder as et, restoreCommand as f, getMigrationFiles as fn, getOAuth2Client as ft, getCommand as g, reconstructSnapshotFromMigrations as gn, listMachineUsers as gt, listWorkspaces as h, loadDiff as hn, listCommand$7 as ht, updateCommand as i, SCHEMA_FILE_NAME as in, getFolder as it, listWorkflows as j, assertWritable as jn, listExecutorJobs as jt, resumeWorkflow as k, apiCommand as kn, getExecutorWaitFailureMessage as kt, listUsers as l, getLatestMigrationNumber as ln, listCommand$6 as lt, listCommand$1 as m, isValidMigrationNumber as mn, tokenCommand as mt, query as n, INITIAL_SCHEMA_NUMBER as nn, listFolders as nt, removeCommand as o, compareLocalTypesWithSnapshot as on, deleteFolder as ot, restoreWorkspace as p, getNextMigrationNumber as pn, getMachineUserToken as pt, organizationTree as q, bundleMigrationScript as qt, queryCommand as r, MIGRATE_FILE_NAME as rn, getCommand$2 as rt, removeUser as s, compareSnapshots as sn, createCommand$1 as st, isNativeTypeScriptRuntime as t, DIFF_FILE_NAME as tn, listCommand$5 as tt, inviteCommand as u, getMigrationDirPath as un, listOAuth2Clients as ut, deleteCommand as v, parseMigrationNumberArg as vn, listCommand$8 as vt, getAppHealth as w, resourceTrn as wn, triggerCommand as wt, createWorkspace as x, hasChanges as xn, getFunctionRegistry as xt, deleteWorkspace as y, formatDiffSummary as yn, listFunctionRegistries as yt, openInConfiguredEditor as z, paginationArgs as zn, listWorkflowExecutions as zt };
|
|
18250
|
+
//# sourceMappingURL=runtime-jowoN6qC.mjs.map
|