@tailor-platform/sdk 1.60.3 → 1.62.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 (59) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/{application-pusdxz35.mjs → application-BezXGbrU.mjs} +73 -509
  3. package/dist/application-BezXGbrU.mjs.map +1 -0
  4. package/dist/application-DSXntqnV.mjs +4 -0
  5. package/dist/assert-CKfwrmCV.mjs +10 -0
  6. package/dist/assert-CKfwrmCV.mjs.map +1 -0
  7. package/dist/cli/index.mjs +376 -136
  8. package/dist/cli/index.mjs.map +1 -1
  9. package/dist/cli/lib.d.mts +3 -1
  10. package/dist/cli/lib.mjs +13 -6
  11. package/dist/cli/lib.mjs.map +1 -1
  12. package/dist/{client-B-jRdlC_.mjs → client-C68VWo4g.mjs} +1 -1
  13. package/dist/{client-W5P4NYYX.mjs → client-CobIRHl-.mjs} +207 -2
  14. package/dist/{client-W5P4NYYX.mjs.map → client-CobIRHl-.mjs.map} +1 -1
  15. package/dist/configure/index.mjs +2 -2
  16. package/dist/{crashreport-D3DvAzdg.mjs → crashreport-BhD0y14F.mjs} +2 -2
  17. package/dist/{crashreport-D3DvAzdg.mjs.map → crashreport-BhD0y14F.mjs.map} +1 -1
  18. package/dist/{crashreport-lnVTnbB5.mjs → crashreport-D1wKBJ8N.mjs} +1 -1
  19. package/dist/{mock-Dpu__UeJ.mjs → mock-DMgIygjE.mjs} +3 -2
  20. package/dist/mock-DMgIygjE.mjs.map +1 -0
  21. package/dist/plugin/builtin/seed/index.mjs +1 -1
  22. package/dist/plugin/index.mjs +1 -1
  23. package/dist/plugin/index.mjs.map +1 -1
  24. package/dist/registry-D0uB0OrK.mjs.map +1 -1
  25. package/dist/{repl-editor-Y9QJDL0K.mjs → repl-editor-CJG3sz7A.mjs} +11 -9
  26. package/dist/repl-editor-CJG3sz7A.mjs.map +1 -0
  27. package/dist/{runtime-C0_FZWdE.mjs → runtime-C6o4hiYq.mjs} +903 -579
  28. package/dist/runtime-C6o4hiYq.mjs.map +1 -0
  29. package/dist/{schema-DYKNTu-n.mjs → schema-1msIhXwA.mjs} +12 -7
  30. package/dist/schema-1msIhXwA.mjs.map +1 -0
  31. package/dist/{seed-C0fE2sJB.mjs → seed-BH2FbrPV.mjs} +4 -3
  32. package/dist/seed-BH2FbrPV.mjs.map +1 -0
  33. package/dist/service-BHQIerYh.mjs +4 -0
  34. package/dist/{service-aPT0fx3y.mjs → service-DMohAx8a2.mjs} +3 -3
  35. package/dist/service-DMohAx8a2.mjs.map +1 -0
  36. package/dist/service-wI3Hvrgx.mjs +460 -0
  37. package/dist/service-wI3Hvrgx.mjs.map +1 -0
  38. package/dist/{types-Ccwchyj5.mjs → types-2Be3wSMc.mjs} +1 -1
  39. package/dist/{types-BwGth3a1.mjs → types-CmzfQP_m.mjs} +3 -3
  40. package/dist/types-CmzfQP_m.mjs.map +1 -0
  41. package/dist/utils/test/index.mjs +1 -1
  42. package/dist/utils/test/index.mjs.map +1 -1
  43. package/dist/vitest/index.mjs +7 -4
  44. package/dist/vitest/index.mjs.map +1 -1
  45. package/dist/vitest/setup.mjs +1 -1
  46. package/docs/cli/application.md +11 -10
  47. package/docs/cli/tailordb.md +54 -0
  48. package/docs/cli-reference.md +1 -0
  49. package/docs/services/tailordb-migration.md +17 -1
  50. package/package.json +2 -1
  51. package/dist/application-D4tRNn90.mjs +0 -4
  52. package/dist/application-pusdxz35.mjs.map +0 -1
  53. package/dist/mock-Dpu__UeJ.mjs.map +0 -1
  54. package/dist/repl-editor-Y9QJDL0K.mjs.map +0 -1
  55. package/dist/runtime-C0_FZWdE.mjs.map +0 -1
  56. package/dist/schema-DYKNTu-n.mjs.map +0 -1
  57. package/dist/seed-C0fE2sJB.mjs.map +0 -1
  58. package/dist/service-aPT0fx3y.mjs.map +0 -1
  59. package/dist/types-BwGth3a1.mjs.map +0 -1
@@ -1,8 +1,10 @@
1
1
 
2
- import { t as db } from "./schema-DYKNTu-n.mjs";
3
- import { $ as Subgraph_ServiceType, A as IdPLang, B as AuthIDPConfig_AuthType, C as TailorDBGQLPermission_Operator, D as TailorDBType_PermitAction, E as TailorDBType_Permission_Permit, F as ExecutorJobStatus, G as AuthSCIMAttribute_Type, H as AuthOAuth2Client_ClientType, I as ExecutorTargetType, K as AuthSCIMAttribute_Uniqueness, L as ExecutorTriggerType, M as IdPPermissionPermit, N as FunctionExecution_Status, Q as ApplicationSchemaUpdateAttemptStatus, R as AuthConnection_Type, S as TailorDBGQLPermission_Action, T as TailorDBType_Permission_Operator, U as AuthOAuth2Client_GrantType, V as AuthInvokerSchema, W as AuthSCIMAttribute_Mutability, X as UserProfileProviderConfig_UserProfileProviderType, Y as TenantProviderConfig_TenantProviderType, Z as GetApplicationSchemaHealthResponse_ApplicationSchemaHealthStatus, _ as userAgent, a as fetchAll, b as WorkflowExecution_Status, et as ConditionSchema, f as initOperatorClient, h as resolveStaticWebsiteUrls, j as IdPPermissionOperator, k as PipelineResolver_OperationType, m as platformBaseUrl, nt as FilterSchema, o as fetchMachineUserToken, q as AuthSCIMConfig_AuthorizationType, rt as PageDirection, s as fetchPaged, tt as Condition_Operator, v as OperatorService, w as TailorDBGQLPermission_Permit, x as WorkflowJobExecution_Status, y as WorkspacePlatformUserRole, z as AuthHookPoint } from "./client-W5P4NYYX.mjs";
2
+ import { t as db } from "./schema-1msIhXwA.mjs";
3
+ import { $ as CreateExecutorExecutorRequestSchema, A as TailorDBGQLPermission_Permit, At as AuthSCIMAttribute_Type, B as UpdateSecretManagerSecretRequestSchema, Bt as Subgraph_ServiceType, C as WorkflowExecution_Status, Ct as AuthConnection_Type, D as UpdateTailorDBTypeRequestSchema, Dt as AuthOAuth2Client_ClientType, E as CreateTailorDBTypeRequestSchema, Et as AuthInvokerSchema, F as CreateStaticWebsiteRequestSchema, Ft as UserProfileProviderConfig_UserProfileProviderType, G as PipelineResolver_OperationType, H as CreatePipelineServiceRequestSchema, Ht as Condition_Operator, I as UpdateStaticWebsiteRequestSchema, It as CreateApplicationRequestSchema, J as IdPLang, K as CreateIdPServiceRequestSchema, Lt as GetApplicationSchemaHealthResponse_ApplicationSchemaHealthStatus, M as TailorDBType_Permission_Permit, Mt as AuthSCIMConfig_AuthorizationType, N as TailorDBType_PermitAction, O as TailorDBGQLPermission_Action, Ot as AuthOAuth2Client_GrantType, P as AddCustomDomainRequestSchema, Pt as TenantProviderConfig_TenantProviderType, R as CreateSecretManagerSecretRequestSchema, Rt as UpdateApplicationRequestSchema, S as UpdateWorkflowRequestSchema, St as UpdateUserProfileConfigRequestSchema, T as CreateTailorDBServiceRequestSchema, Tt as AuthIDPConfig_AuthType, U as UpdatePipelineResolverRequestSchema, Ut as FilterSchema, V as CreatePipelineResolverRequestSchema, Vt as ConditionSchema, W as UpdatePipelineServiceRequestSchema, Wt as PageDirection, X as IdPPermissionPermit, Y as IdPPermissionOperator, Z as FunctionExecution_Status, _ as userAgent, _t as UpdateAuthOAuth2ClientRequestSchema, a as fetchAll, at as CreateAuthHookRequestSchema, b as CreateWorkflowJobFunctionRequestSchema, bt as UpdateAuthServiceRequestSchema, ct as CreateAuthOAuth2ClientRequestSchema, dt as CreateAuthServiceRequestSchema, et as UpdateExecutorExecutorRequestSchema, f as initOperatorClient, ft as CreateTenantConfigRequestSchema, gt as UpdateAuthMachineUserRequestSchema, h as resolveStaticWebsiteUrls, ht as UpdateAuthIDPConfigRequestSchema, it as CreateAuthConnectionRequestSchema, j as TailorDBType_Permission_Operator, jt as AuthSCIMAttribute_Uniqueness, k as TailorDBGQLPermission_Operator, kt as AuthSCIMAttribute_Mutability, lt as CreateAuthSCIMConfigRequestSchema, m as platformBaseUrl, mt as UpdateAuthHookRequestSchema, nt as ExecutorTargetType, o as fetchMachineUserToken, ot as CreateAuthIDPConfigRequestSchema, pt as CreateUserProfileConfigRequestSchema, q as UpdateIdPServiceRequestSchema, rt as ExecutorTriggerType, s as fetchPaged, st as CreateAuthMachineUserRequestSchema, tt as ExecutorJobStatus, ut as CreateAuthSCIMResourceRequestSchema, v as OperatorService, vt as UpdateAuthSCIMConfigRequestSchema, w as WorkflowJobExecution_Status, wt as AuthHookPoint, x as CreateWorkflowRequestSchema, xt as UpdateTenantConfigRequestSchema, y as WorkspacePlatformUserRole, yt as UpdateAuthSCIMResourceRequestSchema, z as CreateSecretManagerVaultRequestSchema, zt as ApplicationSchemaUpdateAttemptStatus } from "./client-CobIRHl-.mjs";
4
+ import { t as assertDefined } from "./assert-CKfwrmCV.mjs";
4
5
  import { a as parseBoolean, i as symbols, n as logger, r as styles, t as CIPromptError } from "./logger-DpJyJvNz.mjs";
5
- import { A as loadConfigPath, C as getDistDir, E as loadConfig, F as writePlatformConfig, M as readPlatformConfig, S as createBundleCache, T as hashFile, _ as loadFilesWithIgnores, c as createExecutorService, d as buildExecutorArgsExpr, f as buildResolverOperationHookExpr, g as stringifyFunction, h as TailorDBTypeSchema, j as loadWorkspaceId, k as loadAccessToken, m as assertUniqueTailorDBTypeNamesWithExternal, n as generatePluginFilesIfNeeded, p as assertUniqueLocalTailorDBTypeNames, r as loadApplication, s as HTTP_METHODS, t as defineApplication, v as platformBundleDefinePlugin } from "./application-pusdxz35.mjs";
6
+ import { C as loadConfig, D as loadConfigPath, E as loadAccessToken, M as writePlatformConfig, O as loadWorkspaceId, S as hashFile, b as getDistDir, d as assertUniqueLocalTailorDBTypeNames, f as assertUniqueTailorDBTypeNamesWithExternal, h as platformBundleDefinePlugin, k as readPlatformConfig, l as buildExecutorArgsExpr, m as stringifyFunction, n as generatePluginFilesIfNeeded, p as TailorDBTypeSchema, r as loadApplication, s as HTTP_METHODS, t as defineApplication, u as buildResolverOperationHookExpr, y as createBundleCache } from "./application-BezXGbrU.mjs";
7
+ import { o as loadFilesWithIgnores, t as createExecutorService } from "./service-wI3Hvrgx.mjs";
6
8
  import { t as multiline } from "./multiline-Cf9ODpr1.mjs";
7
9
  import { t as readPackageJson } from "./package-json-DcQApfPQ.mjs";
8
10
  import { n as isCLIError, t as createCLIError } from "./errors-EsY4XO6O.mjs";
@@ -33,6 +35,9 @@ import * as fs from "node:fs/promises";
33
35
  import { glob } from "node:fs/promises";
34
36
  import { parseSync } from "oxc-parser";
35
37
  import * as inflection from "inflection";
38
+ import pLimit from "p-limit";
39
+ import { pathToString } from "@bufbuild/protobuf/reflect";
40
+ import { createValidator } from "@bufbuild/protovalidate";
36
41
  import { setTimeout as setTimeout$1 } from "timers/promises";
37
42
  import { spawn } from "node:child_process";
38
43
  import { watch } from "chokidar";
@@ -54,7 +59,9 @@ const durationPattern = /^(\d+)(ms|s|m)$/;
54
59
  */
55
60
  const durationArg = z.string().refine((val) => durationPattern.test(val), { message: "Invalid duration format. Expected format: '3s', '500ms', '1m'" }).refine((val) => {
56
61
  const match = val.match(durationPattern);
57
- return parseInt(match[1], 10) > 0;
62
+ if (!match) return false;
63
+ const digits = match[1];
64
+ return digits !== void 0 && parseInt(digits, 10) > 0;
58
65
  }, { message: "Duration must be greater than 0" });
59
66
  /**
60
67
  * Parse a validated duration string into milliseconds
@@ -62,8 +69,8 @@ const durationArg = z.string().refine((val) => durationPattern.test(val), { mess
62
69
  * @returns Duration in milliseconds
63
70
  */
64
71
  function parseDuration(duration) {
65
- const match = duration.match(durationPattern);
66
- return parseInt(match[1], 10) * unitToMs[match[2]];
72
+ const match = assertDefined(duration.match(durationPattern), `invalid duration format: ${duration}`);
73
+ return parseInt(assertDefined(match[1], "duration digits group missing"), 10) * unitToMs[assertDefined(match[2], "duration unit group missing")];
67
74
  }
68
75
  /**
69
76
  * Schema for positive integer validation (from string input)
@@ -308,10 +315,7 @@ async function assertWritable(opts) {
308
315
  * @returns Response status and data
309
316
  */
310
317
  async function apiCall(options) {
311
- const accessToken = await loadAccessToken({
312
- useProfile: true,
313
- profile: options.profile
314
- });
318
+ const accessToken = await loadAccessToken({ profile: options.profile });
315
319
  let endpointPath;
316
320
  if (options.endpoint.includes("/")) endpointPath = options.endpoint;
317
321
  else endpointPath = `tailor.v1.OperatorService/${options.endpoint}`;
@@ -650,7 +654,7 @@ const listCommand$10 = defineAppCommand({
650
654
  function resolveNamespaceName(methodName, config) {
651
655
  if (/Auth|Tenant|UserProfile/.test(methodName)) return config.auth?.name;
652
656
  if (/IdP/.test(methodName)) {
653
- if (config.idp?.length === 1) return config.idp[0].name;
657
+ if (config.idp?.length === 1) return assertDefined(config.idp[0], "idp config missing").name;
654
658
  return;
655
659
  }
656
660
  if (/TailorDB/.test(methodName)) {
@@ -691,12 +695,12 @@ function parseBodyAsObject(body) {
691
695
  function setNestedPath(obj, path, value) {
692
696
  let cursor = obj;
693
697
  for (let i = 0; i < path.length - 1; i++) {
694
- const key = path[i];
698
+ const key = assertDefined(path[i], "path segment missing");
695
699
  const next = cursor[key];
696
700
  if (typeof next !== "object" || next === null || Array.isArray(next)) cursor[key] = {};
697
701
  cursor = cursor[key];
698
702
  }
699
- cursor[path[path.length - 1]] = value;
703
+ cursor[assertDefined(path[path.length - 1], "path last segment missing")] = value;
700
704
  }
701
705
  /**
702
706
  * Coerces a raw `--field` string value to match the leaf proto type so the
@@ -1321,7 +1325,7 @@ var PluginManager = class {
1321
1325
  };
1322
1326
  }
1323
1327
  if (output.types && Object.keys(output.types).length > 0) {
1324
- const importPath = plugin.importPath;
1328
+ const importPath = assertDefined(plugin.importPath, `plugin "${plugin.id}" missing importPath`);
1325
1329
  for (const [kind, type] of Object.entries(output.types)) this.generatedTypes.push({
1326
1330
  pluginId: context.pluginId,
1327
1331
  pluginImportPath: importPath,
@@ -1384,7 +1388,7 @@ var PluginManager = class {
1384
1388
  });
1385
1389
  }
1386
1390
  if (output.types && Object.keys(output.types).length > 0) {
1387
- const importPath = plugin.importPath;
1391
+ const importPath = assertDefined(plugin.importPath, `plugin "${plugin.id}" missing importPath`);
1388
1392
  for (const [kind, type] of Object.entries(output.types)) {
1389
1393
  const typeKey = `${pluginId}:${kind}:${type.name}`;
1390
1394
  if (this.namespaceGeneratedTypeKeys.has(typeKey)) continue;
@@ -1593,13 +1597,13 @@ function copyMetadataToExtendedType(original, extended) {
1593
1597
  let result = extended;
1594
1598
  if (original._description) result = result.description(original._description);
1595
1599
  const metadata = original.metadata;
1596
- if (metadata.files && Object.keys(metadata.files).length > 0) result = result.files(metadata.files);
1600
+ if (Object.keys(metadata.files).length > 0) result = result.files(metadata.files);
1597
1601
  if (metadata.settings) {
1598
1602
  const { pluralForm: _pluralForm, ...features } = metadata.settings;
1599
1603
  if (Object.keys(features).length > 0) result = result.features(features);
1600
1604
  }
1601
- if (metadata.permissions?.record) result = result.permission(metadata.permissions.record);
1602
- if (metadata.permissions?.gql) result = result.gqlPermission(metadata.permissions.gql);
1605
+ if (metadata.permissions.record) result = result.permission(metadata.permissions.record);
1606
+ if (metadata.permissions.gql) result = result.gqlPermission(metadata.permissions.gql);
1603
1607
  if (metadata.indexes && Object.keys(metadata.indexes).length > 0) {
1604
1608
  const indexDefs = Object.entries(metadata.indexes).map(([name, def]) => ({
1605
1609
  name,
@@ -1608,7 +1612,7 @@ function copyMetadataToExtendedType(original, extended) {
1608
1612
  }));
1609
1613
  result = result.indexes(...indexDefs);
1610
1614
  }
1611
- if (original.plugins && original.plugins.length > 0) for (const plugin of original.plugins) result = result.plugin({ [plugin.pluginId]: plugin.config });
1615
+ if (original.plugins.length > 0) for (const plugin of original.plugins) result = result.plugin({ [plugin.pluginId]: plugin.config });
1612
1616
  return result;
1613
1617
  }
1614
1618
 
@@ -1815,15 +1819,15 @@ async function applyApplication(client, changeSet, phase = "create-update") {
1815
1819
  if (phase === "create-update") {
1816
1820
  const updates = [...changeSet.updates, ...changeSet.unchanged];
1817
1821
  await Promise.all([...changeSet.creates.map(async (create) => {
1818
- create.request.cors = await resolveStaticWebsiteUrls(client, create.request.workspaceId, create.request.cors, "CORS");
1822
+ create.request.cors = await resolveStaticWebsiteUrls(client, assertDefined(create.request.workspaceId, "request missing workspaceId"), create.request.cors, "CORS");
1819
1823
  await client.createApplication(create.request);
1820
1824
  await client.setMetadata(create.metaRequest);
1821
1825
  }), ...updates.map(async (update) => {
1822
- update.request.cors = await resolveStaticWebsiteUrls(client, update.request.workspaceId, update.request.cors, "CORS");
1826
+ update.request.cors = await resolveStaticWebsiteUrls(client, assertDefined(update.request.workspaceId, "request missing workspaceId"), update.request.cors, "CORS");
1823
1827
  await client.updateApplication(update.request);
1824
1828
  await client.setMetadata(update.metaRequest);
1825
1829
  })]);
1826
- } else if (phase === "delete") await Promise.all(changeSet.deletes.map(async (del) => {
1830
+ } else await Promise.all(changeSet.deletes.map(async (del) => {
1827
1831
  await client.deleteApplication(del.request);
1828
1832
  }));
1829
1833
  }
@@ -1832,7 +1836,7 @@ function sortStrings(values) {
1832
1836
  }
1833
1837
  function normalizeSubgraphs(subgraphs) {
1834
1838
  return [...subgraphs ?? []].map((subgraph) => ({
1835
- serviceType: subgraph.serviceType,
1839
+ serviceType: assertDefined(subgraph.serviceType, "subgraph missing serviceType"),
1836
1840
  serviceNamespace: subgraph.serviceNamespace ?? ""
1837
1841
  })).toSorted((left, right) => {
1838
1842
  if (left.serviceType !== right.serviceType) return left.serviceType - right.serviceType;
@@ -1928,7 +1932,7 @@ async function planApplication(context, httpAdapterBuildResult) {
1928
1932
  if (application.subgraphs.length === 0) return changeSet;
1929
1933
  let authNamespace;
1930
1934
  let authIdpConfigName;
1931
- if (application.authService && application.authService.config) {
1935
+ if (application.authService) {
1932
1936
  authNamespace = application.authService.config.name;
1933
1937
  const idProvider = application.authService.config.idProvider;
1934
1938
  if (idProvider) authIdpConfigName = idProvider.name;
@@ -1938,7 +1942,7 @@ async function planApplication(context, httpAdapterBuildResult) {
1938
1942
  try {
1939
1943
  const { idpConfigs, nextPageToken } = await client.listAuthIDPConfigs({
1940
1944
  workspaceId,
1941
- namespaceName: authNamespace,
1945
+ namespaceName: assertDefined(authNamespace, "authNamespace must be set before listing IDP configs"),
1942
1946
  pageToken,
1943
1947
  pageSize: maxPageSize
1944
1948
  });
@@ -1948,7 +1952,10 @@ async function planApplication(context, httpAdapterBuildResult) {
1948
1952
  throw error;
1949
1953
  }
1950
1954
  });
1951
- if (idpConfigs.length > 0) authIdpConfigName = idpConfigs[0].name;
1955
+ if (idpConfigs.length > 0) {
1956
+ const [firstConfig] = idpConfigs;
1957
+ if (firstConfig) authIdpConfigName = firstConfig.name;
1958
+ }
1952
1959
  }
1953
1960
  const metaRequest = await buildMetaRequest({
1954
1961
  trn: resourceTrn(workspaceId, "application", application.name),
@@ -2191,7 +2198,7 @@ async function planAuthConnections(client, workspaceId, appName, appId, auths) {
2191
2198
  const unmanaged = [];
2192
2199
  const resourceOwners = /* @__PURE__ */ new Set();
2193
2200
  const desiredConnections = {};
2194
- for (const auth of auths) if (auth.connections) for (const [name, config] of Object.entries(auth.connections)) desiredConnections[name] = config;
2201
+ for (const auth of auths) for (const [name, config] of Object.entries(auth.connections)) desiredConnections[name] = config;
2195
2202
  const existingList = await fetchAll(async (pageToken, maxPageSize) => {
2196
2203
  try {
2197
2204
  const { connections, nextPageToken } = await client.listAuthConnections({
@@ -2280,7 +2287,7 @@ async function planAuthConnections(client, workspaceId, appName, appId, auths) {
2280
2287
  function extractOAuth2Config(connection) {
2281
2288
  if (!connection) return void 0;
2282
2289
  const config = connection.config;
2283
- if (!config || config.case !== "oauth2" || !config.value) return void 0;
2290
+ if (!config || config.case !== "oauth2") return void 0;
2284
2291
  const v = config.value;
2285
2292
  return {
2286
2293
  type: "oauth2",
@@ -2324,7 +2331,7 @@ async function applyAuthConnections(client, result, phase) {
2324
2331
  if (oauth2) state.connections[replace.name] = hashConnectionConfig(oauth2);
2325
2332
  }
2326
2333
  saveSecretsState(state);
2327
- } else if (phase === "delete-resources" || phase === "delete") {
2334
+ } else {
2328
2335
  await Promise.all(changeSet.deletes.map(async (del) => {
2329
2336
  await client.deleteAuthConnection(del.request);
2330
2337
  }));
@@ -2662,7 +2669,7 @@ async function applyFunctionRegistry(client, workspaceId, result, phase = "creat
2662
2669
  await uploadFunctionScript(client, workspaceId, update.entry, false);
2663
2670
  await client.setMetadata(update.metaRequest);
2664
2671
  }
2665
- } else if (phase === "delete") await Promise.all(changeSet.deletes.map((del) => client.deleteFunctionRegistry({
2672
+ } else await Promise.all(changeSet.deletes.map((del) => client.deleteFunctionRegistry({
2666
2673
  workspaceId: del.workspaceId,
2667
2674
  name: del.name
2668
2675
  })));
@@ -2874,11 +2881,11 @@ function printGroupedDisplaySection(title, entries, serviceActions) {
2874
2881
  namespaceOrder.push(ns);
2875
2882
  byNamespace.set(ns, []);
2876
2883
  }
2877
- byNamespace.get(ns).push(entry);
2884
+ assertDefined(byNamespace.get(ns), "namespace group missing").push(entry);
2878
2885
  }
2879
2886
  const printedServices = /* @__PURE__ */ new Set();
2880
2887
  for (const ns of namespaceOrder) {
2881
- const group = byNamespace.get(ns);
2888
+ const group = assertDefined(byNamespace.get(ns), "namespace group missing");
2882
2889
  if (ns) {
2883
2890
  const svcAction = serviceMap.get(ns);
2884
2891
  const prefix = svcAction ? `${ACTION_SYMBOLS[svcAction]} ` : "";
@@ -3041,8 +3048,8 @@ async function applyIdP(client, result, phase = "create-update") {
3041
3048
  })]);
3042
3049
  await Promise.all([...changeSet.client.creates.map(async (create) => {
3043
3050
  const resp = await client.createIdPClient(create.request);
3044
- const vaultName = idpClientVaultName(create.request.namespaceName, create.request.client?.name || "");
3045
- const secretName = idpClientSecretName(create.request.namespaceName, create.request.client?.name || "");
3051
+ const vaultName = idpClientVaultName(assertDefined(create.request.namespaceName, "request missing namespaceName"), create.request.client?.name || "");
3052
+ const secretName = idpClientSecretName(assertDefined(create.request.namespaceName, "request missing namespaceName"), create.request.client?.name || "");
3046
3053
  await client.createSecretManagerVault({
3047
3054
  workspaceId: create.request.workspaceId,
3048
3055
  secretmanagerVaultName: vaultName
@@ -3084,7 +3091,7 @@ async function applyIdP(client, result, phase = "create-update") {
3084
3091
  secretmanagerVaultName: vaultName
3085
3092
  });
3086
3093
  }));
3087
- else if (phase === "delete-services") await Promise.all(changeSet.service.deletes.map((del) => client.deleteIdPService(del.request)));
3094
+ else await Promise.all(changeSet.service.deletes.map((del) => client.deleteIdPService(del.request)));
3088
3095
  }
3089
3096
  /**
3090
3097
  * Plan IdP-related changes based on current and desired state.
@@ -3323,10 +3330,9 @@ async function planClients(client, workspaceId, idps, deletedServices, forceAppl
3323
3330
  });
3324
3331
  };
3325
3332
  const clientsByIdp = await Promise.all(idps.map((idp) => fetchClients(idp.name)));
3326
- for (let i = 0; i < idps.length; i++) {
3327
- const idp = idps[i];
3333
+ for (const [i, idp] of idps.entries()) {
3328
3334
  const namespaceName = idp.name;
3329
- const existingClients = clientsByIdp[i];
3335
+ const existingClients = assertDefined(clientsByIdp[i], "clientsByIdp missing entry for idp index");
3330
3336
  const existingNameMap = /* @__PURE__ */ new Map();
3331
3337
  existingClients.forEach((client) => {
3332
3338
  existingNameMap.set(client.name, client.clientSecret);
@@ -3360,19 +3366,16 @@ async function planClients(client, workspaceId, idps, deletedServices, forceAppl
3360
3366
  });
3361
3367
  }
3362
3368
  const deletedClientsByService = await Promise.all(deletedServices.map((namespaceName) => fetchClients(namespaceName)));
3363
- for (let i = 0; i < deletedServices.length; i++) {
3364
- const namespaceName = deletedServices[i];
3365
- deletedClientsByService[i].forEach((client) => {
3366
- changeSet.deletes.push({
3367
- name: client.name,
3368
- request: {
3369
- workspaceId,
3370
- namespaceName,
3371
- name: client.name
3372
- }
3373
- });
3369
+ for (const [i, namespaceName] of deletedServices.entries()) assertDefined(deletedClientsByService[i], "deletedClientsByService missing entry for service index").forEach((client) => {
3370
+ changeSet.deletes.push({
3371
+ name: client.name,
3372
+ request: {
3373
+ workspaceId,
3374
+ namespaceName,
3375
+ name: client.name
3376
+ }
3374
3377
  });
3375
- }
3378
+ });
3376
3379
  return changeSet;
3377
3380
  }
3378
3381
  function convertLang(lang) {
@@ -3487,12 +3490,12 @@ async function applyAuth(client, result, phase = "create-update") {
3487
3490
  await client.updateAuthService(update.request);
3488
3491
  await client.setMetadata(update.metaRequest);
3489
3492
  })]);
3490
- if (changeSet.connection) await applyAuthConnections(client, { changeSet: changeSet.connection }, "create-update");
3493
+ await applyAuthConnections(client, { changeSet: changeSet.connection }, "create-update");
3491
3494
  await Promise.all([...changeSet.idpConfig.creates.map(async (create) => {
3492
- if (create.idpConfig.kind === "BuiltInIdP") create.request.idpConfig.config = await protoBuiltinIdPConfig(client, create.request.workspaceId, create.idpConfig);
3495
+ if (create.idpConfig.kind === "BuiltInIdP") assertDefined(create.request.idpConfig, "request missing idpConfig").config = await protoBuiltinIdPConfig(client, assertDefined(create.request.workspaceId, "request missing workspaceId"), create.idpConfig);
3493
3496
  return client.createAuthIDPConfig(create.request);
3494
3497
  }), ...changeSet.idpConfig.updates.map(async (update) => {
3495
- if (update.idpConfig.kind === "BuiltInIdP") update.request.idpConfig.config = await protoBuiltinIdPConfig(client, update.request.workspaceId, update.idpConfig);
3498
+ if (update.idpConfig.kind === "BuiltInIdP") assertDefined(update.request.idpConfig, "request missing idpConfig").config = await protoBuiltinIdPConfig(client, assertDefined(update.request.workspaceId, "request missing workspaceId"), update.idpConfig);
3496
3499
  return client.updateAuthIDPConfig(update.request);
3497
3500
  })]);
3498
3501
  await Promise.all([...changeSet.userProfileConfig.creates.map((create) => client.createUserProfileConfig(create.request)), ...changeSet.userProfileConfig.updates.map((update) => client.updateUserProfileConfig(update.request))]);
@@ -3500,15 +3503,18 @@ async function applyAuth(client, result, phase = "create-update") {
3500
3503
  await Promise.all([...changeSet.machineUser.creates.map((create) => client.createAuthMachineUser(create.request)), ...changeSet.machineUser.updates.map((update) => client.updateAuthMachineUser(update.request))]);
3501
3504
  await Promise.all([...changeSet.authHook.creates.map((create) => client.createAuthHook(create.request)), ...changeSet.authHook.updates.map((update) => client.updateAuthHook(update.request))]);
3502
3505
  await Promise.all([...changeSet.oauth2Client.creates.map(async (create) => {
3503
- create.request.oauth2Client.redirectUris = await resolveStaticWebsiteUrls(client, create.request.workspaceId, create.request.oauth2Client.redirectUris, "OAuth2 redirect URIs");
3506
+ const oauth2Client = assertDefined(create.request.oauth2Client, "request missing oauth2Client");
3507
+ oauth2Client.redirectUris = await resolveStaticWebsiteUrls(client, assertDefined(create.request.workspaceId, "request missing workspaceId"), oauth2Client.redirectUris, "OAuth2 redirect URIs");
3504
3508
  return client.createAuthOAuth2Client(create.request);
3505
3509
  }), ...changeSet.oauth2Client.updates.map(async (update) => {
3506
- update.request.oauth2Client.redirectUris = await resolveStaticWebsiteUrls(client, update.request.workspaceId, update.request.oauth2Client.redirectUris, "OAuth2 redirect URIs");
3510
+ const oauth2Client = assertDefined(update.request.oauth2Client, "request missing oauth2Client");
3511
+ oauth2Client.redirectUris = await resolveStaticWebsiteUrls(client, assertDefined(update.request.workspaceId, "request missing workspaceId"), oauth2Client.redirectUris, "OAuth2 redirect URIs");
3507
3512
  return client.updateAuthOAuth2Client(update.request);
3508
3513
  })]);
3509
3514
  for (const replace of changeSet.oauth2Client.replaces) {
3510
3515
  await client.deleteAuthOAuth2Client(replace.deleteRequest);
3511
- replace.createRequest.oauth2Client.redirectUris = await resolveStaticWebsiteUrls(client, replace.createRequest.workspaceId, replace.createRequest.oauth2Client.redirectUris, "OAuth2 redirect URIs");
3516
+ const replaceOauth2Client = assertDefined(replace.createRequest.oauth2Client, "createRequest missing oauth2Client");
3517
+ replaceOauth2Client.redirectUris = await resolveStaticWebsiteUrls(client, assertDefined(replace.createRequest.workspaceId, "createRequest missing workspaceId"), replaceOauth2Client.redirectUris, "OAuth2 redirect URIs");
3512
3518
  await client.createAuthOAuth2Client(replace.createRequest);
3513
3519
  }
3514
3520
  await Promise.all([...changeSet.scim.creates.map((create) => client.createAuthSCIMConfig(create.request)), ...changeSet.scim.updates.map((update) => client.updateAuthSCIMConfig(update.request))]);
@@ -3522,8 +3528,8 @@ async function applyAuth(client, result, phase = "create-update") {
3522
3528
  await Promise.all(changeSet.tenantConfig.deletes.map((del) => client.deleteTenantConfig(del.request)));
3523
3529
  await Promise.all(changeSet.userProfileConfig.deletes.map((del) => client.deleteUserProfileConfig(del.request)));
3524
3530
  await Promise.all(changeSet.idpConfig.deletes.map((del) => client.deleteAuthIDPConfig(del.request)));
3525
- if (changeSet.connection) await applyAuthConnections(client, { changeSet: changeSet.connection }, "delete-resources");
3526
- } else if (phase === "delete-services") await Promise.all(changeSet.service.deletes.map((del) => client.deleteAuthService(del.request)));
3531
+ await applyAuthConnections(client, { changeSet: changeSet.connection }, "delete-resources");
3532
+ } else await Promise.all(changeSet.service.deletes.map((del) => client.deleteAuthService(del.request)));
3527
3533
  }
3528
3534
  /**
3529
3535
  * Plan auth-related changes based on current and desired state.
@@ -3789,7 +3795,7 @@ function protoIdPConfig(idpConfig) {
3789
3795
  config: { config: {
3790
3796
  case: "saml",
3791
3797
  value: {
3792
- ...idpConfig.metadataURL !== void 0 ? { metadataUrl: idpConfig.metadataURL } : { rawMetadata: idpConfig.rawMetadata },
3798
+ ...idpConfig.metadataURL !== void 0 ? { metadataUrl: idpConfig.metadataURL } : { rawMetadata: assertDefined(idpConfig.rawMetadata, "SAML config missing rawMetadata") },
3793
3799
  enableSignRequest: idpConfig.enableSignRequest,
3794
3800
  defaultRedirectUrl: idpConfig.defaultRedirectURL
3795
3801
  }
@@ -4191,7 +4197,7 @@ async function planOAuth2Clients(client, workspaceId, auths, deletedServices, ex
4191
4197
  const newOAuth2Client = protoOAuth2Client(oauth2ClientName, oauth2Client);
4192
4198
  const resolvedRedirectUris = await resolveStaticWebsiteUrls(client, workspaceId, newOAuth2Client.redirectUris ?? [], "OAuth2 redirect URIs", { expectedLocalNames: expectedLocalWebsites });
4193
4199
  if (existingClientsMap.has(oauth2ClientName)) {
4194
- const existingClient = existingClientsMap.get(oauth2ClientName);
4200
+ const existingClient = assertDefined(existingClientsMap.get(oauth2ClientName), "existingClientsMap missing entry for oauth2ClientName");
4195
4201
  if (existingClient.clientType !== newOAuth2Client.clientType) changeSet.replaces.push({
4196
4202
  name: oauth2ClientName,
4197
4203
  deleteRequest: {
@@ -4648,7 +4654,7 @@ async function ensureConfigId(configPath) {
4648
4654
  findDefineConfigCalls(program, calls);
4649
4655
  if (calls.length === 0) return null;
4650
4656
  if (calls.length > 1) throw new Error(`Multiple defineConfig() calls found in ${configPath}. Only one is supported.`);
4651
- const { configObj } = calls[0];
4657
+ const { configObj } = assertDefined(calls[0], "defineConfig call site missing");
4652
4658
  if (!configObj) throw new Error(`defineConfig() argument must be an inline object literal in ${configPath} so the SDK can manage the 'id' field.`);
4653
4659
  const idProp = findIdProperty(configObj);
4654
4660
  if (idProp) {
@@ -4675,7 +4681,7 @@ const idComment = "// SDK-managed app id — do not edit, except when copying th
4675
4681
  function insertIdProperty(source, configObj, id) {
4676
4682
  const idLiteral = `id: ${JSON.stringify(id)}`;
4677
4683
  if (configObj.properties.length > 0) {
4678
- const firstProp = configObj.properties[0];
4684
+ const firstProp = assertDefined(configObj.properties[0], "first property missing");
4679
4685
  const lineStart = source.lastIndexOf("\n", firstProp.start - 1) + 1;
4680
4686
  const indent = source.slice(lineStart, firstProp.start);
4681
4687
  const insertion = `${idComment}\n${indent}${idLiteral},\n${indent}`;
@@ -4927,7 +4933,7 @@ async function applyExecutor(client, result, phase = "create-update") {
4927
4933
  await client.updateExecutorExecutor(update.request);
4928
4934
  await client.setMetadata(update.metaRequest);
4929
4935
  })]);
4930
- else if (phase === "delete") await Promise.all(changeSet.deletes.map((del) => client.deleteExecutorExecutor(del.request)));
4936
+ else await Promise.all(changeSet.deletes.map((del) => client.deleteExecutorExecutor(del.request)));
4931
4937
  }
4932
4938
  /**
4933
4939
  * Plan executor-related changes based on current and desired state.
@@ -5042,7 +5048,7 @@ function formatExecutorChangeEntries(changeSet, executors, functionRegistryExecu
5042
5048
  });
5043
5049
  }
5044
5050
  function normalizeComparableExecutor(executor) {
5045
- const normalized = normalizeProtoConfig(executor) ?? {};
5051
+ const normalized = normalizeProtoConfig(executor);
5046
5052
  const webhookHeaders = normalized.targetConfig?.config?.case === "webhook" ? (normalized.targetConfig.config.value.headers ?? []).toSorted((left, right) => (left.key ?? "").localeCompare(right.key ?? "")) : void 0;
5047
5053
  const triggerConfig = normalized.triggerConfig?.config?.case === "incomingWebhook" ? {
5048
5054
  ...normalized.triggerConfig,
@@ -5095,7 +5101,7 @@ function areExecutorsEqual(existing, desired) {
5095
5101
  return areNormalizedEqual(normalizeComparableExecutor(existing), normalizeComparableExecutor(desired));
5096
5102
  }
5097
5103
  function resolveTailorDBNamespace(application, typeName) {
5098
- for (const service of application.tailorDBServices) if (service.types[typeName]) return service.namespace;
5104
+ for (const service of application.tailorDBServices) if (Object.hasOwn(service.types, typeName)) return service.namespace;
5099
5105
  throw new Error(`TailorDB type "${typeName}" not found in any namespace. Available namespaces: ${application.tailorDBServices.map((s) => s.namespace).join(", ")}`);
5100
5106
  }
5101
5107
  function resolveResolverNamespace(application, resolverName) {
@@ -5116,7 +5122,7 @@ function resolveIdpNamespace(application, executorName, idpName) {
5116
5122
  const available = application.idpServices.map((idp) => idp.name).join(", ");
5117
5123
  throw new Error(`Executor "${executorName}" uses an idpUser trigger but the project defines multiple IdPs (${available}). Specify which IdP to subscribe to via the trigger's "idp" option.`);
5118
5124
  }
5119
- return application.idpServices[0].name;
5125
+ return assertDefined(application.idpServices[0], "idp service missing").name;
5120
5126
  }
5121
5127
  function resolveAuthNamespace(application) {
5122
5128
  if (!application.authService) throw new Error("No Auth service configured");
@@ -5345,7 +5351,7 @@ async function applyPipeline(client, result, phase = "create-update") {
5345
5351
  })]);
5346
5352
  await Promise.all([...changeSet.resolver.creates.map((create) => client.createPipelineResolver(create.request)), ...changeSet.resolver.updates.map((update) => client.updatePipelineResolver(update.request))]);
5347
5353
  } else if (phase === "delete-resources") await Promise.all(changeSet.resolver.deletes.map((del) => client.deletePipelineResolver(del.request)));
5348
- else if (phase === "delete-services") await Promise.all(changeSet.service.deletes.map((del) => client.deletePipelineService(del.request)));
5354
+ else await Promise.all(changeSet.service.deletes.map((del) => client.deletePipelineService(del.request)));
5349
5355
  }
5350
5356
  /**
5351
5357
  * Plan resolver pipeline changes based on current and desired state.
@@ -5544,7 +5550,7 @@ function formatResolverChangeEntries(changeSet, resolverFunctionChanges) {
5544
5550
  }, { getNamespace: (item) => item.request.namespaceName });
5545
5551
  }
5546
5552
  function normalizeComparableResolver(resolver) {
5547
- const normalized = normalizeProtoConfig(resolver) ?? {};
5553
+ const normalized = normalizeProtoConfig(resolver);
5548
5554
  return {
5549
5555
  name: normalized.name,
5550
5556
  description: normalized.description ?? "",
@@ -5609,7 +5615,7 @@ function processResolver(namespace, resolver, executorUsedResolvers, env, authNa
5609
5615
  }];
5610
5616
  const typeBaseName = inflection.camelize(resolver.name);
5611
5617
  const inputs = resolver.input ? protoFields(resolver.input, `${typeBaseName}Input`, true) : [];
5612
- const response = protoFields({ "": resolver.output }, `${typeBaseName}Output`, false)[0];
5618
+ const response = assertDefined(protoFields({ "": resolver.output }, `${typeBaseName}Output`, false)[0], "resolver output field missing");
5613
5619
  const resolverDescription = resolver.description || `${resolver.name} resolver`;
5614
5620
  const outputDescription = resolver.output.metadata.description;
5615
5621
  const combinedDescription = outputDescription ? `${resolverDescription}\n\nReturns:\n${outputDescription}` : resolverDescription;
@@ -5628,7 +5634,6 @@ function processResolver(namespace, resolver, executorUsedResolvers, env, authNa
5628
5634
  };
5629
5635
  }
5630
5636
  function protoFields(fields, baseName, isInput) {
5631
- if (!fields) return [];
5632
5637
  return Object.entries(fields).map(([fieldName, field]) => {
5633
5638
  let type;
5634
5639
  const required = isInput && field.metadata.hooks?.create !== void 0 ? false : field.metadata.required ?? true;
@@ -5664,6 +5669,43 @@ function protoFields(fields, baseName, isInput) {
5664
5669
  //#endregion
5665
5670
  //#region src/cli/commands/deploy/secret-manager.ts
5666
5671
  /**
5672
+ * Build the CreateSecretManagerVault request for a planned vault create.
5673
+ * @param create - Planned vault create
5674
+ * @returns Request init shape
5675
+ */
5676
+ function vaultCreateRequest(create) {
5677
+ return {
5678
+ workspaceId: create.workspaceId,
5679
+ secretmanagerVaultName: create.name
5680
+ };
5681
+ }
5682
+ /**
5683
+ * Build the CreateSecretManagerSecret request for a planned secret create.
5684
+ * @param create - Planned secret create
5685
+ * @returns Request init shape
5686
+ */
5687
+ function secretCreateRequest(create) {
5688
+ return {
5689
+ workspaceId: create.workspaceId,
5690
+ secretmanagerVaultName: create.vaultName,
5691
+ secretmanagerSecretName: create.secretName,
5692
+ secretmanagerSecretValue: create.value
5693
+ };
5694
+ }
5695
+ /**
5696
+ * Build the UpdateSecretManagerSecret request for a planned secret update.
5697
+ * @param update - Planned secret update
5698
+ * @returns Request init shape
5699
+ */
5700
+ function secretUpdateRequest(update) {
5701
+ return {
5702
+ workspaceId: update.workspaceId,
5703
+ secretmanagerVaultName: update.vaultName,
5704
+ secretmanagerSecretName: update.secretName,
5705
+ secretmanagerSecretValue: update.value
5706
+ };
5707
+ }
5708
+ /**
5667
5709
  * Plan secret manager changes based on current and desired state.
5668
5710
  * @param context - Planning context
5669
5711
  * @returns Planned changes for vaults and secrets
@@ -5830,10 +5872,7 @@ async function applySecretManager(client, result, phase = "create-update", appli
5830
5872
  const { vaultChangeSet, secretChangeSet } = result;
5831
5873
  if (phase === "create-update") {
5832
5874
  await Promise.all(vaultChangeSet.creates.map(async (create) => {
5833
- await client.createSecretManagerVault({
5834
- workspaceId: create.workspaceId,
5835
- secretmanagerVaultName: create.name
5836
- });
5875
+ await client.createSecretManagerVault(vaultCreateRequest(create));
5837
5876
  if (application) {
5838
5877
  const metaRequest = await buildMetaRequest({
5839
5878
  trn: resourceTrn(create.workspaceId, "vault", create.name),
@@ -5851,27 +5890,17 @@ async function applySecretManager(client, result, phase = "create-update", appli
5851
5890
  });
5852
5891
  await client.setMetadata(metaRequest);
5853
5892
  }));
5854
- await Promise.all(secretChangeSet.creates.map((create) => client.createSecretManagerSecret({
5855
- workspaceId: create.workspaceId,
5856
- secretmanagerVaultName: create.vaultName,
5857
- secretmanagerSecretName: create.secretName,
5858
- secretmanagerSecretValue: create.value
5859
- })));
5860
- await Promise.all(secretChangeSet.updates.map((update) => client.updateSecretManagerSecret({
5861
- workspaceId: update.workspaceId,
5862
- secretmanagerVaultName: update.vaultName,
5863
- secretmanagerSecretName: update.secretName,
5864
- secretmanagerSecretValue: update.value
5865
- })));
5893
+ await Promise.all(secretChangeSet.creates.map((create) => client.createSecretManagerSecret(secretCreateRequest(create))));
5894
+ await Promise.all(secretChangeSet.updates.map((update) => client.updateSecretManagerSecret(secretUpdateRequest(update))));
5866
5895
  if (application) {
5867
5896
  const state = loadSecretsState();
5868
5897
  for (const vault of application.secrets) {
5869
- if (!state.vaults[vault.vaultName]) state.vaults[vault.vaultName] = {};
5870
- for (const secret of vault.secrets) if (secret.value != null) state.vaults[vault.vaultName][secret.name] = hashValue(secret.value);
5898
+ if (!Object.hasOwn(state.vaults, vault.vaultName)) state.vaults[vault.vaultName] = {};
5899
+ for (const secret of vault.secrets) if (secret.value != null) assertDefined(state.vaults[vault.vaultName], "vault state entry missing")[secret.name] = hashValue(secret.value);
5871
5900
  }
5872
5901
  saveSecretsState(state);
5873
5902
  }
5874
- } else if (phase === "delete") {
5903
+ } else {
5875
5904
  await Promise.all(secretChangeSet.deletes.map((del) => client.deleteSecretManagerSecret({
5876
5905
  workspaceId: del.workspaceId,
5877
5906
  secretmanagerVaultName: del.vaultName,
@@ -5883,9 +5912,9 @@ async function applySecretManager(client, result, phase = "create-update", appli
5883
5912
  })));
5884
5913
  if (secretChangeSet.deletes.length > 0 || vaultChangeSet.deletes.length > 0) {
5885
5914
  const state = loadSecretsState();
5886
- for (const del of secretChangeSet.deletes) if (state.vaults[del.vaultName]) {
5887
- delete state.vaults[del.vaultName][del.secretName];
5888
- if (Object.keys(state.vaults[del.vaultName]).length === 0) delete state.vaults[del.vaultName];
5915
+ for (const del of secretChangeSet.deletes) if (Object.hasOwn(state.vaults, del.vaultName)) {
5916
+ delete assertDefined(state.vaults[del.vaultName], "vault state entry missing")[del.secretName];
5917
+ if (Object.keys(assertDefined(state.vaults[del.vaultName], "vault state entry missing")).length === 0) delete state.vaults[del.vaultName];
5889
5918
  }
5890
5919
  for (const del of vaultChangeSet.deletes) delete state.vaults[del.name];
5891
5920
  saveSecretsState(state);
@@ -5916,7 +5945,7 @@ async function applyStaticWebsite(client, result, phase = "create-update") {
5916
5945
  await client.addCustomDomain(add.request);
5917
5946
  await client.setMetadata(add.metaRequest);
5918
5947
  }), ...customDomainChangeSet.deletes.map((del) => client.removeCustomDomain(del.request))]);
5919
- } else if (phase === "delete") await Promise.all(changeSet.deletes.map((del) => client.deleteStaticWebsite(del.request)));
5948
+ } else await Promise.all(changeSet.deletes.map((del) => client.deleteStaticWebsite(del.request)));
5920
5949
  }
5921
5950
  function customDomainTrn(workspaceId, websiteName, domain) {
5922
5951
  return `trn:v1:workspace:${workspaceId}:staticwebsite:${websiteName}:custom_domain:${domain}`;
@@ -6296,6 +6325,24 @@ function formatDiffSummary(diff) {
6296
6325
  function formatMigrationNumber(num) {
6297
6326
  return num.toString().padStart(4, "0");
6298
6327
  }
6328
+ /**
6329
+ * Parse a migration number CLI argument.
6330
+ *
6331
+ * Accepts the canonical 4-digit form ("0001") or a bare integer without
6332
+ * leading zeros ("0"–"9999"). Commands that disallow the baseline reject
6333
+ * 0 themselves with a context-specific message.
6334
+ * @param numberStr - Raw CLI argument
6335
+ * @returns Parsed migration number
6336
+ */
6337
+ function parseMigrationNumberArg(numberStr) {
6338
+ if (/^\d{4}$/.test(numberStr)) return parseInt(numberStr, 10);
6339
+ if (/^(0|[1-9]\d*)$/.test(numberStr)) {
6340
+ const parsed = parseInt(numberStr, 10);
6341
+ if (parsed > 9999) throw new Error(`Migration number ${numberStr} is out of range. Expected 0-9999.`);
6342
+ return parsed;
6343
+ }
6344
+ throw new Error(`Invalid migration number format: ${numberStr}. Expected 4-digit format (e.g., 0001) or integer 0-9999 (e.g., 1).`);
6345
+ }
6299
6346
 
6300
6347
  //#endregion
6301
6348
  //#region src/cli/commands/tailordb/migrate/snapshot-types.ts
@@ -6675,96 +6722,112 @@ function applyDiffToSnapshot(snapshot, diff) {
6675
6722
  case "type_removed":
6676
6723
  delete types[change.typeName];
6677
6724
  break;
6678
- case "type_modified":
6679
- if (types[change.typeName] && change.after) {
6725
+ case "type_modified": {
6726
+ const existing = types[change.typeName];
6727
+ if (existing && change.after) {
6680
6728
  const after = change.after;
6681
6729
  types[change.typeName] = {
6682
- ...types[change.typeName],
6730
+ ...existing,
6683
6731
  ...after.indexes !== void 0 && { indexes: after.indexes },
6684
6732
  ...after.files !== void 0 && { files: after.files }
6685
6733
  };
6686
6734
  }
6687
6735
  break;
6736
+ }
6688
6737
  case "field_added":
6689
- case "field_modified":
6690
- if (types[change.typeName] && change.fieldName) types[change.typeName] = {
6691
- ...types[change.typeName],
6738
+ case "field_modified": {
6739
+ const existing = types[change.typeName];
6740
+ if (existing && change.fieldName) types[change.typeName] = {
6741
+ ...existing,
6692
6742
  fields: {
6693
- ...types[change.typeName].fields,
6743
+ ...existing.fields,
6694
6744
  [change.fieldName]: change.after
6695
6745
  }
6696
6746
  };
6697
6747
  break;
6698
- case "field_removed":
6699
- if (types[change.typeName] && change.fieldName) {
6700
- const { [change.fieldName]: _, ...remainingFields } = types[change.typeName].fields;
6748
+ }
6749
+ case "field_removed": {
6750
+ const existing = types[change.typeName];
6751
+ if (existing && change.fieldName) {
6752
+ const { [change.fieldName]: _, ...remainingFields } = existing.fields;
6701
6753
  types[change.typeName] = {
6702
- ...types[change.typeName],
6754
+ ...existing,
6703
6755
  fields: remainingFields
6704
6756
  };
6705
6757
  }
6706
6758
  break;
6759
+ }
6707
6760
  case "index_added":
6708
- case "index_modified":
6709
- if (types[change.typeName] && change.indexName) types[change.typeName] = {
6710
- ...types[change.typeName],
6761
+ case "index_modified": {
6762
+ const existing = types[change.typeName];
6763
+ if (existing && change.indexName) types[change.typeName] = {
6764
+ ...existing,
6711
6765
  indexes: {
6712
- ...types[change.typeName].indexes,
6766
+ ...existing.indexes,
6713
6767
  [change.indexName]: change.after
6714
6768
  }
6715
6769
  };
6716
6770
  break;
6717
- case "index_removed":
6718
- if (types[change.typeName] && change.indexName && types[change.typeName].indexes) {
6719
- const { [change.indexName]: _, ...remainingIndexes } = types[change.typeName].indexes;
6771
+ }
6772
+ case "index_removed": {
6773
+ const existing = types[change.typeName];
6774
+ if (existing && change.indexName && existing.indexes) {
6775
+ const { [change.indexName]: _, ...remainingIndexes } = existing.indexes;
6720
6776
  types[change.typeName] = {
6721
- ...types[change.typeName],
6777
+ ...existing,
6722
6778
  indexes: Object.keys(remainingIndexes).length > 0 ? remainingIndexes : void 0
6723
6779
  };
6724
6780
  }
6725
6781
  break;
6782
+ }
6726
6783
  case "file_added":
6727
- case "file_modified":
6728
- if (types[change.typeName] && change.fieldName) types[change.typeName] = {
6729
- ...types[change.typeName],
6784
+ case "file_modified": {
6785
+ const existing = types[change.typeName];
6786
+ if (existing && change.fieldName) types[change.typeName] = {
6787
+ ...existing,
6730
6788
  files: {
6731
- ...types[change.typeName].files,
6789
+ ...existing.files,
6732
6790
  [change.fieldName]: change.after
6733
6791
  }
6734
6792
  };
6735
6793
  break;
6736
- case "file_removed":
6737
- if (types[change.typeName] && change.fieldName && types[change.typeName].files) {
6738
- const { [change.fieldName]: _, ...remainingFiles } = types[change.typeName].files;
6794
+ }
6795
+ case "file_removed": {
6796
+ const existing = types[change.typeName];
6797
+ if (existing && change.fieldName && existing.files) {
6798
+ const { [change.fieldName]: _, ...remainingFiles } = existing.files;
6739
6799
  types[change.typeName] = {
6740
- ...types[change.typeName],
6800
+ ...existing,
6741
6801
  files: Object.keys(remainingFiles).length > 0 ? remainingFiles : void 0
6742
6802
  };
6743
6803
  }
6744
6804
  break;
6805
+ }
6745
6806
  case "relationship_added":
6746
- case "relationship_modified":
6747
- if (types[change.typeName] && change.relationshipName) {
6807
+ case "relationship_modified": {
6808
+ const existing = types[change.typeName];
6809
+ if (existing && change.relationshipName) {
6748
6810
  const rel = change.after;
6749
- if ((change.relationshipType ?? (types[change.typeName].forwardRelationships?.[change.relationshipName] ? "forward" : types[change.typeName].backwardRelationships?.[change.relationshipName] ? "backward" : "forward")) === "forward") types[change.typeName] = {
6750
- ...types[change.typeName],
6811
+ if ((change.relationshipType ?? (existing.forwardRelationships?.[change.relationshipName] ? "forward" : existing.backwardRelationships?.[change.relationshipName] ? "backward" : "forward")) === "forward") types[change.typeName] = {
6812
+ ...existing,
6751
6813
  forwardRelationships: {
6752
- ...types[change.typeName].forwardRelationships,
6814
+ ...existing.forwardRelationships,
6753
6815
  [change.relationshipName]: rel
6754
6816
  }
6755
6817
  };
6756
6818
  else types[change.typeName] = {
6757
- ...types[change.typeName],
6819
+ ...existing,
6758
6820
  backwardRelationships: {
6759
- ...types[change.typeName].backwardRelationships,
6821
+ ...existing.backwardRelationships,
6760
6822
  [change.relationshipName]: rel
6761
6823
  }
6762
6824
  };
6763
6825
  }
6764
6826
  break;
6765
- case "relationship_removed":
6766
- if (types[change.typeName] && change.relationshipName) {
6767
- const type = types[change.typeName];
6827
+ }
6828
+ case "relationship_removed": {
6829
+ const type = types[change.typeName];
6830
+ if (type && change.relationshipName) {
6768
6831
  const targetType = change.relationshipType ?? (type.forwardRelationships?.[change.relationshipName] ? "forward" : type.backwardRelationships?.[change.relationshipName] ? "backward" : null);
6769
6832
  if (targetType === "forward" && type.forwardRelationships?.[change.relationshipName]) {
6770
6833
  const { [change.relationshipName]: _, ...remaining } = type.forwardRelationships;
@@ -6781,11 +6844,13 @@ function applyDiffToSnapshot(snapshot, diff) {
6781
6844
  }
6782
6845
  }
6783
6846
  break;
6784
- case "permission_modified":
6785
- if (types[change.typeName] && change.after) {
6847
+ }
6848
+ case "permission_modified": {
6849
+ const existing = types[change.typeName];
6850
+ if (existing && change.after) {
6786
6851
  const after = change.after;
6787
6852
  types[change.typeName] = {
6788
- ...types[change.typeName],
6853
+ ...existing,
6789
6854
  permissions: {
6790
6855
  record: after.recordPermission,
6791
6856
  gql: after.gqlPermission
@@ -6793,6 +6858,7 @@ function applyDiffToSnapshot(snapshot, diff) {
6793
6858
  };
6794
6859
  }
6795
6860
  break;
6861
+ }
6796
6862
  }
6797
6863
  return {
6798
6864
  ...snapshot,
@@ -6869,8 +6935,10 @@ function areFieldsDifferent(oldField, newField) {
6869
6935
  const newValidate = newField.validate ?? [];
6870
6936
  if (oldValidate.length !== newValidate.length) return true;
6871
6937
  for (let i = 0; i < oldValidate.length; i++) {
6872
- if (oldValidate[i].script.expr !== newValidate[i].script.expr) return true;
6873
- if (oldValidate[i].errorMessage !== newValidate[i].errorMessage) return true;
6938
+ const oldV = assertDefined(oldValidate[i], `oldValidate missing index ${i}`);
6939
+ const newV = assertDefined(newValidate[i], `newValidate missing index ${i}`);
6940
+ if (oldV.script.expr !== newV.script.expr) return true;
6941
+ if (oldV.errorMessage !== newV.errorMessage) return true;
6874
6942
  }
6875
6943
  const oldSerial = oldField.serial;
6876
6944
  const newSerial = newField.serial;
@@ -6887,8 +6955,10 @@ function areFieldsDifferent(oldField, newField) {
6887
6955
  const newFieldNames = Object.keys(newFields);
6888
6956
  if (oldFieldNames.length !== newFieldNames.length) return true;
6889
6957
  for (const fieldName of oldFieldNames) {
6890
- if (!newFields[fieldName]) return true;
6891
- if (areFieldsDifferent(oldFields[fieldName], newFields[fieldName])) return true;
6958
+ const oldF = oldFields[fieldName];
6959
+ const newF = newFields[fieldName];
6960
+ if (!newF) return true;
6961
+ if (areFieldsDifferent(assertDefined(oldF, `field "${fieldName}" missing from oldFields`), newF)) return true;
6892
6962
  }
6893
6963
  return false;
6894
6964
  }
@@ -6973,22 +7043,28 @@ function addChange(ctx, change, oldField, newField) {
6973
7043
  function compareTypeFields(ctx, typeName, prevType, currType) {
6974
7044
  const prevFieldNames = new Set(Object.keys(prevType.fields));
6975
7045
  const currFieldNames = new Set(Object.keys(currType.fields));
6976
- for (const fieldName of currFieldNames) if (!prevFieldNames.has(fieldName)) addChange(ctx, {
6977
- kind: "field_added",
6978
- typeName,
6979
- fieldName,
6980
- after: currType.fields[fieldName]
6981
- }, void 0, currType.fields[fieldName]);
6982
- for (const fieldName of prevFieldNames) if (!currFieldNames.has(fieldName)) addChange(ctx, {
6983
- kind: "field_removed",
6984
- typeName,
6985
- fieldName,
6986
- before: prevType.fields[fieldName]
6987
- }, prevType.fields[fieldName], void 0);
7046
+ for (const fieldName of currFieldNames) if (!prevFieldNames.has(fieldName)) {
7047
+ const currField = assertDefined(currType.fields[fieldName], `field "${fieldName}" missing from currType`);
7048
+ addChange(ctx, {
7049
+ kind: "field_added",
7050
+ typeName,
7051
+ fieldName,
7052
+ after: currField
7053
+ }, void 0, currField);
7054
+ }
7055
+ for (const fieldName of prevFieldNames) if (!currFieldNames.has(fieldName)) {
7056
+ const prevField = assertDefined(prevType.fields[fieldName], `field "${fieldName}" missing from prevType`);
7057
+ addChange(ctx, {
7058
+ kind: "field_removed",
7059
+ typeName,
7060
+ fieldName,
7061
+ before: prevField
7062
+ }, prevField, void 0);
7063
+ }
6988
7064
  for (const fieldName of currFieldNames) {
6989
7065
  if (!prevFieldNames.has(fieldName)) continue;
6990
- const prevField = prevType.fields[fieldName];
6991
- const currField = currType.fields[fieldName];
7066
+ const prevField = assertDefined(prevType.fields[fieldName], `field "${fieldName}" missing from prevType`);
7067
+ const currField = assertDefined(currType.fields[fieldName], `field "${fieldName}" missing from currType`);
6992
7068
  if (areFieldsDifferent(prevField, currField)) addChange(ctx, {
6993
7069
  kind: "field_modified",
6994
7070
  typeName,
@@ -7009,21 +7085,20 @@ function compareTypeFields(ctx, typeName, prevType, currType) {
7009
7085
  function compareIndexes(ctx, typeName, oldIndexes, newIndexes) {
7010
7086
  const oldKeys = new Set(Object.keys(oldIndexes || {}));
7011
7087
  const newKeys = new Set(Object.keys(newIndexes || {}));
7012
- for (const indexName of newKeys) if (!oldKeys.has(indexName)) ctx.changes.push({
7088
+ for (const [indexName, indexConfig] of Object.entries(newIndexes ?? {})) if (!oldKeys.has(indexName)) ctx.changes.push({
7013
7089
  kind: "index_added",
7014
7090
  typeName,
7015
7091
  indexName,
7016
- after: newIndexes[indexName]
7092
+ after: indexConfig
7017
7093
  });
7018
- for (const indexName of oldKeys) if (!newKeys.has(indexName)) ctx.changes.push({
7094
+ for (const [indexName, indexConfig] of Object.entries(oldIndexes ?? {})) if (!newKeys.has(indexName)) ctx.changes.push({
7019
7095
  kind: "index_removed",
7020
7096
  typeName,
7021
7097
  indexName,
7022
- before: oldIndexes[indexName]
7098
+ before: indexConfig
7023
7099
  });
7024
- for (const indexName of newKeys) if (oldKeys.has(indexName)) {
7025
- const oldIndex = oldIndexes[indexName];
7026
- const newIndex = newIndexes[indexName];
7100
+ for (const [indexName, newIndex] of Object.entries(newIndexes ?? {})) if (oldKeys.has(indexName)) {
7101
+ const oldIndex = assertDefined(assertDefined(oldIndexes, "oldIndexes is undefined when oldKeys has entry")[indexName], `index "${indexName}" missing from oldIndexes`);
7027
7102
  const oldFieldsStr = JSON.stringify(oldIndex.fields.toSorted());
7028
7103
  const newFieldsStr = JSON.stringify(newIndex.fields.toSorted());
7029
7104
  if (oldFieldsStr !== newFieldsStr || oldIndex.unique !== newIndex.unique) {
@@ -7052,26 +7127,27 @@ function compareIndexes(ctx, typeName, oldIndexes, newIndexes) {
7052
7127
  function compareFiles(ctx, typeName, oldFiles, newFiles) {
7053
7128
  const oldKeys = new Set(Object.keys(oldFiles || {}));
7054
7129
  const newKeys = new Set(Object.keys(newFiles || {}));
7055
- for (const fileName of newKeys) if (!oldKeys.has(fileName)) ctx.changes.push({
7130
+ for (const [fileName, fileDesc] of Object.entries(newFiles ?? {})) if (!oldKeys.has(fileName)) ctx.changes.push({
7056
7131
  kind: "file_added",
7057
7132
  typeName,
7058
7133
  fieldName: fileName,
7059
- after: newFiles[fileName]
7134
+ after: fileDesc
7060
7135
  });
7061
- for (const fileName of oldKeys) if (!newKeys.has(fileName)) ctx.changes.push({
7136
+ for (const [fileName, fileDesc] of Object.entries(oldFiles ?? {})) if (!newKeys.has(fileName)) ctx.changes.push({
7062
7137
  kind: "file_removed",
7063
7138
  typeName,
7064
7139
  fieldName: fileName,
7065
- before: oldFiles[fileName]
7140
+ before: fileDesc
7066
7141
  });
7067
- for (const fileName of newKeys) if (oldKeys.has(fileName)) {
7068
- if (oldFiles[fileName] !== newFiles[fileName]) ctx.changes.push({
7142
+ for (const [fileName, newDesc] of Object.entries(newFiles ?? {})) if (oldKeys.has(fileName)) {
7143
+ const oldDesc = assertDefined(assertDefined(oldFiles, "oldFiles is undefined when oldKeys has entry")[fileName], `file "${fileName}" missing from oldFiles`);
7144
+ if (oldDesc !== newDesc) ctx.changes.push({
7069
7145
  kind: "file_modified",
7070
7146
  typeName,
7071
7147
  fieldName: fileName,
7072
7148
  reason: "description changed",
7073
- before: oldFiles[fileName],
7074
- after: newFiles[fileName]
7149
+ before: oldDesc,
7150
+ after: newDesc
7075
7151
  });
7076
7152
  }
7077
7153
  }
@@ -7087,23 +7163,22 @@ function compareFiles(ctx, typeName, oldFiles, newFiles) {
7087
7163
  function compareRelationships(ctx, typeName, relationshipType, oldRelationships, newRelationships) {
7088
7164
  const oldKeys = new Set(Object.keys(oldRelationships || {}));
7089
7165
  const newKeys = new Set(Object.keys(newRelationships || {}));
7090
- for (const relName of newKeys) if (!oldKeys.has(relName)) ctx.changes.push({
7166
+ for (const [relName, rel] of Object.entries(newRelationships ?? {})) if (!oldKeys.has(relName)) ctx.changes.push({
7091
7167
  kind: "relationship_added",
7092
7168
  typeName,
7093
7169
  relationshipName: relName,
7094
7170
  relationshipType,
7095
- after: newRelationships[relName]
7171
+ after: rel
7096
7172
  });
7097
- for (const relName of oldKeys) if (!newKeys.has(relName)) ctx.changes.push({
7173
+ for (const [relName, rel] of Object.entries(oldRelationships ?? {})) if (!newKeys.has(relName)) ctx.changes.push({
7098
7174
  kind: "relationship_removed",
7099
7175
  typeName,
7100
7176
  relationshipName: relName,
7101
7177
  relationshipType,
7102
- before: oldRelationships[relName]
7178
+ before: rel
7103
7179
  });
7104
- for (const relName of newKeys) if (oldKeys.has(relName)) {
7105
- const oldRel = oldRelationships[relName];
7106
- const newRel = newRelationships[relName];
7180
+ for (const [relName, newRel] of Object.entries(newRelationships ?? {})) if (oldKeys.has(relName)) {
7181
+ const oldRel = assertDefined(assertDefined(oldRelationships, "oldRelationships is undefined when oldKeys has entry")[relName], `relationship "${relName}" missing from oldRelationships`);
7107
7182
  const reasons = [];
7108
7183
  if (oldRel.targetType !== newRel.targetType) reasons.push("targetType changed");
7109
7184
  if (oldRel.targetField !== newRel.targetField) reasons.push("targetField changed");
@@ -7168,16 +7243,16 @@ function compareSnapshots(previous, current) {
7168
7243
  };
7169
7244
  const previousTypeNames = new Set(Object.keys(previous.types));
7170
7245
  const currentTypeNames = new Set(Object.keys(current.types));
7171
- for (const typeName of currentTypeNames) if (!previousTypeNames.has(typeName)) ctx.changes.push({
7246
+ for (const [typeName, type] of Object.entries(current.types)) if (!previousTypeNames.has(typeName)) ctx.changes.push({
7172
7247
  kind: "type_added",
7173
7248
  typeName,
7174
- after: current.types[typeName]
7249
+ after: type
7175
7250
  });
7176
- for (const typeName of previousTypeNames) if (!currentTypeNames.has(typeName)) {
7251
+ for (const [typeName, type] of Object.entries(previous.types)) if (!currentTypeNames.has(typeName)) {
7177
7252
  ctx.changes.push({
7178
7253
  kind: "type_removed",
7179
7254
  typeName,
7180
- before: previous.types[typeName]
7255
+ before: type
7181
7256
  });
7182
7257
  ctx.warnings.push({
7183
7258
  typeName,
@@ -7186,8 +7261,8 @@ function compareSnapshots(previous, current) {
7186
7261
  }
7187
7262
  for (const typeName of currentTypeNames) {
7188
7263
  if (!previousTypeNames.has(typeName)) continue;
7189
- const prevType = previous.types[typeName];
7190
- const currType = current.types[typeName];
7264
+ const prevType = assertDefined(previous.types[typeName], `type "${typeName}" missing from previous snapshot`);
7265
+ const currType = assertDefined(current.types[typeName], `type "${typeName}" missing from current snapshot`);
7191
7266
  compareTypeFields(ctx, typeName, prevType, currType);
7192
7267
  compareIndexes(ctx, typeName, prevType.indexes, currType.indexes);
7193
7268
  compareFiles(ctx, typeName, prevType.files, currType.files);
@@ -7245,7 +7320,7 @@ function validateMigrationFiles(migrationsDir) {
7245
7320
  const schemaFiles = [];
7246
7321
  const diffFiles = [];
7247
7322
  for (const file of migrationFiles) if (file.type === "schema") schemaFiles.push(file.number);
7248
- else if (file.type === "diff") diffFiles.push(file.number);
7323
+ else diffFiles.push(file.number);
7249
7324
  if (!schemaFiles.includes(0)) errors.push({
7250
7325
  type: "missing_schema",
7251
7326
  message: `Initial schema snapshot (${formatMigrationNumber(0)}/schema.json) is missing`,
@@ -7414,8 +7489,8 @@ function compareRemoteWithSnapshot(remoteTypes, snapshot) {
7414
7489
  });
7415
7490
  for (const typeName of snapshotTypeNames) {
7416
7491
  if (!remoteTypeNames.has(typeName)) continue;
7417
- const remoteType = remoteTypeMap.get(typeName);
7418
- const snapshotType = snapshot.types[typeName];
7492
+ const remoteType = assertDefined(remoteTypeMap.get(typeName), `type "${typeName}" missing from remoteTypeMap`);
7493
+ const snapshotType = assertDefined(snapshot.types[typeName], `type "${typeName}" missing from snapshot`);
7419
7494
  const remoteFields = convertRemoteFieldsToSnapshot(remoteType);
7420
7495
  const snapshotFields = snapshotType.fields;
7421
7496
  const remoteFieldNames = new Set(Object.keys(remoteFields).filter((f) => !SYSTEM_FIELDS.has(f)));
@@ -7434,7 +7509,7 @@ function compareRemoteWithSnapshot(remoteTypes, snapshot) {
7434
7509
  });
7435
7510
  for (const fieldName of snapshotFieldNames) {
7436
7511
  if (!remoteFieldNames.has(fieldName)) continue;
7437
- const drift = compareFields(typeName, fieldName, remoteFields[fieldName], snapshotFields[fieldName]);
7512
+ const drift = compareFields(typeName, fieldName, assertDefined(remoteFields[fieldName], `field "${fieldName}" missing from remoteFields`), assertDefined(snapshotFields[fieldName], `field "${fieldName}" missing from snapshotFields`));
7438
7513
  if (drift) drifts.push(drift);
7439
7514
  }
7440
7515
  }
@@ -7752,6 +7827,145 @@ function convertOperandToProto(operand) {
7752
7827
  value: fromJson(ValueSchema, operand)
7753
7828
  } };
7754
7829
  }
7830
+ /**
7831
+ * Generate all TailorDB type manifests from a schema snapshot
7832
+ * @param {SchemaSnapshot} snapshot - Schema snapshot
7833
+ * @param {GenerateAllManifestsOptions} options - Generation options
7834
+ * @returns {Map<string, MessageInitShape<typeof TailorDBTypeSchema>>} Map of type name to manifest
7835
+ */
7836
+ function generateAllTypeManifestsFromSnapshot(snapshot, options = {}) {
7837
+ const manifests = /* @__PURE__ */ new Map();
7838
+ const { executorUsedTypes, ...baseOptions } = options;
7839
+ for (const [typeName, snapshotType] of Object.entries(snapshot.types)) {
7840
+ if (executorUsedTypes?.has(typeName) && snapshotType.settings?.publishEvents === false) throw new Error(`Type "${typeName}" has publishEvents set to false, but it is used by an executor with a record trigger. Either remove the publishEvents: false setting or remove the executor trigger for this type.`);
7841
+ let publishRecordEvents;
7842
+ if (snapshotType.settings?.publishEvents !== void 0) publishRecordEvents = snapshotType.settings.publishEvents;
7843
+ else if (executorUsedTypes?.has(typeName)) publishRecordEvents = true;
7844
+ else publishRecordEvents = baseOptions.publishRecordEvents ?? false;
7845
+ const typeOptions = {
7846
+ ...baseOptions,
7847
+ publishRecordEvents
7848
+ };
7849
+ manifests.set(typeName, generateTailorDBTypeManifestFromSnapshot(snapshotType, typeOptions));
7850
+ }
7851
+ return manifests;
7852
+ }
7853
+ /**
7854
+ * Compare snapshot types with existing remote type names
7855
+ * @param {SchemaSnapshot} snapshot - Schema snapshot
7856
+ * @param {ReadonlySet<string>} existingTypeNames - Set of existing type names in remote
7857
+ * @returns {SnapshotTypeComparison} Comparison result
7858
+ */
7859
+ function compareSnapshotWithRemote(snapshot, existingTypeNames) {
7860
+ const snapshotTypeNames = new Set(Object.keys(snapshot.types));
7861
+ const creates = [];
7862
+ const updates = [];
7863
+ const deletes = [];
7864
+ for (const typeName of snapshotTypeNames) if (existingTypeNames.has(typeName)) updates.push(typeName);
7865
+ else creates.push(typeName);
7866
+ for (const typeName of existingTypeNames) if (!snapshotTypeNames.has(typeName)) deletes.push(typeName);
7867
+ return {
7868
+ creates,
7869
+ updates,
7870
+ deletes
7871
+ };
7872
+ }
7873
+ /**
7874
+ * Convert snapshot GQL permission policies to the proto request shape.
7875
+ * @param permission - Snapshot GQL permission policies
7876
+ * @returns Proto GQL permission
7877
+ */
7878
+ function protoGqlPermission(permission) {
7879
+ return { policies: permission.map((policy) => protoGqlPolicy(policy)) };
7880
+ }
7881
+ function protoGqlPolicy(policy) {
7882
+ const actions = [];
7883
+ for (const action of policy.actions) switch (action) {
7884
+ case "all":
7885
+ actions.push(TailorDBGQLPermission_Action.ALL);
7886
+ break;
7887
+ case "create":
7888
+ actions.push(TailorDBGQLPermission_Action.CREATE);
7889
+ break;
7890
+ case "read":
7891
+ actions.push(TailorDBGQLPermission_Action.READ);
7892
+ break;
7893
+ case "update":
7894
+ actions.push(TailorDBGQLPermission_Action.UPDATE);
7895
+ break;
7896
+ case "delete":
7897
+ actions.push(TailorDBGQLPermission_Action.DELETE);
7898
+ break;
7899
+ case "aggregate":
7900
+ actions.push(TailorDBGQLPermission_Action.AGGREGATE);
7901
+ break;
7902
+ case "bulkUpsert":
7903
+ actions.push(TailorDBGQLPermission_Action.BULK_UPSERT);
7904
+ break;
7905
+ default: throw new Error(`Unknown action: ${action}`);
7906
+ }
7907
+ let permit;
7908
+ switch (policy.permit) {
7909
+ case "allow":
7910
+ permit = TailorDBGQLPermission_Permit.ALLOW;
7911
+ break;
7912
+ case "deny":
7913
+ permit = TailorDBGQLPermission_Permit.DENY;
7914
+ break;
7915
+ default: throw new Error(`Unknown permission: ${policy.permit}`);
7916
+ }
7917
+ return {
7918
+ conditions: policy.conditions.map((cond) => protoGqlCondition(cond)),
7919
+ actions,
7920
+ permit,
7921
+ description: policy.description
7922
+ };
7923
+ }
7924
+ function protoGqlCondition(condition) {
7925
+ const [left, operator, right] = condition;
7926
+ const l = protoGqlOperand(left);
7927
+ const r = protoGqlOperand(right);
7928
+ let op;
7929
+ switch (operator) {
7930
+ case "eq":
7931
+ op = TailorDBGQLPermission_Operator.EQ;
7932
+ break;
7933
+ case "ne":
7934
+ op = TailorDBGQLPermission_Operator.NE;
7935
+ break;
7936
+ case "in":
7937
+ op = TailorDBGQLPermission_Operator.IN;
7938
+ break;
7939
+ case "nin":
7940
+ op = TailorDBGQLPermission_Operator.NIN;
7941
+ break;
7942
+ case "hasAny":
7943
+ op = TailorDBGQLPermission_Operator.HAS_ANY;
7944
+ break;
7945
+ case "nhasAny":
7946
+ op = TailorDBGQLPermission_Operator.NHAS_ANY;
7947
+ break;
7948
+ default: throw new Error(`Unknown operator: ${operator}`);
7949
+ }
7950
+ return {
7951
+ left: l,
7952
+ operator: op,
7953
+ right: r
7954
+ };
7955
+ }
7956
+ function protoGqlOperand(operand) {
7957
+ if (isSnapshotFieldRefOperand(operand)) {
7958
+ if ("user" in operand) return { kind: {
7959
+ case: "userField",
7960
+ value: operand.user
7961
+ } };
7962
+ throw new Error(`Unsupported field-ref operand in GQL permission: ${JSON.stringify(operand)} — GQL permissions only support { user } field references`);
7963
+ }
7964
+ return { kind: {
7965
+ case: "value",
7966
+ value: fromJson(ValueSchema, operand)
7967
+ } };
7968
+ }
7755
7969
 
7756
7970
  //#endregion
7757
7971
  //#region src/cli/commands/tailordb/migrate/pre-migration-schema.ts
@@ -7850,6 +8064,45 @@ function applyPreMigrationFieldAdjustments(fields, typeChanges) {
7850
8064
  }
7851
8065
  }
7852
8066
 
8067
+ //#endregion
8068
+ //#region src/cli/commands/tailordb/migrate/types.ts
8069
+ /**
8070
+ * Types for TailorDB migration execution
8071
+ */
8072
+ /**
8073
+ * Prefix added to migration numbers in labels (required because migration names start with numbers)
8074
+ */
8075
+ const MIGRATION_LABEL_PREFIX = "m";
8076
+ /**
8077
+ * Label key for storing migration state in TailorDB Service metadata
8078
+ */
8079
+ const MIGRATION_LABEL_KEY = "sdk-migration";
8080
+ /**
8081
+ * Parse migration number from label value
8082
+ * @param {string} label - Label value (e.g., "m0001")
8083
+ * @returns {number | null} Parsed number or null if invalid
8084
+ */
8085
+ function parseMigrationLabelNumber(label) {
8086
+ if (!label.startsWith("m")) return null;
8087
+ const numStr = label.slice(1);
8088
+ if (!/^\d+$/.test(numStr)) return null;
8089
+ const num = parseInt(numStr, 10);
8090
+ return num > 9999 ? null : num;
8091
+ }
8092
+ /**
8093
+ * Handle optional-to-required field change error with helpful message
8094
+ * @param {unknown} error - Error to handle
8095
+ * @param {string[]} messages - Additional messages to display
8096
+ */
8097
+ function handleOptionalToRequiredError(error, messages) {
8098
+ if (error instanceof ConnectError && error.code === Code.FailedPrecondition && error.message.includes("cannot be updated from non-required to required when records exist")) {
8099
+ logger.error("Schema change failed: Cannot change field from optional to required when records exist.");
8100
+ logger.newline();
8101
+ for (const message of messages) logger.info(message);
8102
+ }
8103
+ throw error;
8104
+ }
8105
+
7853
8106
  //#endregion
7854
8107
  //#region src/cli/commands/tailordb/migrate/bundler.ts
7855
8108
  /**
@@ -7929,28 +8182,6 @@ async function bundleMigrationScript(sourceFile, namespace, migrationNumber, env
7929
8182
  };
7930
8183
  }
7931
8184
 
7932
- //#endregion
7933
- //#region src/cli/commands/tailordb/migrate/types.ts
7934
- /**
7935
- * Prefix added to migration numbers in labels (required because migration names start with numbers)
7936
- */
7937
- const MIGRATION_LABEL_PREFIX = "m";
7938
- /**
7939
- * Label key for storing migration state in TailorDB Service metadata
7940
- */
7941
- const MIGRATION_LABEL_KEY = "sdk-migration";
7942
- /**
7943
- * Parse migration number from label value
7944
- * @param {string} label - Label value (e.g., "m0001")
7945
- * @returns {number | null} Parsed number or null if invalid
7946
- */
7947
- function parseMigrationLabelNumber(label) {
7948
- if (!label.startsWith("m")) return null;
7949
- const numStr = label.slice(1);
7950
- const num = parseInt(numStr, 10);
7951
- return isNaN(num) ? null : num;
7952
- }
7953
-
7954
8185
  //#endregion
7955
8186
  //#region src/cli/shared/script-executor.ts
7956
8187
  /**
@@ -8155,7 +8386,7 @@ var Spinner = class {
8155
8386
  #renderFrame() {
8156
8387
  this.#stream.write(SYNC_BEGIN);
8157
8388
  this.#clearDrawn();
8158
- const frame = styles.info(FRAMES[this.#frame] ?? FRAMES[0]);
8389
+ const frame = styles.info(FRAMES[this.#frame] ?? assertDefined(FRAMES[0], "spinner frames empty"));
8159
8390
  this.#frame = (this.#frame + 1) % FRAMES.length;
8160
8391
  const line = `${" ".repeat(this.#indent)}${frame} ${this.text}`;
8161
8392
  this.#stream.write(line);
@@ -8401,10 +8632,10 @@ async function getRemoteMigrationNumber(client, workspaceId, namespace) {
8401
8632
  try {
8402
8633
  const trn = resourceTrn(workspaceId, "tailordb", namespace);
8403
8634
  const { metadata } = await client.getMetadata({ trn });
8404
- const label = metadata?.labels?.["sdk-migration"];
8635
+ const label = metadata?.labels["sdk-migration"];
8405
8636
  if (!label) return null;
8406
8637
  const match = label.match(/^m(\d+)$/);
8407
- return match ? parseInt(match[1], 10) : null;
8638
+ return match ? parseInt(assertDefined(match[1], "migration label capture group missing"), 10) : null;
8408
8639
  } catch {
8409
8640
  return null;
8410
8641
  }
@@ -8619,20 +8850,7 @@ async function applyTailorDB(client, result, phase = "create-update") {
8619
8850
  } else if (phase === "delete-resources") {
8620
8851
  await Promise.all(changeSet.gqlPermission.deletes.map((del) => client.deleteTailorDBGQLPermission(del.request)));
8621
8852
  await Promise.all(changeSet.type.deletes.map((del) => client.deleteTailorDBType(del.request)));
8622
- } else if (phase === "delete-services") await Promise.all(changeSet.service.deletes.map((del) => client.deleteTailorDBService(del.request)));
8623
- }
8624
- /**
8625
- * Handle optional-to-required field change error with helpful message
8626
- * @param {unknown} error - Error to handle
8627
- * @param {string[]} messages - Additional messages to display
8628
- */
8629
- function handleOptionalToRequiredError(error, messages) {
8630
- if (error instanceof ConnectError && error.code === Code.FailedPrecondition && error.message.includes("cannot be updated from non-required to required when records exist")) {
8631
- logger.error("Schema change failed: Cannot change field from optional to required when records exist.");
8632
- logger.newline();
8633
- for (const message of messages) logger.info(message);
8634
- }
8635
- throw error;
8853
+ } else await Promise.all(changeSet.service.deletes.map((del) => client.deleteTailorDBService(del.request)));
8636
8854
  }
8637
8855
  /**
8638
8856
  * Get the set of type names affected by a migration
@@ -8746,7 +8964,7 @@ async function executeSingleMigrationPrePhase(client, changeSet, migration, tail
8746
8964
  const clonedRequest = structuredClone(create.request);
8747
8965
  clonedRequest.tailordbType = snapshotType;
8748
8966
  const typeChanges = typeName ? preMigrationChanges.get(typeName) : void 0;
8749
- if (typeChanges && typeChanges.size > 0 && clonedRequest.tailordbType?.schema?.fields) applyPreMigrationFieldAdjustments(clonedRequest.tailordbType.schema.fields, typeChanges);
8967
+ if (typeChanges && typeChanges.size > 0 && clonedRequest.tailordbType.schema?.fields) applyPreMigrationFieldAdjustments(clonedRequest.tailordbType.schema.fields, typeChanges);
8750
8968
  return client.createTailorDBType(clonedRequest);
8751
8969
  }),
8752
8970
  ...changeSet.type.creates.filter((create) => {
@@ -8777,7 +8995,7 @@ async function executeSingleMigrationPrePhase(client, changeSet, migration, tail
8777
8995
  const clonedRequest = structuredClone(update.request);
8778
8996
  clonedRequest.tailordbType = snapshotType;
8779
8997
  const typeChanges = typeName ? preMigrationChanges.get(typeName) : void 0;
8780
- if (typeChanges && typeChanges.size > 0 && clonedRequest.tailordbType?.schema?.fields) applyPreMigrationFieldAdjustments(clonedRequest.tailordbType.schema.fields, typeChanges);
8998
+ if (typeChanges && typeChanges.size > 0 && clonedRequest.tailordbType.schema?.fields) applyPreMigrationFieldAdjustments(clonedRequest.tailordbType.schema.fields, typeChanges);
8781
8999
  return client.updateTailorDBType(clonedRequest);
8782
9000
  })
8783
9001
  ]);
@@ -9075,17 +9293,14 @@ async function planTypes(client, workspaceId, tailordbs, executorUsedTypes, dele
9075
9293
  };
9076
9294
  for (const tailordb of tailordbs) {
9077
9295
  const types = filteredTypesByNamespace?.get(tailordb.namespace) ?? tailordb.types;
9078
- for (const typeName of Object.keys(types)) {
9079
- const type = types[typeName];
9080
- if (executorUsedTypes.has(typeName) && type.settings?.publishEvents === false) throw new Error(`Type "${typeName}" has publishEvents set to false, but it is used by an executor with a record trigger. Either remove the publishEvents: false setting or remove the executor trigger for this type.`);
9081
- }
9296
+ for (const [typeName, type] of Object.entries(types)) if (executorUsedTypes.has(typeName) && type.settings?.publishEvents === false) throw new Error(`Type "${typeName}" has publishEvents set to false, but it is used by an executor with a record trigger. Either remove the publishEvents: false setting or remove the executor trigger for this type.`);
9082
9297
  }
9083
9298
  for (const tailordb of tailordbs) {
9084
9299
  const existingTypes = await fetchTypes(tailordb.namespace);
9085
9300
  const existingTypesMap = new Map(existingTypes.map((type) => [type.name, type]));
9086
9301
  const types = filteredTypesByNamespace?.get(tailordb.namespace) ?? tailordb.types;
9087
- for (const typeName of Object.keys(types)) {
9088
- const tailordbType = generateTailorDBTypeManifestFromSnapshot(types[typeName], {
9302
+ for (const [typeName, tailordbTypeSnapshot] of Object.entries(types)) {
9303
+ const tailordbType = generateTailorDBTypeManifestFromSnapshot(tailordbTypeSnapshot, {
9089
9304
  publishRecordEvents: executorUsedTypes.has(typeName),
9090
9305
  namespaceGqlOperations: tailordb.config.gqlOperations
9091
9306
  });
@@ -9230,8 +9445,8 @@ async function planGqlPermissions(client, workspaceId, tailordbs, deletedService
9230
9445
  existingNameSet.add(gqlPermission.typeName);
9231
9446
  });
9232
9447
  const types = tailordb.types;
9233
- for (const typeName of Object.keys(types)) {
9234
- const gqlPermission = types[typeName].permissions?.gql;
9448
+ for (const [typeName, typeEntry] of Object.entries(types)) {
9449
+ const gqlPermission = typeEntry.permissions?.gql;
9235
9450
  if (!gqlPermission) continue;
9236
9451
  const desiredPermission = protoGqlPermission(gqlPermission);
9237
9452
  const existingPermission = existingGqlPermissions.find((entry) => entry.typeName === typeName);
@@ -9286,97 +9501,6 @@ function normalizeComparableGqlPermission(permission) {
9286
9501
  actions: (policy.actions ?? []).toSorted((left, right) => left - right)
9287
9502
  })) };
9288
9503
  }
9289
- function protoGqlPermission(permission) {
9290
- return { policies: permission.map((policy) => protoGqlPolicy(policy)) };
9291
- }
9292
- function protoGqlPolicy(policy) {
9293
- const actions = [];
9294
- for (const action of policy.actions) switch (action) {
9295
- case "all":
9296
- actions.push(TailorDBGQLPermission_Action.ALL);
9297
- break;
9298
- case "create":
9299
- actions.push(TailorDBGQLPermission_Action.CREATE);
9300
- break;
9301
- case "read":
9302
- actions.push(TailorDBGQLPermission_Action.READ);
9303
- break;
9304
- case "update":
9305
- actions.push(TailorDBGQLPermission_Action.UPDATE);
9306
- break;
9307
- case "delete":
9308
- actions.push(TailorDBGQLPermission_Action.DELETE);
9309
- break;
9310
- case "aggregate":
9311
- actions.push(TailorDBGQLPermission_Action.AGGREGATE);
9312
- break;
9313
- case "bulkUpsert":
9314
- actions.push(TailorDBGQLPermission_Action.BULK_UPSERT);
9315
- break;
9316
- default: throw new Error(`Unknown action: ${action}`);
9317
- }
9318
- let permit;
9319
- switch (policy.permit) {
9320
- case "allow":
9321
- permit = TailorDBGQLPermission_Permit.ALLOW;
9322
- break;
9323
- case "deny":
9324
- permit = TailorDBGQLPermission_Permit.DENY;
9325
- break;
9326
- default: throw new Error(`Unknown permission: ${policy.permit}`);
9327
- }
9328
- return {
9329
- conditions: policy.conditions.map((cond) => protoGqlCondition(cond)),
9330
- actions,
9331
- permit,
9332
- description: policy.description
9333
- };
9334
- }
9335
- function protoGqlCondition(condition) {
9336
- const [left, operator, right] = condition;
9337
- const l = protoGqlOperand(left);
9338
- const r = protoGqlOperand(right);
9339
- let op;
9340
- switch (operator) {
9341
- case "eq":
9342
- op = TailorDBGQLPermission_Operator.EQ;
9343
- break;
9344
- case "ne":
9345
- op = TailorDBGQLPermission_Operator.NE;
9346
- break;
9347
- case "in":
9348
- op = TailorDBGQLPermission_Operator.IN;
9349
- break;
9350
- case "nin":
9351
- op = TailorDBGQLPermission_Operator.NIN;
9352
- break;
9353
- case "hasAny":
9354
- op = TailorDBGQLPermission_Operator.HAS_ANY;
9355
- break;
9356
- case "nhasAny":
9357
- op = TailorDBGQLPermission_Operator.NHAS_ANY;
9358
- break;
9359
- default: throw new Error(`Unknown operator: ${operator}`);
9360
- }
9361
- return {
9362
- left: l,
9363
- operator: op,
9364
- right: r
9365
- };
9366
- }
9367
- function protoGqlOperand(operand) {
9368
- if (isSnapshotFieldRefOperand(operand)) {
9369
- if ("user" in operand) return { kind: {
9370
- case: "userField",
9371
- value: operand.user
9372
- } };
9373
- throw new Error(`Unsupported field-ref operand in GQL permission: ${JSON.stringify(operand)} — GQL permissions only support { user } field references`);
9374
- }
9375
- return { kind: {
9376
- case: "value",
9377
- value: fromJson(ValueSchema, operand)
9378
- } };
9379
- }
9380
9504
  /**
9381
9505
  * Check if there are schema differences between migration snapshots and local definitions
9382
9506
  * @param {ReadonlyMap<string, Record<string, TailorDBSnapshotType>>} typesByNamespace - Snapshot-shaped local types by namespace
@@ -9454,28 +9578,30 @@ async function applyWorkflow(client, result, phase = "create-update") {
9454
9578
  const jobFunctionVersions = await registerJobFunctions(client, changeSet, appName, appId, result.unchangedWorkflowJobNames);
9455
9579
  await Promise.all([...changeSet.creates.map(async (create) => {
9456
9580
  const filteredVersions = filterJobFunctionVersions(jobFunctionVersions, create.usedJobNames);
9581
+ const shape = buildWorkflowValidationShape(create.workspaceId, create.workflow);
9457
9582
  await client.createWorkflow({
9458
- workspaceId: create.workspaceId,
9459
- workflowName: create.workflow.name,
9460
- mainJobFunctionName: create.workflow.mainJob.name,
9461
- jobFunctions: filteredVersions,
9462
- ...create.workflow.retryPolicy && { retryPolicy: toRetryPolicy(create.workflow.retryPolicy) },
9463
- ...create.workflow.concurrencyPolicy && { concurrencyPolicy: toConcurrencyPolicy(create.workflow.concurrencyPolicy) }
9583
+ workspaceId: shape.workspaceId,
9584
+ workflowName: shape.workflowName,
9585
+ mainJobFunctionName: shape.mainJobFunctionName,
9586
+ retryPolicy: shape.retryPolicy,
9587
+ concurrencyPolicy: shape.concurrencyPolicy,
9588
+ jobFunctions: filteredVersions
9464
9589
  });
9465
9590
  await client.setMetadata(create.metaRequest);
9466
9591
  }), ...changeSet.updates.map(async (update) => {
9467
9592
  const filteredVersions = filterJobFunctionVersions(jobFunctionVersions, update.usedJobNames);
9593
+ const shape = buildWorkflowValidationShape(update.workspaceId, update.workflow);
9468
9594
  await client.updateWorkflow({
9469
- workspaceId: update.workspaceId,
9470
- workflowName: update.workflow.name,
9471
- mainJobFunctionName: update.workflow.mainJob.name,
9472
- jobFunctions: filteredVersions,
9473
- ...update.workflow.retryPolicy && { retryPolicy: toRetryPolicy(update.workflow.retryPolicy) },
9474
- ...update.workflow.concurrencyPolicy && { concurrencyPolicy: toConcurrencyPolicy(update.workflow.concurrencyPolicy) }
9595
+ workspaceId: shape.workspaceId,
9596
+ workflowName: shape.workflowName,
9597
+ mainJobFunctionName: shape.mainJobFunctionName,
9598
+ retryPolicy: shape.retryPolicy,
9599
+ concurrencyPolicy: shape.concurrencyPolicy,
9600
+ jobFunctions: filteredVersions
9475
9601
  });
9476
9602
  await client.setMetadata(update.metaRequest);
9477
9603
  })]);
9478
- } else if (phase === "delete") {
9604
+ } else {
9479
9605
  await deleteAllSettled(changeSet.deletes.map((del) => ({
9480
9606
  resourceType: "workflow",
9481
9607
  resourceName: del.name,
@@ -9499,12 +9625,8 @@ async function deleteAllSettled(operations) {
9499
9625
  const errors = [];
9500
9626
  results.forEach((result, index) => {
9501
9627
  if (result.status === "fulfilled") return;
9502
- const operation = operations[index];
9628
+ const operation = assertDefined(operations[index], "operation missing at index");
9503
9629
  const error = result.reason;
9504
- if (!operation) {
9505
- errors.push(error);
9506
- return;
9507
- }
9508
9630
  if (error instanceof ConnectError && error.code === Code.NotFound) return;
9509
9631
  if (error instanceof ConnectError && error.code === Code.FailedPrecondition) {
9510
9632
  logger.warn(`Skipped deleting ${operation.resourceType} "${operation.resourceName}" because it is still referenced.`);
@@ -9615,6 +9737,21 @@ function toConcurrencyPolicy(policy) {
9615
9737
  return { maxConcurrentExecutions: policy.maxConcurrentExecutions };
9616
9738
  }
9617
9739
  /**
9740
+ * Build the plan-time validation init shape for a workflow.
9741
+ * @param workspaceId - Workspace ID
9742
+ * @param workflow - Parsed workflow object
9743
+ * @returns Init shape suitable for validating against CreateWorkflowRequestSchema and UpdateWorkflowRequestSchema
9744
+ */
9745
+ function buildWorkflowValidationShape(workspaceId, workflow) {
9746
+ return {
9747
+ workspaceId,
9748
+ workflowName: workflow.name,
9749
+ mainJobFunctionName: workflow.mainJob.name,
9750
+ ...workflow.retryPolicy && { retryPolicy: toRetryPolicy(workflow.retryPolicy) },
9751
+ ...workflow.concurrencyPolicy && { concurrencyPolicy: toConcurrencyPolicy(workflow.concurrencyPolicy) }
9752
+ };
9753
+ }
9754
+ /**
9618
9755
  * Plan workflow changes and job functions based on current and desired state.
9619
9756
  * @param client - Operator client instance
9620
9757
  * @param workspaceId - Workspace ID
@@ -9814,6 +9951,191 @@ function normalizeRetryPolicyForCompare(policy) {
9814
9951
  };
9815
9952
  }
9816
9953
 
9954
+ //#endregion
9955
+ //#region src/cli/commands/deploy/validate-plan.ts
9956
+ function validateItems(params) {
9957
+ const { validator, schema, kind, action, items, requestKey, violations } = params;
9958
+ for (const item of items) {
9959
+ const init = item[requestKey];
9960
+ const msg = create(schema, init);
9961
+ const result = validator.validate(schema, msg);
9962
+ if (result.kind === "invalid") for (const v of result.violations) violations.push({
9963
+ kind,
9964
+ name: item.name,
9965
+ action,
9966
+ fieldPath: v.field.length > 0 ? pathToString(v.field) : "(message)",
9967
+ message: v.message
9968
+ });
9969
+ else if (result.kind === "error") logger.warn(`Could not validate ${kind} "${item.name}" (${action}): ${result.error.message}`);
9970
+ }
9971
+ }
9972
+ /**
9973
+ * Validate all plan-time create/update requests against buf.validate constraints embedded in the
9974
+ * generated proto descriptors.
9975
+ *
9976
+ * Collections not validated: idp client, tailorDB gqlPermission, functionRegistry — no
9977
+ * buf.validate annotations.
9978
+ * Application cors is excluded: static-website URL placeholders are resolved at apply time
9979
+ * and a bare cors array carries no constraint that would false-positive when omitted.
9980
+ * Workflow jobFunctions map excluded: versions are registered at apply time (registerJobFunctions)
9981
+ * and the map field carries no min_items constraint. Job names are validated separately via
9982
+ * CreateWorkflowJobFunctionRequestSchema using usedJobNames from the workflow change set.
9983
+ * auth idpConfig.config (provider oneof) is absent at plan time for BuiltInIdP but carries no
9984
+ * required constraint — the request is validated as-is from the changeset.
9985
+ *
9986
+ * @param input - Plan results from the plan phase
9987
+ */
9988
+ async function validatePlan(input) {
9989
+ const { tailorDB, staticWebsite, idp, auth, pipeline, app, executor, workflow, secretManager } = input;
9990
+ const validator = createValidator();
9991
+ const violations = [];
9992
+ function creates(schema, kind, items) {
9993
+ validateItems({
9994
+ validator,
9995
+ schema,
9996
+ kind,
9997
+ action: "create",
9998
+ items,
9999
+ requestKey: "request",
10000
+ violations
10001
+ });
10002
+ }
10003
+ function updates(schema, kind, items) {
10004
+ validateItems({
10005
+ validator,
10006
+ schema,
10007
+ kind,
10008
+ action: "update",
10009
+ items,
10010
+ requestKey: "request",
10011
+ violations
10012
+ });
10013
+ }
10014
+ function replaces(schema, kind, items) {
10015
+ validateItems({
10016
+ validator,
10017
+ schema,
10018
+ kind,
10019
+ action: "replace",
10020
+ items,
10021
+ requestKey: "createRequest",
10022
+ violations
10023
+ });
10024
+ }
10025
+ creates(CreateTailorDBServiceRequestSchema, "TailorDB service", tailorDB.changeSet.service.creates);
10026
+ creates(CreateTailorDBTypeRequestSchema, "TailorDB type", tailorDB.changeSet.type.creates);
10027
+ updates(UpdateTailorDBTypeRequestSchema, "TailorDB type", tailorDB.changeSet.type.updates);
10028
+ creates(CreateStaticWebsiteRequestSchema, "StaticWebsite", staticWebsite.changeSet.creates);
10029
+ updates(UpdateStaticWebsiteRequestSchema, "StaticWebsite", staticWebsite.changeSet.updates);
10030
+ creates(AddCustomDomainRequestSchema, "StaticWebsite custom domain", staticWebsite.customDomainChangeSet.creates);
10031
+ creates(CreateIdPServiceRequestSchema, "IdP service", idp.changeSet.service.creates);
10032
+ updates(UpdateIdPServiceRequestSchema, "IdP service", idp.changeSet.service.updates);
10033
+ const idpClientVaultItems = [...idp.changeSet.client.creates.map((c) => ({
10034
+ clientName: c.request.client?.name ?? "",
10035
+ namespaceName: c.request.namespaceName ?? "",
10036
+ workspaceId: c.request.workspaceId ?? ""
10037
+ })), ...idp.changeSet.client.updates.map((u) => ({
10038
+ clientName: u.name,
10039
+ namespaceName: u.namespaceName,
10040
+ workspaceId: u.workspaceId
10041
+ }))];
10042
+ creates(CreateSecretManagerVaultRequestSchema, "IdP client secret", idpClientVaultItems.map((item) => ({
10043
+ name: item.clientName,
10044
+ request: {
10045
+ workspaceId: item.workspaceId,
10046
+ secretmanagerVaultName: idpClientVaultName(item.namespaceName, item.clientName)
10047
+ }
10048
+ })));
10049
+ creates(CreateSecretManagerSecretRequestSchema, "IdP client secret", idpClientVaultItems.map((item) => ({
10050
+ name: item.clientName,
10051
+ request: {
10052
+ workspaceId: item.workspaceId,
10053
+ secretmanagerVaultName: idpClientVaultName(item.namespaceName, item.clientName),
10054
+ secretmanagerSecretName: idpClientSecretName(item.namespaceName, item.clientName)
10055
+ }
10056
+ })));
10057
+ creates(CreateAuthServiceRequestSchema, "Auth service", auth.changeSet.service.creates);
10058
+ updates(UpdateAuthServiceRequestSchema, "Auth service", auth.changeSet.service.updates);
10059
+ creates(CreateAuthIDPConfigRequestSchema, "Auth IDP config", auth.changeSet.idpConfig.creates);
10060
+ updates(UpdateAuthIDPConfigRequestSchema, "Auth IDP config", auth.changeSet.idpConfig.updates);
10061
+ creates(CreateUserProfileConfigRequestSchema, "Auth user profile config", auth.changeSet.userProfileConfig.creates);
10062
+ updates(UpdateUserProfileConfigRequestSchema, "Auth user profile config", auth.changeSet.userProfileConfig.updates);
10063
+ creates(CreateTenantConfigRequestSchema, "Auth tenant config", auth.changeSet.tenantConfig.creates);
10064
+ updates(UpdateTenantConfigRequestSchema, "Auth tenant config", auth.changeSet.tenantConfig.updates);
10065
+ creates(CreateAuthMachineUserRequestSchema, "Auth machine user", auth.changeSet.machineUser.creates);
10066
+ updates(UpdateAuthMachineUserRequestSchema, "Auth machine user", auth.changeSet.machineUser.updates);
10067
+ creates(CreateAuthHookRequestSchema, "Auth hook", auth.changeSet.authHook.creates);
10068
+ updates(UpdateAuthHookRequestSchema, "Auth hook", auth.changeSet.authHook.updates);
10069
+ creates(CreateAuthSCIMConfigRequestSchema, "Auth SCIM config", auth.changeSet.scim.creates);
10070
+ updates(UpdateAuthSCIMConfigRequestSchema, "Auth SCIM config", auth.changeSet.scim.updates);
10071
+ creates(CreateAuthSCIMResourceRequestSchema, "Auth SCIM resource", auth.changeSet.scimResource.creates);
10072
+ updates(UpdateAuthSCIMResourceRequestSchema, "Auth SCIM resource", auth.changeSet.scimResource.updates);
10073
+ creates(CreateAuthOAuth2ClientRequestSchema, "OAuth2 client", auth.changeSet.oauth2Client.creates);
10074
+ updates(UpdateAuthOAuth2ClientRequestSchema, "OAuth2 client", auth.changeSet.oauth2Client.updates);
10075
+ replaces(CreateAuthOAuth2ClientRequestSchema, "OAuth2 client", auth.changeSet.oauth2Client.replaces);
10076
+ creates(CreatePipelineServiceRequestSchema, "Pipeline service", pipeline.changeSet.service.creates);
10077
+ updates(UpdatePipelineServiceRequestSchema, "Pipeline service", pipeline.changeSet.service.updates);
10078
+ creates(CreatePipelineResolverRequestSchema, "Resolver", pipeline.changeSet.resolver.creates);
10079
+ updates(UpdatePipelineResolverRequestSchema, "Resolver", pipeline.changeSet.resolver.updates);
10080
+ creates(CreateExecutorExecutorRequestSchema, "Executor", executor.changeSet.creates);
10081
+ updates(UpdateExecutorExecutorRequestSchema, "Executor", executor.changeSet.updates);
10082
+ creates(CreateWorkflowRequestSchema, "Workflow", workflow.changeSet.creates.map((item) => ({
10083
+ name: item.name,
10084
+ request: buildWorkflowValidationShape(item.workspaceId, item.workflow)
10085
+ })));
10086
+ updates(UpdateWorkflowRequestSchema, "Workflow", workflow.changeSet.updates.map((item) => ({
10087
+ name: item.name,
10088
+ request: buildWorkflowValidationShape(item.workspaceId, item.workflow)
10089
+ })));
10090
+ const workflowJobNameWorkspaceId = workflow.changeSet.creates[0]?.workspaceId ?? workflow.changeSet.updates[0]?.workspaceId ?? "";
10091
+ if (workflowJobNameWorkspaceId) {
10092
+ const allJobNames = /* @__PURE__ */ new Set();
10093
+ for (const item of [...workflow.changeSet.creates, ...workflow.changeSet.updates]) for (const jobName of item.usedJobNames) allJobNames.add(jobName);
10094
+ for (const jobName of workflow.unchangedWorkflowJobNames) allJobNames.add(jobName);
10095
+ creates(CreateWorkflowJobFunctionRequestSchema, "Workflow job function", [...allJobNames].map((jobName) => ({
10096
+ name: jobName,
10097
+ request: {
10098
+ workspaceId: workflowJobNameWorkspaceId,
10099
+ jobFunctionName: jobName,
10100
+ scriptRef: jobName
10101
+ }
10102
+ })));
10103
+ }
10104
+ creates(CreateSecretManagerVaultRequestSchema, "Secret Manager vault", secretManager.vaultChangeSet.creates.map((item) => ({
10105
+ name: item.name,
10106
+ request: vaultCreateRequest(item)
10107
+ })));
10108
+ creates(CreateSecretManagerSecretRequestSchema, "Secret Manager secret", secretManager.secretChangeSet.creates.map((item) => ({
10109
+ name: item.name,
10110
+ request: secretCreateRequest(item)
10111
+ })));
10112
+ updates(UpdateSecretManagerSecretRequestSchema, "Secret Manager secret", secretManager.secretChangeSet.updates.map((item) => ({
10113
+ name: item.name,
10114
+ request: secretUpdateRequest(item)
10115
+ })));
10116
+ creates(CreateApplicationRequestSchema, "Application", app.creates.map((item) => ({
10117
+ name: item.name,
10118
+ request: {
10119
+ ...item.request,
10120
+ cors: void 0
10121
+ }
10122
+ })));
10123
+ updates(UpdateApplicationRequestSchema, "Application", [...app.updates, ...app.unchanged].map((item) => ({
10124
+ name: item.name,
10125
+ request: {
10126
+ ...item.request,
10127
+ cors: void 0
10128
+ }
10129
+ })));
10130
+ creates(CreateAuthConnectionRequestSchema, "Auth connection", auth.changeSet.connection.creates);
10131
+ replaces(CreateAuthConnectionRequestSchema, "Auth connection", auth.changeSet.connection.replaces);
10132
+ if (violations.length === 0) return;
10133
+ const resourceNames = new Set(violations.map((v) => `${v.kind}:${v.name}`));
10134
+ logger.error(`Pre-flight validation found ${violations.length} violation(s) across ${resourceNames.size} resource(s):`);
10135
+ for (const v of violations) logger.log(` ${styles.resourceType(v.kind)} ${styles.resourceName(v.name)} (${v.action}) — ${styles.bold(v.fieldPath)}: ${v.message}`);
10136
+ throw new Error(`${violations.length} validation error(s) found in ${resourceNames.size} resource(s)`);
10137
+ }
10138
+
9817
10139
  //#endregion
9818
10140
  //#region src/cli/commands/deploy/deploy.ts
9819
10141
  /**
@@ -9831,7 +10153,10 @@ function collectIdpUserTriggerTargets(application) {
9831
10153
  for (const executor of Object.values(application.executorService?.executors ?? {})) {
9832
10154
  if (executor.trigger.kind !== "idpUser") continue;
9833
10155
  if (executor.trigger.idp != null) targets.add(executor.trigger.idp);
9834
- else if (idps.length === 1) targets.add(idps[0].name);
10156
+ else if (idps.length === 1) {
10157
+ const [idp] = idps;
10158
+ if (idp) targets.add(idp.name);
10159
+ }
9835
10160
  }
9836
10161
  return targets;
9837
10162
  }
@@ -9914,7 +10239,7 @@ function printPlanResults(results) {
9914
10239
  ...formatChangeSetEntries(results.auth.changeSet.oauth2Client, ["oauth2Client"], namespaceOf),
9915
10240
  ...formatChangeSetEntries(results.auth.changeSet.scim, ["scimConfig"], namespaceOf),
9916
10241
  ...formatChangeSetEntries(results.auth.changeSet.scimResource, ["scimResource"], namespaceOf),
9917
- ...results.auth.changeSet.connection ? formatChangeSetEntries(results.auth.changeSet.connection, ["connection"], namespaceOf) : []
10242
+ ...formatChangeSetEntries(results.auth.changeSet.connection, ["connection"], namespaceOf)
9918
10243
  ];
9919
10244
  const { otherChanges: otherFunctionRegistryChanges } = splitFunctionRegistryChanges(results.functionRegistry.changeSet);
9920
10245
  printGroupedDisplaySection(results.functionRegistry.changeSet.title, formatChangeSetEntries(otherFunctionRegistryChanges));
@@ -10056,10 +10381,7 @@ async function deploy(options) {
10056
10381
  };
10057
10382
  });
10058
10383
  if (buildOnly) return { bundledScripts };
10059
- const client = await initOperatorClient(await loadAccessToken({
10060
- useProfile: true,
10061
- profile: options?.profile
10062
- }));
10384
+ const client = await initOperatorClient(await loadAccessToken({ profile: options?.profile }));
10063
10385
  const workspaceId = await loadWorkspaceId({
10064
10386
  workspaceId: options?.workspaceId,
10065
10387
  profile: options?.profile
@@ -10204,6 +10526,19 @@ async function deploy(options) {
10204
10526
  workflow,
10205
10527
  secretManager
10206
10528
  });
10529
+ if (options?.noValidate) logger.warn("Client-side validation skipped (--no-validate).");
10530
+ else await validatePlan({
10531
+ functionRegistry,
10532
+ tailorDB,
10533
+ staticWebsite,
10534
+ idp,
10535
+ auth,
10536
+ pipeline,
10537
+ app,
10538
+ executor,
10539
+ workflow,
10540
+ secretManager
10541
+ });
10207
10542
  if (dryRun) {
10208
10543
  logger.info("Dry run enabled. No changes applied.");
10209
10544
  return;
@@ -10566,10 +10901,7 @@ async function resolveExecutor(client, workspaceId, name) {
10566
10901
  }
10567
10902
  async function getExecutor(options) {
10568
10903
  const name = "name" in options ? options.name : options.executor.name;
10569
- const client = await initOperatorClient(await loadAccessToken({
10570
- useProfile: true,
10571
- profile: options.profile
10572
- }));
10904
+ const client = await initOperatorClient(await loadAccessToken({ profile: options.profile }));
10573
10905
  const workspaceId = await loadWorkspaceId({
10574
10906
  workspaceId: options.workspaceId,
10575
10907
  profile: options.profile
@@ -10818,10 +11150,7 @@ function parseStatus(status) {
10818
11150
  }
10819
11151
  async function listWorkflowExecutions(options) {
10820
11152
  const workflowName = options && "workflowName" in options ? options.workflowName : options && "workflow" in options ? options.workflow?.name : void 0;
10821
- const client = await initOperatorClient(await loadAccessToken({
10822
- useProfile: true,
10823
- profile: options?.profile
10824
- }));
11153
+ const client = await initOperatorClient(await loadAccessToken({ profile: options?.profile }));
10825
11154
  const workspaceId = await loadWorkspaceId({
10826
11155
  workspaceId: options?.workspaceId,
10827
11156
  profile: options?.profile
@@ -10858,10 +11187,7 @@ async function listWorkflowExecutions(options) {
10858
11187
  * @returns Workflow execution with optional logs
10859
11188
  */
10860
11189
  async function getWorkflowExecution(options) {
10861
- const client = await initOperatorClient(await loadAccessToken({
10862
- useProfile: true,
10863
- profile: options.profile
10864
- }));
11190
+ const client = await initOperatorClient(await loadAccessToken({ profile: options.profile }));
10865
11191
  const workspaceId = await loadWorkspaceId({
10866
11192
  workspaceId: options.workspaceId,
10867
11193
  profile: options.profile
@@ -11046,10 +11372,7 @@ async function resolveWorkflow(client, workspaceId, name) {
11046
11372
  }
11047
11373
  async function getWorkflow(options) {
11048
11374
  const name = "name" in options ? options.name : options.workflow.name;
11049
- const client = await initOperatorClient(await loadAccessToken({
11050
- useProfile: true,
11051
- profile: options.profile
11052
- }));
11375
+ const client = await initOperatorClient(await loadAccessToken({ profile: options.profile }));
11053
11376
  const workspaceId = await loadWorkspaceId({
11054
11377
  workspaceId: options.workspaceId,
11055
11378
  profile: options.profile
@@ -11193,10 +11516,7 @@ async function startWorkflowCore(options) {
11193
11516
  }
11194
11517
  }
11195
11518
  async function startWorkflowByName(options) {
11196
- const client = await initOperatorClient(await loadAccessToken({
11197
- useProfile: true,
11198
- profile: options.profile
11199
- }));
11519
+ const client = await initOperatorClient(await loadAccessToken({ profile: options.profile }));
11200
11520
  const workspaceId = await loadWorkspaceId({
11201
11521
  workspaceId: options.workspaceId,
11202
11522
  profile: options.profile
@@ -11222,10 +11542,7 @@ async function startWorkflowByName(options) {
11222
11542
  async function startWorkflow(options) {
11223
11543
  if ("name" in options) return await startWorkflowByName(options);
11224
11544
  return await startWorkflowCore({
11225
- client: await initOperatorClient(await loadAccessToken({
11226
- useProfile: true,
11227
- profile: options.profile
11228
- })),
11545
+ client: await initOperatorClient(await loadAccessToken({ profile: options.profile })),
11229
11546
  workspaceId: await loadWorkspaceId({
11230
11547
  workspaceId: options.workspaceId,
11231
11548
  profile: options.profile
@@ -11288,10 +11605,7 @@ function formatTime(date) {
11288
11605
  }
11289
11606
  async function listExecutorJobs(options) {
11290
11607
  const executorName = "executorName" in options ? options.executorName : options.executor.name;
11291
- const client = await initOperatorClient(await loadAccessToken({
11292
- useProfile: true,
11293
- profile: options.profile
11294
- }));
11608
+ const client = await initOperatorClient(await loadAccessToken({ profile: options.profile }));
11295
11609
  const workspaceId = await loadWorkspaceId({
11296
11610
  workspaceId: options.workspaceId,
11297
11611
  profile: options.profile
@@ -11329,10 +11643,7 @@ async function listExecutorJobs(options) {
11329
11643
  }
11330
11644
  async function getExecutorJob(options) {
11331
11645
  const executorName = "executorName" in options ? options.executorName : options.executor.name;
11332
- const client = await initOperatorClient(await loadAccessToken({
11333
- useProfile: true,
11334
- profile: options.profile
11335
- }));
11646
+ const client = await initOperatorClient(await loadAccessToken({ profile: options.profile }));
11336
11647
  const workspaceId = await loadWorkspaceId({
11337
11648
  workspaceId: options.workspaceId,
11338
11649
  profile: options.profile
@@ -11369,10 +11680,7 @@ async function getExecutorJob(options) {
11369
11680
  }
11370
11681
  async function watchExecutorJob(options) {
11371
11682
  const executorName = "executorName" in options ? options.executorName : options.executor.name;
11372
- const client = await initOperatorClient(await loadAccessToken({
11373
- useProfile: true,
11374
- profile: options.profile
11375
- }));
11683
+ const client = await initOperatorClient(await loadAccessToken({ profile: options.profile }));
11376
11684
  const workspaceId = await loadWorkspaceId({
11377
11685
  workspaceId: options.workspaceId,
11378
11686
  profile: options.profile
@@ -11672,10 +11980,7 @@ const jobsCommand = defineAppCommand({
11672
11980
  * @returns List of executors
11673
11981
  */
11674
11982
  async function listExecutors(options) {
11675
- const client = await initOperatorClient(await loadAccessToken({
11676
- useProfile: true,
11677
- profile: options?.profile
11678
- }));
11983
+ const client = await initOperatorClient(await loadAccessToken({ profile: options?.profile }));
11679
11984
  const workspaceId = await loadWorkspaceId({
11680
11985
  workspaceId: options?.workspaceId,
11681
11986
  profile: options?.profile
@@ -11748,10 +12053,7 @@ const headerArg = z.string().superRefine((val, ctx) => {
11748
12053
  };
11749
12054
  }).refine((h) => h.key.length > 0, { message: "Header name cannot be empty" });
11750
12055
  async function triggerExecutorByName(options) {
11751
- const client = await initOperatorClient(await loadAccessToken({
11752
- useProfile: true,
11753
- profile: options.profile
11754
- }));
12056
+ const client = await initOperatorClient(await loadAccessToken({ profile: options.profile }));
11755
12057
  const workspaceId = await loadWorkspaceId({
11756
12058
  workspaceId: options.workspaceId,
11757
12059
  profile: options.profile
@@ -11847,10 +12149,7 @@ The \`--logs\` option displays logs from the downstream execution when available
11847
12149
  }).strict(),
11848
12150
  run: async (args) => {
11849
12151
  await assertWritable({ profile: args.profile });
11850
- const client = await initOperatorClient(await loadAccessToken({
11851
- useProfile: true,
11852
- profile: args.profile
11853
- }));
12152
+ const client = await initOperatorClient(await loadAccessToken({ profile: args.profile }));
11854
12153
  const workspaceId = await loadWorkspaceId({
11855
12154
  workspaceId: args["workspace-id"],
11856
12155
  profile: args.profile
@@ -11938,10 +12237,7 @@ The \`--logs\` option displays logs from the downstream execution when available
11938
12237
  * @returns List of webhook executors with URLs
11939
12238
  */
11940
12239
  async function listWebhookExecutors(options) {
11941
- const client = await initOperatorClient(await loadAccessToken({
11942
- useProfile: true,
11943
- profile: options?.profile
11944
- }));
12240
+ const client = await initOperatorClient(await loadAccessToken({ profile: options?.profile }));
11945
12241
  const workspaceId = await loadWorkspaceId({
11946
12242
  workspaceId: options?.workspaceId,
11947
12243
  profile: options?.profile
@@ -12016,12 +12312,9 @@ const getFunctionRegistryOptionsSchema = z.object({
12016
12312
  });
12017
12313
  async function loadOptions$12(options) {
12018
12314
  const result = getFunctionRegistryOptionsSchema.safeParse(options);
12019
- if (!result.success) throw new Error(result.error.issues[0].message);
12315
+ if (!result.success) throw new Error(assertDefined(result.error.issues[0], "Zod returned no issues").message);
12020
12316
  return {
12021
- client: await initOperatorClient(await loadAccessToken({
12022
- useProfile: true,
12023
- profile: result.data.profile
12024
- })),
12317
+ client: await initOperatorClient(await loadAccessToken({ profile: result.data.profile })),
12025
12318
  workspaceId: await loadWorkspaceId({
12026
12319
  workspaceId: result.data.workspaceId,
12027
12320
  profile: result.data.profile
@@ -12084,12 +12377,9 @@ const listFunctionRegistriesOptionsSchema = z.object({
12084
12377
  });
12085
12378
  async function loadOptions$11(options) {
12086
12379
  const result = listFunctionRegistriesOptionsSchema.safeParse(options);
12087
- if (!result.success) throw new Error(result.error.issues[0].message);
12380
+ if (!result.success) throw new Error(assertDefined(result.error.issues[0], "Zod returned no issues").message);
12088
12381
  return {
12089
- client: await initOperatorClient(await loadAccessToken({
12090
- useProfile: true,
12091
- profile: result.data.profile
12092
- })),
12382
+ client: await initOperatorClient(await loadAccessToken({ profile: result.data.profile })),
12093
12383
  workspaceId: await loadWorkspaceId({
12094
12384
  workspaceId: result.data.workspaceId,
12095
12385
  profile: result.data.profile
@@ -12584,13 +12874,13 @@ function createGenerationManager(params) {
12584
12874
  };
12585
12875
  }
12586
12876
  async function processTailorDBNamespace(gen, namespace, typeInfo) {
12587
- const results = generatorResults[gen.id];
12877
+ const results = assertDefined(generatorResults[gen.id], `generator result not initialized for ${gen.id}`);
12588
12878
  results.tailordbResults[namespace] = {};
12589
12879
  if (!gen.processType) return;
12590
12880
  const processType = gen.processType;
12591
12881
  await Promise.allSettled(Object.entries(typeInfo.types).map(async ([typeName, type]) => {
12592
12882
  try {
12593
- results.tailordbResults[namespace][typeName] = await processType({
12883
+ assertDefined(results.tailordbResults[namespace], `tailordb results not initialized for namespace ${namespace}`)[typeName] = await processType({
12594
12884
  type,
12595
12885
  namespace,
12596
12886
  source: typeInfo.sourceInfo[typeName],
@@ -12613,13 +12903,13 @@ function createGenerationManager(params) {
12613
12903
  else results.tailordbNamespaceResults[namespace] = results.tailordbResults[namespace];
12614
12904
  }
12615
12905
  async function processResolverNamespace(gen, namespace, resolvers) {
12616
- const results = generatorResults[gen.id];
12906
+ const results = assertDefined(generatorResults[gen.id], `generator result not initialized for ${gen.id}`);
12617
12907
  results.resolverResults[namespace] = {};
12618
12908
  if (!gen.processResolver) return;
12619
12909
  const processResolver = gen.processResolver;
12620
12910
  await Promise.allSettled(Object.entries(resolvers).map(async ([resolverName, resolver]) => {
12621
12911
  try {
12622
- results.resolverResults[namespace][resolverName] = await processResolver({
12912
+ assertDefined(results.resolverResults[namespace], `resolver results not initialized for namespace ${namespace}`)[resolverName] = await processResolver({
12623
12913
  resolver,
12624
12914
  namespace
12625
12915
  });
@@ -12640,7 +12930,7 @@ function createGenerationManager(params) {
12640
12930
  else results.resolverNamespaceResults[namespace] = results.resolverResults[namespace];
12641
12931
  }
12642
12932
  async function processExecutors(gen) {
12643
- const results = generatorResults[gen.id];
12933
+ const results = assertDefined(generatorResults[gen.id], `generator result not initialized for ${gen.id}`);
12644
12934
  if (!gen.processExecutor) return;
12645
12935
  const processExecutor = gen.processExecutor;
12646
12936
  await Promise.allSettled(Object.entries(services.executor).map(async ([executorId, executor]) => {
@@ -12653,7 +12943,7 @@ function createGenerationManager(params) {
12653
12943
  }));
12654
12944
  }
12655
12945
  async function aggregate(gen) {
12656
- const results = generatorResults[gen.id];
12946
+ const results = assertDefined(generatorResults[gen.id], `generator result not initialized for ${gen.id}`);
12657
12947
  const tailordbResults = [];
12658
12948
  const resolverResults = [];
12659
12949
  for (const [namespace, types] of Object.entries(results.tailordbNamespaceResults)) tailordbResults.push({
@@ -12711,7 +13001,7 @@ function createGenerationManager(params) {
12711
13001
  let result;
12712
13002
  switch (hookName) {
12713
13003
  case "onTailorDBReady":
12714
- result = await plugin.onTailorDBReady({
13004
+ result = await assertDefined(plugin.onTailorDBReady, "plugin.onTailorDBReady hook missing")({
12715
13005
  tailordb,
12716
13006
  auth,
12717
13007
  baseDir: pluginBaseDir,
@@ -12720,7 +13010,7 @@ function createGenerationManager(params) {
12720
13010
  });
12721
13011
  break;
12722
13012
  case "onResolverReady":
12723
- result = await plugin.onResolverReady({
13013
+ result = await assertDefined(plugin.onResolverReady, "plugin.onResolverReady hook missing")({
12724
13014
  tailordb,
12725
13015
  resolvers: buildResolverData(),
12726
13016
  auth,
@@ -12730,7 +13020,7 @@ function createGenerationManager(params) {
12730
13020
  });
12731
13021
  break;
12732
13022
  case "onExecutorReady":
12733
- result = await plugin.onExecutorReady({
13023
+ result = await assertDefined(plugin.onExecutorReady, "plugin.onExecutorReady hook missing")({
12734
13024
  tailordb,
12735
13025
  resolvers: buildResolverData(),
12736
13026
  executors: { ...services.executor },
@@ -12844,7 +13134,7 @@ function createGenerationManager(params) {
12844
13134
  ...process.env,
12845
13135
  TAILOR_WATCH_GENERATION: (parseInt(process.env.TAILOR_WATCH_GENERATION || "0", 10) + 1).toString()
12846
13136
  };
12847
- const child = spawn(process.argv[0], [process.argv[1], ...args], {
13137
+ const child = spawn(assertDefined(process.argv[0], "argv[0] missing"), [assertDefined(process.argv[1], "argv[1] missing"), ...args], {
12848
13138
  stdio: "inherit",
12849
13139
  env,
12850
13140
  detached: false
@@ -12908,7 +13198,10 @@ function createGenerationManager(params) {
12908
13198
  executorService: app.executorService ?? (pluginExecutorFiles.length > 0 ? createExecutorService({ config: { files: [] } }) : void 0)
12909
13199
  };
12910
13200
  });
12911
- if (app.authService) await withSpan("generate.resolveAuthNamespaces", async () => app.authService.resolveNamespaces());
13201
+ if (app.authService) {
13202
+ const authService = app.authService;
13203
+ await withSpan("generate.resolveAuthNamespaces", async () => authService.resolveNamespaces());
13204
+ }
12912
13205
  if (app.tailorDBServices.length > 0 || pluginExecutorFiles.length > 0) logger.newline();
12913
13206
  const readyAfterTailorDB = getReadyGenerators("tailordb");
12914
13207
  const hasOnTailorDBReady = generationPlugins.some((p) => p.onTailorDBReady != null);
@@ -12924,9 +13217,10 @@ function createGenerationManager(params) {
12924
13217
  await withSpan(`generate.loadResolvers.${namespace}`, async () => {
12925
13218
  try {
12926
13219
  await resolverService.loadResolvers();
12927
- services.resolver[namespace] = {};
13220
+ const namespaceResolvers = {};
13221
+ services.resolver[namespace] = namespaceResolvers;
12928
13222
  Object.entries(resolverService.resolvers).forEach(([_, resolver]) => {
12929
- services.resolver[namespace][resolver.name] = resolver;
13223
+ namespaceResolvers[resolver.name] = resolver;
12930
13224
  });
12931
13225
  } catch (error) {
12932
13226
  logger.error(`Error loading resolvers for Resolver service ${styles.bold(namespace)}`);
@@ -12972,11 +13266,11 @@ function createGenerationManager(params) {
12972
13266
  const app = application;
12973
13267
  for (const db of app.tailorDBServices) {
12974
13268
  const dbNamespace = db.namespace;
12975
- await watcher?.addWatchGroup(`TailorDB/${dbNamespace}`, db.config.files);
13269
+ await watcher.addWatchGroup(`TailorDB/${dbNamespace}`, db.config.files);
12976
13270
  }
12977
13271
  for (const resolverService of app.resolverServices) {
12978
13272
  const resolverNamespace = resolverService.namespace;
12979
- await watcher?.addWatchGroup(`Resolver/${resolverNamespace}`, resolverService["config"].files);
13273
+ await watcher.addWatchGroup(`Resolver/${resolverNamespace}`, resolverService["config"].files);
12980
13274
  }
12981
13275
  await new Promise(() => {});
12982
13276
  }
@@ -13040,10 +13334,7 @@ function machineUserInfo(user) {
13040
13334
  * @returns List of machine users
13041
13335
  */
13042
13336
  async function listMachineUsers(options) {
13043
- const client = await initOperatorClient(await loadAccessToken({
13044
- useProfile: true,
13045
- profile: options?.profile
13046
- }));
13337
+ const client = await initOperatorClient(await loadAccessToken({ profile: options?.profile }));
13047
13338
  const workspaceId = await loadWorkspaceId({
13048
13339
  workspaceId: options?.workspaceId,
13049
13340
  profile: options?.profile
@@ -13096,10 +13387,7 @@ const listCommand$7 = defineAppCommand({
13096
13387
  * @returns Machine user token info
13097
13388
  */
13098
13389
  async function getMachineUserToken(options) {
13099
- const client = await initOperatorClient(await loadAccessToken({
13100
- useProfile: true,
13101
- profile: options.profile
13102
- }));
13390
+ const client = await initOperatorClient(await loadAccessToken({ profile: options.profile }));
13103
13391
  const workspaceId = await loadWorkspaceId({
13104
13392
  workspaceId: options.workspaceId,
13105
13393
  profile: options.profile
@@ -13200,10 +13488,7 @@ function toOAuth2ClientCredentials(client) {
13200
13488
  * @returns OAuth2 client credentials
13201
13489
  */
13202
13490
  async function getOAuth2Client(options) {
13203
- const client = await initOperatorClient(await loadAccessToken({
13204
- useProfile: true,
13205
- profile: options.profile
13206
- }));
13491
+ const client = await initOperatorClient(await loadAccessToken({ profile: options.profile }));
13207
13492
  const workspaceId = await loadWorkspaceId({
13208
13493
  workspaceId: options.workspaceId,
13209
13494
  profile: options.profile
@@ -13220,7 +13505,7 @@ async function getOAuth2Client(options) {
13220
13505
  namespaceName: application.authNamespace,
13221
13506
  name: options.name
13222
13507
  });
13223
- return toOAuth2ClientCredentials(oauth2Client);
13508
+ return toOAuth2ClientCredentials(assertDefined(oauth2Client, "oauth2Client missing in response"));
13224
13509
  } catch (error) {
13225
13510
  if (error instanceof ConnectError && error.code === Code.NotFound) throw new Error(`OAuth2 client '${options.name}' not found.`, { cause: error });
13226
13511
  throw error;
@@ -13255,10 +13540,7 @@ const getCommand$3 = defineAppCommand({
13255
13540
  * @returns List of OAuth2 clients
13256
13541
  */
13257
13542
  async function listOAuth2Clients(options) {
13258
- const client = await initOperatorClient(await loadAccessToken({
13259
- useProfile: true,
13260
- profile: options?.profile
13261
- }));
13543
+ const client = await initOperatorClient(await loadAccessToken({ profile: options?.profile }));
13262
13544
  const workspaceId = await loadWorkspaceId({
13263
13545
  workspaceId: options?.workspaceId,
13264
13546
  profile: options?.profile
@@ -13342,7 +13624,7 @@ const createFolderOptionsSchema = z.object({
13342
13624
  */
13343
13625
  async function createFolder(options) {
13344
13626
  const result = createFolderOptionsSchema.safeParse(options);
13345
- if (!result.success) throw new Error(result.error.issues[0].message);
13627
+ if (!result.success) throw new Error(assertDefined(result.error.issues[0], "Zod returned no issues").message);
13346
13628
  const response = await (await initOperatorClient(await loadAccessToken())).createOrganizationFolder({
13347
13629
  organizationId: result.data.organizationId,
13348
13630
  parentFolderId: result.data.parentFolderId ?? "",
@@ -13387,7 +13669,7 @@ const deleteFolderOptionsSchema = z.object({
13387
13669
  */
13388
13670
  async function deleteFolder(options) {
13389
13671
  const result = deleteFolderOptionsSchema.safeParse(options);
13390
- if (!result.success) throw new Error(result.error.issues[0].message);
13672
+ if (!result.success) throw new Error(assertDefined(result.error.issues[0], "Zod returned no issues").message);
13391
13673
  await (await initOperatorClient(await loadAccessToken())).deleteOrganizationFolder({
13392
13674
  organizationId: result.data.organizationId,
13393
13675
  folderId: result.data.folderId
@@ -13440,7 +13722,7 @@ const getFolderOptionsSchema = z.object({
13440
13722
  */
13441
13723
  async function getFolder(options) {
13442
13724
  const result = getFolderOptionsSchema.safeParse(options);
13443
- if (!result.success) throw new Error(result.error.issues[0].message);
13725
+ if (!result.success) throw new Error(assertDefined(result.error.issues[0], "Zod returned no issues").message);
13444
13726
  const response = await (await initOperatorClient(await loadAccessToken())).getOrganizationFolder({
13445
13727
  organizationId: result.data.organizationId,
13446
13728
  folderId: result.data.folderId
@@ -13484,7 +13766,7 @@ const listFoldersOptionsSchema = z.object({
13484
13766
  */
13485
13767
  async function listFolders(options) {
13486
13768
  const result = listFoldersOptionsSchema.safeParse(options);
13487
- if (!result.success) throw new Error(result.error.issues[0].message);
13769
+ if (!result.success) throw new Error(assertDefined(result.error.issues[0], "Zod returned no issues").message);
13488
13770
  const { organizationId, parentFolderId, order, limit } = result.data;
13489
13771
  const client = await initOperatorClient(await loadAccessToken());
13490
13772
  const pageDirection = toPageDirection(order);
@@ -13532,7 +13814,7 @@ const updateFolderOptionsSchema = z.object({
13532
13814
  */
13533
13815
  async function updateFolder(options) {
13534
13816
  const result = updateFolderOptionsSchema.safeParse(options);
13535
- if (!result.success) throw new Error(result.error.issues[0].message);
13817
+ if (!result.success) throw new Error(assertDefined(result.error.issues[0], "Zod returned no issues").message);
13536
13818
  const response = await (await initOperatorClient(await loadAccessToken())).updateOrganizationFolder({
13537
13819
  organizationId: result.data.organizationId,
13538
13820
  folderId: result.data.folderId,
@@ -13574,7 +13856,7 @@ const getOrganizationOptionsSchema = z.object({ organizationId: z.uuid({ message
13574
13856
  */
13575
13857
  async function getOrganization(options) {
13576
13858
  const result = getOrganizationOptionsSchema.safeParse(options);
13577
- if (!result.success) throw new Error(result.error.issues[0].message);
13859
+ if (!result.success) throw new Error(assertDefined(result.error.issues[0], "Zod returned no issues").message);
13578
13860
  const response = await (await initOperatorClient(await loadAccessToken())).getOrganization({ organizationId: result.data.organizationId });
13579
13861
  if (!response.organization) throw new Error(`Organization "${result.data.organizationId}" not found.`);
13580
13862
  return organizationInfo(response.organization);
@@ -13668,12 +13950,12 @@ async function buildFolderTreeJson(client, organizationId, parentFolderId, curre
13668
13950
  }
13669
13951
  function renderTree(nodes, prefix) {
13670
13952
  let output = "";
13671
- for (let i = 0; i < nodes.length; i++) {
13953
+ for (const [i, node] of nodes.entries()) {
13672
13954
  const isLast = i === nodes.length - 1;
13673
13955
  const connector = isLast ? "└── " : "├── ";
13674
13956
  const childPrefix = isLast ? " " : "│ ";
13675
- output += `${prefix}${connector}${nodes[i].name}\n`;
13676
- if (nodes[i].children.length > 0) output += renderTree(nodes[i].children, prefix + childPrefix);
13957
+ output += `${prefix}${connector}${node.name}\n`;
13958
+ if (node.children.length > 0) output += renderTree(node.children, prefix + childPrefix);
13677
13959
  }
13678
13960
  return output;
13679
13961
  }
@@ -13760,7 +14042,7 @@ const updateOrganizationOptionsSchema = z.object({
13760
14042
  */
13761
14043
  async function updateOrganization(options) {
13762
14044
  const result = updateOrganizationOptionsSchema.safeParse(options);
13763
- if (!result.success) throw new Error(result.error.issues[0].message);
14045
+ if (!result.success) throw new Error(assertDefined(result.error.issues[0], "Zod returned no issues").message);
13764
14046
  const response = await (await initOperatorClient(await loadAccessToken())).updateOrganization({
13765
14047
  organizationId: result.data.organizationId,
13766
14048
  organizationName: result.data.name
@@ -13792,10 +14074,7 @@ const updateCommand$1 = defineAppCommand({
13792
14074
  //#endregion
13793
14075
  //#region src/cli/commands/remove.ts
13794
14076
  async function loadOptions$10(options) {
13795
- const client = await initOperatorClient(await loadAccessToken({
13796
- useProfile: true,
13797
- profile: options?.profile
13798
- }));
14077
+ const client = await initOperatorClient(await loadAccessToken({ profile: options?.profile }));
13799
14078
  const workspaceId = await loadWorkspaceId({
13800
14079
  workspaceId: options?.workspaceId,
13801
14080
  profile: options?.profile
@@ -13847,7 +14126,7 @@ async function execRemove(client, workspaceId, application, config, confirm) {
13847
14126
  auth.changeSet.authHook.print();
13848
14127
  auth.changeSet.scim.print();
13849
14128
  auth.changeSet.scimResource.print();
13850
- auth.changeSet.connection?.print();
14129
+ auth.changeSet.connection.print();
13851
14130
  secretManager.vaultChangeSet.print();
13852
14131
  secretManager.secretChangeSet.print();
13853
14132
  if (tailorDB.changeSet.service.deletes.length === 0 && staticWebsite.changeSet.deletes.length === 0 && idp.changeSet.service.deletes.length === 0 && auth.changeSet.service.deletes.length === 0 && pipeline.changeSet.service.deletes.length === 0 && app.deletes.length === 0 && executor.changeSet.deletes.length === 0 && workflow.changeSet.deletes.length === 0 && functionRegistry.changeSet.deletes.length === 0 && secretManager.vaultChangeSet.deletes.length === 0 && secretManager.secretChangeSet.deletes.length === 0) return;
@@ -13918,6 +14197,82 @@ function logBetaWarning(featureName) {
13918
14197
  logger.newline();
13919
14198
  }
13920
14199
 
14200
+ //#endregion
14201
+ //#region src/cli/commands/workspace/transform.ts
14202
+ const workspaceInfo = (workspace, folderName) => {
14203
+ const info = {
14204
+ id: workspace.id,
14205
+ name: workspace.name,
14206
+ region: workspace.region,
14207
+ createdAt: formatTimestamp(workspace.createTime),
14208
+ updatedAt: formatTimestamp(workspace.updateTime)
14209
+ };
14210
+ return folderName ? {
14211
+ ...info,
14212
+ folderName
14213
+ } : info;
14214
+ };
14215
+ const workspaceDetails = (workspace, folderName) => {
14216
+ return {
14217
+ ...workspaceInfo(workspace, folderName),
14218
+ deleteProtection: workspace.deleteProtection,
14219
+ organizationId: workspace.organizationId,
14220
+ folderId: workspace.folderId
14221
+ };
14222
+ };
14223
+ async function resolveWorkspaceFolderName(client, workspace) {
14224
+ if (!workspace.organizationId || !workspace.folderId) return void 0;
14225
+ try {
14226
+ return (await client.getOrganizationFolder({
14227
+ organizationId: workspace.organizationId,
14228
+ folderId: workspace.folderId
14229
+ })).folder?.name || void 0;
14230
+ } catch (error) {
14231
+ if (error instanceof ConnectError && (error.code === Code.NotFound || error.code === Code.PermissionDenied)) return;
14232
+ logger.warn(`Failed to resolve workspace folder name: ${error}`);
14233
+ return;
14234
+ }
14235
+ }
14236
+ function createWorkspaceFolderNameResolver(client) {
14237
+ const cache = /* @__PURE__ */ new Map();
14238
+ return (workspace) => {
14239
+ if (!workspace.organizationId || !workspace.folderId) return Promise.resolve(void 0);
14240
+ const cacheKey = `${workspace.organizationId}/${workspace.folderId}`;
14241
+ const cached = cache.get(cacheKey);
14242
+ if (cached) return cached;
14243
+ const promise = resolveWorkspaceFolderName(client, workspace);
14244
+ cache.set(cacheKey, promise);
14245
+ return promise;
14246
+ };
14247
+ }
14248
+ async function workspaceInfoWithFolderName(client, workspace) {
14249
+ return workspaceInfo(workspace, await resolveWorkspaceFolderName(client, workspace));
14250
+ }
14251
+ async function workspaceDetailsWithFolderName(client, workspace) {
14252
+ return workspaceDetails(workspace, await resolveWorkspaceFolderName(client, workspace));
14253
+ }
14254
+ async function workspaceInfosWithFolderNames(client, workspaces) {
14255
+ const resolveFolderName = createWorkspaceFolderNameResolver(client);
14256
+ const limit = pLimit(5);
14257
+ return Promise.all(workspaces.map((workspace) => limit(async () => workspaceInfo(workspace, await resolveFolderName(workspace)))));
14258
+ }
14259
+ function workspaceDisplayName(workspace) {
14260
+ return workspace.folderName ? `${workspace.folderName}/${workspace.name}` : workspace.name;
14261
+ }
14262
+ function createWorkspaceNameTransformer(nameKey, folderNameKey) {
14263
+ return (value, item) => {
14264
+ const workspace = item;
14265
+ const name = workspace[nameKey];
14266
+ const folderName = workspace[folderNameKey];
14267
+ if (typeof name === "string" && typeof folderName === "string") return workspaceDisplayName({
14268
+ name,
14269
+ folderName
14270
+ });
14271
+ return String(value ?? "");
14272
+ };
14273
+ }
14274
+ const workspaceNameTransformer = createWorkspaceNameTransformer("name", "folderName");
14275
+
13921
14276
  //#endregion
13922
14277
  //#region src/cli/commands/show.ts
13923
14278
  function applicationInfo(app) {
@@ -13939,10 +14294,7 @@ function applicationInfo(app) {
13939
14294
  * @returns Application information
13940
14295
  */
13941
14296
  async function show(options) {
13942
- const client = await initOperatorClient(await loadAccessToken({
13943
- useProfile: true,
13944
- profile: options?.profile
13945
- }));
14297
+ const client = await initOperatorClient(await loadAccessToken({ profile: options?.profile }));
13946
14298
  const workspaceId = await loadWorkspaceId({
13947
14299
  workspaceId: options?.workspaceId,
13948
14300
  profile: options?.profile
@@ -13952,15 +14304,19 @@ async function show(options) {
13952
14304
  workspaceId,
13953
14305
  applicationName: config.name
13954
14306
  })]);
13955
- const { name, ...appInfo } = applicationInfo(resp.application);
14307
+ const { name, ...appInfo } = applicationInfo(assertDefined(resp.application, `application "${config.name}" not found in workspace`));
14308
+ const workspace = workspaceResp.workspace;
14309
+ const workspaceFolderName = workspace ? await resolveWorkspaceFolderName(client, workspace) : "";
13956
14310
  return {
13957
14311
  name,
13958
14312
  workspaceId,
13959
- workspaceName: workspaceResp.workspace?.name ?? "",
13960
- workspaceRegion: workspaceResp.workspace?.region ?? "",
14313
+ workspaceName: workspace?.name ?? "",
14314
+ ...workspaceFolderName ? { workspaceFolderName } : {},
14315
+ workspaceRegion: workspace?.region ?? "",
13961
14316
  ...appInfo
13962
14317
  };
13963
14318
  }
14319
+ const showWorkspaceNameTransformer = createWorkspaceNameTransformer("workspaceName", "workspaceFolderName");
13964
14320
  const showCommand = defineAppCommand({
13965
14321
  name: "show",
13966
14322
  description: "Show information about the deployed application.",
@@ -13971,7 +14327,10 @@ const showCommand = defineAppCommand({
13971
14327
  profile: args.profile,
13972
14328
  configPath: args.config
13973
14329
  });
13974
- logger.out(appInfo);
14330
+ logger.out(appInfo, { display: {
14331
+ workspaceName: showWorkspaceNameTransformer,
14332
+ workspaceFolderName: null
14333
+ } });
13975
14334
  }
13976
14335
  });
13977
14336
 
@@ -14060,7 +14419,7 @@ function extractBreakingChangeFields(diff) {
14060
14419
  const { before, after } = change;
14061
14420
  if (before && after && !before.required && after.required) {
14062
14421
  if (!optionalToRequired.has(change.typeName)) optionalToRequired.set(change.typeName, /* @__PURE__ */ new Set());
14063
- optionalToRequired.get(change.typeName).add(change.fieldName);
14422
+ assertDefined(optionalToRequired.get(change.typeName), "optionalToRequired entry missing").add(change.fieldName);
14064
14423
  }
14065
14424
  if (before && after && before.type === "enum" && after.type === "enum" && before.allowedValues && after.allowedValues) {
14066
14425
  const beforeValues = before.allowedValues.map((v) => v.value);
@@ -14069,7 +14428,7 @@ function extractBreakingChangeFields(diff) {
14069
14428
  const afterSet = new Set(afterValues);
14070
14429
  if (beforeValues.some((v) => !afterSet.has(v)) || afterValues.some((v) => !beforeSet.has(v))) {
14071
14430
  if (!enumValueChanges.has(change.typeName)) enumValueChanges.set(change.typeName, /* @__PURE__ */ new Map());
14072
- enumValueChanges.get(change.typeName).set(change.fieldName, {
14431
+ assertDefined(enumValueChanges.get(change.typeName), "enumValueChanges entry missing").set(change.fieldName, {
14073
14432
  beforeValues,
14074
14433
  afterValues
14075
14434
  });
@@ -14079,7 +14438,7 @@ function extractBreakingChangeFields(diff) {
14079
14438
  const { after } = change;
14080
14439
  if (after && after.required) {
14081
14440
  if (!addedRequiredFields.has(change.typeName)) addedRequiredFields.set(change.typeName, /* @__PURE__ */ new Map());
14082
- addedRequiredFields.get(change.typeName).set(change.fieldName, after);
14441
+ assertDefined(addedRequiredFields.get(change.typeName), "addedRequiredFields entry missing").set(change.fieldName, after);
14083
14442
  }
14084
14443
  }
14085
14444
  return {
@@ -14561,7 +14920,7 @@ async function generate(options) {
14561
14920
  if (options.init) await handleInitOption(namespacesWithMigrations, options.yes);
14562
14921
  let pluginManager;
14563
14922
  if (plugins.length > 0) pluginManager = new PluginManager(plugins);
14564
- const { defineApplication } = await import("./application-D4tRNn90.mjs");
14923
+ const { defineApplication } = await import("./application-DSXntqnV.mjs");
14565
14924
  const application = defineApplication({
14566
14925
  config,
14567
14926
  pluginManager
@@ -14732,7 +15091,7 @@ function extractAllNamespaces(config) {
14732
15091
  function extractOwnedNamespaces(config) {
14733
15092
  const namespaces = /* @__PURE__ */ new Set();
14734
15093
  if (config.db) for (const [namespaceName, nsConfig] of Object.entries(config.db)) {
14735
- if ("external" in nsConfig && nsConfig.external === true) continue;
15094
+ if ("external" in nsConfig) continue;
14736
15095
  namespaces.add(namespaceName);
14737
15096
  }
14738
15097
  return Array.from(namespaces);
@@ -14809,18 +15168,15 @@ async function truncate(options) {
14809
15168
  yes: true
14810
15169
  });
14811
15170
  }
14812
- async function $truncate(options) {
14813
- const client = await initOperatorClient(await loadAccessToken({
14814
- useProfile: true,
14815
- profile: options?.profile
14816
- }));
15171
+ async function $truncate(options = {}) {
15172
+ const client = await initOperatorClient(await loadAccessToken({ profile: options.profile }));
14817
15173
  const workspaceId = await loadWorkspaceId({
14818
- workspaceId: options?.workspaceId,
14819
- profile: options?.profile
15174
+ workspaceId: options.workspaceId,
15175
+ profile: options.profile
14820
15176
  });
14821
- const hasTypes = options?.types && options.types.length > 0;
14822
- const hasNamespace = !!options?.namespace;
14823
- const hasAll = !!options?.all;
15177
+ const hasTypes = options.types && options.types.length > 0;
15178
+ const hasNamespace = !!options.namespace;
15179
+ const hasAll = !!options.all;
14824
15180
  const optionCount = [
14825
15181
  hasAll,
14826
15182
  hasNamespace,
@@ -14828,14 +15184,14 @@ async function $truncate(options) {
14828
15184
  ].filter(Boolean).length;
14829
15185
  if (optionCount === 0) throw new Error("Please specify one of: --all, --namespace <name>, or type names");
14830
15186
  if (optionCount > 1) throw new Error("Options --all, --namespace, and type names are mutually exclusive. Please specify only one.");
14831
- const { config } = await loadConfig(options?.configPath);
15187
+ const { config } = await loadConfig(options.configPath);
14832
15188
  const namespaces = extractOwnedNamespaces(config);
14833
15189
  if (hasAll) {
14834
15190
  if (namespaces.length === 0) {
14835
15191
  logger.warn("No namespaces found in config file.");
14836
15192
  return;
14837
15193
  }
14838
- if (!options?.yes) {
15194
+ if (!options.yes) {
14839
15195
  const namespaceList = namespaces.join(", ");
14840
15196
  if (!await prompt.confirm({
14841
15197
  message: `This will truncate ALL tables in the following owned namespaces (external namespaces are excluded): ${namespaceList}. Continue?`,
@@ -14849,11 +15205,11 @@ async function $truncate(options) {
14849
15205
  logger.success("Truncated all tables in all owned namespaces");
14850
15206
  return;
14851
15207
  }
14852
- if (hasNamespace && options?.namespace) {
14853
- const namespace = options.namespace;
15208
+ if (hasNamespace) {
15209
+ const namespace = assertDefined(options.namespace, "namespace option missing");
14854
15210
  if (!namespaces.includes(namespace)) {
14855
15211
  const dbConfig = config.db?.[namespace];
14856
- if (dbConfig && "external" in dbConfig && dbConfig.external === true) throw new Error(`Namespace "${namespace}" is declared as external in this app's config and cannot be truncated from here. Run truncate from the app that owns it.`);
15212
+ if (dbConfig && "external" in dbConfig) throw new Error(`Namespace "${namespace}" is declared as external in this app's config and cannot be truncated from here. Run truncate from the app that owns it.`);
14857
15213
  throw new Error(`Namespace "${namespace}" not found in config. Available owned namespaces (external namespaces are excluded): ${namespaces.join(", ")}`);
14858
15214
  }
14859
15215
  if (!options.yes) {
@@ -14868,8 +15224,8 @@ async function $truncate(options) {
14868
15224
  await truncateNamespace(workspaceId, namespace, client);
14869
15225
  return;
14870
15226
  }
14871
- if (hasTypes && options?.types) {
14872
- const typeNames = options.types;
15227
+ if (hasTypes) {
15228
+ const typeNames = assertDefined(options.types, "types option missing");
14873
15229
  const typeNamespaceMap = await resolveTypeNamespaces({
14874
15230
  workspaceId,
14875
15231
  namespaces,
@@ -14941,10 +15297,7 @@ const truncateCommand = defineAppCommand({
14941
15297
  * @returns List of workflows
14942
15298
  */
14943
15299
  async function listWorkflows(options) {
14944
- const client = await initOperatorClient(await loadAccessToken({
14945
- useProfile: true,
14946
- profile: options?.profile
14947
- }));
15300
+ const client = await initOperatorClient(await loadAccessToken({ profile: options?.profile }));
14948
15301
  const workspaceId = await loadWorkspaceId({
14949
15302
  workspaceId: options?.workspaceId,
14950
15303
  profile: options?.profile
@@ -14991,10 +15344,7 @@ const listCommand$3 = defineAppCommand({
14991
15344
  * @returns Resume result with wait helper
14992
15345
  */
14993
15346
  async function resumeWorkflow(options) {
14994
- const client = await initOperatorClient(await loadAccessToken({
14995
- useProfile: true,
14996
- profile: options.profile
14997
- }));
15347
+ const client = await initOperatorClient(await loadAccessToken({ profile: options.profile }));
14998
15348
  const workspaceId = await loadWorkspaceId({
14999
15349
  workspaceId: options.workspaceId,
15000
15350
  profile: options.profile
@@ -15102,12 +15452,9 @@ const healthOptionsSchema = z.object({
15102
15452
  });
15103
15453
  async function loadOptions$9(options) {
15104
15454
  const result = healthOptionsSchema.safeParse(options);
15105
- if (!result.success) throw new Error(result.error.issues[0].message);
15455
+ if (!result.success) throw new Error(assertDefined(result.error.issues[0], "Zod returned no issues").message);
15106
15456
  return {
15107
- client: await initOperatorClient(await loadAccessToken({
15108
- useProfile: true,
15109
- profile: result.data.profile
15110
- })),
15457
+ client: await initOperatorClient(await loadAccessToken({ profile: result.data.profile })),
15111
15458
  workspaceId: await loadWorkspaceId({
15112
15459
  workspaceId: result.data.workspaceId,
15113
15460
  profile: result.data.profile
@@ -15162,12 +15509,9 @@ const listAppsOptionsSchema = z.object({
15162
15509
  });
15163
15510
  async function loadOptions$8(options) {
15164
15511
  const result = listAppsOptionsSchema.safeParse(options);
15165
- if (!result.success) throw new Error(result.error.issues[0].message);
15512
+ if (!result.success) throw new Error(assertDefined(result.error.issues[0], "Zod returned no issues").message);
15166
15513
  return {
15167
- client: await initOperatorClient(await loadAccessToken({
15168
- useProfile: true,
15169
- profile: result.data.profile
15170
- })),
15514
+ client: await initOperatorClient(await loadAccessToken({ profile: result.data.profile })),
15171
15515
  workspaceId: await loadWorkspaceId({
15172
15516
  workspaceId: result.data.workspaceId,
15173
15517
  profile: result.data.profile
@@ -15217,26 +15561,6 @@ const listCommand$2 = defineAppCommand({
15217
15561
  }
15218
15562
  });
15219
15563
 
15220
- //#endregion
15221
- //#region src/cli/commands/workspace/transform.ts
15222
- const workspaceInfo = (workspace) => {
15223
- return {
15224
- id: workspace.id,
15225
- name: workspace.name,
15226
- region: workspace.region,
15227
- createdAt: formatTimestamp(workspace.createTime),
15228
- updatedAt: formatTimestamp(workspace.updateTime)
15229
- };
15230
- };
15231
- const workspaceDetails = (workspace) => {
15232
- return {
15233
- ...workspaceInfo(workspace),
15234
- deleteProtection: workspace.deleteProtection,
15235
- organizationId: workspace.organizationId,
15236
- folderId: workspace.folderId
15237
- };
15238
- };
15239
-
15240
15564
  //#endregion
15241
15565
  //#region src/cli/commands/workspace/create.ts
15242
15566
  /**
@@ -15262,17 +15586,17 @@ const validateRegion = async (region, client) => {
15262
15586
  */
15263
15587
  async function createWorkspace(options) {
15264
15588
  const result = createWorkspaceOptionsSchema.safeParse(options);
15265
- if (!result.success) throw new Error(result.error.issues[0].message);
15589
+ if (!result.success) throw new Error(assertDefined(result.error.issues[0], "Zod returned no issues").message);
15266
15590
  const validated = result.data;
15267
15591
  const client = await initOperatorClient(await loadAccessToken());
15268
15592
  await validateRegion(validated.region, client);
15269
- return workspaceInfo((await client.createWorkspace({
15593
+ return workspaceInfoWithFolderName(client, assertDefined((await client.createWorkspace({
15270
15594
  workspaceName: validated.name,
15271
15595
  workspaceRegion: validated.region,
15272
15596
  deleteProtection: validated.deleteProtection ?? false,
15273
15597
  organizationId: validated.organizationId,
15274
15598
  folderId: validated.folderId
15275
- })).workspace);
15599
+ })).workspace, "createWorkspace response missing workspace"));
15276
15600
  }
15277
15601
  const createCommand = defineAppCommand({
15278
15602
  name: "create",
@@ -15338,7 +15662,7 @@ const createCommand = defineAppCommand({
15338
15662
  };
15339
15663
  if (!args.json) logger.success(`Profile "${profileName}" created successfully.`);
15340
15664
  }
15341
- if (!args.json) logger.success(`Workspace "${args.name}" created successfully.`);
15665
+ if (!args.json) logger.success(`Workspace "${workspaceDisplayName(workspace)}" created successfully.`);
15342
15666
  if (args.json && profileInfo) {
15343
15667
  logger.out({
15344
15668
  ...workspace,
@@ -15346,7 +15670,10 @@ const createCommand = defineAppCommand({
15346
15670
  });
15347
15671
  return;
15348
15672
  }
15349
- logger.out(workspace);
15673
+ logger.out(workspace, { display: {
15674
+ name: workspaceNameTransformer,
15675
+ folderName: null
15676
+ } });
15350
15677
  if (profileInfo) {
15351
15678
  logger.out("Profile:");
15352
15679
  logger.out(profileInfo);
@@ -15359,7 +15686,7 @@ const createCommand = defineAppCommand({
15359
15686
  const deleteWorkspaceOptionsSchema = z.object({ workspaceId: z.uuid({ message: "workspace-id must be a valid UUID" }) });
15360
15687
  async function loadOptions$7(options) {
15361
15688
  const result = deleteWorkspaceOptionsSchema.safeParse(options);
15362
- if (!result.success) throw new Error(result.error.issues[0].message);
15689
+ if (!result.success) throw new Error(assertDefined(result.error.issues[0], "Zod returned no issues").message);
15363
15690
  return {
15364
15691
  client: await initOperatorClient(await loadAccessToken()),
15365
15692
  workspaceId: result.data.workspaceId
@@ -15393,8 +15720,15 @@ const deleteCommand = defineAppCommand({
15393
15720
  } catch {
15394
15721
  throw new Error(`Workspace "${workspaceId}" not found.`);
15395
15722
  }
15723
+ const workspaceResource = workspace.workspace;
15724
+ const workspaceName = workspaceResource?.name ?? workspaceId;
15725
+ const displayName = workspaceDisplayName({
15726
+ name: workspaceName,
15727
+ folderName: workspaceResource ? await resolveWorkspaceFolderName(client, workspaceResource) : ""
15728
+ });
15396
15729
  if (!args.yes) {
15397
- if (await prompt.text({ message: `Enter the workspace name to confirm deletion (${workspace.workspace?.name}):` }) !== workspace.workspace?.name) {
15730
+ const confirmation = await prompt.text({ message: `Enter the workspace name to confirm deletion (${displayName}):` });
15731
+ if (confirmation !== workspaceName && confirmation !== displayName) {
15398
15732
  logger.info("Workspace deletion cancelled.");
15399
15733
  return;
15400
15734
  }
@@ -15406,8 +15740,8 @@ const deleteCommand = defineAppCommand({
15406
15740
  for (const [profileName] of profilesToDelete) delete pfConfig.profiles[profileName];
15407
15741
  writePlatformConfig(pfConfig);
15408
15742
  }
15409
- if (profilesToDelete.length > 0) logger.success(`Workspace "${args["workspace-id"]}" and ${profilesToDelete.length} associated profile(s) deleted successfully.`);
15410
- else logger.success(`Workspace "${args["workspace-id"]}" deleted successfully.`);
15743
+ if (profilesToDelete.length > 0) logger.success(`Workspace "${displayName}" and ${profilesToDelete.length} associated profile(s) deleted successfully.`);
15744
+ else logger.success(`Workspace "${displayName}" deleted successfully.`);
15411
15745
  }
15412
15746
  });
15413
15747
 
@@ -15419,12 +15753,9 @@ const getWorkspaceOptionsSchema = z.object({
15419
15753
  });
15420
15754
  async function loadOptions$6(options) {
15421
15755
  const result = getWorkspaceOptionsSchema.safeParse(options);
15422
- if (!result.success) throw new Error(result.error.issues[0].message);
15756
+ if (!result.success) throw new Error(assertDefined(result.error.issues[0], "Zod returned no issues").message);
15423
15757
  return {
15424
- client: await initOperatorClient(await loadAccessToken({
15425
- useProfile: true,
15426
- profile: result.data.profile
15427
- })),
15758
+ client: await initOperatorClient(await loadAccessToken({ profile: result.data.profile })),
15428
15759
  workspaceId: await loadWorkspaceId({
15429
15760
  workspaceId: result.data.workspaceId,
15430
15761
  profile: result.data.profile
@@ -15440,7 +15771,7 @@ async function getWorkspace(options) {
15440
15771
  const { client, workspaceId } = await loadOptions$6(options);
15441
15772
  const response = await client.getWorkspace({ workspaceId });
15442
15773
  if (!response.workspace) throw new Error(`Workspace "${workspaceId}" not found.`);
15443
- return workspaceDetails(response.workspace);
15774
+ return workspaceDetailsWithFolderName(client, response.workspace);
15444
15775
  }
15445
15776
  const getCommand = defineAppCommand({
15446
15777
  name: "get",
@@ -15456,7 +15787,10 @@ const getCommand = defineAppCommand({
15456
15787
  createdAt: humanizeRelativeTime(workspace.createdAt),
15457
15788
  updatedAt: humanizeRelativeTime(workspace.updatedAt)
15458
15789
  };
15459
- logger.out(formattedWorkspace);
15790
+ logger.out(formattedWorkspace, { display: {
15791
+ name: workspaceNameTransformer,
15792
+ folderName: null
15793
+ } });
15460
15794
  }
15461
15795
  });
15462
15796
 
@@ -15470,14 +15804,14 @@ const getCommand = defineAppCommand({
15470
15804
  async function listWorkspaces(options) {
15471
15805
  const client = await initOperatorClient(await loadAccessToken());
15472
15806
  const pageDirection = toPageDirection(options?.order);
15473
- return (await fetchPaged(async (pageToken, pageSize) => {
15807
+ return workspaceInfosWithFolderNames(client, await fetchPaged(async (pageToken, pageSize) => {
15474
15808
  const { workspaces, nextPageToken } = await client.listWorkspaces({
15475
15809
  pageToken,
15476
15810
  pageSize,
15477
15811
  pageDirection
15478
15812
  });
15479
15813
  return [workspaces, nextPageToken];
15480
- }, { limit: options?.limit })).map(workspaceInfo);
15814
+ }, { limit: options?.limit }));
15481
15815
  }
15482
15816
  const listCommand$1 = defineAppCommand({
15483
15817
  name: "list",
@@ -15488,7 +15822,11 @@ const listCommand$1 = defineAppCommand({
15488
15822
  order: args.order,
15489
15823
  limit: args.limit
15490
15824
  });
15491
- logger.out(workspaces, { display: { updatedAt: null } });
15825
+ logger.out(workspaces, { display: {
15826
+ name: workspaceNameTransformer,
15827
+ folderName: null,
15828
+ updatedAt: null
15829
+ } });
15492
15830
  }
15493
15831
  });
15494
15832
 
@@ -15497,7 +15835,7 @@ const listCommand$1 = defineAppCommand({
15497
15835
  const restoreWorkspaceOptionsSchema = z.object({ workspaceId: z.uuid({ message: "workspace-id must be a valid UUID" }) });
15498
15836
  async function loadOptions$5(options) {
15499
15837
  const result = restoreWorkspaceOptionsSchema.safeParse(options);
15500
- if (!result.success) throw new Error(result.error.issues[0].message);
15838
+ if (!result.success) throw new Error(assertDefined(result.error.issues[0], "Zod returned no issues").message);
15501
15839
  return {
15502
15840
  client: await initOperatorClient(await loadAccessToken()),
15503
15841
  workspaceId: result.data.workspaceId
@@ -15577,12 +15915,9 @@ const inviteUserOptionsSchema = z.object({
15577
15915
  });
15578
15916
  async function loadOptions$4(options) {
15579
15917
  const result = inviteUserOptionsSchema.safeParse(options);
15580
- if (!result.success) throw new Error(result.error.issues[0].message);
15918
+ if (!result.success) throw new Error(assertDefined(result.error.issues[0], "Zod returned no issues").message);
15581
15919
  return {
15582
- client: await initOperatorClient(await loadAccessToken({
15583
- useProfile: true,
15584
- profile: result.data.profile
15585
- })),
15920
+ client: await initOperatorClient(await loadAccessToken({ profile: result.data.profile })),
15586
15921
  workspaceId: await loadWorkspaceId({
15587
15922
  workspaceId: result.data.workspaceId,
15588
15923
  profile: result.data.profile
@@ -15637,12 +15972,9 @@ const listUsersOptionsSchema = z.object({
15637
15972
  });
15638
15973
  async function loadOptions$3(options) {
15639
15974
  const result = listUsersOptionsSchema.safeParse(options);
15640
- if (!result.success) throw new Error(result.error.issues[0].message);
15975
+ if (!result.success) throw new Error(assertDefined(result.error.issues[0], "Zod returned no issues").message);
15641
15976
  return {
15642
- client: await initOperatorClient(await loadAccessToken({
15643
- useProfile: true,
15644
- profile: result.data.profile
15645
- })),
15977
+ client: await initOperatorClient(await loadAccessToken({ profile: result.data.profile })),
15646
15978
  workspaceId: await loadWorkspaceId({
15647
15979
  workspaceId: result.data.workspaceId,
15648
15980
  profile: result.data.profile
@@ -15696,12 +16028,9 @@ const removeUserOptionsSchema = z.object({
15696
16028
  });
15697
16029
  async function loadOptions$2(options) {
15698
16030
  const result = removeUserOptionsSchema.safeParse(options);
15699
- if (!result.success) throw new Error(result.error.issues[0].message);
16031
+ if (!result.success) throw new Error(assertDefined(result.error.issues[0], "Zod returned no issues").message);
15700
16032
  return {
15701
- client: await initOperatorClient(await loadAccessToken({
15702
- useProfile: true,
15703
- profile: result.data.profile
15704
- })),
16033
+ client: await initOperatorClient(await loadAccessToken({ profile: result.data.profile })),
15705
16034
  workspaceId: await loadWorkspaceId({
15706
16035
  workspaceId: result.data.workspaceId,
15707
16036
  profile: result.data.profile
@@ -15756,12 +16085,9 @@ const updateUserOptionsSchema = z.object({
15756
16085
  });
15757
16086
  async function loadOptions$1(options) {
15758
16087
  const result = updateUserOptionsSchema.safeParse(options);
15759
- if (!result.success) throw new Error(result.error.issues[0].message);
16088
+ if (!result.success) throw new Error(assertDefined(result.error.issues[0], "Zod returned no issues").message);
15760
16089
  return {
15761
- client: await initOperatorClient(await loadAccessToken({
15762
- useProfile: true,
15763
- profile: result.data.profile
15764
- })),
16090
+ client: await initOperatorClient(await loadAccessToken({ profile: result.data.profile })),
15765
16091
  workspaceId: await loadWorkspaceId({
15766
16092
  workspaceId: result.data.workspaceId,
15767
16093
  profile: result.data.profile
@@ -15982,7 +16308,7 @@ function isSqlInputComplete(input) {
15982
16308
  let dollarQuoteTag = null;
15983
16309
  let lastSignificantTokenWasSemicolon = false;
15984
16310
  for (let i = 0; i < input.length; i += 1) {
15985
- const char = input[i];
16311
+ const char = assertDefined(input[i], `character at index ${i} missing`);
15986
16312
  const next = input[i + 1];
15987
16313
  if (inLineComment) {
15988
16314
  if (char === "\n") inLineComment = false;
@@ -16185,7 +16511,7 @@ const queryBaseOptionsSchema = z.object({
16185
16511
  const queryOptionsSchema = queryBaseOptionsSchema.extend({ query: z.string() });
16186
16512
  async function getNamespaceFromSqlQuery(workspaceId, query, client, namespaces) {
16187
16513
  if (namespaces.length === 0) throw new Error("No namespaces found in configuration.");
16188
- if (namespaces.length === 1) return namespaces[0];
16514
+ if (namespaces.length === 1) return assertDefined(namespaces[0], "namespace missing");
16189
16515
  const typeNames = extractTypeNamesFromSql(query);
16190
16516
  if (typeNames.length === 0) throw new Error(`Could not infer namespace from query. Detected namespaces: ${namespaces.join(", ")}.`);
16191
16517
  const typeNamespaceMap = await resolveTypeNamespaces({
@@ -16197,16 +16523,13 @@ async function getNamespaceFromSqlQuery(workspaceId, query, client, namespaces)
16197
16523
  const notFoundTypes = typeNames.filter((typeName) => !typeNamespaceMap.has(typeName));
16198
16524
  if (notFoundTypes.length > 0) throw new Error(`Could not find namespace for types in query: ${notFoundTypes.join(", ")}.`);
16199
16525
  const namespacesFromTypes = new Set(typeNamespaceMap.values());
16200
- if (namespacesFromTypes.size === 1) return [...namespacesFromTypes][0];
16526
+ if (namespacesFromTypes.size === 1) return assertDefined([...namespacesFromTypes][0], "namespace from types missing");
16201
16527
  throw new Error(`Query references types from multiple namespaces: ${[...namespacesFromTypes].join(", ")}.`);
16202
16528
  }
16203
16529
  async function loadOptions(options) {
16204
16530
  const result = queryBaseOptionsSchema.safeParse(options);
16205
- if (!result.success) throw new Error(result.error.issues[0].message);
16206
- const client = await initOperatorClient(await loadAccessToken({
16207
- useProfile: true,
16208
- profile: result.data.profile
16209
- }));
16531
+ if (!result.success) throw new Error(assertDefined(result.error.issues[0], "validation error missing issues").message);
16532
+ const client = await initOperatorClient(await loadAccessToken({ profile: result.data.profile }));
16210
16533
  const workspaceId = await loadWorkspaceId({
16211
16534
  workspaceId: result.data.workspaceId,
16212
16535
  profile: result.data.profile
@@ -16339,7 +16662,7 @@ async function resolveEditedQueryInput(engine) {
16339
16662
  */
16340
16663
  async function query(options) {
16341
16664
  const result = queryOptionsSchema.safeParse(options);
16342
- if (!result.success) throw new Error(result.error.issues[0].message);
16665
+ if (!result.success) throw new Error(assertDefined(result.error.issues[0], "validation error missing issues").message);
16343
16666
  return await (await prepareQueryExecutor(result.data))(result.data.query);
16344
16667
  }
16345
16668
  async function prepareQueryExecutor(options) {
@@ -16421,7 +16744,7 @@ async function runRepl(options) {
16421
16744
  const execute = await prepareQueryExecutor(options);
16422
16745
  const historyPath = getReplHistoryPath(options.engine, options.profile, options.workspaceId);
16423
16746
  const validate = createReplValidator(options.engine);
16424
- const { highlightSqlLine, highlightGraphqlLine, replTransform } = await import("./repl-editor-Y9QJDL0K.mjs");
16747
+ const { highlightSqlLine, highlightGraphqlLine, replTransform } = await import("./repl-editor-CJG3sz7A.mjs");
16425
16748
  const highlight = options.engine === "sql" ? highlightSqlLine : highlightGraphqlLine;
16426
16749
  const prompt = createPrompt({
16427
16750
  prefix: "",
@@ -16682,8 +17005,9 @@ function printSingleSqlResult(execResult, options = {}) {
16682
17005
  function splitSqlStatements(query) {
16683
17006
  const statements = parse(query, { locationTracking: true });
16684
17007
  return statements.map((s, i) => {
16685
- const start = s._location.start;
16686
- const end = i + 1 < statements.length ? statements[i + 1]._location.start : query.length;
17008
+ const start = assertDefined(s._location, "SQL statement location missing").start;
17009
+ const nextStmt = statements[i + 1];
17010
+ const end = nextStmt !== void 0 ? assertDefined(nextStmt._location, "SQL statement location missing").start : query.length;
16687
17011
  return query.substring(start, end);
16688
17012
  });
16689
17013
  }
@@ -16703,7 +17027,7 @@ function printSqlResult(result, options = {}) {
16703
17027
  for (let i = 0; i < result.result.length; i++) {
16704
17028
  if (i > 0) logger.log("");
16705
17029
  logger.info(queries[i] ?? `Statement ${i + 1}`);
16706
- printSingleSqlResult(result.result[i], options);
17030
+ printSingleSqlResult(assertDefined(result.result[i], `SQL result at index ${i} missing`), options);
16707
17031
  }
16708
17032
  return;
16709
17033
  }
@@ -16754,5 +17078,5 @@ function isDeno() {
16754
17078
  }
16755
17079
 
16756
17080
  //#endregion
16757
- export { listCommand$5 as $, compareSnapshots as $t, truncate as A, toPageDirection as An, startCommand as At, logBetaWarning as B, getExecutor as Bt, listCommand$2 as C, commonArgs as Cn, triggerExecutor as Ct, resumeWorkflow as D, isVerbose as Dn, jobsCommand as Dt, resumeCommand as E, deploymentArgs as En, getExecutorJob as Et, writeDbTypesFile as F, getWorkflowExecution as Ft, organizationTree as G, parseMigrationLabelNumber as Gt, removeCommand$1 as H, executeScript as Ht, getConfiguredEditorCommand as I, listWorkflowExecutions as It, listOrganizations as J, DIFF_FILE_NAME as Jt, treeCommand as K, bundleMigrationScript as Kt, openInConfiguredEditor as L, functionExecutionStatusToString as Lt, generate as M, getCommand$5 as Mt, generateCommand as N, getWorkflow as Nt, listCommand$3 as O, pagedLogArgs as On, listExecutorJobs as Ot, generateMigrationScript as P, executionsCommand as Pt, updateFolder as Q, compareLocalTypesWithSnapshot as Qt, show as R, formatKeyValueTable as Rt, listApps as S, defineAppCommand as Sn, triggerCommand as St, healthCommand as T, confirmationArgs as Tn, listExecutors as Tt, updateCommand$1 as U, waitForExecution$1 as Ut, remove as V, deploy as Vt, updateOrganization as W, MIGRATION_LABEL_KEY as Wt, getOrganization as X, MIGRATE_FILE_NAME as Xt, getCommand$1 as Y, INITIAL_SCHEMA_NUMBER as Yt, updateCommand$2 as Z, SCHEMA_FILE_NAME as Zt, getWorkspace as _, generateUserTypes as _n, listFunctionRegistries as _t, updateUser as a, getNextMigrationNumber as an, createCommand$1 as at, createCommand as b, apiCall as bn, listWebhookExecutors as bt, listCommand as c, reconstructSnapshotFromMigrations as cn, listOAuth2Clients as ct, inviteUser as d, formatMigrationDiff as dn, getMachineUserToken as dt, createSnapshotFromLocalTypes as en, listFolders as et, restoreCommand as f, hasChanges as fn, tokenCommand as ft, getCommand as g, PluginManager as gn, listCommand$8 as gt, listWorkspaces as h, sdkNameLabelKey as hn, generate$1 as ht, updateCommand as i, getMigrationFiles as in, deleteFolder as it, truncateCommand as j, workspaceArgs as jn, startWorkflow as jt, listWorkflows as k, paginationArgs as kn, watchExecutorJob as kt, listUsers as l, formatMigrationNumber as ln, getCommand$3 as lt, listCommand$1 as m, resourceTrn as mn, listMachineUsers as mt, query as n, getMigrationDirPath as nn, getFolder as nt, removeCommand as o, isValidMigrationNumber as on, createFolder as ot, restoreWorkspace as p, getNamespacesWithMigrations as pn, listCommand$7 as pt, listCommand$4 as q, DB_TYPES_FILE_NAME as qt, queryCommand as r, getMigrationFilePath as rn, deleteCommand$1 as rt, removeUser as s, loadDiff as sn, listCommand$6 as st, isNativeTypeScriptRuntime as t, getLatestMigrationNumber as tn, getCommand$2 as tt, inviteCommand as u, formatDiffSummary as un, getOAuth2Client as ut, deleteCommand as v, prompt as vn, getCommand$4 as vt, getAppHealth as w, configArg as wn, listCommand$9 as wt, createWorkspace as x, assertWritable as xn, webhookCommand as xt, deleteWorkspace as y, apiCommand as yn, getFunctionRegistry as yt, showCommand as z, getCommand$6 as zt };
16758
- //# sourceMappingURL=runtime-C0_FZWdE.mjs.map
17081
+ export { listCommand$5 as $, INITIAL_SCHEMA_NUMBER as $t, truncate as A, configArg as An, startCommand as At, logBetaWarning as B, getExecutor as Bt, listCommand$2 as C, generateUserTypes as Cn, triggerExecutor as Ct, resumeWorkflow as D, assertWritable as Dn, jobsCommand as Dt, resumeCommand as E, apiCall as En, getExecutorJob as Et, writeDbTypesFile as F, paginationArgs as Fn, getWorkflowExecution as Ft, organizationTree as G, MIGRATION_LABEL_KEY as Gt, removeCommand$1 as H, executeScript as Ht, getConfiguredEditorCommand as I, toPageDirection as In, listWorkflowExecutions as It, listOrganizations as J, compareSnapshotWithRemote as Jt, treeCommand as K, handleOptionalToRequiredError as Kt, openInConfiguredEditor as L, workspaceArgs as Ln, functionExecutionStatusToString as Lt, generate as M, deploymentArgs as Mn, getCommand$5 as Mt, generateCommand as N, isVerbose as Nn, getWorkflow as Nt, listCommand$3 as O, defineAppCommand as On, listExecutorJobs as Ot, generateMigrationScript as P, pagedLogArgs as Pn, executionsCommand as Pt, updateFolder as Q, DIFF_FILE_NAME as Qt, show as R, formatKeyValueTable as Rt, listApps as S, PluginManager as Sn, triggerCommand as St, healthCommand as T, apiCommand as Tn, listExecutors as Tt, updateCommand$1 as U, waitForExecution$1 as Ut, remove as V, deploy as Vt, updateOrganization as W, bundleMigrationScript as Wt, getOrganization as X, protoGqlPermission as Xt, getCommand$1 as Y, generateAllTypeManifestsFromSnapshot as Yt, updateCommand$2 as Z, DB_TYPES_FILE_NAME as Zt, getWorkspace as _, formatMigrationDiff as _n, listFunctionRegistries as _t, updateUser as a, createSnapshotFromLocalTypes as an, createCommand$1 as at, createCommand as b, resourceTrn as bn, listWebhookExecutors as bt, listCommand as c, getMigrationFilePath as cn, listOAuth2Clients as ct, inviteUser as d, isValidMigrationNumber as dn, getMachineUserToken as dt, MIGRATE_FILE_NAME as en, listFolders as et, restoreCommand as f, loadDiff as fn, tokenCommand as ft, getCommand as g, formatDiffSummary as gn, listCommand$8 as gt, listWorkspaces as h, parseMigrationNumberArg as hn, generate$1 as ht, updateCommand as i, compareSnapshots as in, deleteFolder as it, truncateCommand as j, confirmationArgs as jn, startWorkflow as jt, listWorkflows as k, commonArgs as kn, watchExecutorJob as kt, listUsers as l, getMigrationFiles as ln, getCommand$3 as lt, listCommand$1 as m, formatMigrationNumber as mn, listMachineUsers as mt, query as n, assertValidMigrationFiles as nn, getFolder as nt, removeCommand as o, getLatestMigrationNumber as on, createFolder as ot, restoreWorkspace as p, reconstructSnapshotFromMigrations as pn, listCommand$7 as pt, listCommand$4 as q, parseMigrationLabelNumber as qt, queryCommand as r, compareLocalTypesWithSnapshot as rn, deleteCommand$1 as rt, removeUser as s, getMigrationDirPath as sn, listCommand$6 as st, isNativeTypeScriptRuntime as t, SCHEMA_FILE_NAME as tn, getCommand$2 as tt, inviteCommand as u, getNextMigrationNumber as un, getOAuth2Client as ut, deleteCommand as v, hasChanges as vn, getCommand$4 as vt, getAppHealth as w, prompt as wn, listCommand$9 as wt, createWorkspace as x, sdkNameLabelKey as xn, webhookCommand as xt, deleteWorkspace as y, getNamespacesWithMigrations as yn, getFunctionRegistry as yt, showCommand as z, getCommand$6 as zt };
17082
+ //# sourceMappingURL=runtime-C6o4hiYq.mjs.map