@tailor-platform/sdk 1.76.2 → 1.79.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.
Files changed (103) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/dist/application-BB6BlUfk.mjs +3 -0
  3. package/dist/{application-CqjCcZ2n.mjs → application-fjqb-Gh8.mjs} +57 -10
  4. package/dist/application-fjqb-Gh8.mjs.map +1 -0
  5. package/dist/cli/commands/deploy/deploy.d.mts +8 -3
  6. package/dist/cli/commands/show.d.mts +9 -3
  7. package/dist/cli/commands/workspace/create.d.mts +3 -0
  8. package/dist/cli/commands/workspace/list.d.mts +1 -0
  9. package/dist/cli/commands/workspace/transform.d.mts +2 -0
  10. package/dist/cli/index.mjs +47 -22
  11. package/dist/cli/index.mjs.map +1 -1
  12. package/dist/cli/lib.d.mts +2 -2
  13. package/dist/cli/lib.mjs +2 -2
  14. package/dist/cli/lib.mjs.map +1 -1
  15. package/dist/cli/shared/workspace-name.d.mts +1 -0
  16. package/dist/cli/skills.mjs +1 -1
  17. package/dist/completion/zsh-worker.zsh +18 -1
  18. package/dist/configure/index.mjs +202 -7
  19. package/dist/configure/index.mjs.map +1 -1
  20. package/dist/configure/services/idp/index.d.mts +1 -4
  21. package/dist/configure/services/tailordb/schema.d.mts +1 -7
  22. package/dist/configure/services/workflow/execution-policy.d.mts +2 -2
  23. package/dist/configure/types/type.d.mts +1 -9
  24. package/dist/{crashreport-DZDr-TvH.mjs → crashreport-BNWUM6Kf.mjs} +2 -2
  25. package/dist/{crashreport-DZDr-TvH.mjs.map → crashreport-BNWUM6Kf.mjs.map} +1 -1
  26. package/dist/{crashreport-np4-_DX2.mjs → crashreport-BafWvjjX.mjs} +1 -1
  27. package/dist/errors-DVFS0AZk.mjs +100 -0
  28. package/dist/errors-DVFS0AZk.mjs.map +1 -0
  29. package/dist/{globals-z6zYMjlr.mjs → globals-B-n_3uYu.mjs} +11 -5
  30. package/dist/globals-B-n_3uYu.mjs.map +1 -0
  31. package/dist/{logger-BEiZZ3qT.mjs → logger-BwS4ppwO.mjs} +3 -3
  32. package/dist/logger-BwS4ppwO.mjs.map +1 -0
  33. package/dist/{registry-CTgoVWc_.mjs → registry-CXi7rJq7.mjs} +4 -3
  34. package/dist/registry-CXi7rJq7.mjs.map +1 -0
  35. package/dist/runtime/field-parse.d.mts +11 -0
  36. package/dist/runtime/globals.d.mts +4 -1
  37. package/dist/runtime/index.mjs +1 -1
  38. package/dist/runtime/workflow.d.mts +79 -15
  39. package/dist/runtime/workflow.mjs +2 -2
  40. package/dist/{runtime-DlklyuHN.mjs → runtime-CjMeYuPA.mjs} +1169 -539
  41. package/dist/runtime-CjMeYuPA.mjs.map +1 -0
  42. package/dist/{schema-DbTR1c6M.mjs → schema-CYrle8JZ.mjs} +222 -4
  43. package/dist/schema-CYrle8JZ.mjs.map +1 -0
  44. package/dist/{secretmanager-Bd45j7an.mjs → secretmanager-IY4UvinW.mjs} +42 -9
  45. package/dist/secretmanager-IY4UvinW.mjs.map +1 -0
  46. package/dist/service-CghpdV-9.mjs +3 -0
  47. package/dist/{service-DBFZQloR.mjs → service-Cp0I7ZFe.mjs} +3 -3
  48. package/dist/{service-DBFZQloR.mjs.map → service-Cp0I7ZFe.mjs.map} +1 -1
  49. package/dist/{service-BCRJ-3NV.mjs → service-D12iQGcS.mjs} +2 -2
  50. package/dist/{service-BCRJ-3NV.mjs.map → service-D12iQGcS.mjs.map} +1 -1
  51. package/dist/{test-env-key-IPapa1KJ.mjs → test-env-key-DuZycyWM.mjs} +2 -2
  52. package/dist/{test-env-key-IPapa1KJ.mjs.map → test-env-key-DuZycyWM.mjs.map} +1 -1
  53. package/dist/types/auth.generated.d.mts +9 -36
  54. package/dist/types/executor.generated.d.mts +19 -59
  55. package/dist/types/idp.generated.d.mts +518 -517
  56. package/dist/types/resolver.generated.d.mts +6 -2
  57. package/dist/types/tailordb.generated.d.mts +8 -7
  58. package/dist/utils/test/index.mjs +1 -1
  59. package/dist/vitest/environment.mjs +1 -1
  60. package/dist/vitest/index.d.mts +8 -8
  61. package/dist/vitest/index.mjs +635 -195
  62. package/dist/vitest/index.mjs.map +1 -1
  63. package/dist/vitest/mock.d.mts +8 -8
  64. package/dist/vitest/mocks/aigateway.d.mts +14 -4
  65. package/dist/vitest/mocks/authconnection.d.mts +14 -4
  66. package/dist/vitest/mocks/file.d.mts +24 -6
  67. package/dist/vitest/mocks/iconv.d.mts +28 -4
  68. package/dist/vitest/mocks/idp.d.mts +25 -9
  69. package/dist/vitest/mocks/secretmanager.d.mts +13 -4
  70. package/dist/vitest/mocks/tailordb.d.mts +48 -7
  71. package/dist/vitest/mocks/workflow.d.mts +68 -22
  72. package/dist/vitest/setup.mjs +2 -2
  73. package/dist/workflow-CkIDJpdg.mjs +69 -0
  74. package/dist/workflow-CkIDJpdg.mjs.map +1 -0
  75. package/docs/cli/application.md +58 -11
  76. package/docs/cli/setup.md +1 -1
  77. package/docs/cli/workspace.md +6 -4
  78. package/docs/cli-reference.md +12 -8
  79. package/docs/runtime.md +5 -6
  80. package/docs/services/aigateway.md +2 -0
  81. package/docs/services/tailordb.md +44 -0
  82. package/docs/services/workflow.md +3 -3
  83. package/docs/testing.md +105 -91
  84. package/package.json +7 -7
  85. package/dist/application-6zsDLGKv.mjs +0 -3
  86. package/dist/application-CqjCcZ2n.mjs.map +0 -1
  87. package/dist/configure/types/field-runtime.d.mts +0 -17
  88. package/dist/errors-Dtf2WPaW.mjs +0 -42
  89. package/dist/errors-Dtf2WPaW.mjs.map +0 -1
  90. package/dist/field-runtime-D4QWRiB1.mjs +0 -203
  91. package/dist/field-runtime-D4QWRiB1.mjs.map +0 -1
  92. package/dist/globals-z6zYMjlr.mjs.map +0 -1
  93. package/dist/logger-BEiZZ3qT.mjs.map +0 -1
  94. package/dist/registry-CTgoVWc_.mjs.map +0 -1
  95. package/dist/runtime-DlklyuHN.mjs.map +0 -1
  96. package/dist/schema-DbTR1c6M.mjs.map +0 -1
  97. package/dist/secretmanager-Bd45j7an.mjs.map +0 -1
  98. package/dist/service-CPMlIg3X.mjs +0 -3
  99. package/dist/types-BzJ7A_fn.mjs +0 -199
  100. package/dist/types-BzJ7A_fn.mjs.map +0 -1
  101. package/dist/types-CG9H7HuE.mjs +0 -4
  102. package/dist/workflow-DSwnYPPP.mjs +0 -45
  103. package/dist/workflow-DSwnYPPP.mjs.map +0 -1
@@ -1,9 +1,9 @@
1
- import { t as db } from "./schema-DbTR1c6M.mjs";
1
+ import { t as db } from "./schema-CYrle8JZ.mjs";
2
2
  import { $ as CreateAuthIDPConfigRequestSchema, A as CreatePipelineResolverRequestSchema, At as TenantProviderConfig_TenantProviderType, B as IdPPermissionOperator, Bt as CreateAIGatewayRequestSchema, C as UpdateStaticWebsiteRequestSchema, Ct as AuthOAuth2Client_ClientType, D as CreateSecretManagerVaultRequestSchema, Dt as AuthSCIMAttribute_Uniqueness, E as CreateSecretManagerSecretRequestSchema, Et as AuthSCIMAttribute_Type, F as PipelineResolver_OperationType, Ft as GetApplicationSchemaHealthResponse_ApplicationSchemaHealthStatus, G as CreateExecutorExecutorRequestSchema, Gt as ConditionSchema, H as FunctionExecution_Status, I as CreateIdPServiceRequestSchema, It as UpdateApplicationRequestSchema, J as ExecutorJobStatus, Jt as PageDirection, K as UpdateExecutorExecutorRequestSchema, Kt as Condition_Operator, L as UpdateIdPServiceRequestSchema, M as UpdatePipelineResolverRequestSchema, N as UpdatePipelineServiceRequestSchema, O as UpdateSecretManagerSecretRequestSchema, Ot as AuthSCIMConfig_AuthorizationType, Pt as CreateApplicationRequestSchema, Q as CreateAuthHookRequestSchema, Rt as ApplicationSchemaUpdateAttemptStatus, S as CreateStaticWebsiteRequestSchema, St as AuthInvokerSchema, Tt as AuthSCIMAttribute_Mutability, V as IdPPermissionPermit, Vt as UpdateAIGatewayRequestSchema, X as ExecutorTriggerType, Y as ExecutorTargetType, Z as CreateAuthConnectionRequestSchema, _ as TailorDBGQLPermission_Permit, a as CreateWorkflowRequestSchema, at as CreateTenantConfigRequestSchema, b as TailorDBType_PermitAction, bt as AuthHookPoint, ct as UpdateAuthHookRequestSchema, d as CreateTailorDBServiceRequestSchema, dt as UpdateAuthOAuth2ClientRequestSchema, et as CreateAuthMachineUserRequestSchema, f as CreateTailorDBTypeRequestSchema, ft as UpdateAuthSCIMConfigRequestSchema, g as TailorDBGQLPermission_Operator, gt as UpdateUserProfileConfigRequestSchema, h as TailorDBGQLPermission_Action, ht as UpdateTenantConfigRequestSchema, i as CreateWorkflowJobFunctionRequestSchema, it as CreateAuthServiceRequestSchema, j as CreatePipelineServiceRequestSchema, jt as UserProfileProviderConfig_UserProfileProviderType, l as WorkflowExecution_Status, lt as UpdateAuthIDPConfigRequestSchema, mt as UpdateAuthServiceRequestSchema, nt as CreateAuthSCIMConfigRequestSchema, o as UpdateWorkflowJobFunctionExecutionPolicyRequestSchema, ot as CreateUserProfileConfigRequestSchema, p as UpdateTailorDBTypeRequestSchema, pt as UpdateAuthSCIMResourceRequestSchema, qt as FilterSchema, r as CreateWorkflowJobFunctionExecutionPolicyRequestSchema, rt as CreateAuthSCIMResourceRequestSchema, s as UpdateWorkflowRequestSchema, st as UpdateAuthConnectionRequestSchema, t as WorkspacePlatformUserRole, tt as CreateAuthOAuth2ClientRequestSchema, u as WorkflowJobExecution_Status, ut as UpdateAuthMachineUserRequestSchema, v as TailorDBType_Permission_Operator, vt as AuthConnection_Status, wt as AuthOAuth2Client_GrantType, x as AddCustomDomainRequestSchema, xt as AuthIDPConfig_AuthType, y as TailorDBType_Permission_Permit, yt as AuthConnection_Type, z as IdPLang, zt as Subgraph_ServiceType } from "./workspace_resource_pb-Db3fv68L.mjs";
3
3
  import { t as assertDefined } from "./assert-DBxo8jPo.mjs";
4
- import { a as parseBoolean, i as symbols, n as logger, r as styles, t as CIPromptError } from "./logger-BEiZZ3qT.mjs";
5
- import { A as fetchAllTolerant, B as initOperatorClient, C as createBundleCache, E as hashFile, F as getConsoleBaseUrl, G as byName, H as normalizeBaseUrl, I as getOAuth2ClientId, K as LOG_LEVELS, L as getOrNull, M as fetchPaged, O as defaultPlatformBaseUrl, R as getPlatformBaseUrl, S as hasGenerationHooks, T as hashContent, U as rememberPlatformConfigForToken, V as isDefaultPlatform, W as resolveStaticWebsiteUrls, _ as platformBundleDefinePlugin, d as buildExecutorArgsExpr, f as buildResolverOperationHookExpr, g as stringifyFunction, h as TailorDBTypeSchema, i as resolverBundleKey, j as fetchMachineUserToken, k as fetchAll, l as HTTP_METHODS, m as assertUniqueTailorDBTypeNamesWithExternal, n as generatePluginFilesIfNeeded, o as WorkflowJobFunctionExecutionPolicySchema, p as assertUniqueLocalTailorDBTypeNames, r as loadApplication, t as defineApplication, w as getDistDir, x as getPluginGenerationDependencies, z as initOAuth2Client } from "./application-CqjCcZ2n.mjs";
6
- import { o as loadFilesWithIgnores, s as functionSchema, t as createExecutorService } from "./service-BCRJ-3NV.mjs";
4
+ import { a as parseBoolean, i as symbols, n as logger, r as styles, t as CIPromptError } from "./logger-BwS4ppwO.mjs";
5
+ import { A as fetchAllTolerant, B as initOperatorClient, C as createBundleCache, E as hashFile, F as getConsoleBaseUrl, G as byName, H as normalizeBaseUrl, I as getOAuth2ClientId, K as LOG_LEVELS, L as getOrNull, M as fetchPaged, O as defaultPlatformBaseUrl, R as getPlatformBaseUrl, S as hasGenerationHooks, T as hashContent, U as rememberPlatformConfigForToken, V as isDefaultPlatform, W as resolveStaticWebsiteUrls, _ as platformBundleDefinePlugin, d as buildExecutorArgsExpr, f as buildResolverOperationHookExpr, g as stringifyFunction, h as TailorDBTypeSchema, i as resolverBundleKey, j as fetchMachineUserToken, k as fetchAll, l as HTTP_METHODS, m as assertUniqueTailorDBTypeNamesWithExternal, n as generatePluginFilesIfNeeded, o as WorkflowJobFunctionExecutionPolicySchema, p as assertUniqueLocalTailorDBTypeNames, r as loadApplication, t as defineApplication, w as getDistDir, x as getPluginGenerationDependencies, z as initOAuth2Client } from "./application-fjqb-Gh8.mjs";
6
+ import { o as loadFilesWithIgnores, s as functionSchema, t as createExecutorService } from "./service-D12iQGcS.mjs";
7
7
  import { n as enumConstantsPlugin, t as EnumConstantsGeneratorID } from "./enum-constants-j9QBF0cB.mjs";
8
8
  import { t as multiline } from "./multiline-sfHpTZZK.mjs";
9
9
  import { n as fileUtilsPlugin, t as FileUtilsGeneratorID } from "./file-utils-DcyIPFQh.mjs";
@@ -11,7 +11,7 @@ import { n as kyselyTypePlugin, t as KyselyGeneratorID } from "./kysely-type-D-z
11
11
  import { n as seedPlugin, t as SeedGeneratorID } from "./seed-DFFigL8V.mjs";
12
12
  import { t as readPackageJson } from "./package-json-8b0O9TlX.mjs";
13
13
  import { t as userAgent } from "./user-agent-DX2Jnw0-.mjs";
14
- import { n as isCLIError, t as createCLIError } from "./errors-Dtf2WPaW.mjs";
14
+ import { r as isCLIError, t as createCLIError } from "./errors-DVFS0AZk.mjs";
15
15
  import { n as tightenSecretFilePermissions, r as writeSecretFile } from "./secret-file-DBqZhjFQ.mjs";
16
16
  import { r as withSpan } from "./telemetry-CdqJEzkj.mjs";
17
17
  import { arg, createDefineCommand, defineCommand, runCommand } from "politty";
@@ -22,6 +22,7 @@ import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
22
22
  import { parseEnv } from "node:util";
23
23
  import { ValueSchema, timestampDate } from "@bufbuild/protobuf/wkt";
24
24
  import * as path from "pathe";
25
+ import { basename, dirname, join, resolve } from "pathe";
25
26
  import { formatDistanceToNowStrict } from "date-fns";
26
27
  import { getBorderCharacters, table } from "table";
27
28
  import { pathToFileURL } from "node:url";
@@ -35,13 +36,13 @@ import { Code, ConnectError } from "@connectrpc/connect";
35
36
  import pLimit from "p-limit";
36
37
  import { resolveTSConfig } from "pkg-types";
37
38
  import * as crypto$1 from "node:crypto";
38
- import { createHash } from "node:crypto";
39
+ import { createHash, randomUUID } from "node:crypto";
39
40
  import { ExitPromptError } from "@inquirer/core";
40
- import { confirm, input, password } from "@inquirer/prompts";
41
+ import { confirm, input, password, select } from "@inquirer/prompts";
41
42
  import { isCI } from "std-env";
42
43
  import * as rolldown from "rolldown";
43
44
  import * as fs from "node:fs/promises";
44
- import { glob } from "node:fs/promises";
45
+ import { glob, mkdir, readFile, rename, rm, writeFile } from "node:fs/promises";
45
46
  import { parseSync } from "oxc-parser";
46
47
  import * as inflection from "inflection";
47
48
  import { pathToString } from "@bufbuild/protobuf/reflect";
@@ -802,18 +803,27 @@ function validateUUID(value, source) {
802
803
  * @returns Resolved workspace ID
803
804
  */
804
805
  async function loadWorkspaceId(opts) {
806
+ const workspaceId = await tryLoadWorkspaceId(opts);
807
+ if (workspaceId) return workspaceId;
808
+ throw new Error(multiline`
809
+ Workspace ID not found.
810
+ Please specify workspace ID via --workspace-id option or TAILOR_PLATFORM_WORKSPACE_ID environment variable.
811
+ `);
812
+ }
813
+ /**
814
+ * Load a workspace ID when one is explicitly configured.
815
+ * @param opts - Workspace and profile options
816
+ * @returns Resolved workspace ID, or undefined when no source is configured
817
+ */
818
+ async function tryLoadWorkspaceId(opts) {
805
819
  const profile = opts?.profile || process.env.TAILOR_PLATFORM_PROFILE;
806
- if (opts?.workspaceId) return validateUUID(opts.workspaceId, "--workspace-id option");
820
+ if (opts?.workspaceId !== void 0) return validateUUID(opts.workspaceId, "--workspace-id option");
807
821
  if (process.env.TAILOR_PLATFORM_WORKSPACE_ID) return validateUUID(process.env.TAILOR_PLATFORM_WORKSPACE_ID, "TAILOR_PLATFORM_WORKSPACE_ID environment variable");
808
822
  if (profile) {
809
823
  const wsId = (await readPlatformConfig()).profiles[profile]?.workspace_id;
810
824
  if (!wsId) throw new Error(`Profile "${profile}" not found`);
811
825
  return validateUUID(wsId, `profile "${profile}"`);
812
826
  }
813
- throw new Error(multiline`
814
- Workspace ID not found.
815
- Please specify workspace ID via --workspace-id option or TAILOR_PLATFORM_WORKSPACE_ID environment variable.
816
- `);
817
827
  }
818
828
  /**
819
829
  * Load machine user name from command options, environment variables, or platform config.
@@ -1228,14 +1238,18 @@ async function apiCall(options) {
1228
1238
 
1229
1239
  //#endregion
1230
1240
  //#region src/cli/shared/prompt.ts
1241
+ function canPrompt() {
1242
+ return !isCI && process.stdin.isTTY === true && process.stdout.isTTY === true && !logger.jsonMode;
1243
+ }
1231
1244
  /**
1232
1245
  * Wraps a prompt function with CI guard and cancellation handling.
1233
1246
  * @param fn - A prompt function from `@inquirer/prompts`
1247
+ * @param unavailableMessage - Message used when interactive input is unavailable
1234
1248
  * @returns A wrapped function that throws in CI and exits on cancel
1235
1249
  */
1236
- function withGuard(fn) {
1250
+ function withGuard(fn, unavailableMessage) {
1237
1251
  return async (...args) => {
1238
- if (isCI) throw new CIPromptError();
1252
+ if (!canPrompt()) throw new CIPromptError(unavailableMessage);
1239
1253
  try {
1240
1254
  return await fn(...args);
1241
1255
  } catch (error) {
@@ -1245,9 +1259,10 @@ function withGuard(fn) {
1245
1259
  };
1246
1260
  }
1247
1261
  const prompt = {
1248
- confirm: withGuard(confirm),
1262
+ confirm: withGuard(confirm, "Interactive confirmations are not available in this environment. Use --yes to skip confirmation prompts, or provide the required options explicitly."),
1249
1263
  text: withGuard(input),
1250
- password: withGuard(password)
1264
+ password: withGuard(password),
1265
+ select: withGuard(select)
1251
1266
  };
1252
1267
 
1253
1268
  //#endregion
@@ -11935,132 +11950,957 @@ async function validatePlan(input) {
11935
11950
  }
11936
11951
 
11937
11952
  //#endregion
11938
- //#region src/cli/commands/deploy/deploy.ts
11953
+ //#region src/cli/shared/profile-name.ts
11954
+ const profileNameSchema = z.string().min(1, "Profile must not be empty");
11955
+
11956
+ //#endregion
11957
+ //#region src/cli/shared/workspace-name.ts
11958
+ const workspaceNameSchema = z.string().min(3, "Name must be at least 3 characters").max(63, "Name must be at most 63 characters").regex(/^[a-z0-9-]+$/, "Name can only contain lowercase letters, numbers, and hyphens").refine((name) => !name.startsWith("-") && !name.endsWith("-"), "Name cannot start or end with a hyphen");
11939
11959
  /**
11940
- * Resolve the set of IdP names that have at least one executor subscribed to
11941
- * their user events. When an executor's idpUser trigger omits the `idp` option
11942
- * and exactly one IdP is configured, that IdP is implicitly the target.
11943
- * Executors that omit `idp` while multiple IdPs exist are skipped here; the
11944
- * apply pipeline throws a clearer error for them later.
11945
- * @param application - Loaded application
11946
- * @returns Set of IdP names targeted by idpUser triggers
11960
+ * Validate a workspace name for use in an interactive prompt.
11961
+ * @param name - Candidate workspace name
11962
+ * @returns True when valid, otherwise a validation message
11947
11963
  */
11948
- function collectIdpUserTriggerTargets(application) {
11949
- const targets = /* @__PURE__ */ new Set();
11950
- const idps = collectApplicationIdpNames(application);
11951
- for (const executor of Object.values(application.executorService?.executors ?? {})) {
11952
- if (executor.trigger.kind !== "idpUser") continue;
11953
- if (executor.trigger.idp != null) targets.add(executor.trigger.idp);
11954
- else if (idps.size === 1) {
11955
- const [idp] = idps;
11956
- if (idp) targets.add(idp);
11957
- }
11958
- }
11959
- return targets;
11964
+ function validateWorkspaceName(name) {
11965
+ const result = workspaceNameSchema.safeParse(name);
11966
+ return result.success ? true : assertDefined(result.error.issues[0], "Zod returned no issues").message;
11960
11967
  }
11961
- function collectDeployIdpUserTriggerTargets(targets) {
11962
- const triggerTargets = /* @__PURE__ */ new Set();
11963
- for (const target of targets) for (const idpName of collectIdpUserTriggerTargets(target.application)) triggerTargets.add(idpName);
11964
- return triggerTargets;
11968
+
11969
+ //#endregion
11970
+ //#region src/cli/shared/format.ts
11971
+ /**
11972
+ * Format a protobuf Timestamp to ISO string.
11973
+ * @param timestamp - Protobuf timestamp
11974
+ * @returns Date object or null if invalid
11975
+ */
11976
+ function formatTimestamp(timestamp) {
11977
+ if (!timestamp) return null;
11978
+ const date = timestampDate(timestamp);
11979
+ if (Number.isNaN(date.getTime())) return null;
11980
+ return date;
11965
11981
  }
11966
- function collectExecutorUsedTailorDBTypes(owner, targets) {
11967
- const usedTypes = /* @__PURE__ */ new Set();
11968
- const ownerNamespaces = new Set(owner.application.tailorDBServices.map((service) => service.namespace));
11969
- const applications = targets.map((target) => target.application);
11970
- for (const target of targets) {
11971
- const visibleNamespaces = collectVisibleTailorDBTypeNamespaces(target.application, applications);
11972
- for (const executor of Object.values(target.application.executorService?.executors ?? {})) if (executor.trigger.kind === "tailordb") {
11973
- const namespace = findTailorDBNamespace(target.application, executor.trigger.typeName) ?? resolveSameRunNamespace(visibleNamespaces, executor.trigger.typeName, "TailorDB type");
11974
- if (namespace && ownerNamespaces.has(namespace)) usedTypes.add(executor.trigger.typeName);
11975
- }
11976
- }
11977
- return usedTypes;
11982
+ /**
11983
+ * Formats a table with consistent single-line border style.
11984
+ * Use this instead of importing `table` directly.
11985
+ * @param data - Table data
11986
+ * @param config - Table configuration
11987
+ * @returns Formatted table string
11988
+ */
11989
+ function formatTable(data, config) {
11990
+ return table(data, {
11991
+ ...config,
11992
+ border: getBorderCharacters("norc")
11993
+ });
11978
11994
  }
11979
- function collectExecutorUsedResolvers(owner, targets) {
11980
- const usedResolvers = /* @__PURE__ */ new Set();
11981
- const ownerNamespaces = new Set(owner.application.resolverServices.map((service) => service.namespace));
11982
- const applications = targets.map((target) => target.application);
11983
- for (const target of targets) {
11984
- const visibleNamespaces = collectVisibleResolverNamespaces(target.application, applications);
11985
- for (const executor of Object.values(target.application.executorService?.executors ?? {})) if (executor.trigger.kind === "resolverExecuted") {
11986
- const namespace = findResolverNamespace(target.application, executor.trigger.resolverName) ?? resolveSameRunNamespace(visibleNamespaces, executor.trigger.resolverName, "Resolver");
11987
- if (namespace && ownerNamespaces.has(namespace)) usedResolvers.add(executor.trigger.resolverName);
11988
- }
11989
- }
11990
- return usedResolvers;
11995
+ /**
11996
+ * Formats a key-value table with single-line border style.
11997
+ * @param data - Key-value pairs
11998
+ * @returns Formatted key-value table string
11999
+ */
12000
+ function formatKeyValueTable(data) {
12001
+ return formatTable(data, { singleLine: true });
11991
12002
  }
11992
- function collectExpectedLocalStaticWebsiteNames(targets) {
11993
- const websiteNames = /* @__PURE__ */ new Set();
11994
- for (const target of targets) for (const website of target.application.staticWebsiteServices) websiteNames.add(website.name);
11995
- return websiteNames;
12003
+ /**
12004
+ * Format a Date or ISO timestamp string as a human-readable relative time.
12005
+ * @param value - Date object, ISO date string, or null
12006
+ * @returns Relative time (e.g., "5 minutes ago") or "N/A" for null/invalid
12007
+ */
12008
+ function humanizeRelativeTime(value) {
12009
+ if (value === null) return "N/A";
12010
+ const date = value instanceof Date ? value : new Date(value);
12011
+ if (Number.isNaN(date.getTime())) return typeof value === "string" ? value : "N/A";
12012
+ return formatDistanceToNowStrict(date, { addSuffix: true });
11996
12013
  }
11997
- function addPossiblyAmbiguousNamespace(namespaces, key, namespace) {
11998
- if (namespaces.has(key)) {
11999
- if (namespaces.get(key) !== namespace) namespaces.set(key, void 0);
12014
+
12015
+ //#endregion
12016
+ //#region src/cli/commands/workspace/transform.ts
12017
+ const workspaceInfo = (workspace, folderName) => {
12018
+ const info = {
12019
+ id: workspace.id,
12020
+ name: workspace.name,
12021
+ region: workspace.region,
12022
+ ...workspace.organizationId ? { organizationId: workspace.organizationId } : {},
12023
+ ...workspace.folderId ? { folderId: workspace.folderId } : {},
12024
+ createdAt: formatTimestamp(workspace.createTime),
12025
+ updatedAt: formatTimestamp(workspace.updateTime)
12026
+ };
12027
+ return folderName ? {
12028
+ ...info,
12029
+ folderName
12030
+ } : info;
12031
+ };
12032
+ const workspaceDetails = (workspace, folderName) => {
12033
+ return {
12034
+ ...workspaceInfo(workspace, folderName),
12035
+ deleteProtection: workspace.deleteProtection,
12036
+ organizationId: workspace.organizationId,
12037
+ folderId: workspace.folderId
12038
+ };
12039
+ };
12040
+ async function resolveWorkspaceFolderName(client, workspace) {
12041
+ if (!workspace.organizationId || !workspace.folderId) return void 0;
12042
+ try {
12043
+ return (await client.getOrganizationFolder({
12044
+ organizationId: workspace.organizationId,
12045
+ folderId: workspace.folderId
12046
+ })).folder?.name || void 0;
12047
+ } catch (error) {
12048
+ if (error instanceof ConnectError && (error.code === Code.NotFound || error.code === Code.PermissionDenied)) return;
12049
+ logger.warn(`Failed to resolve workspace folder name: ${error}`);
12000
12050
  return;
12001
12051
  }
12002
- namespaces.set(key, namespace);
12003
12052
  }
12004
- function collectVisibleResources(params) {
12005
- const { application, applications, visibleKeysOf, resourcesOf, createResult, addResource } = params;
12006
- const visibleKeys = visibleKeysOf(application);
12007
- const result = createResult();
12008
- for (const candidate of applications) for (const resource of resourcesOf(candidate)) {
12009
- if (!visibleKeys.has(resource.visibilityKey)) continue;
12010
- addResource(result, resource.resourceKey, resource.visibilityKey);
12011
- }
12012
- return result;
12053
+ function createWorkspaceFolderNameResolver(client) {
12054
+ const cache = /* @__PURE__ */ new Map();
12055
+ return (workspace) => {
12056
+ if (!workspace.organizationId || !workspace.folderId) return Promise.resolve(void 0);
12057
+ const cacheKey = `${workspace.organizationId}/${workspace.folderId}`;
12058
+ const cached = cache.get(cacheKey);
12059
+ if (cached) return cached;
12060
+ const promise = resolveWorkspaceFolderName(client, workspace);
12061
+ cache.set(cacheKey, promise);
12062
+ return promise;
12063
+ };
12013
12064
  }
12014
- function collectApplicationTailorDBNamespaces(application) {
12015
- return /* @__PURE__ */ new Set([...application.tailorDBServices.map((service) => service.namespace), ...application.externalTailorDBNamespaces]);
12065
+ async function workspaceInfoWithFolderName(client, workspace) {
12066
+ const folderName = await resolveWorkspaceFolderName(client, workspace);
12067
+ return workspaceInfo(workspace, folderName);
12016
12068
  }
12017
- function* tailorDBTypeResources(application) {
12018
- for (const service of application.tailorDBServices) for (const typeName of Object.keys(service.types)) yield {
12019
- visibilityKey: service.namespace,
12020
- resourceKey: typeName
12021
- };
12069
+ async function workspaceDetailsWithFolderName(client, workspace) {
12070
+ const folderName = await resolveWorkspaceFolderName(client, workspace);
12071
+ return workspaceDetails(workspace, folderName);
12022
12072
  }
12023
- function collectVisibleTailorDBTypeNamespaces(application, applications) {
12024
- return collectVisibleResources({
12025
- application,
12026
- applications,
12027
- visibleKeysOf: collectApplicationTailorDBNamespaces,
12028
- resourcesOf: tailorDBTypeResources,
12029
- createResult: () => /* @__PURE__ */ new Map(),
12030
- addResource: addPossiblyAmbiguousNamespace
12031
- });
12073
+ async function workspaceInfosWithFolderNames(client, workspaces) {
12074
+ const resolveFolderName = createWorkspaceFolderNameResolver(client);
12075
+ const limit = pLimit(5);
12076
+ return Promise.all(workspaces.map((workspace) => limit(async () => workspaceInfo(workspace, await resolveFolderName(workspace)))));
12032
12077
  }
12033
- function collectApplicationResolverNamespaces(application) {
12034
- return new Set(application.subgraphs.filter((subgraph) => subgraph.Type === "pipeline").map((subgraph) => subgraph.Name));
12078
+ function workspaceDisplayName(workspace) {
12079
+ return workspace.folderName ? `${workspace.folderName}/${workspace.name}` : workspace.name;
12035
12080
  }
12036
- function* idpNameResources(application) {
12037
- for (const name of collectApplicationIdpNames(application)) yield {
12038
- visibilityKey: name,
12039
- resourceKey: name
12081
+ function createWorkspaceNameTransformer(nameKey, folderNameKey) {
12082
+ return (value, item) => {
12083
+ const workspace = item;
12084
+ const name = workspace[nameKey];
12085
+ const folderName = workspace[folderNameKey];
12086
+ if (typeof name === "string" && typeof folderName === "string") return workspaceDisplayName({
12087
+ name,
12088
+ folderName
12089
+ });
12090
+ return String(value ?? "");
12040
12091
  };
12041
12092
  }
12042
- function collectVisibleIdpNames(application, applications) {
12043
- return collectVisibleResources({
12044
- application,
12045
- applications,
12046
- visibleKeysOf: collectApplicationIdpNames,
12047
- resourcesOf: idpNameResources,
12048
- createResult: () => /* @__PURE__ */ new Set(),
12049
- addResource: (names, name) => {
12050
- names.add(name);
12051
- }
12052
- });
12053
- }
12054
- function* resolverResources(application) {
12055
- for (const service of application.resolverServices) for (const resolver of Object.values(service.resolvers)) yield {
12056
- visibilityKey: service.namespace,
12057
- resourceKey: resolver.name
12093
+ const workspaceNameTransformer = createWorkspaceNameTransformer("name", "folderName");
12094
+
12095
+ //#endregion
12096
+ //#region src/cli/commands/workspace/create.ts
12097
+ /**
12098
+ * Schema for workspace creation options
12099
+ * - name: 3-63 chars, lowercase alphanumeric and hyphens, cannot start/end with hyphen
12100
+ * - organizationId, folderId: optional UUIDs
12101
+ */
12102
+ const createWorkspaceOptionsSchema = z.object({
12103
+ name: workspaceNameSchema,
12104
+ region: z.string(),
12105
+ deleteProtection: z.boolean().optional(),
12106
+ organizationId: z.uuid().optional(),
12107
+ folderId: z.uuid().optional(),
12108
+ profile: profileNameSchema.optional()
12109
+ });
12110
+ const validateRegion = async (region, client) => {
12111
+ const availableRegions = await client.listAvailableWorkspaceRegions({});
12112
+ if (!availableRegions.regions.includes(region)) throw new Error(`Region must be one of: ${availableRegions.regions.join(", ")}.`);
12113
+ };
12114
+ function profilePlatformSettings(platformConfig) {
12115
+ const hasOAuth2ClientId = platformConfig?.oauth2ClientId || process.env.TAILOR_PLATFORM_OAUTH2_CLIENT_ID;
12116
+ const hasConsoleUrl = platformConfig?.consoleUrl || process.env.TAILOR_PLATFORM_CONSOLE_URL;
12117
+ return {
12118
+ ...isDefaultPlatform(platformConfig) ? {} : { platform_url: getPlatformBaseUrl(platformConfig) },
12119
+ ...hasOAuth2ClientId ? { oauth2_client_id: getOAuth2ClientId(platformConfig) } : {},
12120
+ ...hasConsoleUrl ? { console_url: getConsoleBaseUrl(platformConfig) } : {}
12058
12121
  };
12059
12122
  }
12060
- function collectVisibleResolverNamespaces(application, applications) {
12061
- return collectVisibleResources({
12062
- application,
12063
- applications,
12123
+ /**
12124
+ * Create a new workspace with the given options.
12125
+ * @param options - Workspace creation options
12126
+ * @returns Created workspace info
12127
+ */
12128
+ async function createWorkspace$1(options) {
12129
+ const validated = validateCreateWorkspaceOptions(options);
12130
+ const client = await initOperatorClient(await loadAccessToken({ profile: validated.profile }), await loadPlatformClientConfig({ profile: validated.profile }));
12131
+ await validateRegion(validated.region, client);
12132
+ return createValidatedWorkspaceWithClient(client, validated);
12133
+ }
12134
+ /**
12135
+ * Create a workspace after its local options and region have been validated.
12136
+ * @param client - Authenticated Operator client
12137
+ * @param options - Validated workspace creation options
12138
+ * @returns Created workspace info
12139
+ */
12140
+ async function createValidatedWorkspaceWithClient(client, options) {
12141
+ return workspaceInfoWithFolderName(client, assertDefined((await client.createWorkspace({
12142
+ workspaceName: options.name,
12143
+ workspaceRegion: options.region,
12144
+ deleteProtection: options.deleteProtection ?? false,
12145
+ organizationId: options.organizationId,
12146
+ folderId: options.folderId
12147
+ })).workspace, "createWorkspace response missing workspace"));
12148
+ }
12149
+ /**
12150
+ * Validate workspace creation options without making API calls.
12151
+ * @param options - Workspace creation options
12152
+ * @returns Validated workspace creation options
12153
+ */
12154
+ function validateCreateWorkspaceOptions(options) {
12155
+ const result = createWorkspaceOptionsSchema.safeParse(options);
12156
+ if (!result.success) throw new Error(assertDefined(result.error.issues[0], "Zod returned no issues").message);
12157
+ return result.data;
12158
+ }
12159
+ const createCommand$1 = defineAppCommand({
12160
+ name: "create",
12161
+ description: "Create a new Tailor Platform workspace.",
12162
+ args: z.object({
12163
+ name: arg(z.string(), {
12164
+ alias: "n",
12165
+ description: "Workspace name"
12166
+ }),
12167
+ region: arg(z.string(), {
12168
+ alias: "r",
12169
+ description: "Workspace region (us-west, asia-northeast)"
12170
+ }),
12171
+ "delete-protection": arg(z.boolean().default(false), {
12172
+ alias: "d",
12173
+ description: "Enable delete protection"
12174
+ }),
12175
+ "organization-id": arg(z.string().optional(), {
12176
+ alias: "o",
12177
+ description: "Organization ID to workspace associate with",
12178
+ env: "TAILOR_PLATFORM_ORGANIZATION_ID"
12179
+ }),
12180
+ "folder-id": arg(z.string().optional(), {
12181
+ alias: "f",
12182
+ description: "Folder ID to workspace associate with",
12183
+ env: "TAILOR_PLATFORM_FOLDER_ID"
12184
+ }),
12185
+ "profile-name": arg(z.string().optional(), {
12186
+ alias: "p",
12187
+ description: "Profile name to create"
12188
+ }),
12189
+ profile: arg(profileNameSchema.optional(), {
12190
+ description: "Workspace profile used for authentication and Platform selection",
12191
+ env: "TAILOR_PLATFORM_PROFILE"
12192
+ }),
12193
+ "profile-user": arg(z.string().optional(), { description: "User email for the profile (defaults to current user)" }),
12194
+ permission: arg(z.enum(["write", "read"]).default("write"), { description: "Profile permission (requires --profile-name). 'read' blocks all write commands while the profile is active." })
12195
+ }).strict(),
12196
+ run: async (args) => {
12197
+ await assertWritable({ profile: args.profile });
12198
+ const profileName = args["profile-name"];
12199
+ let profileSetup;
12200
+ if (profileName) {
12201
+ const config = await readPlatformConfig();
12202
+ if (config.profiles[profileName]) throw new Error(`Profile "${profileName}" already exists.`);
12203
+ const activeProfileName = args.profile;
12204
+ const activeProfileEntry = activeProfileName ? config.profiles[activeProfileName] : void 0;
12205
+ const platformConfig = activeProfileEntry ? platformConfigFromProfile(activeProfileEntry) : void 0;
12206
+ const profileUser = args["profile-user"] || activeProfileEntry?.user || config.current_user;
12207
+ if (!profileUser) throw new Error("Current user not found. Please login or specify --profile-user to create a profile.");
12208
+ if (!hasUserTokenEntry(config, profileUser, platformConfig)) throw new Error(`User "${profileUser}" not found.\nPlease verify your user name and login using 'tailor-sdk login' command.`);
12209
+ profileSetup = {
12210
+ name: profileName,
12211
+ user: profileUser,
12212
+ platformSettings: profilePlatformSettings(platformConfig)
12213
+ };
12214
+ }
12215
+ const workspace = await createWorkspace$1({
12216
+ name: args.name,
12217
+ region: args.region,
12218
+ deleteProtection: args["delete-protection"],
12219
+ organizationId: args["organization-id"],
12220
+ folderId: args["folder-id"],
12221
+ profile: args.profile
12222
+ });
12223
+ let profileInfo;
12224
+ if (profileSetup) {
12225
+ const config = await readPlatformConfig();
12226
+ const platformSettings = profileSetup.platformSettings;
12227
+ config.profiles[profileSetup.name] = {
12228
+ user: profileSetup.user,
12229
+ workspace_id: workspace.id,
12230
+ ...args.permission === "read" ? { readonly: true } : {},
12231
+ ...platformSettings
12232
+ };
12233
+ writePlatformConfig(config);
12234
+ profileInfo = {
12235
+ name: profileSetup.name,
12236
+ user: profileSetup.user,
12237
+ workspaceId: workspace.id,
12238
+ permission: args.permission,
12239
+ ...platformSettings.platform_url ? { platformUrl: platformSettings.platform_url } : {},
12240
+ ...platformSettings.oauth2_client_id ? { oauth2ClientId: platformSettings.oauth2_client_id } : {},
12241
+ ...platformSettings.console_url ? { consoleUrl: platformSettings.console_url } : {}
12242
+ };
12243
+ if (!args.json) logger.success(`Profile "${profileSetup.name}" created successfully.`);
12244
+ }
12245
+ if (!args.json) logger.success(`Workspace "${workspaceDisplayName(workspace)}" created successfully.`);
12246
+ if (args.json && profileInfo) {
12247
+ logger.out({
12248
+ ...workspace,
12249
+ profile: profileInfo
12250
+ });
12251
+ return;
12252
+ }
12253
+ logger.out(workspace, { display: {
12254
+ name: workspaceNameTransformer,
12255
+ folderName: null
12256
+ } });
12257
+ if (profileInfo) {
12258
+ logger.out("Profile:");
12259
+ logger.out(profileInfo);
12260
+ }
12261
+ }
12262
+ });
12263
+
12264
+ //#endregion
12265
+ //#region src/cli/commands/workspace/list.ts
12266
+ /**
12267
+ * List workspaces with an optional order and limit.
12268
+ * @param options - Workspace listing options
12269
+ * @returns List of workspaces
12270
+ */
12271
+ async function listWorkspaces(options) {
12272
+ const profile = profileNameSchema.optional().parse(options?.profile);
12273
+ return listWorkspacesWithClient(await initOperatorClient(await loadAccessToken({ profile }), await loadPlatformClientConfig({ profile })), options);
12274
+ }
12275
+ /**
12276
+ * List workspaces using an existing Operator client.
12277
+ * @param client - Authenticated Operator client
12278
+ * @param options - Workspace listing options
12279
+ * @returns List of workspaces
12280
+ */
12281
+ async function listWorkspacesWithClient(client, options) {
12282
+ const pageDirection = toPageDirection(options?.order);
12283
+ return workspaceInfosWithFolderNames(client, await fetchPaged(async (pageToken, pageSize) => {
12284
+ const { workspaces, nextPageToken } = await client.listWorkspaces({
12285
+ pageToken,
12286
+ pageSize,
12287
+ pageDirection
12288
+ });
12289
+ return [workspaces, nextPageToken];
12290
+ }, { limit: options?.limit }));
12291
+ }
12292
+ const listCommand$9 = defineAppCommand({
12293
+ name: "list",
12294
+ description: "List all Tailor Platform workspaces.",
12295
+ args: z.object({
12296
+ ...paginationArgs(),
12297
+ profile: arg(profileNameSchema.optional(), {
12298
+ description: "Workspace profile used for authentication and Platform selection",
12299
+ env: "TAILOR_PLATFORM_PROFILE"
12300
+ })
12301
+ }).strict(),
12302
+ run: async (args) => {
12303
+ const workspaces = await listWorkspaces({
12304
+ order: args.order,
12305
+ limit: args.limit,
12306
+ profile: args.profile
12307
+ });
12308
+ logger.out(workspaces, { display: {
12309
+ name: workspaceNameTransformer,
12310
+ folderName: null,
12311
+ organizationId: null,
12312
+ folderId: null,
12313
+ updatedAt: null
12314
+ } });
12315
+ }
12316
+ });
12317
+
12318
+ //#endregion
12319
+ //#region src/cli/commands/deploy/workspace-context.ts
12320
+ const workspaceContextSchema = z.object({
12321
+ version: z.literal(1),
12322
+ platformUrl: z.url(),
12323
+ applicationId: z.string().min(1).optional(),
12324
+ workspaceId: z.uuid()
12325
+ });
12326
+ function defaultConfigPath() {
12327
+ return resolve(process.cwd(), "tailor.config.ts");
12328
+ }
12329
+ function contextPath(configPath) {
12330
+ return join(dirname(configPath), ".tailor-sdk", `${basename(configPath)}.context.json`);
12331
+ }
12332
+ /**
12333
+ * Load the project workspace context when it belongs to the current platform.
12334
+ * Missing, malformed, and cross-platform state is ignored.
12335
+ * @param platformUrl - Current Platform API base URL
12336
+ * @param configPath - Configuration file whose workspace selection is loaded
12337
+ * @param applicationId - Application identity that must match the saved context
12338
+ * @returns Valid context for the current platform, or undefined
12339
+ */
12340
+ async function loadWorkspaceContext(platformUrl, configPath = defaultConfigPath(), applicationId) {
12341
+ let contents;
12342
+ try {
12343
+ contents = await readFile(contextPath(configPath), "utf8");
12344
+ } catch (error) {
12345
+ if (error instanceof Error && "code" in error && error.code === "ENOENT") return void 0;
12346
+ throw error;
12347
+ }
12348
+ let value;
12349
+ try {
12350
+ value = JSON.parse(contents);
12351
+ } catch {
12352
+ return;
12353
+ }
12354
+ const result = workspaceContextSchema.safeParse(value);
12355
+ if (!result.success || result.data.platformUrl !== platformUrl || applicationId !== void 0 && result.data.applicationId !== applicationId) return;
12356
+ return result.data;
12357
+ }
12358
+ /**
12359
+ * Persist the selected workspace as project-local SDK state.
12360
+ * @param context - Workspace context to persist
12361
+ * @param configPath - Configuration file whose workspace selection is persisted
12362
+ * @param applicationId - Application identity stored with the workspace selection
12363
+ */
12364
+ async function saveWorkspaceContext(context, configPath = defaultConfigPath(), applicationId) {
12365
+ const validated = workspaceContextSchema.parse({
12366
+ ...context,
12367
+ ...applicationId === void 0 ? {} : { applicationId }
12368
+ });
12369
+ const stateDirectory = join(dirname(configPath), ".tailor-sdk");
12370
+ const targetPath = contextPath(configPath);
12371
+ const serialized = `${JSON.stringify(validated, null, 2)}\n`;
12372
+ try {
12373
+ if (await readFile(targetPath, "utf8") === serialized) return;
12374
+ } catch {}
12375
+ const temporaryPath = `${targetPath}.${process.pid}.${randomUUID()}.tmp`;
12376
+ await mkdir(stateDirectory, { recursive: true });
12377
+ try {
12378
+ await writeFile(temporaryPath, serialized, { mode: 384 });
12379
+ await rename(temporaryPath, targetPath);
12380
+ } catch (error) {
12381
+ await rm(temporaryPath, { force: true }).catch(() => void 0);
12382
+ throw error;
12383
+ }
12384
+ }
12385
+
12386
+ //#endregion
12387
+ //#region src/cli/commands/deploy/workspace.ts
12388
+ function suggestedWorkspaceName() {
12389
+ const name = basename(process.cwd()).toLowerCase().replaceAll(/[^a-z0-9-]+/g, "-").replaceAll(/^-+|-+$/g, "").slice(0, 63).replace(/-+$/, "");
12390
+ return validateWorkspaceName(name) === true ? name : "my-workspace";
12391
+ }
12392
+ function executableAction(args) {
12393
+ return {
12394
+ command: "tailor-sdk",
12395
+ args
12396
+ };
12397
+ }
12398
+ function deployArgs(options) {
12399
+ return options.deployArgs ?? ["deploy"];
12400
+ }
12401
+ function workspaceCommandArgs(options) {
12402
+ return options.workspaceCommandArgs ?? [];
12403
+ }
12404
+ function createDeployArgs(options, name, region) {
12405
+ return [
12406
+ ...deployArgs(options),
12407
+ "--create-workspace",
12408
+ "--workspace-name",
12409
+ name,
12410
+ "--workspace-region",
12411
+ region,
12412
+ ...options.organizationId ? ["--organization-id", options.organizationId] : [],
12413
+ ...options.folderId ? ["--folder-id", options.folderId] : []
12414
+ ];
12415
+ }
12416
+ function selectDeployArgs(options) {
12417
+ return [
12418
+ ...deployArgs(options),
12419
+ "--workspace-id",
12420
+ "<workspace-id>"
12421
+ ];
12422
+ }
12423
+ function workspaceLabel(workspace) {
12424
+ const organization = workspace.organizationId ?? "personal";
12425
+ return `${workspaceDisplayName(workspace)} (${workspace.region}, org: ${organization}, id: ${workspace.id})`;
12426
+ }
12427
+ function workspaceMatchesRequestedIdentity(workspace, options) {
12428
+ return options.workspaceName === workspace.name && options.workspaceRegion === workspace.region && options.organizationId === workspace.organizationId && options.folderId === workspace.folderId;
12429
+ }
12430
+ function workspaceIdentity(workspace) {
12431
+ const { id, name, region, organizationId, folderId } = workspace;
12432
+ return {
12433
+ id,
12434
+ name,
12435
+ region,
12436
+ organizationId,
12437
+ folderId
12438
+ };
12439
+ }
12440
+ function projectContextTargets(contextTargets) {
12441
+ if (!contextTargets) return void 0;
12442
+ return [...new Map(contextTargets.map((target) => [target.configPath, target])).values()];
12443
+ }
12444
+ async function loadProjectContexts(platformUrl, contextTargets) {
12445
+ const targets = projectContextTargets(contextTargets);
12446
+ if (!targets || targets.length === 0) {
12447
+ const context = await loadWorkspaceContext(platformUrl);
12448
+ return context ? [context] : [];
12449
+ }
12450
+ return (await Promise.all(targets.map(({ configPath, applicationId }) => loadWorkspaceContext(platformUrl, configPath, applicationId)))).filter((context) => context !== void 0);
12451
+ }
12452
+ async function persistWorkspaceContext(context, contextTargets) {
12453
+ const targets = projectContextTargets(contextTargets);
12454
+ if (!targets || targets.length === 0) {
12455
+ await saveWorkspaceContext(context);
12456
+ return;
12457
+ }
12458
+ const failures = (await Promise.allSettled(targets.map(({ configPath, applicationId }) => saveWorkspaceContext(context, configPath, applicationId)))).filter((result) => result.status === "rejected");
12459
+ if (failures.length > 0) throw new Error(failures.map(({ reason }) => reason instanceof Error ? reason.message : String(reason)).join("; "));
12460
+ }
12461
+ async function rememberWorkspaceContext(context, options, failurePolicy = "error-on-partial") {
12462
+ if (options.dryRun) return;
12463
+ try {
12464
+ await persistWorkspaceContext(context, options.contextTargets);
12465
+ } catch (error) {
12466
+ if ((projectContextTargets(options.contextTargets)?.length ?? 0) > 1 && failurePolicy === "error-on-partial") throw createCLIError({
12467
+ code: "WORKSPACE_CONTEXT_SAVE_FAILED",
12468
+ message: "The workspace selection could not be saved for every configuration file.",
12469
+ details: error instanceof Error ? error.message : String(error),
12470
+ suggestion: "Fix project state permissions, then rerun deploy with the workspace ID.",
12471
+ next: executableAction([
12472
+ ...deployArgs(options),
12473
+ "--workspace-id",
12474
+ context.workspaceId
12475
+ ]),
12476
+ context: {
12477
+ workspaceId: context.workspaceId,
12478
+ configPaths: options.contextTargets?.map(({ configPath }) => configPath)
12479
+ }
12480
+ });
12481
+ logger.warn(`Could not save the project workspace selection (${error instanceof Error ? error.message : String(error)}). Continue with --workspace-id ${context.workspaceId} on later runs.`);
12482
+ }
12483
+ }
12484
+ async function useWorkspace(client, platformUrl, workspace, options, failurePolicy = "error-on-partial") {
12485
+ await rememberWorkspaceContext({
12486
+ version: 1,
12487
+ platformUrl,
12488
+ workspaceId: workspace.id
12489
+ }, options, failurePolicy);
12490
+ logger.info(`Using workspace: ${workspaceLabel(workspace)}`);
12491
+ return {
12492
+ client,
12493
+ workspaceId: workspace.id
12494
+ };
12495
+ }
12496
+ function useRememberedWorkspace(client, workspace) {
12497
+ logger.warn(`Using saved workspace selection: ${workspaceLabel(workspace)}`);
12498
+ return {
12499
+ client,
12500
+ workspaceId: workspace.id
12501
+ };
12502
+ }
12503
+ const createNewWorkspaceSelection = "create-new-workspace";
12504
+ async function chooseWorkspace(client, platformUrl, workspaces, options) {
12505
+ const workspaceId = await prompt.select({
12506
+ message: "Select a workspace",
12507
+ choices: [...workspaces.map((workspace) => ({
12508
+ name: workspaceLabel(workspace),
12509
+ value: workspace.id
12510
+ })), {
12511
+ name: "Create new workspace",
12512
+ value: createNewWorkspaceSelection
12513
+ }]
12514
+ });
12515
+ if (workspaceId === createNewWorkspaceSelection) return createWorkspaceForDeploy(client, platformUrl, options);
12516
+ const workspace = workspaces.find(({ id }) => id === workspaceId);
12517
+ if (!workspace) throw new Error("Selected workspace was not found");
12518
+ return useWorkspace(client, platformUrl, workspace, options);
12519
+ }
12520
+ function invalidCreateOptionsError(options, name, region, details) {
12521
+ return createCLIError({
12522
+ code: "WORKSPACE_CREATE_OPTIONS_INVALID",
12523
+ message: "Workspace creation options are invalid.",
12524
+ details,
12525
+ suggestion: "Correct the workspace creation options and rerun deploy.",
12526
+ next: executableAction(createDeployArgs(options, name, region))
12527
+ });
12528
+ }
12529
+ async function createWorkspace(client, platformUrl, options, availableRegions, validatedOptions) {
12530
+ let name = options.workspaceName;
12531
+ let region = options.workspaceRegion;
12532
+ const interactive = canPrompt();
12533
+ if (interactive) {
12534
+ name ??= await prompt.text({
12535
+ message: "Workspace name",
12536
+ default: suggestedWorkspaceName(),
12537
+ validate: validateWorkspaceName
12538
+ });
12539
+ region ??= await prompt.select({
12540
+ message: "Workspace region",
12541
+ choices: availableRegions.map((value) => ({
12542
+ name: value,
12543
+ value
12544
+ }))
12545
+ });
12546
+ } else {
12547
+ const missingOptions = [...name === void 0 ? ["--workspace-name"] : [], ...region === void 0 ? ["--workspace-region"] : []];
12548
+ if (missingOptions.length > 0) throw createCLIError({
12549
+ code: "WORKSPACE_CREATE_OPTIONS_REQUIRED",
12550
+ message: "Workspace creation requires a name and region in non-interactive mode.",
12551
+ suggestion: "Provide every workspace creation option and rerun deploy.",
12552
+ next: executableAction(createDeployArgs(options, name ?? "<name>", region ?? "<region>")),
12553
+ context: { missingOptions }
12554
+ });
12555
+ }
12556
+ if (!name || !region) throw new Error("Workspace creation options were not resolved");
12557
+ let validated = validatedOptions;
12558
+ if (!validated) {
12559
+ try {
12560
+ validated = validateCreateWorkspaceOptions({
12561
+ name,
12562
+ region,
12563
+ organizationId: options.organizationId,
12564
+ folderId: options.folderId
12565
+ });
12566
+ } catch (error) {
12567
+ throw invalidCreateOptionsError(options, name, region, error instanceof Error ? error.message : String(error));
12568
+ }
12569
+ if (!availableRegions.includes(region)) throw invalidCreateOptionsError(options, name, region, `Region must be one of: ${availableRegions.join(", ")}.`);
12570
+ }
12571
+ if (interactive) {
12572
+ const scope = [options.organizationId ? `organization: ${options.organizationId}` : void 0, options.folderId ? `folder: ${options.folderId}` : void 0].filter((value) => value !== void 0);
12573
+ if (!await prompt.confirm({
12574
+ message: `Create workspace "${name}" in ${region}${scope.length > 0 ? ` (${scope.join(", ")})` : ""}?`,
12575
+ default: true
12576
+ })) throw createCLIError({
12577
+ code: "WORKSPACE_CREATION_CANCELLED",
12578
+ message: "Workspace creation was cancelled."
12579
+ });
12580
+ }
12581
+ let workspace;
12582
+ try {
12583
+ workspace = await createValidatedWorkspaceWithClient(client, validated);
12584
+ } catch (error) {
12585
+ if (error instanceof ConnectError && ![
12586
+ Code.Canceled,
12587
+ Code.Unknown,
12588
+ Code.DeadlineExceeded,
12589
+ Code.Aborted,
12590
+ Code.Internal,
12591
+ Code.Unavailable,
12592
+ Code.DataLoss
12593
+ ].includes(error.code)) throw error;
12594
+ throw createCLIError({
12595
+ code: "WORKSPACE_CREATION_FAILED",
12596
+ message: "Workspace creation did not complete successfully.",
12597
+ details: error instanceof Error ? error.message : String(error),
12598
+ suggestion: "The outcome may be uncertain. List workspaces before retrying creation to avoid duplicates.",
12599
+ next: executableAction([
12600
+ "workspace",
12601
+ "list",
12602
+ ...workspaceCommandArgs(options),
12603
+ "--json"
12604
+ ])
12605
+ });
12606
+ }
12607
+ await rememberWorkspaceContext({
12608
+ version: 1,
12609
+ platformUrl,
12610
+ workspaceId: workspace.id
12611
+ }, options);
12612
+ logger.success(`Created workspace: ${workspaceLabel(workspace)}`);
12613
+ logger.info(`Reuse this workspace with: tailor-sdk deploy --workspace-id ${workspace.id}`);
12614
+ logger.info(`Or set TAILOR_PLATFORM_WORKSPACE_ID=${workspace.id}.`);
12615
+ return {
12616
+ client,
12617
+ workspaceId: workspace.id
12618
+ };
12619
+ }
12620
+ async function createWorkspaceForDeploy(client, platformUrl, options, requestedRegions, validatedOptions) {
12621
+ const regions = requestedRegions ?? (await client.listAvailableWorkspaceRegions({})).regions;
12622
+ if (options.dryRun) throw createCLIError({
12623
+ code: "WORKSPACE_CREATION_DISABLED_IN_DRY_RUN",
12624
+ message: "Dry-run cannot create the workspace required to build a deployment plan.",
12625
+ suggestion: "Create a workspace explicitly, then rerun the same dry-run with its workspace ID.",
12626
+ context: { availableRegions: regions }
12627
+ });
12628
+ return createWorkspace(client, platformUrl, options, regions, validatedOptions);
12629
+ }
12630
+ /**
12631
+ * Resolve or provision the workspace used by deploy.
12632
+ * Explicit configuration wins over project context and account discovery.
12633
+ * @param options - Deploy workspace selection and creation options
12634
+ * @returns Authenticated client and resolved workspace ID
12635
+ */
12636
+ async function resolveDeployWorkspace(options = {}) {
12637
+ const createOptionNames = [options.workspaceName !== void 0 ? "--workspace-name" : void 0, options.workspaceRegion !== void 0 ? "--workspace-region" : void 0].filter((name) => name !== void 0);
12638
+ if (!options.createWorkspace && createOptionNames.length > 0) throw createCLIError({
12639
+ code: "WORKSPACE_CREATE_FLAG_REQUIRED",
12640
+ message: "Workspace creation options require --create-workspace.",
12641
+ suggestion: "Add --create-workspace or remove the workspace creation options.",
12642
+ next: executableAction(createDeployArgs(options, options.workspaceName ?? "<name>", options.workspaceRegion ?? "<region>")),
12643
+ context: { options: createOptionNames }
12644
+ });
12645
+ if (options.createWorkspace && options.workspaceName !== void 0) {
12646
+ const nameValidation = validateWorkspaceName(options.workspaceName);
12647
+ if (nameValidation !== true) throw invalidCreateOptionsError(options, options.workspaceName, options.workspaceRegion ?? "<region>", nameValidation);
12648
+ }
12649
+ if (options.createWorkspace && options.workspaceRegion === "") throw invalidCreateOptionsError(options, options.workspaceName ?? "<name>", options.workspaceRegion, "Region must not be empty.");
12650
+ const explicitWorkspaceId = await tryLoadWorkspaceId({
12651
+ workspaceId: options.workspaceId,
12652
+ profile: options.profile
12653
+ });
12654
+ const accessToken = await loadAccessToken({ profile: options.profile });
12655
+ const platformConfig = await loadPlatformClientConfig({
12656
+ profile: options.profile,
12657
+ allowMissingProfile: explicitWorkspaceId !== void 0
12658
+ });
12659
+ const platformUrl = getPlatformBaseUrl(platformConfig);
12660
+ const client = await initOperatorClient(accessToken, platformConfig);
12661
+ if (explicitWorkspaceId) {
12662
+ let response;
12663
+ try {
12664
+ response = await client.getWorkspace({ workspaceId: explicitWorkspaceId });
12665
+ } catch (error) {
12666
+ if (error instanceof ConnectError && error.code === Code.NotFound) throw createCLIError({
12667
+ code: "WORKSPACE_NOT_FOUND",
12668
+ message: `Workspace "${explicitWorkspaceId}" was not found.`
12669
+ });
12670
+ throw error;
12671
+ }
12672
+ if (!response.workspace) throw createCLIError({
12673
+ code: "WORKSPACE_NOT_FOUND",
12674
+ message: `Workspace "${explicitWorkspaceId}" was not found.`
12675
+ });
12676
+ return useWorkspace(client, platformUrl, workspaceInfo(response.workspace), options, "warn");
12677
+ }
12678
+ let requestedCreateOptions;
12679
+ if (options.createWorkspace && options.workspaceName !== void 0 && options.workspaceRegion !== void 0) try {
12680
+ requestedCreateOptions = validateCreateWorkspaceOptions({
12681
+ name: options.workspaceName,
12682
+ region: options.workspaceRegion,
12683
+ organizationId: options.organizationId,
12684
+ folderId: options.folderId
12685
+ });
12686
+ } catch (error) {
12687
+ throw invalidCreateOptionsError(options, options.workspaceName, options.workspaceRegion, error instanceof Error ? error.message : String(error));
12688
+ }
12689
+ const [contexts, workspaces] = await Promise.all([loadProjectContexts(platformUrl, options.contextTargets), listWorkspacesWithClient(client)]);
12690
+ const interactive = canPrompt();
12691
+ const contextWorkspaceIds = new Set(contexts.map(({ workspaceId }) => workspaceId));
12692
+ const linkedWorkspace = contextWorkspaceIds.size === 1 ? workspaces.find(({ id }) => contextWorkspaceIds.has(id)) : void 0;
12693
+ if (linkedWorkspace && (!options.createWorkspace || workspaceMatchesRequestedIdentity(linkedWorkspace, options))) {
12694
+ const contextTargetCount = projectContextTargets(options.contextTargets)?.length ?? 1;
12695
+ return contexts.length === contextTargetCount ? useRememberedWorkspace(client, linkedWorkspace) : useWorkspace(client, platformUrl, linkedWorkspace, options);
12696
+ }
12697
+ const onlyWorkspace = workspaces.length === 1 ? workspaces[0] : void 0;
12698
+ const canReuseOnlyWorkspace = onlyWorkspace !== void 0 && requestedCreateOptions !== void 0 && workspaceMatchesRequestedIdentity(onlyWorkspace, options);
12699
+ let requestedRegions;
12700
+ if (requestedCreateOptions && !canReuseOnlyWorkspace) {
12701
+ requestedRegions = await client.listAvailableWorkspaceRegions({});
12702
+ if (!requestedRegions.regions.includes(requestedCreateOptions.region)) throw invalidCreateOptionsError(options, requestedCreateOptions.name, requestedCreateOptions.region, `Region must be one of: ${requestedRegions.regions.join(", ")}.`);
12703
+ }
12704
+ if (workspaces.length === 0 && (interactive || options.createWorkspace || contexts.length === 0)) {
12705
+ const regions = requestedRegions?.regions ?? (await client.listAvailableWorkspaceRegions({})).regions;
12706
+ if (options.dryRun || interactive || options.createWorkspace) return createWorkspaceForDeploy(client, platformUrl, options, regions, requestedCreateOptions);
12707
+ throw createCLIError({
12708
+ code: "WORKSPACE_NOT_FOUND",
12709
+ message: "No workspaces are available for this account.",
12710
+ suggestion: "Create one during deploy by providing the workspace name and one of the available regions.",
12711
+ next: executableAction(createDeployArgs(options, "<name>", "<region>")),
12712
+ context: { availableRegions: regions }
12713
+ });
12714
+ }
12715
+ if (contextWorkspaceIds.size > 1) {
12716
+ const canReplaceStaleContexts = options.createWorkspace === true && options.workspaceName !== void 0 && options.workspaceRegion !== void 0 && workspaces.length === 0;
12717
+ if (!interactive && !canReplaceStaleContexts) throw createCLIError({
12718
+ code: "WORKSPACE_CONTEXT_CONFLICT",
12719
+ message: "The deployed configuration files are linked to different workspaces.",
12720
+ suggestion: "Choose one workspace explicitly for the combined deployment.",
12721
+ next: executableAction(selectDeployArgs(options)),
12722
+ context: { savedWorkspaceIds: [...contextWorkspaceIds] }
12723
+ });
12724
+ if (workspaces.length > 0 && !options.createWorkspace) return chooseWorkspace(client, platformUrl, workspaces, options);
12725
+ }
12726
+ if (!linkedWorkspace && contexts.length > 0) {
12727
+ const explicitlyEnsuringSingleTarget = options.createWorkspace === true && options.workspaceName !== void 0 && options.workspaceRegion !== void 0 && workspaces.length <= 1;
12728
+ if (!interactive && !explicitlyEnsuringSingleTarget) throw createCLIError({
12729
+ code: "WORKSPACE_CONTEXT_STALE",
12730
+ message: "The saved project workspace is no longer available.",
12731
+ suggestion: "Choose an available workspace explicitly before deploying.",
12732
+ next: executableAction(selectDeployArgs(options)),
12733
+ context: {
12734
+ savedWorkspaceIds: [...contextWorkspaceIds],
12735
+ workspaces: workspaces.map(workspaceIdentity)
12736
+ }
12737
+ });
12738
+ if (workspaces.length > 0 && interactive && !options.createWorkspace) return chooseWorkspace(client, platformUrl, workspaces, options);
12739
+ }
12740
+ if (workspaces.length === 1) {
12741
+ const [workspace] = workspaces;
12742
+ if (!workspace) throw new Error("Workspace discovery returned an invalid result");
12743
+ if (options.createWorkspace && !workspaceMatchesRequestedIdentity(workspace, options)) throw createCLIError({
12744
+ code: "WORKSPACE_CREATE_CONFLICT",
12745
+ message: "The existing workspace does not match the requested workspace.",
12746
+ suggestion: "Use the existing workspace, or run the explicit workspace create command to create another one.",
12747
+ next: executableAction([
12748
+ "workspace",
12749
+ "create",
12750
+ ...workspaceCommandArgs(options),
12751
+ ...options.workspaceCommandJson ? ["--json"] : [],
12752
+ "--name",
12753
+ options.workspaceName ?? "<name>",
12754
+ "--region",
12755
+ options.workspaceRegion ?? "<region>",
12756
+ ...options.organizationId ? ["--organization-id", options.organizationId] : [],
12757
+ ...options.folderId ? ["--folder-id", options.folderId] : []
12758
+ ]),
12759
+ context: { existingWorkspace: workspaceIdentity(workspace) }
12760
+ });
12761
+ if (interactive && !options.createWorkspace) return chooseWorkspace(client, platformUrl, workspaces, options);
12762
+ return useWorkspace(client, platformUrl, workspace, options);
12763
+ }
12764
+ if (workspaces.length > 1) {
12765
+ if (!interactive) throw createCLIError({
12766
+ code: "WORKSPACE_SELECTION_REQUIRED",
12767
+ message: "Multiple workspaces are available.",
12768
+ suggestion: "Choose one explicitly for non-interactive deployment.",
12769
+ next: executableAction(selectDeployArgs(options)),
12770
+ context: { workspaces: workspaces.map(workspaceIdentity) }
12771
+ });
12772
+ return chooseWorkspace(client, platformUrl, workspaces, options);
12773
+ }
12774
+ throw new Error("Workspace discovery returned an invalid result");
12775
+ }
12776
+
12777
+ //#endregion
12778
+ //#region src/cli/commands/deploy/deploy.ts
12779
+ /**
12780
+ * Resolve the set of IdP names that have at least one executor subscribed to
12781
+ * their user events. When an executor's idpUser trigger omits the `idp` option
12782
+ * and exactly one IdP is configured, that IdP is implicitly the target.
12783
+ * Executors that omit `idp` while multiple IdPs exist are skipped here; the
12784
+ * apply pipeline throws a clearer error for them later.
12785
+ * @param application - Loaded application
12786
+ * @returns Set of IdP names targeted by idpUser triggers
12787
+ */
12788
+ function collectIdpUserTriggerTargets(application) {
12789
+ const targets = /* @__PURE__ */ new Set();
12790
+ const idps = collectApplicationIdpNames(application);
12791
+ for (const executor of Object.values(application.executorService?.executors ?? {})) {
12792
+ if (executor.trigger.kind !== "idpUser") continue;
12793
+ if (executor.trigger.idp != null) targets.add(executor.trigger.idp);
12794
+ else if (idps.size === 1) {
12795
+ const [idp] = idps;
12796
+ if (idp) targets.add(idp);
12797
+ }
12798
+ }
12799
+ return targets;
12800
+ }
12801
+ function collectDeployIdpUserTriggerTargets(targets) {
12802
+ const triggerTargets = /* @__PURE__ */ new Set();
12803
+ for (const target of targets) for (const idpName of collectIdpUserTriggerTargets(target.application)) triggerTargets.add(idpName);
12804
+ return triggerTargets;
12805
+ }
12806
+ function collectExecutorUsedTailorDBTypes(owner, targets) {
12807
+ const usedTypes = /* @__PURE__ */ new Set();
12808
+ const ownerNamespaces = new Set(owner.application.tailorDBServices.map((service) => service.namespace));
12809
+ const applications = targets.map((target) => target.application);
12810
+ for (const target of targets) {
12811
+ const visibleNamespaces = collectVisibleTailorDBTypeNamespaces(target.application, applications);
12812
+ for (const executor of Object.values(target.application.executorService?.executors ?? {})) if (executor.trigger.kind === "tailordb") {
12813
+ const namespace = findTailorDBNamespace(target.application, executor.trigger.typeName) ?? resolveSameRunNamespace(visibleNamespaces, executor.trigger.typeName, "TailorDB type");
12814
+ if (namespace && ownerNamespaces.has(namespace)) usedTypes.add(executor.trigger.typeName);
12815
+ }
12816
+ }
12817
+ return usedTypes;
12818
+ }
12819
+ function collectExecutorUsedResolvers(owner, targets) {
12820
+ const usedResolvers = /* @__PURE__ */ new Set();
12821
+ const ownerNamespaces = new Set(owner.application.resolverServices.map((service) => service.namespace));
12822
+ const applications = targets.map((target) => target.application);
12823
+ for (const target of targets) {
12824
+ const visibleNamespaces = collectVisibleResolverNamespaces(target.application, applications);
12825
+ for (const executor of Object.values(target.application.executorService?.executors ?? {})) if (executor.trigger.kind === "resolverExecuted") {
12826
+ const namespace = findResolverNamespace(target.application, executor.trigger.resolverName) ?? resolveSameRunNamespace(visibleNamespaces, executor.trigger.resolverName, "Resolver");
12827
+ if (namespace && ownerNamespaces.has(namespace)) usedResolvers.add(executor.trigger.resolverName);
12828
+ }
12829
+ }
12830
+ return usedResolvers;
12831
+ }
12832
+ function collectExpectedLocalStaticWebsiteNames(targets) {
12833
+ const websiteNames = /* @__PURE__ */ new Set();
12834
+ for (const target of targets) for (const website of target.application.staticWebsiteServices) websiteNames.add(website.name);
12835
+ return websiteNames;
12836
+ }
12837
+ function addPossiblyAmbiguousNamespace(namespaces, key, namespace) {
12838
+ if (namespaces.has(key)) {
12839
+ if (namespaces.get(key) !== namespace) namespaces.set(key, void 0);
12840
+ return;
12841
+ }
12842
+ namespaces.set(key, namespace);
12843
+ }
12844
+ function collectVisibleResources(params) {
12845
+ const { application, applications, visibleKeysOf, resourcesOf, createResult, addResource } = params;
12846
+ const visibleKeys = visibleKeysOf(application);
12847
+ const result = createResult();
12848
+ for (const candidate of applications) for (const resource of resourcesOf(candidate)) {
12849
+ if (!visibleKeys.has(resource.visibilityKey)) continue;
12850
+ addResource(result, resource.resourceKey, resource.visibilityKey);
12851
+ }
12852
+ return result;
12853
+ }
12854
+ function collectApplicationTailorDBNamespaces(application) {
12855
+ return /* @__PURE__ */ new Set([...application.tailorDBServices.map((service) => service.namespace), ...application.externalTailorDBNamespaces]);
12856
+ }
12857
+ function* tailorDBTypeResources(application) {
12858
+ for (const service of application.tailorDBServices) for (const typeName of Object.keys(service.types)) yield {
12859
+ visibilityKey: service.namespace,
12860
+ resourceKey: typeName
12861
+ };
12862
+ }
12863
+ function collectVisibleTailorDBTypeNamespaces(application, applications) {
12864
+ return collectVisibleResources({
12865
+ application,
12866
+ applications,
12867
+ visibleKeysOf: collectApplicationTailorDBNamespaces,
12868
+ resourcesOf: tailorDBTypeResources,
12869
+ createResult: () => /* @__PURE__ */ new Map(),
12870
+ addResource: addPossiblyAmbiguousNamespace
12871
+ });
12872
+ }
12873
+ function collectApplicationResolverNamespaces(application) {
12874
+ return new Set(application.subgraphs.filter((subgraph) => subgraph.Type === "pipeline").map((subgraph) => subgraph.Name));
12875
+ }
12876
+ function* idpNameResources(application) {
12877
+ for (const name of collectApplicationIdpNames(application)) yield {
12878
+ visibilityKey: name,
12879
+ resourceKey: name
12880
+ };
12881
+ }
12882
+ function collectVisibleIdpNames(application, applications) {
12883
+ return collectVisibleResources({
12884
+ application,
12885
+ applications,
12886
+ visibleKeysOf: collectApplicationIdpNames,
12887
+ resourcesOf: idpNameResources,
12888
+ createResult: () => /* @__PURE__ */ new Set(),
12889
+ addResource: (names, name) => {
12890
+ names.add(name);
12891
+ }
12892
+ });
12893
+ }
12894
+ function* resolverResources(application) {
12895
+ for (const service of application.resolverServices) for (const resolver of Object.values(service.resolvers)) yield {
12896
+ visibilityKey: service.namespace,
12897
+ resourceKey: resolver.name
12898
+ };
12899
+ }
12900
+ function collectVisibleResolverNamespaces(application, applications) {
12901
+ return collectVisibleResources({
12902
+ application,
12903
+ applications,
12064
12904
  visibleKeysOf: collectApplicationResolverNamespaces,
12065
12905
  resourcesOf: resolverResources,
12066
12906
  createResult: () => /* @__PURE__ */ new Map(),
@@ -12351,19 +13191,40 @@ function parseDeployConfigPaths(configPath) {
12351
13191
  if (configPaths.some((entry) => entry.length === 0)) throw new Error("--config must contain one or more non-empty config paths.");
12352
13192
  return configPaths;
12353
13193
  }
13194
+ function recoveryEnvironmentArgs(options, cliContext) {
13195
+ return [
13196
+ ...cliContext?.envFile ? ["--env-file", path.resolve(process.cwd(), cliContext.envFile)] : [],
13197
+ ...cliContext?.envFileIfExists ? ["--env-file-if-exists", path.resolve(process.cwd(), cliContext.envFileIfExists)] : [],
13198
+ ...options?.profile ? ["--profile", options.profile] : []
13199
+ ];
13200
+ }
13201
+ function recoveryOutputArgs(cliContext) {
13202
+ return [...cliContext?.verbose ? ["--verbose"] : [], ...cliContext?.json || logger.jsonMode ? ["--json"] : []];
13203
+ }
13204
+ function retryDeployArgs(options, configPaths, cliContext) {
13205
+ return [
13206
+ "deploy",
13207
+ "--config",
13208
+ configPaths.join(","),
13209
+ ...recoveryEnvironmentArgs(options, cliContext),
13210
+ ...options?.dryRun ? ["--dry-run"] : [],
13211
+ ...options?.yes ? ["--yes"] : [],
13212
+ ...options?.noSchemaCheck ? ["--no-schema-check"] : [],
13213
+ ...options?.noValidate ? ["--no-validate"] : [],
13214
+ ...options?.noCache ? ["--no-cache"] : [],
13215
+ ...options?.cleanCache ? ["--clean-cache"] : [],
13216
+ ...recoveryOutputArgs(cliContext)
13217
+ ];
13218
+ }
13219
+ function workspaceRecoveryArgs(options, cliContext) {
13220
+ return [...recoveryEnvironmentArgs(options, cliContext), ...cliContext?.verbose ? ["--verbose"] : []];
13221
+ }
12354
13222
  async function buildDeploymentTarget(params) {
12355
- const { configPath, dryRun, buildOnly, noCache, packageVersion, cacheDir } = params;
12356
- const { config, plugins } = await withSpan("build.loadConfig", async () => {
12357
- const foundPath = loadConfigPath(configPath);
12358
- if (foundPath) {
12359
- const resolvedPath = path.resolve(process.cwd(), foundPath);
12360
- if (fs$1.existsSync(resolvedPath)) await ensureConfigIdForDeploy({
12361
- configPath: resolvedPath,
12362
- dryRun,
12363
- buildOnly
12364
- });
12365
- }
12366
- return loadConfig(configPath);
13223
+ const { configPath, loadedConfig, dryRun, buildOnly, noCache, packageVersion, cacheDir } = params;
13224
+ const { config, plugins } = loadedConfig ?? await loadDeployConfig({
13225
+ configPath,
13226
+ dryRun,
13227
+ buildOnly
12367
13228
  });
12368
13229
  const configDir = path.dirname(config.path);
12369
13230
  const lockfilePath = findUpSync("pnpm-lock.yaml", { cwd: configDir }) ?? findUpSync("package-lock.json", { cwd: configDir }) ?? findUpSync("yarn.lock", { cwd: configDir }) ?? findUpSync("bun.lock", { cwd: configDir });
@@ -12404,11 +13265,27 @@ async function buildDeploymentTarget(params) {
12404
13265
  bundledScripts
12405
13266
  };
12406
13267
  }
13268
+ async function loadDeployConfig(params) {
13269
+ const { configPath, dryRun, buildOnly } = params;
13270
+ return withSpan("build.loadConfig", async () => {
13271
+ const foundPath = loadConfigPath(configPath);
13272
+ if (foundPath) {
13273
+ const resolvedPath = path.resolve(process.cwd(), foundPath);
13274
+ if (fs$1.existsSync(resolvedPath)) await ensureConfigIdForDeploy({
13275
+ configPath: resolvedPath,
13276
+ dryRun,
13277
+ buildOnly
13278
+ });
13279
+ }
13280
+ return loadConfig(configPath);
13281
+ });
13282
+ }
12407
13283
  async function buildDeploymentTargets(params) {
12408
- const { configPaths, buildTarget = buildDeploymentTarget, ...targetParams } = params;
12409
- return Promise.all(configPaths.map((configPath) => buildTarget({
13284
+ const { configPaths, loadedConfigs, buildTarget = buildDeploymentTarget, ...targetParams } = params;
13285
+ return Promise.all(configPaths.map((configPath, index) => buildTarget({
12410
13286
  ...targetParams,
12411
- configPath
13287
+ configPath,
13288
+ loadedConfig: loadedConfigs?.[index]
12412
13289
  })));
12413
13290
  }
12414
13291
  function setBundledScript(target, name, code, kind) {
@@ -12987,16 +13864,41 @@ async function validateDeploymentPlans(deployments) {
12987
13864
  }
12988
13865
  /**
12989
13866
  * Deploy the configured application to the Tailor platform.
12990
- * @param options - Options for deploy execution
13867
+ * @param options - Deploy execution options
13868
+ * @param cliContext - Global CLI arguments to preserve in recovery actions
12991
13869
  * @returns Promise that resolves to `{ bundledScripts }` when `buildOnly` is true, otherwise void
12992
13870
  */
12993
- async function deploy(options) {
13871
+ async function deployInternal(options, cliContext) {
12994
13872
  return withSpan("deploy", async (rootSpan) => {
12995
13873
  rootSpan.setAttribute("deploy.dry_run", options?.dryRun ?? false);
12996
13874
  const configPaths = parseDeployConfigPaths(options?.configPath);
12997
- const { targets, buildOnly } = await withSpan("build", async () => {
12998
- const dryRun = options?.dryRun ?? false;
12999
- const buildOnly = options?.buildOnly ?? parseBoolean(process.env.TAILOR_PLATFORM_SDK_BUILD_ONLY) === true;
13875
+ const dryRun = options?.dryRun ?? false;
13876
+ const buildOnly = options?.buildOnly ?? parseBoolean(process.env.TAILOR_PLATFORM_SDK_BUILD_ONLY) === true;
13877
+ const preflightConfigs = buildOnly ? [] : await withSpan("config.preflight", () => Promise.all(configPaths.map((configPath) => loadDeployConfig({
13878
+ configPath,
13879
+ dryRun,
13880
+ buildOnly
13881
+ }))));
13882
+ const resolvedConfigPaths = preflightConfigs.map(({ config }) => config.path);
13883
+ const workspaceContextTargets = preflightConfigs.map(({ config }) => ({
13884
+ configPath: config.path,
13885
+ applicationId: config.id ?? `name:${config.name}`
13886
+ }));
13887
+ const workspace = buildOnly ? void 0 : await resolveDeployWorkspace({
13888
+ workspaceId: options?.workspaceId,
13889
+ profile: options?.profile,
13890
+ createWorkspace: options?.createWorkspace,
13891
+ workspaceName: options?.workspaceName,
13892
+ workspaceRegion: options?.workspaceRegion,
13893
+ organizationId: options?.organizationId,
13894
+ folderId: options?.folderId,
13895
+ dryRun,
13896
+ contextTargets: workspaceContextTargets,
13897
+ deployArgs: retryDeployArgs(options, resolvedConfigPaths, cliContext),
13898
+ workspaceCommandArgs: workspaceRecoveryArgs(options, cliContext),
13899
+ workspaceCommandJson: cliContext?.json || logger.jsonMode
13900
+ });
13901
+ const targets = await withSpan("build", async () => {
13000
13902
  const noCache = options?.noCache ?? false;
13001
13903
  const packageJson = await readPackageJson();
13002
13904
  const cacheDir = path.resolve(getDistDir(), "cache");
@@ -13007,25 +13909,20 @@ async function deploy(options) {
13007
13909
  });
13008
13910
  logger.info("Bundle cache cleaned");
13009
13911
  }
13010
- return {
13011
- targets: await buildDeploymentTargets({
13012
- configPaths,
13013
- dryRun,
13014
- buildOnly,
13015
- noCache,
13016
- packageVersion: packageJson.version ?? "unknown",
13017
- cacheDir
13018
- }),
13019
- buildOnly
13020
- };
13912
+ return await buildDeploymentTargets({
13913
+ configPaths,
13914
+ loadedConfigs: preflightConfigs,
13915
+ dryRun,
13916
+ buildOnly,
13917
+ noCache,
13918
+ packageVersion: packageJson.version ?? "unknown",
13919
+ cacheDir
13920
+ });
13021
13921
  });
13022
13922
  if (buildOnly) return { bundledScripts: mergeBundledScripts(targets) };
13023
13923
  assertUniqueGlobalResourceNames(targets);
13024
- const client = await initOperatorClient(await loadAccessToken({ profile: options?.profile }));
13025
- const workspaceId = await loadWorkspaceId({
13026
- workspaceId: options?.workspaceId,
13027
- profile: options?.profile
13028
- });
13924
+ if (!workspace) throw new Error("Workspace was not resolved");
13925
+ const { client, workspaceId } = workspace;
13029
13926
  rootSpan.setAttribute("app.name", targets.map((target) => target.application.name).join(","));
13030
13927
  rootSpan.setAttribute("workspace.id", workspaceId);
13031
13928
  const deployments = await planDeploymentTargets({
@@ -13035,7 +13932,6 @@ async function deploy(options) {
13035
13932
  workspaceId,
13036
13933
  noSchemaCheck: options?.noSchemaCheck
13037
13934
  });
13038
- const dryRun = options?.dryRun ?? false;
13039
13935
  const yes = options?.yes ?? false;
13040
13936
  dropCrossDeploymentManagedDeletes(deployments);
13041
13937
  await withSpan("confirm", async () => {
@@ -13059,6 +13955,23 @@ async function deploy(options) {
13059
13955
  else logger.success("Successfully applied changes.");
13060
13956
  });
13061
13957
  }
13958
+ /**
13959
+ * Deploy using the programmatic CLI API.
13960
+ * @param options - Deploy execution options
13961
+ * @returns Deploy result
13962
+ */
13963
+ function deploy(options) {
13964
+ return deployInternal(options);
13965
+ }
13966
+ /**
13967
+ * Deploy from the command adapter while preserving global CLI arguments in recovery actions.
13968
+ * @param options - Deploy execution options
13969
+ * @param cliContext - Global CLI arguments already applied by the command runner
13970
+ * @returns Deploy result
13971
+ */
13972
+ function deployFromCLI(options, cliContext) {
13973
+ return deployInternal(options, cliContext);
13974
+ }
13062
13975
 
13063
13976
  //#endregion
13064
13977
  //#region src/cli/commands/executor/status.ts
@@ -13448,52 +14361,6 @@ const getCommand$6 = defineAppCommand({
13448
14361
  }
13449
14362
  });
13450
14363
 
13451
- //#endregion
13452
- //#region src/cli/shared/format.ts
13453
- /**
13454
- * Format a protobuf Timestamp to ISO string.
13455
- * @param timestamp - Protobuf timestamp
13456
- * @returns Date object or null if invalid
13457
- */
13458
- function formatTimestamp(timestamp) {
13459
- if (!timestamp) return null;
13460
- const date = timestampDate(timestamp);
13461
- if (Number.isNaN(date.getTime())) return null;
13462
- return date;
13463
- }
13464
- /**
13465
- * Formats a table with consistent single-line border style.
13466
- * Use this instead of importing `table` directly.
13467
- * @param data - Table data
13468
- * @param config - Table configuration
13469
- * @returns Formatted table string
13470
- */
13471
- function formatTable(data, config) {
13472
- return table(data, {
13473
- ...config,
13474
- border: getBorderCharacters("norc")
13475
- });
13476
- }
13477
- /**
13478
- * Formats a key-value table with single-line border style.
13479
- * @param data - Key-value pairs
13480
- * @returns Formatted key-value table string
13481
- */
13482
- function formatKeyValueTable(data) {
13483
- return formatTable(data, { singleLine: true });
13484
- }
13485
- /**
13486
- * Format a Date or ISO timestamp string as a human-readable relative time.
13487
- * @param value - Date object, ISO date string, or null
13488
- * @returns Relative time (e.g., "5 minutes ago") or "N/A" for null/invalid
13489
- */
13490
- function humanizeRelativeTime(value) {
13491
- if (value === null) return "N/A";
13492
- const date = value instanceof Date ? value : new Date(value);
13493
- if (Number.isNaN(date.getTime())) return typeof value === "string" ? value : "N/A";
13494
- return formatDistanceToNowStrict(date, { addSuffix: true });
13495
- }
13496
-
13497
14364
  //#endregion
13498
14365
  //#region src/cli/shared/function-execution.ts
13499
14366
  /**
@@ -14892,7 +15759,7 @@ async function listExecutors(options) {
14892
15759
  return [executors, nextPageToken];
14893
15760
  }, { limit: options?.limit })).map((e) => toExecutorListInfo(e));
14894
15761
  }
14895
- const listCommand$9 = defineAppCommand({
15762
+ const listCommand$8 = defineAppCommand({
14896
15763
  name: "list",
14897
15764
  description: "List all executors",
14898
15765
  args: z.object({
@@ -15317,7 +16184,7 @@ async function listFunctionRegistries(options) {
15317
16184
  }
15318
16185
  }, { limit })).map(functionRegistryInfo);
15319
16186
  }
15320
- const listCommand$8 = defineAppCommand({
16187
+ const listCommand$7 = defineAppCommand({
15321
16188
  name: "list",
15322
16189
  description: "List function registries in a workspace",
15323
16190
  args: z.object({
@@ -16262,7 +17129,7 @@ async function listMachineUsers(options) {
16262
17129
  return [machineUsers, nextPageToken];
16263
17130
  }, { limit: options?.limit })).map(machineUserInfo);
16264
17131
  }
16265
- const listCommand$7 = defineAppCommand({
17132
+ const listCommand$6 = defineAppCommand({
16266
17133
  name: "list",
16267
17134
  description: "List all machine users in the application.",
16268
17135
  args: z.object({
@@ -16478,7 +17345,7 @@ async function listOAuth2Clients(options) {
16478
17345
  return [oauth2Clients, nextPageToken];
16479
17346
  }, { limit: options?.limit })).map(toOAuth2ClientInfo);
16480
17347
  }
16481
- const listCommand$6 = defineAppCommand({
17348
+ const listCommand$5 = defineAppCommand({
16482
17349
  name: "list",
16483
17350
  description: "List all OAuth2 clients in the application.",
16484
17351
  args: z.object({
@@ -16548,7 +17415,7 @@ async function createFolder(options) {
16548
17415
  if (!response.folder) throw new Error("Failed to create folder.");
16549
17416
  return folderInfo(response.folder);
16550
17417
  }
16551
- const createCommand$1 = defineAppCommand({
17418
+ const createCommand = defineAppCommand({
16552
17419
  name: "create",
16553
17420
  description: "Create a new folder in an organization.",
16554
17421
  args: z.object({
@@ -16696,7 +17563,7 @@ async function listFolders(options) {
16696
17563
  return [response.folders, response.nextPageToken];
16697
17564
  }, { limit })).map(folderListInfo);
16698
17565
  }
16699
- const listCommand$5 = defineAppCommand({
17566
+ const listCommand$4 = defineAppCommand({
16700
17567
  name: "list",
16701
17568
  description: "List folders in an organization.",
16702
17569
  args: z.object({
@@ -16805,7 +17672,7 @@ async function listOrganizations(options) {
16805
17672
  if (limit !== void 0) return results.slice(0, limit);
16806
17673
  return results;
16807
17674
  }
16808
- const listCommand$4 = defineAppCommand({
17675
+ const listCommand$3 = defineAppCommand({
16809
17676
  name: "list",
16810
17677
  description: "List organizations you belong to.",
16811
17678
  args: z.object({ limit: arg(positiveIntArg.optional(), {
@@ -17095,141 +17962,63 @@ const removeCommand$1 = defineAppCommand({
17095
17962
  profile: args.profile,
17096
17963
  configPath: args.config
17097
17964
  });
17098
- logger.info(`Planning removal of resources managed by "${application.name}"...`);
17099
- logger.newline();
17100
- await execRemove(client, workspaceId, application, config, async () => {
17101
- if (!args.yes) {
17102
- if (!await prompt.confirm({
17103
- message: "Are you sure you want to remove all resources?",
17104
- default: false
17105
- })) throw new Error(multiline`
17106
- Remove cancelled. No resources were deleted.
17107
- To override, run again and confirm, or use --yes flag.
17108
- `);
17109
- } else logger.success("Removing all resources (--yes flag specified)...");
17110
- });
17111
- logger.success(`Successfully removed all resources managed by "${application.name}".`);
17112
- }
17113
- });
17114
-
17115
- //#endregion
17116
- //#region src/cli/shared/beta.ts
17117
- /**
17118
- * Warn that a feature is in beta.
17119
- * @param {string} featureName - Name of the beta feature (e.g., "tailordb erd", "tailordb migration")
17120
- */
17121
- function logBetaWarning(featureName) {
17122
- logger.warn(`The '${featureName}' command is a beta feature and may introduce breaking changes in future releases.`);
17123
- logger.newline();
17124
- }
17125
-
17126
- //#endregion
17127
- //#region src/cli/shared/config.ts
17128
- /**
17129
- * Extracts every namespace key declared under `config.db`, including those
17130
- * declared with `{ external: true }`.
17131
- * @param config - Loaded application configuration.
17132
- * @returns Namespace names in insertion order.
17133
- */
17134
- function extractAllNamespaces(config) {
17135
- const namespaces = /* @__PURE__ */ new Set();
17136
- if (config.db) for (const namespaceName of Object.keys(config.db)) namespaces.add(namespaceName);
17137
- return Array.from(namespaces);
17138
- }
17139
- /**
17140
- * Extracts namespace keys under `config.db` that this app owns
17141
- * (i.e. not declared with `{ external: true }`). Use this for destructive
17142
- * operations like `tailordb truncate --all` to avoid touching namespaces
17143
- * owned by other apps.
17144
- * @param config - Loaded application configuration.
17145
- * @returns Owned namespace names in insertion order.
17146
- */
17147
- function extractOwnedNamespaces(config) {
17148
- const namespaces = /* @__PURE__ */ new Set();
17149
- if (config.db) for (const [namespaceName, nsConfig] of Object.entries(config.db)) {
17150
- if ("external" in nsConfig) continue;
17151
- namespaces.add(namespaceName);
17152
- }
17153
- return Array.from(namespaces);
17154
- }
17155
-
17156
- //#endregion
17157
- //#region src/cli/commands/workspace/transform.ts
17158
- const workspaceInfo = (workspace, folderName) => {
17159
- const info = {
17160
- id: workspace.id,
17161
- name: workspace.name,
17162
- region: workspace.region,
17163
- createdAt: formatTimestamp(workspace.createTime),
17164
- updatedAt: formatTimestamp(workspace.updateTime)
17165
- };
17166
- return folderName ? {
17167
- ...info,
17168
- folderName
17169
- } : info;
17170
- };
17171
- const workspaceDetails = (workspace, folderName) => {
17172
- return {
17173
- ...workspaceInfo(workspace, folderName),
17174
- deleteProtection: workspace.deleteProtection,
17175
- organizationId: workspace.organizationId,
17176
- folderId: workspace.folderId
17177
- };
17178
- };
17179
- async function resolveWorkspaceFolderName(client, workspace) {
17180
- if (!workspace.organizationId || !workspace.folderId) return void 0;
17181
- try {
17182
- return (await client.getOrganizationFolder({
17183
- organizationId: workspace.organizationId,
17184
- folderId: workspace.folderId
17185
- })).folder?.name || void 0;
17186
- } catch (error) {
17187
- if (error instanceof ConnectError && (error.code === Code.NotFound || error.code === Code.PermissionDenied)) return;
17188
- logger.warn(`Failed to resolve workspace folder name: ${error}`);
17189
- return;
17190
- }
17191
- }
17192
- function createWorkspaceFolderNameResolver(client) {
17193
- const cache = /* @__PURE__ */ new Map();
17194
- return (workspace) => {
17195
- if (!workspace.organizationId || !workspace.folderId) return Promise.resolve(void 0);
17196
- const cacheKey = `${workspace.organizationId}/${workspace.folderId}`;
17197
- const cached = cache.get(cacheKey);
17198
- if (cached) return cached;
17199
- const promise = resolveWorkspaceFolderName(client, workspace);
17200
- cache.set(cacheKey, promise);
17201
- return promise;
17202
- };
17203
- }
17204
- async function workspaceInfoWithFolderName(client, workspace) {
17205
- const folderName = await resolveWorkspaceFolderName(client, workspace);
17206
- return workspaceInfo(workspace, folderName);
17207
- }
17208
- async function workspaceDetailsWithFolderName(client, workspace) {
17209
- const folderName = await resolveWorkspaceFolderName(client, workspace);
17210
- return workspaceDetails(workspace, folderName);
17211
- }
17212
- async function workspaceInfosWithFolderNames(client, workspaces) {
17213
- const resolveFolderName = createWorkspaceFolderNameResolver(client);
17214
- const limit = pLimit(5);
17215
- return Promise.all(workspaces.map((workspace) => limit(async () => workspaceInfo(workspace, await resolveFolderName(workspace)))));
17965
+ logger.info(`Planning removal of resources managed by "${application.name}"...`);
17966
+ logger.newline();
17967
+ await execRemove(client, workspaceId, application, config, async () => {
17968
+ if (!args.yes) {
17969
+ if (!await prompt.confirm({
17970
+ message: "Are you sure you want to remove all resources?",
17971
+ default: false
17972
+ })) throw new Error(multiline`
17973
+ Remove cancelled. No resources were deleted.
17974
+ To override, run again and confirm, or use --yes flag.
17975
+ `);
17976
+ } else logger.success("Removing all resources (--yes flag specified)...");
17977
+ });
17978
+ logger.success(`Successfully removed all resources managed by "${application.name}".`);
17979
+ }
17980
+ });
17981
+
17982
+ //#endregion
17983
+ //#region src/cli/shared/beta.ts
17984
+ /**
17985
+ * Warn that a feature is in beta.
17986
+ * @param {string} featureName - Name of the beta feature (e.g., "tailordb erd", "tailordb migration")
17987
+ */
17988
+ function logBetaWarning(featureName) {
17989
+ logger.warn(`The '${featureName}' command is a beta feature and may introduce breaking changes in future releases.`);
17990
+ logger.newline();
17216
17991
  }
17217
- function workspaceDisplayName(workspace) {
17218
- return workspace.folderName ? `${workspace.folderName}/${workspace.name}` : workspace.name;
17992
+
17993
+ //#endregion
17994
+ //#region src/cli/shared/config.ts
17995
+ /**
17996
+ * Extracts every namespace key declared under `config.db`, including those
17997
+ * declared with `{ external: true }`.
17998
+ * @param config - Loaded application configuration.
17999
+ * @returns Namespace names in insertion order.
18000
+ */
18001
+ function extractAllNamespaces(config) {
18002
+ const namespaces = /* @__PURE__ */ new Set();
18003
+ if (config.db) for (const namespaceName of Object.keys(config.db)) namespaces.add(namespaceName);
18004
+ return Array.from(namespaces);
17219
18005
  }
17220
- function createWorkspaceNameTransformer(nameKey, folderNameKey) {
17221
- return (value, item) => {
17222
- const workspace = item;
17223
- const name = workspace[nameKey];
17224
- const folderName = workspace[folderNameKey];
17225
- if (typeof name === "string" && typeof folderName === "string") return workspaceDisplayName({
17226
- name,
17227
- folderName
17228
- });
17229
- return String(value ?? "");
17230
- };
18006
+ /**
18007
+ * Extracts namespace keys under `config.db` that this app owns
18008
+ * (i.e. not declared with `{ external: true }`). Use this for destructive
18009
+ * operations like `tailordb truncate --all` to avoid touching namespaces
18010
+ * owned by other apps.
18011
+ * @param config - Loaded application configuration.
18012
+ * @returns Owned namespace names in insertion order.
18013
+ */
18014
+ function extractOwnedNamespaces(config) {
18015
+ const namespaces = /* @__PURE__ */ new Set();
18016
+ if (config.db) for (const [namespaceName, nsConfig] of Object.entries(config.db)) {
18017
+ if ("external" in nsConfig) continue;
18018
+ namespaces.add(namespaceName);
18019
+ }
18020
+ return Array.from(namespaces);
17231
18021
  }
17232
- const workspaceNameTransformer = createWorkspaceNameTransformer("name", "folderName");
17233
18022
 
17234
18023
  //#endregion
17235
18024
  //#region src/cli/commands/show.ts
@@ -17246,10 +18035,27 @@ function applicationInfo(app) {
17246
18035
  updatedAt: app.updateTime ? timestampDate(app.updateTime) : null
17247
18036
  };
17248
18037
  }
18038
+ async function fetchAIGateways(client, workspaceId, names) {
18039
+ return (await Promise.all(names.map(async (name) => {
18040
+ try {
18041
+ const { aigateway } = await client.getAIGateway({
18042
+ workspaceId,
18043
+ aigatewayName: name
18044
+ });
18045
+ return aigateway ? {
18046
+ name: aigateway.name,
18047
+ url: aigateway.url
18048
+ } : void 0;
18049
+ } catch (error) {
18050
+ if (error instanceof ConnectError && error.code === Code.NotFound) return;
18051
+ throw error;
18052
+ }
18053
+ }))).filter((gateway) => gateway !== void 0);
18054
+ }
17249
18055
  /**
17250
18056
  * Show applied application information for the current workspace.
17251
18057
  * @param options - Show options
17252
- * @returns Application information
18058
+ * @returns Deployed application, workspace, and AI Gateway information
17253
18059
  */
17254
18060
  async function show(options) {
17255
18061
  const client = await initOperatorClient(await loadAccessToken({ profile: options?.profile }));
@@ -17258,10 +18064,15 @@ async function show(options) {
17258
18064
  profile: options?.profile
17259
18065
  });
17260
18066
  const { config } = await loadConfig(options?.configPath);
17261
- const [workspaceResp, resp] = await Promise.all([client.getWorkspace({ workspaceId }), client.getApplication({
17262
- workspaceId,
17263
- applicationName: config.name
17264
- })]);
18067
+ const aiGatewayNames = config.aiGateways?.length ? [...new Set(config.aiGateways.map((gateway) => gateway.name))] : [];
18068
+ const [workspaceResp, resp, aiGateways] = await Promise.all([
18069
+ client.getWorkspace({ workspaceId }),
18070
+ client.getApplication({
18071
+ workspaceId,
18072
+ applicationName: config.name
18073
+ }),
18074
+ fetchAIGateways(client, workspaceId, aiGatewayNames)
18075
+ ]);
17265
18076
  const { name, ...appInfo } = applicationInfo(assertDefined(resp.application, `application "${config.name}" not found in workspace`));
17266
18077
  const workspace = workspaceResp.workspace;
17267
18078
  const workspaceFolderName = workspace ? await resolveWorkspaceFolderName(client, workspace) : "";
@@ -17271,7 +18082,8 @@ async function show(options) {
17271
18082
  workspaceName: workspace?.name ?? "",
17272
18083
  ...workspaceFolderName ? { workspaceFolderName } : {},
17273
18084
  workspaceRegion: workspace?.region ?? "",
17274
- ...appInfo
18085
+ ...appInfo,
18086
+ aiGateways
17275
18087
  };
17276
18088
  }
17277
18089
  const showWorkspaceNameTransformer = createWorkspaceNameTransformer("workspaceName", "workspaceFolderName");
@@ -17878,7 +18690,7 @@ async function generate(options) {
17878
18690
  if (options.init) await handleInitOption(namespacesWithMigrations, options.yes);
17879
18691
  let pluginManager;
17880
18692
  if (plugins.length > 0) pluginManager = new PluginManager(plugins);
17881
- const { defineApplication } = await import("./application-6zsDLGKv.mjs");
18693
+ const { defineApplication } = await import("./application-BB6BlUfk.mjs");
17882
18694
  const application = defineApplication({
17883
18695
  config,
17884
18696
  pluginManager
@@ -18238,7 +19050,7 @@ async function listWorkflows(options) {
18238
19050
  return [workflows, nextPageToken];
18239
19051
  }, { limit: options?.limit })).map(toWorkflowListInfo);
18240
19052
  }
18241
- const listCommand$3 = defineAppCommand({
19053
+ const listCommand$2 = defineAppCommand({
18242
19054
  name: "list",
18243
19055
  description: "List all workflows in the workspace.",
18244
19056
  args: z.object({
@@ -18571,7 +19383,7 @@ async function listApps(options) {
18571
19383
  return [applications, nextPageToken];
18572
19384
  }, { limit })).map(appInfo);
18573
19385
  }
18574
- const listCommand$2 = defineAppCommand({
19386
+ const listCommand$1 = defineAppCommand({
18575
19387
  name: "list",
18576
19388
  description: "List applications in a workspace",
18577
19389
  args: z.object({
@@ -18594,152 +19406,6 @@ const listCommand$2 = defineAppCommand({
18594
19406
  }
18595
19407
  });
18596
19408
 
18597
- //#endregion
18598
- //#region src/cli/commands/workspace/create.ts
18599
- /**
18600
- * Schema for workspace creation options
18601
- * - name: 3-63 chars, lowercase alphanumeric and hyphens, cannot start/end with hyphen
18602
- * - organizationId, folderId: optional UUIDs
18603
- */
18604
- const createWorkspaceOptionsSchema = z.object({
18605
- name: z.string().min(3, "Name must be at least 3 characters").max(63, "Name must be at most 63 characters").regex(/^[a-z0-9-]+$/, "Name can only contain lowercase letters, numbers, and hyphens").refine((n) => !n.startsWith("-") && !n.endsWith("-"), "Name cannot start or end with a hyphen"),
18606
- region: z.string(),
18607
- deleteProtection: z.boolean().optional(),
18608
- organizationId: z.uuid().optional(),
18609
- folderId: z.uuid().optional()
18610
- });
18611
- const validateRegion = async (region, client) => {
18612
- const availableRegions = await client.listAvailableWorkspaceRegions({});
18613
- if (!availableRegions.regions.includes(region)) throw new Error(`Region must be one of: ${availableRegions.regions.join(", ")}.`);
18614
- };
18615
- function profilePlatformSettings(platformConfig) {
18616
- const hasOAuth2ClientId = platformConfig?.oauth2ClientId || process.env.TAILOR_PLATFORM_OAUTH2_CLIENT_ID;
18617
- const hasConsoleUrl = platformConfig?.consoleUrl || process.env.TAILOR_PLATFORM_CONSOLE_URL;
18618
- return {
18619
- ...isDefaultPlatform(platformConfig) ? {} : { platform_url: getPlatformBaseUrl(platformConfig) },
18620
- ...hasOAuth2ClientId ? { oauth2_client_id: getOAuth2ClientId(platformConfig) } : {},
18621
- ...hasConsoleUrl ? { console_url: getConsoleBaseUrl(platformConfig) } : {}
18622
- };
18623
- }
18624
- /**
18625
- * Create a new workspace with the given options.
18626
- * @param options - Workspace creation options
18627
- * @returns Created workspace info
18628
- */
18629
- async function createWorkspace(options) {
18630
- const result = createWorkspaceOptionsSchema.safeParse(options);
18631
- if (!result.success) throw new Error(assertDefined(result.error.issues[0], "Zod returned no issues").message);
18632
- const validated = result.data;
18633
- const client = await initOperatorClient(await loadAccessToken());
18634
- await validateRegion(validated.region, client);
18635
- return workspaceInfoWithFolderName(client, assertDefined((await client.createWorkspace({
18636
- workspaceName: validated.name,
18637
- workspaceRegion: validated.region,
18638
- deleteProtection: validated.deleteProtection ?? false,
18639
- organizationId: validated.organizationId,
18640
- folderId: validated.folderId
18641
- })).workspace, "createWorkspace response missing workspace"));
18642
- }
18643
- const createCommand = defineAppCommand({
18644
- name: "create",
18645
- description: "Create a new Tailor Platform workspace.",
18646
- args: z.object({
18647
- name: arg(z.string(), {
18648
- alias: "n",
18649
- description: "Workspace name"
18650
- }),
18651
- region: arg(z.string(), {
18652
- alias: "r",
18653
- description: "Workspace region (us-west, asia-northeast)"
18654
- }),
18655
- "delete-protection": arg(z.boolean().default(false), {
18656
- alias: "d",
18657
- description: "Enable delete protection"
18658
- }),
18659
- "organization-id": arg(z.string().optional(), {
18660
- alias: "o",
18661
- description: "Organization ID to workspace associate with",
18662
- env: "TAILOR_PLATFORM_ORGANIZATION_ID"
18663
- }),
18664
- "folder-id": arg(z.string().optional(), {
18665
- alias: "f",
18666
- description: "Folder ID to workspace associate with",
18667
- env: "TAILOR_PLATFORM_FOLDER_ID"
18668
- }),
18669
- "profile-name": arg(z.string().optional(), {
18670
- alias: "p",
18671
- description: "Profile name to create"
18672
- }),
18673
- "profile-user": arg(z.string().optional(), { description: "User email for the profile (defaults to current user)" }),
18674
- permission: arg(z.enum(["write", "read"]).default("write"), { description: "Profile permission (requires --profile-name). 'read' blocks all write commands while the profile is active." })
18675
- }).strict(),
18676
- run: async (args) => {
18677
- await assertWritable();
18678
- const profileName = args["profile-name"];
18679
- let profileSetup;
18680
- if (profileName) {
18681
- const config = await readPlatformConfig();
18682
- if (config.profiles[profileName]) throw new Error(`Profile "${profileName}" already exists.`);
18683
- const activeProfileName = process.env.TAILOR_PLATFORM_PROFILE;
18684
- const activeProfileEntry = activeProfileName ? config.profiles[activeProfileName] : void 0;
18685
- const platformConfig = activeProfileEntry ? platformConfigFromProfile(activeProfileEntry) : void 0;
18686
- const profileUser = args["profile-user"] || activeProfileEntry?.user || config.current_user;
18687
- if (!profileUser) throw new Error("Current user not found. Please login or specify --profile-user to create a profile.");
18688
- if (!hasUserTokenEntry(config, profileUser, platformConfig)) throw new Error(`User "${profileUser}" not found.\nPlease verify your user name and login using 'tailor-sdk login' command.`);
18689
- profileSetup = {
18690
- name: profileName,
18691
- user: profileUser,
18692
- platformSettings: profilePlatformSettings(platformConfig)
18693
- };
18694
- }
18695
- const workspace = await createWorkspace({
18696
- name: args.name,
18697
- region: args.region,
18698
- deleteProtection: args["delete-protection"],
18699
- organizationId: args["organization-id"],
18700
- folderId: args["folder-id"]
18701
- });
18702
- let profileInfo;
18703
- if (profileSetup) {
18704
- const config = await readPlatformConfig();
18705
- const platformSettings = profileSetup.platformSettings;
18706
- config.profiles[profileSetup.name] = {
18707
- user: profileSetup.user,
18708
- workspace_id: workspace.id,
18709
- ...args.permission === "read" ? { readonly: true } : {},
18710
- ...platformSettings
18711
- };
18712
- writePlatformConfig(config);
18713
- profileInfo = {
18714
- name: profileSetup.name,
18715
- user: profileSetup.user,
18716
- workspaceId: workspace.id,
18717
- permission: args.permission,
18718
- ...platformSettings.platform_url ? { platformUrl: platformSettings.platform_url } : {},
18719
- ...platformSettings.oauth2_client_id ? { oauth2ClientId: platformSettings.oauth2_client_id } : {},
18720
- ...platformSettings.console_url ? { consoleUrl: platformSettings.console_url } : {}
18721
- };
18722
- if (!args.json) logger.success(`Profile "${profileSetup.name}" created successfully.`);
18723
- }
18724
- if (!args.json) logger.success(`Workspace "${workspaceDisplayName(workspace)}" created successfully.`);
18725
- if (args.json && profileInfo) {
18726
- logger.out({
18727
- ...workspace,
18728
- profile: profileInfo
18729
- });
18730
- return;
18731
- }
18732
- logger.out(workspace, { display: {
18733
- name: workspaceNameTransformer,
18734
- folderName: null
18735
- } });
18736
- if (profileInfo) {
18737
- logger.out("Profile:");
18738
- logger.out(profileInfo);
18739
- }
18740
- }
18741
- });
18742
-
18743
19409
  //#endregion
18744
19410
  //#region src/cli/commands/workspace/delete.ts
18745
19411
  const deleteWorkspaceOptionsSchema = z.object({ workspaceId: z.uuid({ message: "workspace-id must be a valid UUID" }) });
@@ -18853,42 +19519,6 @@ const getCommand = defineAppCommand({
18853
19519
  }
18854
19520
  });
18855
19521
 
18856
- //#endregion
18857
- //#region src/cli/commands/workspace/list.ts
18858
- /**
18859
- * List workspaces with an optional order and limit.
18860
- * @param options - Workspace listing options
18861
- * @returns List of workspaces
18862
- */
18863
- async function listWorkspaces(options) {
18864
- const client = await initOperatorClient(await loadAccessToken());
18865
- const pageDirection = toPageDirection(options?.order);
18866
- return workspaceInfosWithFolderNames(client, await fetchPaged(async (pageToken, pageSize) => {
18867
- const { workspaces, nextPageToken } = await client.listWorkspaces({
18868
- pageToken,
18869
- pageSize,
18870
- pageDirection
18871
- });
18872
- return [workspaces, nextPageToken];
18873
- }, { limit: options?.limit }));
18874
- }
18875
- const listCommand$1 = defineAppCommand({
18876
- name: "list",
18877
- description: "List all Tailor Platform workspaces.",
18878
- args: z.object({ ...paginationArgs() }).strict(),
18879
- run: async (args) => {
18880
- const workspaces = await listWorkspaces({
18881
- order: args.order,
18882
- limit: args.limit
18883
- });
18884
- logger.out(workspaces, { display: {
18885
- name: workspaceNameTransformer,
18886
- folderName: null,
18887
- updatedAt: null
18888
- } });
18889
- }
18890
- });
18891
-
18892
19522
  //#endregion
18893
19523
  //#region src/cli/commands/workspace/restore.ts
18894
19524
  const restoreWorkspaceOptionsSchema = z.object({ workspaceId: z.uuid({ message: "workspace-id must be a valid UUID" }) });
@@ -20145,5 +20775,5 @@ function isDeno() {
20145
20775
  }
20146
20776
 
20147
20777
  //#endregion
20148
- export { getOrganization as $, multiConfigArg as $n, compareSnapshotWithRemote as $t, listCommand$3 as A, apiCall as An, getExecutorWaitFailureMessage as At, show as B, loadStoredUserTokens as Bn, listWorkflowExecutions as Bt, listCommand$2 as C, hasChanges as Cn, listWebhookExecutors as Ct, waitWorkflowExecution as D, PluginManager as Dn, listCommand$9 as Dt, waitCommand as E, sdkNameLabelKey as En, triggerExecutor as Et, generateCommand as F, hasAnyUserTokenEntry as Fn, startWorkflow as Ft, removeCommand$1 as G, saveUserTokens as Gn, deploy as Gt, extractOwnedNamespaces as H, platformConfigFromProfile as Hn, formatKeyValueTable as Ht, generateMigrationScript as I, hasUserTokenEntry as In, getCommand$5 as It, organizationTree as J, commonArgs as Jn, waitForExecution as Jt, updateCommand$1 as K, writePlatformConfig as Kn, ensureConfigId as Kt, writeDbTypesFile as L, loadAccessToken as Ln, getWorkflow as Lt, truncate as M, loadConfig as Mn, listExecutorJobs as Mt, truncateCommand as N, deleteUserTokens as Nn, watchExecutorJob as Nt, resumeCommand as O, generateUserTypes as On, listExecutors as Ot, generate as P, fetchLatestToken as Pn, startCommand as Pt, getCommand$1 as Q, isVerbose as Qn, parseMigrationLabelNumber as Qt, getConfiguredEditorCommand as R, loadConsoleBaseUrl as Rn, executionsCommand as Rt, listApps as S, formatMigrationDiff as Sn, getFunctionRegistry as St, healthCommand as T, resourceTrn as Tn, triggerCommand as Tt, logBetaWarning as U, readPlatformConfig as Un, getCommand$6 as Ut, showCommand as V, loadWorkspaceId as Vn, functionExecutionStatusToString as Vt, remove as W, resolveUserTokenKey as Wn, getExecutor as Wt, listCommand$4 as X, confirmationArgs as Xn, MIGRATION_LABEL_KEY as Xt, treeCommand as Y, configArg as Yn, bundleMigrationScript as Yt, listOrganizations as Z, deploymentArgs as Zn, handleOptionalToRequiredError as Zt, getWorkspace as _, loadDiff as _n, listMachineUsers as _t, updateUser as a, MIGRATE_FILE_NAME as an, getFolder as at, createCommand as b, parseMigrationNumberArg as bn, listFunctionRegistries as bt, listCommand as c, compareLocalTypesWithSnapshot as cn, createCommand$1 as ct, inviteUser as d, getLatestMigrationNumber as dn, listOAuth2Clients as dt, generateAllTypeManifestsFromSnapshot as en, pagedLogArgs as er, updateCommand$2 as et, restoreCommand as f, getMigrationDirPath as fn, getCommand$3 as ft, getCommand as g, isValidMigrationNumber as gn, listCommand$7 as gt, listWorkspaces as h, getNextMigrationNumber as hn, tokenCommand as ht, updateCommand as i, INITIAL_SCHEMA_NUMBER as in, workspaceArgs as ir, getCommand$2 as it, listWorkflows as j, assertWritable as jn, jobsCommand as jt, resumeWorkflow as k, prompt as kn, getExecutorJob as kt, listUsers as l, compareSnapshots as ln, createFolder as lt, listCommand$1 as m, getMigrationFiles as mn, getMachineUserToken as mt, query as n, DB_TYPES_FILE_NAME as nn, resolveMachineUserInputSource as nr, listCommand$5 as nt, removeCommand as o, SCHEMA_FILE_NAME as on, deleteCommand$1 as ot, restoreWorkspace as p, getMigrationFilePath as pn, getOAuth2Client as pt, updateOrganization as q, defineAppCommand as qn, executeScript as qt, queryCommand as r, DIFF_FILE_NAME as rn, toPageDirection as rr, listFolders as rt, removeUser as s, assertValidMigrationFiles as sn, deleteFolder as st, isNativeTypeScriptRuntime as t, protoGqlPermission as tn, paginationArgs as tr, updateFolder as tt, inviteCommand as u, createSnapshotFromLocalTypes as un, listCommand$6 as ut, deleteCommand as v, reconstructSnapshotFromMigrations as vn, generate$1 as vt, getAppHealth as w, getNamespacesWithMigrations as wn, webhookCommand as wt, createWorkspace as x, formatDiffSummary as xn, getCommand$4 as xt, deleteWorkspace as y, formatMigrationNumber as yn, listCommand$8 as yt, openInConfiguredEditor as z, loadMachineUserName as zn, getWorkflowExecution as zt };
20149
- //# sourceMappingURL=runtime-DlklyuHN.mjs.map
20778
+ export { listFolders as $, deploymentArgs as $n, handleOptionalToRequiredError as $t, generate as A, generateUserTypes as An, startCommand as At, remove as B, loadConsoleBaseUrl as Bn, deploy as Bt, waitWorkflowExecution as C, formatDiffSummary as Cn, listCommand$8 as Ct, listWorkflows as D, resourceTrn as Dn, jobsCommand as Dt, listCommand$2 as E, getNamespacesWithMigrations as En, getExecutorWaitFailureMessage as Et, openInConfiguredEditor as F, deleteUserTokens as Fn, getWorkflowExecution as Ft, treeCommand as G, readPlatformConfig as Gn, createWorkspace$1 as Gt, updateCommand$1 as H, loadStoredUserTokens as Hn, listCommand$9 as Ht, show as I, fetchLatestToken as In, listWorkflowExecutions as It, getCommand$1 as J, writePlatformConfig as Jn, ensureConfigId as Jt, listCommand$3 as K, resolveUserTokenKey as Kn, formatKeyValueTable as Kt, showCommand as L, hasAnyUserTokenEntry as Ln, functionExecutionStatusToString as Lt, generateMigrationScript as M, apiCall as Mn, getCommand$5 as Mt, writeDbTypesFile as N, assertWritable as Nn, getWorkflow as Nt, truncate as O, sdkNameLabelKey as On, listExecutorJobs as Ot, getConfiguredEditorCommand as P, loadConfig as Pn, executionsCommand as Pt, listCommand$4 as Q, confirmationArgs as Qn, MIGRATION_LABEL_KEY as Qt, extractOwnedNamespaces as R, hasUserTokenEntry as Rn, getCommand$6 as Rt, waitCommand as S, parseMigrationNumberArg as Sn, triggerExecutor as St, resumeWorkflow as T, hasChanges as Tn, getExecutorJob as Tt, updateOrganization as U, loadWorkspaceId as Un, listWorkspaces as Ut, removeCommand$1 as V, loadMachineUserName as Vn, deployFromCLI as Vt, organizationTree as W, platformConfigFromProfile as Wn, createCommand$1 as Wt, updateCommand$2 as X, commonArgs as Xn, waitForExecution as Xt, getOrganization as Y, defineAppCommand as Yn, executeScript as Yt, updateFolder as Z, configArg as Zn, bundleMigrationScript as Zt, deleteWorkspace as _, getNextMigrationNumber as _n, getCommand$4 as _t, updateUser as a, DIFF_FILE_NAME as an, toPageDirection as ar, createFolder as at, getAppHealth as b, reconstructSnapshotFromMigrations as bn, webhookCommand as bt, listCommand as c, SCHEMA_FILE_NAME as cn, getCommand$3 as ct, inviteUser as d, compareSnapshots as dn, tokenCommand as dt, parseMigrationLabelNumber as en, isVerbose as er, getCommand$2 as et, restoreCommand as f, createSnapshotFromLocalTypes as fn, listCommand$6 as ft, deleteCommand as g, getMigrationFiles as gn, listFunctionRegistries as gt, getWorkspace as h, getMigrationFilePath as hn, listCommand$7 as ht, updateCommand as i, DB_TYPES_FILE_NAME as in, resolveMachineUserInputSource as ir, createCommand as it, generateCommand as j, prompt as jn, startWorkflow as jt, truncateCommand as k, PluginManager as kn, watchExecutorJob as kt, listUsers as l, assertValidMigrationFiles as ln, getOAuth2Client as lt, getCommand as m, getMigrationDirPath as mn, generate$1 as mt, query as n, generateAllTypeManifestsFromSnapshot as nn, pagedLogArgs as nr, deleteCommand$1 as nt, removeCommand as o, INITIAL_SCHEMA_NUMBER as on, workspaceArgs as or, listCommand$5 as ot, restoreWorkspace as p, getLatestMigrationNumber as pn, listMachineUsers as pt, listOrganizations as q, saveUserTokens as qn, workspaceNameSchema as qt, queryCommand as r, protoGqlPermission as rn, paginationArgs as rr, deleteFolder as rt, removeUser as s, MIGRATE_FILE_NAME as sn, listOAuth2Clients as st, isNativeTypeScriptRuntime as t, compareSnapshotWithRemote as tn, multiConfigArg as tr, getFolder as tt, inviteCommand as u, compareLocalTypesWithSnapshot as un, getMachineUserToken as ut, listApps as v, isValidMigrationNumber as vn, getFunctionRegistry as vt, resumeCommand as w, formatMigrationDiff as wn, listExecutors as wt, healthCommand as x, formatMigrationNumber as xn, triggerCommand as xt, listCommand$1 as y, loadDiff as yn, listWebhookExecutors as yt, logBetaWarning as z, loadAccessToken as zn, getExecutor as zt };
20779
+ //# sourceMappingURL=runtime-CjMeYuPA.mjs.map