@tailor-platform/sdk 1.63.0 → 1.66.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 (51) hide show
  1. package/CHANGELOG.md +51 -0
  2. package/dist/{actor-J2gJ0eK5.d.mts → actor-D_2aJjYO.d.mts} +2 -2
  3. package/dist/{application-BezXGbrU.mjs → application-DGDmL8i_.mjs} +72 -9
  4. package/dist/application-DGDmL8i_.mjs.map +1 -0
  5. package/dist/application-nTydHJm8.mjs +4 -0
  6. package/dist/cli/index.mjs +66 -22
  7. package/dist/cli/index.mjs.map +1 -1
  8. package/dist/cli/lib.d.mts +375 -375
  9. package/dist/cli/lib.mjs +3 -3
  10. package/dist/{client-CobIRHl-.mjs → client-F0a4cWUM.mjs} +3 -2
  11. package/dist/client-F0a4cWUM.mjs.map +1 -0
  12. package/dist/{client-C68VWo4g.mjs → client-boxXYevx.mjs} +1 -1
  13. package/dist/completion/zsh-worker.zsh +4043 -0
  14. package/dist/configure/index.d.mts +5 -5
  15. package/dist/configure/index.mjs +17 -1
  16. package/dist/configure/index.mjs.map +1 -1
  17. package/dist/{crashreport-BhD0y14F.mjs → crashreport-0EHy-ayY.mjs} +2 -2
  18. package/dist/{crashreport-BhD0y14F.mjs.map → crashreport-0EHy-ayY.mjs.map} +1 -1
  19. package/dist/{crashreport-D1wKBJ8N.mjs → crashreport-Bf6uT6mf.mjs} +1 -1
  20. package/dist/{index-CLxubakC.d.mts → index-BdLqzJDu.d.mts} +19 -6
  21. package/dist/{index-CfRFkXIO.d.mts → index-Bhjep8cS.d.mts} +2 -2
  22. package/dist/{index-DUupuPhZ.d.mts → index-CZ2r3qiO.d.mts} +2 -2
  23. package/dist/{index-CPRnOjjt.d.mts → index-Db2RvnEH.d.mts} +2 -2
  24. package/dist/{index-CQZVJ5SX.d.mts → index-QpC0TNbH.d.mts} +2 -2
  25. package/dist/plugin/builtin/enum-constants/index.d.mts +1 -1
  26. package/dist/plugin/builtin/file-utils/index.d.mts +1 -1
  27. package/dist/plugin/builtin/kysely-type/index.d.mts +1 -1
  28. package/dist/plugin/builtin/seed/index.d.mts +1 -1
  29. package/dist/plugin/index.d.mts +2 -2
  30. package/dist/{plugin-C_FyVSdl.d.mts → plugin-DylAsA4Z.d.mts} +2 -2
  31. package/dist/{runtime-CW3jcQCc.mjs → runtime-2nzOZCUb.mjs} +728 -182
  32. package/dist/runtime-2nzOZCUb.mjs.map +1 -0
  33. package/dist/{tailordb-BlBGmQK-.d.mts → tailordb-C-ar4XCX.d.mts} +4 -4
  34. package/dist/utils/test/index.d.mts +3 -3
  35. package/dist/{workflow.generated-Bf1tWylx.d.mts → workflow.generated--1Qc15Et.d.mts} +62 -7
  36. package/docs/cli/auth.md +4 -4
  37. package/docs/cli/completion.md +3 -0
  38. package/docs/cli/function.md +8 -8
  39. package/docs/cli/query.md +1 -1
  40. package/docs/cli/workflow.md +10 -10
  41. package/docs/cli/workspace.md +14 -10
  42. package/docs/cli-reference.md +1 -1
  43. package/docs/services/aigateway.md +97 -0
  44. package/docs/services/auth.md +19 -0
  45. package/docs/services/idp.md +96 -0
  46. package/docs/services/tailordb-migration.md +17 -6
  47. package/package.json +12 -12
  48. package/dist/application-BezXGbrU.mjs.map +0 -1
  49. package/dist/application-DSXntqnV.mjs +0 -4
  50. package/dist/client-CobIRHl-.mjs.map +0 -1
  51. package/dist/runtime-CW3jcQCc.mjs.map +0 -1
@@ -1,9 +1,9 @@
1
1
 
2
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";
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-F0a4cWUM.mjs";
4
4
  import { t as assertDefined } from "./assert-CKfwrmCV.mjs";
5
5
  import { a as parseBoolean, i as symbols, n as logger, r as styles, t as CIPromptError } from "./logger-DpJyJvNz.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";
6
+ import { A as readPlatformConfig, C as loadConfig, D as loadConfigPath, E as loadAccessToken, N as writePlatformConfig, O as loadMachineUserName, S as hashFile, b as getDistDir, d as assertUniqueLocalTailorDBTypeNames, f as assertUniqueTailorDBTypeNamesWithExternal, h as platformBundleDefinePlugin, k as loadWorkspaceId, 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-DGDmL8i_.mjs";
7
7
  import { o as loadFilesWithIgnores, t as createExecutorService } from "./service-wI3Hvrgx.mjs";
8
8
  import { t as multiline } from "./multiline-Cf9ODpr1.mjs";
9
9
  import { t as readPackageJson } from "./package-json-DcQApfPQ.mjs";
@@ -1806,6 +1806,219 @@ async function buildMetaRequest(params) {
1806
1806
  };
1807
1807
  }
1808
1808
 
1809
+ //#endregion
1810
+ //#region src/cli/commands/deploy/owned-resource.ts
1811
+ /**
1812
+ * Fetch a workspace-scoped resource list and attach SDK ownership metadata.
1813
+ * @template T
1814
+ * @param params - Resource fetch parameters
1815
+ * @param params.client - Operator client instance
1816
+ * @param params.workspaceId - Workspace ID
1817
+ * @param params.fetchPage - Function that fetches one resource page
1818
+ * @param params.getName - Function that extracts the resource name
1819
+ * @param params.getTrn - Function that builds the resource TRN
1820
+ * @returns Existing resources keyed by resource name, with SDK labels attached
1821
+ */
1822
+ async function fetchExistingResourcesWithLabels(params) {
1823
+ const { client, workspaceId, fetchPage, getName, getTrn } = params;
1824
+ const withoutLabel = await fetchAll(async (pageToken, maxPageSize) => {
1825
+ try {
1826
+ return await fetchPage(pageToken, maxPageSize);
1827
+ } catch (error) {
1828
+ if (error instanceof ConnectError && error.code === Code.NotFound) return [[], ""];
1829
+ throw error;
1830
+ }
1831
+ });
1832
+ const existingResources = {};
1833
+ await Promise.all(withoutLabel.map(async (resource) => {
1834
+ const name = getName(resource);
1835
+ if (!name) return;
1836
+ const { metadata } = await client.getMetadata({ trn: getTrn(workspaceId, name) });
1837
+ existingResources[name] = {
1838
+ resource,
1839
+ label: metadata?.labels[sdkNameLabelKey],
1840
+ allLabels: metadata?.labels
1841
+ };
1842
+ }));
1843
+ return existingResources;
1844
+ }
1845
+ /**
1846
+ * Determine whether a same-named existing resource is managed by this app.
1847
+ * Records the user-facing confirmation data when ownership does not match.
1848
+ * @param params - Ownership classification inputs
1849
+ * @param params.labels - Existing resource labels
1850
+ * @param params.ownerLabel - Existing `sdk-name` label, when present
1851
+ * @param params.appName - Current application name
1852
+ * @param params.appId - Current application id, when present
1853
+ * @param params.resourceType - Resource kind for confirmation messages
1854
+ * @param params.resourceName - Resource name for confirmation messages
1855
+ * @param params.conflicts - Conflict accumulator
1856
+ * @param params.unmanaged - Unmanaged-resource accumulator
1857
+ * @returns True when the resource is owned by the current app
1858
+ */
1859
+ function trackDesiredResourceOwnership(params) {
1860
+ const { labels, ownerLabel, appName, appId, resourceType, resourceName, conflicts, unmanaged } = params;
1861
+ const owned = isOwnedByApp(labels, appName, appId);
1862
+ if (!owned) if (!ownerLabel) unmanaged.push({
1863
+ resourceType,
1864
+ resourceName
1865
+ });
1866
+ else conflicts.push({
1867
+ resourceType,
1868
+ resourceName,
1869
+ currentOwner: ownerLabel
1870
+ });
1871
+ return owned;
1872
+ }
1873
+ /**
1874
+ * Determine whether a remote-only resource is still owned by this app.
1875
+ * Also records other SDK owners so renamed-empty applications can be handled.
1876
+ * @param params - Ownership classification inputs
1877
+ * @param params.labels - Existing resource labels
1878
+ * @param params.ownerLabel - Existing `sdk-name` label, when present
1879
+ * @param params.appName - Current application name
1880
+ * @param params.appId - Current application id, when present
1881
+ * @param params.resourceOwners - Other-owner accumulator
1882
+ * @returns True when the resource is owned by the current app
1883
+ */
1884
+ function trackRemainingResourceOwner(params) {
1885
+ const { labels, ownerLabel, appName, appId, resourceOwners } = params;
1886
+ const owned = isOwnedByApp(labels, appName, appId);
1887
+ if (ownerLabel && !owned) resourceOwners.add(ownerLabel);
1888
+ return owned;
1889
+ }
1890
+
1891
+ //#endregion
1892
+ //#region src/cli/commands/deploy/aigateway.ts
1893
+ /**
1894
+ * Apply AI Gateway changes for the given phase.
1895
+ * @param client - Operator client instance
1896
+ * @param result - Planned AI Gateway changes
1897
+ * @param phase - Apply phase
1898
+ * @returns Promise that resolves when AI Gateways are applied
1899
+ */
1900
+ async function applyAIGateway(client, result, phase = "create-update") {
1901
+ const { changeSet } = result;
1902
+ if (phase === "create-update") await Promise.all([...changeSet.creates.map(async (create) => {
1903
+ create.request.cors = await resolveStaticWebsiteUrls(client, assertDefined(create.request.workspaceId, "request missing workspaceId"), create.request.cors, "AIGateway CORS");
1904
+ await client.createAIGateway(create.request);
1905
+ await client.setMetadata(create.metaRequest);
1906
+ }), ...changeSet.updates.map(async (update) => {
1907
+ update.request.cors = await resolveStaticWebsiteUrls(client, assertDefined(update.request.workspaceId, "request missing workspaceId"), update.request.cors, "AIGateway CORS");
1908
+ await client.updateAIGateway(update.request);
1909
+ await client.setMetadata(update.metaRequest);
1910
+ })]);
1911
+ else await Promise.all(changeSet.deletes.map((del) => client.deleteAIGateway(del.request)));
1912
+ }
1913
+ function normalizeComparableAIGatewayShape(input) {
1914
+ return {
1915
+ authNamespace: input.authNamespace,
1916
+ cors: input.cors.toSorted()
1917
+ };
1918
+ }
1919
+ function normalizeComparableAIGateway(input) {
1920
+ return normalizeComparableAIGatewayShape({
1921
+ authNamespace: input.authNamespace || "",
1922
+ cors: [...input.cors || []]
1923
+ });
1924
+ }
1925
+ function areAIGatewaysEqual(existing, desired) {
1926
+ return areNormalizedEqual(normalizeComparableAIGateway(existing), normalizeComparableAIGateway(desired));
1927
+ }
1928
+ /**
1929
+ * Plan AI Gateway changes based on current and desired state.
1930
+ * @param context - Planning context
1931
+ * @returns Planned changes
1932
+ */
1933
+ async function planAIGateway(context) {
1934
+ const { client, workspaceId, application, forRemoval } = context;
1935
+ const changeSet = createChangeSet("AIGateways");
1936
+ const conflicts = [];
1937
+ const unmanaged = [];
1938
+ const resourceOwners = /* @__PURE__ */ new Set();
1939
+ const existingGateways = await fetchExistingResourcesWithLabels({
1940
+ client,
1941
+ workspaceId,
1942
+ fetchPage: async (pageToken, pageSize) => {
1943
+ const { aigateways, nextPageToken } = await client.listAIGateways({
1944
+ workspaceId,
1945
+ pageToken,
1946
+ pageSize
1947
+ });
1948
+ return [aigateways, nextPageToken];
1949
+ },
1950
+ getName: (resource) => resource.name,
1951
+ getTrn: (workspaceId, name) => resourceTrn(workspaceId, "aigateway", name)
1952
+ });
1953
+ const aiGatewayServices = forRemoval ? [] : application.aiGatewayServices;
1954
+ const expectedLocalWebsites = new Set(application.staticWebsiteServices.map((website) => website.name));
1955
+ for (const gatewayService of aiGatewayServices) {
1956
+ const config = gatewayService;
1957
+ const name = gatewayService.name;
1958
+ const existing = existingGateways[name];
1959
+ const metaRequest = await buildMetaRequest({
1960
+ trn: resourceTrn(workspaceId, "aigateway", name),
1961
+ appName: application.name,
1962
+ appId: application.id
1963
+ });
1964
+ const resolvedCors = await resolveStaticWebsiteUrls(client, workspaceId, config.cors ? [...config.cors] : [], "AIGateway CORS", { expectedLocalNames: expectedLocalWebsites });
1965
+ const desired = normalizeComparableAIGateway({
1966
+ ...config,
1967
+ cors: resolvedCors
1968
+ });
1969
+ const request = {
1970
+ workspaceId,
1971
+ aigatewayName: name,
1972
+ authNamespace: config.authNamespace,
1973
+ cors: config.cors ? [...config.cors] : []
1974
+ };
1975
+ if (existing) {
1976
+ if (trackDesiredResourceOwnership({
1977
+ labels: existing.allLabels,
1978
+ ownerLabel: existing.label,
1979
+ appName: application.name,
1980
+ appId: application.id,
1981
+ resourceType: "AIGateway",
1982
+ resourceName: name,
1983
+ conflicts,
1984
+ unmanaged
1985
+ }) && hasMatchingSdkVersion(existing.allLabels, metaRequest.labels) && areAIGatewaysEqual(existing.resource, desired)) changeSet.unchanged.push({ name });
1986
+ else changeSet.updates.push({
1987
+ name,
1988
+ request,
1989
+ metaRequest
1990
+ });
1991
+ delete existingGateways[name];
1992
+ } else changeSet.creates.push({
1993
+ name,
1994
+ request,
1995
+ metaRequest
1996
+ });
1997
+ }
1998
+ Object.entries(existingGateways).forEach(([name, entry]) => {
1999
+ const label = entry?.label;
2000
+ if (trackRemainingResourceOwner({
2001
+ labels: entry?.allLabels,
2002
+ ownerLabel: label,
2003
+ appName: application.name,
2004
+ appId: application.id,
2005
+ resourceOwners
2006
+ })) changeSet.deletes.push({
2007
+ name,
2008
+ request: {
2009
+ workspaceId,
2010
+ aigatewayName: name
2011
+ }
2012
+ });
2013
+ });
2014
+ return {
2015
+ changeSet,
2016
+ conflicts,
2017
+ unmanaged,
2018
+ resourceOwners
2019
+ };
2020
+ }
2021
+
1809
2022
  //#endregion
1810
2023
  //#region src/cli/commands/deploy/application.ts
1811
2024
  /**
@@ -3003,7 +3216,7 @@ function parseIdPPermission(rawPermission) {
3003
3216
  function findOmittedPermitRules(permission) {
3004
3217
  if (!permission) return [];
3005
3218
  const locations = [];
3006
- for (const action of Object.keys(permission)) permission[action]?.forEach((rule, index) => {
3219
+ for (const action of Object.keys(permission)) permission[action].forEach((rule, index) => {
3007
3220
  if (isObjectFormat(rule) && rule.permit === void 0) locations.push(`${String(action)}[${index}]`);
3008
3221
  });
3009
3222
  return locations;
@@ -4900,88 +5113,6 @@ function normalizeAuthInvoker(authInvoker, authNamespace, context) {
4900
5113
  return authInvoker;
4901
5114
  }
4902
5115
 
4903
- //#endregion
4904
- //#region src/cli/commands/deploy/owned-resource.ts
4905
- /**
4906
- * Fetch a workspace-scoped resource list and attach SDK ownership metadata.
4907
- * @template T
4908
- * @param params - Resource fetch parameters
4909
- * @param params.client - Operator client instance
4910
- * @param params.workspaceId - Workspace ID
4911
- * @param params.fetchPage - Function that fetches one resource page
4912
- * @param params.getName - Function that extracts the resource name
4913
- * @param params.getTrn - Function that builds the resource TRN
4914
- * @returns Existing resources keyed by resource name, with SDK labels attached
4915
- */
4916
- async function fetchExistingResourcesWithLabels(params) {
4917
- const { client, workspaceId, fetchPage, getName, getTrn } = params;
4918
- const withoutLabel = await fetchAll(async (pageToken, maxPageSize) => {
4919
- try {
4920
- return await fetchPage(pageToken, maxPageSize);
4921
- } catch (error) {
4922
- if (error instanceof ConnectError && error.code === Code.NotFound) return [[], ""];
4923
- throw error;
4924
- }
4925
- });
4926
- const existingResources = {};
4927
- await Promise.all(withoutLabel.map(async (resource) => {
4928
- const name = getName(resource);
4929
- if (!name) return;
4930
- const { metadata } = await client.getMetadata({ trn: getTrn(workspaceId, name) });
4931
- existingResources[name] = {
4932
- resource,
4933
- label: metadata?.labels[sdkNameLabelKey],
4934
- allLabels: metadata?.labels
4935
- };
4936
- }));
4937
- return existingResources;
4938
- }
4939
- /**
4940
- * Determine whether a same-named existing resource is managed by this app.
4941
- * Records the user-facing confirmation data when ownership does not match.
4942
- * @param params - Ownership classification inputs
4943
- * @param params.labels - Existing resource labels
4944
- * @param params.ownerLabel - Existing `sdk-name` label, when present
4945
- * @param params.appName - Current application name
4946
- * @param params.appId - Current application id, when present
4947
- * @param params.resourceType - Resource kind for confirmation messages
4948
- * @param params.resourceName - Resource name for confirmation messages
4949
- * @param params.conflicts - Conflict accumulator
4950
- * @param params.unmanaged - Unmanaged-resource accumulator
4951
- * @returns True when the resource is owned by the current app
4952
- */
4953
- function trackDesiredResourceOwnership(params) {
4954
- const { labels, ownerLabel, appName, appId, resourceType, resourceName, conflicts, unmanaged } = params;
4955
- const owned = isOwnedByApp(labels, appName, appId);
4956
- if (!owned) if (!ownerLabel) unmanaged.push({
4957
- resourceType,
4958
- resourceName
4959
- });
4960
- else conflicts.push({
4961
- resourceType,
4962
- resourceName,
4963
- currentOwner: ownerLabel
4964
- });
4965
- return owned;
4966
- }
4967
- /**
4968
- * Determine whether a remote-only resource is still owned by this app.
4969
- * Also records other SDK owners so renamed-empty applications can be handled.
4970
- * @param params - Ownership classification inputs
4971
- * @param params.labels - Existing resource labels
4972
- * @param params.ownerLabel - Existing `sdk-name` label, when present
4973
- * @param params.appName - Current application name
4974
- * @param params.appId - Current application id, when present
4975
- * @param params.resourceOwners - Other-owner accumulator
4976
- * @returns True when the resource is owned by the current app
4977
- */
4978
- function trackRemainingResourceOwner(params) {
4979
- const { labels, ownerLabel, appName, appId, resourceOwners } = params;
4980
- const owned = isOwnedByApp(labels, appName, appId);
4981
- if (ownerLabel && !owned) resourceOwners.add(ownerLabel);
4982
- return owned;
4983
- }
4984
-
4985
5116
  //#endregion
4986
5117
  //#region src/cli/commands/deploy/executor.ts
4987
5118
  /**
@@ -6411,6 +6542,317 @@ function parseMigrationNumberArg(numberStr) {
6411
6542
  throw new Error(`Invalid migration number format: ${numberStr}. Expected 4-digit format (e.g., 0001) or integer 0-9999 (e.g., 1).`);
6412
6543
  }
6413
6544
 
6545
+ //#endregion
6546
+ //#region src/cli/commands/tailordb/migrate/snapshot-schema.ts
6547
+ /**
6548
+ * Zod schemas for TailorDB migration snapshot and diff files.
6549
+ *
6550
+ * Each schema mirrors the corresponding hand-written interface from
6551
+ * snapshot-types.ts / diff-calculator.ts. Schemas are cast to
6552
+ * `z.ZodType<T>` to keep them aligned with the interfaces at compile time.
6553
+ *
6554
+ * All object schemas use `z.looseObject` so that unknown keys written
6555
+ * by newer CLI versions survive a load → save round-trip.
6556
+ */
6557
+ const snapshotHookSchema = z.looseObject({ expr: z.string() });
6558
+ const snapshotValidationSchema = z.looseObject({
6559
+ script: z.looseObject({ expr: z.string() }).optional(),
6560
+ errorMessage: z.string()
6561
+ });
6562
+ const snapshotSerialSchema = z.looseObject({
6563
+ start: z.number(),
6564
+ maxValue: z.number().optional(),
6565
+ format: z.string().optional()
6566
+ });
6567
+ const snapshotEnumValueSchema = z.looseObject({
6568
+ value: z.string(),
6569
+ description: z.string().optional()
6570
+ });
6571
+ const snapshotFieldConfigSchema = z.looseObject({
6572
+ type: z.string(),
6573
+ required: z.boolean().default(true),
6574
+ array: z.boolean().optional(),
6575
+ index: z.boolean().optional(),
6576
+ unique: z.boolean().optional(),
6577
+ allowedValues: z.array(snapshotEnumValueSchema).optional(),
6578
+ foreignKey: z.boolean().optional(),
6579
+ foreignKeyType: z.string().optional(),
6580
+ foreignKeyField: z.string().optional(),
6581
+ description: z.string().optional(),
6582
+ vector: z.boolean().optional(),
6583
+ hooks: z.looseObject({
6584
+ create: snapshotHookSchema.optional(),
6585
+ update: snapshotHookSchema.optional()
6586
+ }).optional(),
6587
+ validate: z.array(snapshotValidationSchema).optional(),
6588
+ serial: snapshotSerialSchema.optional(),
6589
+ scale: z.number().optional(),
6590
+ fields: z.lazy(() => z.record(z.string(), snapshotFieldConfigSchema)).optional()
6591
+ });
6592
+ const snapshotIndexConfigSchema = z.looseObject({
6593
+ fields: z.array(z.string()),
6594
+ unique: z.boolean().optional()
6595
+ });
6596
+ const snapshotRelationshipSchema = z.looseObject({
6597
+ targetType: z.string(),
6598
+ targetField: z.string(),
6599
+ sourceField: z.string(),
6600
+ isArray: z.boolean(),
6601
+ description: z.string()
6602
+ });
6603
+ const FIELD_REF_KEYS = [
6604
+ "user",
6605
+ "record",
6606
+ "newRecord",
6607
+ "oldRecord"
6608
+ ];
6609
+ const snapshotPermissionOperandSchema = z.unknown().refine((v) => {
6610
+ if (typeof v !== "object" || v === null || Array.isArray(v)) return true;
6611
+ const keys = Object.keys(v);
6612
+ return FIELD_REF_KEYS.filter((k) => keys.includes(k)).length < 2;
6613
+ }, "Ambiguous field-ref operand: contains more than one of user/record/newRecord/oldRecord");
6614
+ const snapshotGqlPermissionOperandSchema = z.unknown().refine((v) => {
6615
+ if (typeof v !== "object" || v === null || Array.isArray(v)) return true;
6616
+ const keys = Object.keys(v);
6617
+ return FIELD_REF_KEYS.filter((k) => keys.includes(k)).length < 2;
6618
+ }, "Ambiguous field-ref operand: contains more than one of user/record/newRecord/oldRecord").refine((v) => {
6619
+ if (typeof v !== "object" || v === null || Array.isArray(v)) return true;
6620
+ const keys = Object.keys(v);
6621
+ return ![
6622
+ "record",
6623
+ "newRecord",
6624
+ "oldRecord"
6625
+ ].some((k) => keys.includes(k));
6626
+ }, "GQL permissions only support { user } field references");
6627
+ const snapshotPermissionOperatorSchema = z.string();
6628
+ const snapshotPermissionConditionSchema = z.tuple([
6629
+ snapshotPermissionOperandSchema,
6630
+ snapshotPermissionOperatorSchema,
6631
+ snapshotPermissionOperandSchema
6632
+ ]).rest(z.unknown());
6633
+ const snapshotGqlPermissionConditionSchema = z.tuple([
6634
+ snapshotGqlPermissionOperandSchema,
6635
+ snapshotPermissionOperatorSchema,
6636
+ snapshotGqlPermissionOperandSchema
6637
+ ]).rest(z.unknown());
6638
+ const snapshotActionPermissionSchema = z.looseObject({
6639
+ conditions: z.array(snapshotPermissionConditionSchema),
6640
+ description: z.string().optional(),
6641
+ permit: z.enum(["allow", "deny"])
6642
+ });
6643
+ const snapshotRecordPermissionSchema = z.looseObject({
6644
+ create: z.array(snapshotActionPermissionSchema).default([]),
6645
+ read: z.array(snapshotActionPermissionSchema).default([]),
6646
+ update: z.array(snapshotActionPermissionSchema).default([]),
6647
+ delete: z.array(snapshotActionPermissionSchema).default([])
6648
+ });
6649
+ const snapshotGqlActionSchema = z.string();
6650
+ const snapshotGqlPermissionPolicySchema = z.looseObject({
6651
+ conditions: z.array(snapshotGqlPermissionConditionSchema),
6652
+ actions: z.array(snapshotGqlActionSchema),
6653
+ permit: z.enum(["allow", "deny"]),
6654
+ description: z.string().optional()
6655
+ });
6656
+ const snapshotGqlPermissionSchema = z.array(snapshotGqlPermissionPolicySchema);
6657
+ const tailorDBSnapshotTypeSchema = z.looseObject({
6658
+ name: z.string(),
6659
+ pluralForm: z.string().optional(),
6660
+ description: z.string().optional(),
6661
+ fields: z.record(z.string(), snapshotFieldConfigSchema),
6662
+ settings: z.looseObject({
6663
+ aggregation: z.boolean().optional(),
6664
+ bulkUpsert: z.boolean().optional(),
6665
+ gqlOperations: z.looseObject({
6666
+ create: z.boolean().optional(),
6667
+ update: z.boolean().optional(),
6668
+ delete: z.boolean().optional(),
6669
+ read: z.boolean().optional()
6670
+ }).optional(),
6671
+ publishEvents: z.boolean().optional()
6672
+ }).optional(),
6673
+ indexes: z.record(z.string(), snapshotIndexConfigSchema).optional(),
6674
+ files: z.record(z.string(), z.string()).optional(),
6675
+ forwardRelationships: z.record(z.string(), snapshotRelationshipSchema).optional(),
6676
+ backwardRelationships: z.record(z.string(), snapshotRelationshipSchema).optional(),
6677
+ permissions: z.looseObject({
6678
+ record: snapshotRecordPermissionSchema.optional(),
6679
+ gql: snapshotGqlPermissionSchema.optional()
6680
+ }).optional()
6681
+ });
6682
+ const schemaSnapshotSchema = z.looseObject({
6683
+ version: z.number(),
6684
+ namespace: z.string(),
6685
+ createdAt: z.string(),
6686
+ types: z.record(z.string(), tailorDBSnapshotTypeSchema)
6687
+ });
6688
+ const typeSettingsPatchSchema = z.looseObject({
6689
+ indexes: z.record(z.string(), snapshotIndexConfigSchema).optional(),
6690
+ files: z.record(z.string(), z.string()).optional()
6691
+ });
6692
+ const snapshotPermissionStateSchema = z.looseObject({
6693
+ recordPermission: snapshotRecordPermissionSchema.optional(),
6694
+ gqlPermission: snapshotGqlPermissionSchema.optional()
6695
+ });
6696
+ const typeAddedChangeSchema = z.looseObject({
6697
+ kind: z.literal("type_added"),
6698
+ typeName: z.string(),
6699
+ reason: z.string().optional(),
6700
+ after: tailorDBSnapshotTypeSchema
6701
+ });
6702
+ const typeRemovedChangeSchema = z.looseObject({
6703
+ kind: z.literal("type_removed"),
6704
+ typeName: z.string(),
6705
+ reason: z.string().optional(),
6706
+ before: tailorDBSnapshotTypeSchema
6707
+ });
6708
+ const typeModifiedChangeSchema = z.looseObject({
6709
+ kind: z.literal("type_modified"),
6710
+ typeName: z.string(),
6711
+ reason: z.string().optional(),
6712
+ before: typeSettingsPatchSchema.optional(),
6713
+ after: typeSettingsPatchSchema.optional()
6714
+ });
6715
+ const fieldAddedChangeSchema = z.looseObject({
6716
+ kind: z.literal("field_added"),
6717
+ typeName: z.string(),
6718
+ reason: z.string().optional(),
6719
+ fieldName: z.string(),
6720
+ after: snapshotFieldConfigSchema
6721
+ });
6722
+ const fieldRemovedChangeSchema = z.looseObject({
6723
+ kind: z.literal("field_removed"),
6724
+ typeName: z.string(),
6725
+ reason: z.string().optional(),
6726
+ fieldName: z.string(),
6727
+ before: snapshotFieldConfigSchema
6728
+ });
6729
+ const fieldModifiedChangeSchema = z.looseObject({
6730
+ kind: z.literal("field_modified"),
6731
+ typeName: z.string(),
6732
+ reason: z.string().optional(),
6733
+ fieldName: z.string(),
6734
+ before: snapshotFieldConfigSchema,
6735
+ after: snapshotFieldConfigSchema
6736
+ });
6737
+ const indexAddedChangeSchema = z.looseObject({
6738
+ kind: z.literal("index_added"),
6739
+ typeName: z.string(),
6740
+ reason: z.string().optional(),
6741
+ indexName: z.string(),
6742
+ after: snapshotIndexConfigSchema
6743
+ });
6744
+ const indexRemovedChangeSchema = z.looseObject({
6745
+ kind: z.literal("index_removed"),
6746
+ typeName: z.string(),
6747
+ reason: z.string().optional(),
6748
+ indexName: z.string(),
6749
+ before: snapshotIndexConfigSchema
6750
+ });
6751
+ const indexModifiedChangeSchema = z.looseObject({
6752
+ kind: z.literal("index_modified"),
6753
+ typeName: z.string(),
6754
+ reason: z.string().optional(),
6755
+ indexName: z.string(),
6756
+ before: snapshotIndexConfigSchema,
6757
+ after: snapshotIndexConfigSchema
6758
+ });
6759
+ const fileAddedChangeSchema = z.looseObject({
6760
+ kind: z.literal("file_added"),
6761
+ typeName: z.string(),
6762
+ reason: z.string().optional(),
6763
+ fieldName: z.string(),
6764
+ after: z.string()
6765
+ });
6766
+ const fileRemovedChangeSchema = z.looseObject({
6767
+ kind: z.literal("file_removed"),
6768
+ typeName: z.string(),
6769
+ reason: z.string().optional(),
6770
+ fieldName: z.string(),
6771
+ before: z.string()
6772
+ });
6773
+ const fileModifiedChangeSchema = z.looseObject({
6774
+ kind: z.literal("file_modified"),
6775
+ typeName: z.string(),
6776
+ reason: z.string().optional(),
6777
+ fieldName: z.string(),
6778
+ before: z.string(),
6779
+ after: z.string()
6780
+ });
6781
+ const relationshipAddedChangeSchema = z.looseObject({
6782
+ kind: z.literal("relationship_added"),
6783
+ typeName: z.string(),
6784
+ reason: z.string().optional(),
6785
+ relationshipName: z.string(),
6786
+ relationshipType: z.enum(["forward", "backward"]).optional(),
6787
+ after: snapshotRelationshipSchema
6788
+ });
6789
+ const relationshipRemovedChangeSchema = z.looseObject({
6790
+ kind: z.literal("relationship_removed"),
6791
+ typeName: z.string(),
6792
+ reason: z.string().optional(),
6793
+ relationshipName: z.string(),
6794
+ relationshipType: z.enum(["forward", "backward"]).optional(),
6795
+ before: snapshotRelationshipSchema
6796
+ });
6797
+ const relationshipModifiedChangeSchema = z.looseObject({
6798
+ kind: z.literal("relationship_modified"),
6799
+ typeName: z.string(),
6800
+ reason: z.string().optional(),
6801
+ relationshipName: z.string(),
6802
+ relationshipType: z.enum(["forward", "backward"]).optional(),
6803
+ before: snapshotRelationshipSchema,
6804
+ after: snapshotRelationshipSchema
6805
+ });
6806
+ const permissionModifiedChangeSchema = z.looseObject({
6807
+ kind: z.literal("permission_modified"),
6808
+ typeName: z.string(),
6809
+ reason: z.string().optional(),
6810
+ before: snapshotPermissionStateSchema.optional(),
6811
+ after: snapshotPermissionStateSchema.optional()
6812
+ });
6813
+ const diffChangeSchema = z.discriminatedUnion("kind", [
6814
+ typeAddedChangeSchema,
6815
+ typeRemovedChangeSchema,
6816
+ typeModifiedChangeSchema,
6817
+ fieldAddedChangeSchema,
6818
+ fieldRemovedChangeSchema,
6819
+ fieldModifiedChangeSchema,
6820
+ indexAddedChangeSchema,
6821
+ indexRemovedChangeSchema,
6822
+ indexModifiedChangeSchema,
6823
+ fileAddedChangeSchema,
6824
+ fileRemovedChangeSchema,
6825
+ fileModifiedChangeSchema,
6826
+ relationshipAddedChangeSchema,
6827
+ relationshipRemovedChangeSchema,
6828
+ relationshipModifiedChangeSchema,
6829
+ permissionModifiedChangeSchema
6830
+ ]);
6831
+ const breakingChangeInfoSchema = z.looseObject({
6832
+ typeName: z.string(),
6833
+ fieldName: z.string().optional(),
6834
+ reason: z.string(),
6835
+ unsupported: z.boolean().optional(),
6836
+ showThreeStepHint: z.boolean().optional()
6837
+ });
6838
+ const warningChangeInfoSchema = z.looseObject({
6839
+ typeName: z.string(),
6840
+ fieldName: z.string().optional(),
6841
+ reason: z.string()
6842
+ });
6843
+ const migrationDiffSchema = z.looseObject({
6844
+ version: z.number(),
6845
+ namespace: z.string(),
6846
+ createdAt: z.string(),
6847
+ description: z.string().optional(),
6848
+ changes: z.array(diffChangeSchema),
6849
+ hasBreakingChanges: z.boolean(),
6850
+ breakingChanges: z.array(breakingChangeInfoSchema),
6851
+ hasWarnings: z.boolean().optional(),
6852
+ warnings: z.array(warningChangeInfoSchema).optional(),
6853
+ requiresMigrationScript: z.boolean()
6854
+ });
6855
+
6414
6856
  //#endregion
6415
6857
  //#region src/cli/commands/tailordb/migrate/snapshot-types.ts
6416
6858
  /**
@@ -6620,21 +7062,19 @@ function createSnapshotType(type) {
6620
7062
  fields
6621
7063
  };
6622
7064
  if (type.description) snapshotType.description = type.description;
6623
- if (type.settings) {
6624
- snapshotType.settings = {};
6625
- if (type.settings.aggregation !== void 0) snapshotType.settings.aggregation = type.settings.aggregation;
6626
- if (type.settings.bulkUpsert !== void 0) snapshotType.settings.bulkUpsert = type.settings.bulkUpsert;
6627
- if (type.settings.gqlOperations) {
6628
- const ops = type.settings.gqlOperations;
6629
- snapshotType.settings.gqlOperations = {
6630
- ...ops.create !== void 0 && { create: ops.create },
6631
- ...ops.update !== void 0 && { update: ops.update },
6632
- ...ops.delete !== void 0 && { delete: ops.delete },
6633
- ...ops.read !== void 0 && { read: ops.read }
6634
- };
6635
- }
6636
- if (type.settings.publishEvents !== void 0) snapshotType.settings.publishEvents = type.settings.publishEvents;
7065
+ snapshotType.settings = {};
7066
+ if (type.settings.aggregation !== void 0) snapshotType.settings.aggregation = type.settings.aggregation;
7067
+ if (type.settings.bulkUpsert !== void 0) snapshotType.settings.bulkUpsert = type.settings.bulkUpsert;
7068
+ if (type.settings.gqlOperations) {
7069
+ const ops = type.settings.gqlOperations;
7070
+ snapshotType.settings.gqlOperations = {
7071
+ ...ops.create !== void 0 && { create: ops.create },
7072
+ ...ops.update !== void 0 && { update: ops.update },
7073
+ ...ops.delete !== void 0 && { delete: ops.delete },
7074
+ ...ops.read !== void 0 && { read: ops.read }
7075
+ };
6637
7076
  }
7077
+ if (type.settings.publishEvents !== void 0) snapshotType.settings.publishEvents = type.settings.publishEvents;
6638
7078
  if (type.indexes && Object.keys(type.indexes).length > 0) {
6639
7079
  snapshotType.indexes = {};
6640
7080
  for (const [indexName, indexConfig] of Object.entries(type.indexes)) snapshotType.indexes[indexName] = {
@@ -6715,7 +7155,15 @@ function createSnapshotFromLocalTypes(types, namespace) {
6715
7155
  */
6716
7156
  function loadSnapshot(filePath) {
6717
7157
  const content = fs$1.readFileSync(filePath, "utf-8");
6718
- const snapshot = JSON.parse(content);
7158
+ let raw;
7159
+ try {
7160
+ raw = JSON.parse(content);
7161
+ } catch (error) {
7162
+ throw new Error(`Invalid schema snapshot at ${filePath}: ${String(error)}`, { cause: error });
7163
+ }
7164
+ const result = schemaSnapshotSchema.safeParse(raw);
7165
+ if (!result.success) throw new Error(`Invalid schema snapshot at ${filePath}: ${z.prettifyError(result.error)}`, { cause: result.error });
7166
+ const snapshot = result.data;
6719
7167
  for (const type of Object.values(snapshot.types)) normalizeSnapshotType(type);
6720
7168
  return snapshot;
6721
7169
  }
@@ -6726,7 +7174,15 @@ function loadSnapshot(filePath) {
6726
7174
  */
6727
7175
  function loadDiff(filePath) {
6728
7176
  const content = fs$1.readFileSync(filePath, "utf-8");
6729
- const parsed = JSON.parse(content);
7177
+ let raw;
7178
+ try {
7179
+ raw = JSON.parse(content);
7180
+ } catch (error) {
7181
+ throw new Error(`Invalid migration diff at ${filePath}: ${String(error)}`, { cause: error });
7182
+ }
7183
+ const result = migrationDiffSchema.safeParse(raw);
7184
+ if (!result.success) throw new Error(`Invalid migration diff at ${filePath}: ${z.prettifyError(result.error)}`, { cause: result.error });
7185
+ const parsed = result.data;
6730
7186
  const warnings = parsed.warnings ?? [];
6731
7187
  return {
6732
7188
  ...parsed,
@@ -6804,7 +7260,7 @@ function applyDiffToSnapshot(snapshot, diff) {
6804
7260
  case "field_added":
6805
7261
  case "field_modified": {
6806
7262
  const existing = types[change.typeName];
6807
- if (existing && change.fieldName) types[change.typeName] = {
7263
+ if (existing) types[change.typeName] = {
6808
7264
  ...existing,
6809
7265
  fields: {
6810
7266
  ...existing.fields,
@@ -6815,7 +7271,7 @@ function applyDiffToSnapshot(snapshot, diff) {
6815
7271
  }
6816
7272
  case "field_removed": {
6817
7273
  const existing = types[change.typeName];
6818
- if (existing && change.fieldName) {
7274
+ if (existing) {
6819
7275
  const { [change.fieldName]: _, ...remainingFields } = existing.fields;
6820
7276
  types[change.typeName] = {
6821
7277
  ...existing,
@@ -6827,7 +7283,7 @@ function applyDiffToSnapshot(snapshot, diff) {
6827
7283
  case "index_added":
6828
7284
  case "index_modified": {
6829
7285
  const existing = types[change.typeName];
6830
- if (existing && change.indexName) types[change.typeName] = {
7286
+ if (existing) types[change.typeName] = {
6831
7287
  ...existing,
6832
7288
  indexes: {
6833
7289
  ...existing.indexes,
@@ -6838,7 +7294,7 @@ function applyDiffToSnapshot(snapshot, diff) {
6838
7294
  }
6839
7295
  case "index_removed": {
6840
7296
  const existing = types[change.typeName];
6841
- if (existing && change.indexName && existing.indexes) {
7297
+ if (existing && existing.indexes) {
6842
7298
  const { [change.indexName]: _, ...remainingIndexes } = existing.indexes;
6843
7299
  types[change.typeName] = {
6844
7300
  ...existing,
@@ -6850,7 +7306,7 @@ function applyDiffToSnapshot(snapshot, diff) {
6850
7306
  case "file_added":
6851
7307
  case "file_modified": {
6852
7308
  const existing = types[change.typeName];
6853
- if (existing && change.fieldName) types[change.typeName] = {
7309
+ if (existing) types[change.typeName] = {
6854
7310
  ...existing,
6855
7311
  files: {
6856
7312
  ...existing.files,
@@ -6861,7 +7317,7 @@ function applyDiffToSnapshot(snapshot, diff) {
6861
7317
  }
6862
7318
  case "file_removed": {
6863
7319
  const existing = types[change.typeName];
6864
- if (existing && change.fieldName && existing.files) {
7320
+ if (existing && existing.files) {
6865
7321
  const { [change.fieldName]: _, ...remainingFiles } = existing.files;
6866
7322
  types[change.typeName] = {
6867
7323
  ...existing,
@@ -6873,7 +7329,7 @@ function applyDiffToSnapshot(snapshot, diff) {
6873
7329
  case "relationship_added":
6874
7330
  case "relationship_modified": {
6875
7331
  const existing = types[change.typeName];
6876
- if (existing && change.relationshipName) {
7332
+ if (existing) {
6877
7333
  const rel = change.after;
6878
7334
  if ((change.relationshipType ?? (existing.forwardRelationships?.[change.relationshipName] ? "forward" : existing.backwardRelationships?.[change.relationshipName] ? "backward" : "forward")) === "forward") types[change.typeName] = {
6879
7335
  ...existing,
@@ -6894,7 +7350,7 @@ function applyDiffToSnapshot(snapshot, diff) {
6894
7350
  }
6895
7351
  case "relationship_removed": {
6896
7352
  const type = types[change.typeName];
6897
- if (type && change.relationshipName) {
7353
+ if (type) {
6898
7354
  const targetType = change.relationshipType ?? (type.forwardRelationships?.[change.relationshipName] ? "forward" : type.backwardRelationships?.[change.relationshipName] ? "backward" : null);
6899
7355
  if (targetType === "forward" && type.forwardRelationships?.[change.relationshipName]) {
6900
7356
  const { [change.relationshipName]: _, ...remaining } = type.forwardRelationships;
@@ -7004,7 +7460,7 @@ function areFieldsDifferent(oldField, newField) {
7004
7460
  for (let i = 0; i < oldValidate.length; i++) {
7005
7461
  const oldV = assertDefined(oldValidate[i], `oldValidate missing index ${i}`);
7006
7462
  const newV = assertDefined(newValidate[i], `newValidate missing index ${i}`);
7007
- if (oldV.script.expr !== newV.script.expr) return true;
7463
+ if ((oldV.script?.expr ?? "") !== (newV.script?.expr ?? "")) return true;
7008
7464
  if (oldV.errorMessage !== newV.errorMessage) return true;
7009
7465
  }
7010
7466
  const oldSerial = oldField.serial;
@@ -7452,7 +7908,7 @@ function convertRemoteFieldsToSnapshot(remoteType) {
7452
7908
  if (remoteField.foreignKeyType) config.foreignKeyType = remoteField.foreignKeyType;
7453
7909
  if (remoteField.foreignKeyField) config.foreignKeyField = remoteField.foreignKeyField;
7454
7910
  }
7455
- if (remoteField.allowedValues && remoteField.allowedValues.length > 0) config.allowedValues = remoteField.allowedValues.map((v) => ({
7911
+ if (remoteField.allowedValues.length > 0) config.allowedValues = remoteField.allowedValues.map((v) => ({
7456
7912
  value: v.value,
7457
7913
  ...v.description && { description: v.description }
7458
7914
  }));
@@ -7463,7 +7919,7 @@ function convertRemoteFieldsToSnapshot(remoteType) {
7463
7919
  if (remoteField.hooks.create?.expr) config.hooks.create = { expr: remoteField.hooks.create.expr };
7464
7920
  if (remoteField.hooks.update?.expr) config.hooks.update = { expr: remoteField.hooks.update.expr };
7465
7921
  }
7466
- if (remoteField.validate && remoteField.validate.length > 0) config.validate = remoteField.validate.map((v) => ({
7922
+ if (remoteField.validate.length > 0) config.validate = remoteField.validate.map((v) => ({
7467
7923
  script: { expr: v.script?.expr ?? "" },
7468
7924
  errorMessage: v.errorMessage ?? ""
7469
7925
  }));
@@ -7687,7 +8143,7 @@ function convertFieldConfigToProto(config) {
7687
8143
  foreignKey: config.foreignKey ?? false,
7688
8144
  foreignKeyType: config.foreignKeyType,
7689
8145
  foreignKeyField: config.foreignKeyField,
7690
- required: config.required ?? true,
8146
+ required: config.required,
7691
8147
  vector: config.vector ?? false,
7692
8148
  ...toProtoSnapshotFieldHooks(config),
7693
8149
  ...config.serial && { serial: {
@@ -7704,7 +8160,7 @@ function toProtoSnapshotFieldValidate(config) {
7704
8160
  return (config.validate ?? []).map((val) => ({
7705
8161
  action: TailorDBType_PermitAction.DENY,
7706
8162
  errorMessage: val.errorMessage || "",
7707
- ...val.script && { script: { expr: val.script.expr ? `!${val.script.expr}` : "" } }
8163
+ script: { expr: val.script && val.script.expr ? `!${val.script.expr}` : "" }
7708
8164
  }));
7709
8165
  }
7710
8166
  function toProtoSnapshotFieldHooks(config) {
@@ -7728,7 +8184,7 @@ function processNestedFieldsFromSnapshot(fields) {
7728
8184
  allowedValues: fieldConfig.allowedValues?.map((v) => ({ ...v })) ?? [],
7729
8185
  description: fieldConfig.description || "",
7730
8186
  validate: toProtoSnapshotFieldValidate(fieldConfig),
7731
- required: fieldConfig.required ?? true,
8187
+ required: fieldConfig.required,
7732
8188
  array: fieldConfig.array ?? false,
7733
8189
  index: false,
7734
8190
  unique: false,
@@ -7743,7 +8199,7 @@ function processNestedFieldsFromSnapshot(fields) {
7743
8199
  allowedValues: fieldConfig.type === "enum" ? fieldConfig.allowedValues?.map((v) => ({ ...v })) ?? [] : [],
7744
8200
  description: fieldConfig.description || "",
7745
8201
  validate: toProtoSnapshotFieldValidate(fieldConfig),
7746
- required: fieldConfig.required ?? true,
8202
+ required: fieldConfig.required,
7747
8203
  array: fieldConfig.array ?? false,
7748
8204
  index: false,
7749
8205
  unique: false,
@@ -8104,19 +8560,19 @@ function buildPreMigrationChangesMap(pendingMigrations) {
8104
8560
  function applyPreMigrationFieldAdjustments(fields, typeChanges) {
8105
8561
  for (const [fieldName, change] of typeChanges) {
8106
8562
  if (change.kind === "field_removed") {
8107
- if (change.before) fields[fieldName] = convertFieldConfigToProto(change.before);
8563
+ fields[fieldName] = convertFieldConfigToProto(change.before);
8108
8564
  continue;
8109
8565
  }
8110
8566
  const field = fields[fieldName];
8111
8567
  if (!field) continue;
8112
8568
  if (change.kind === "field_added") {
8113
- if (change.after?.required) field.required = false;
8569
+ if (change.after.required) field.required = false;
8114
8570
  continue;
8115
8571
  }
8116
8572
  const { before, after } = change;
8117
- if (!before?.required && after?.required) field.required = false;
8118
- if (!(before?.unique ?? false) && (after?.unique ?? false)) field.unique = false;
8119
- if (before?.allowedValues && after?.allowedValues) {
8573
+ if (!before.required && after.required) field.required = false;
8574
+ if (!(before.unique ?? false) && (after.unique ?? false)) field.unique = false;
8575
+ if (before.allowedValues && after.allowedValues) {
8120
8576
  const afterValues = new Set(after.allowedValues.map((v) => v.value));
8121
8577
  if (before.allowedValues.filter((v) => !afterValues.has(v.value)).length > 0) {
8122
8578
  const valueMap = /* @__PURE__ */ new Map();
@@ -8885,8 +9341,17 @@ async function applyTailorDB(client, result, phase = "create-update") {
8885
9341
  logger.newline();
8886
9342
  }
8887
9343
  for (const migration of pendingMigrations) {
8888
- await executeSingleMigrationPrePhase(client, changeSet, migration, migrationContext.tailorDBInputs, migrationContext.executorUsedTypes);
8889
- if (migration.hasScript && migrationCtx) await executeMigrations(migrationCtx, [migration]);
9344
+ try {
9345
+ await executeSingleMigrationPrePhase(client, changeSet, migration, migrationContext.tailorDBInputs, migrationContext.executorUsedTypes);
9346
+ if (migration.hasScript && migrationCtx) await executeMigrations(migrationCtx, [migration]);
9347
+ } catch (error) {
9348
+ try {
9349
+ await rollbackSingleMigrationPrePhase(client, changeSet, migration, migrationContext.workspaceId, migrationContext.tailorDBInputs, migrationContext.executorUsedTypes);
9350
+ } catch (rollbackError) {
9351
+ logger.warn(`Failed to roll back migration ${migration.namespace}/${formatMigrationNumber(migration.number)}: ${rollbackError instanceof Error ? rollbackError.message : String(rollbackError)}`);
9352
+ }
9353
+ throw error;
9354
+ }
8890
9355
  await executeSingleMigrationPostPhase(client, changeSet, migration, migrationContext.tailorDBInputs, migrationContext.executorUsedTypes);
8891
9356
  await updateMigrationLabel(client, migrationContext.workspaceId, migration.namespace, migration.number);
8892
9357
  }
@@ -9007,6 +9472,17 @@ function buildSnapshotTypeManifest(migration, typeName, tailorDBInputs, executor
9007
9472
  });
9008
9473
  }
9009
9474
  /**
9475
+ * Await every promise to settle, then throw the first rejection. Unlike
9476
+ * `Promise.all`, this never leaves sibling operations in flight after a failure,
9477
+ * so a following rollback cannot race with still-pending DDL.
9478
+ * @param promises - Promises (or already-resolved values) to await
9479
+ * @returns {Promise<void>} Resolves once all settle; rejects with the first failure
9480
+ */
9481
+ async function awaitAllSettledOrThrow(promises) {
9482
+ const rejected = (await Promise.allSettled(promises)).find((r) => r.status === "rejected");
9483
+ if (rejected) throw rejected.reason;
9484
+ }
9485
+ /**
9010
9486
  * Execute pre-migration phase for a single migration
9011
9487
  * @param {OperatorClient} client - Operator client instance
9012
9488
  * @param {TailorDBChangeSet} changeSet - TailorDB change set
@@ -9019,7 +9495,7 @@ async function executeSingleMigrationPrePhase(client, changeSet, migration, tail
9019
9495
  const preMigrationChanges = buildPreMigrationChangesMap([migration]);
9020
9496
  const affectedTypes = getAffectedTypeNames(migration);
9021
9497
  const createdBeforeMigration = new Set(processedTypes.created);
9022
- await Promise.all([
9498
+ await awaitAllSettledOrThrow([
9023
9499
  ...changeSet.type.creates.filter((create) => {
9024
9500
  const typeName = create.request.tailordbType?.name;
9025
9501
  return typeName && affectedTypes.has(typeName) && !createdBeforeMigration.has(typeName);
@@ -9074,13 +9550,13 @@ async function executeSingleMigrationPrePhase(client, changeSet, migration, tail
9074
9550
  const typeName = create.request.tailordbType?.name;
9075
9551
  return create.request.namespaceName === migration.namespace && typeName && gqlPermissionTypeNames.has(typeName) && !processedTypes.created.has(typeName);
9076
9552
  });
9077
- if (missingTypeCreates.length > 0) await Promise.all(missingTypeCreates.map((create) => {
9553
+ if (missingTypeCreates.length > 0) await awaitAllSettledOrThrow(missingTypeCreates.map((create) => {
9078
9554
  const typeName = create.request.tailordbType?.name;
9079
9555
  if (typeName) processedTypes.created.add(typeName);
9080
9556
  return client.createTailorDBType(create.request);
9081
9557
  }));
9082
9558
  processedTypes.gqlPermissionsProcessed.add(migration.namespace);
9083
- await Promise.all([...gqlPermissionCreatesForNamespace.map((create) => client.createTailorDBGQLPermission(create.request)), ...gqlPermissionUpdatesForNamespace.map((update) => client.updateTailorDBGQLPermission(update.request))]);
9559
+ await awaitAllSettledOrThrow([...gqlPermissionCreatesForNamespace.map((create) => client.createTailorDBGQLPermission(create.request)), ...gqlPermissionUpdatesForNamespace.map((update) => client.updateTailorDBGQLPermission(update.request))]);
9084
9560
  }
9085
9561
  }
9086
9562
  /**
@@ -9161,6 +9637,67 @@ async function executeSingleMigrationPostPhase(client, changeSet, migration, tai
9161
9637
  }
9162
9638
  }
9163
9639
  /**
9640
+ * Revert a single migration's Pre-phase DDL to the prior checkpoint's schema.
9641
+ * @param client - Operator client instance
9642
+ * @param changeSet - TailorDB change set
9643
+ * @param migration - The migration whose Pre-phase DDL must be reverted
9644
+ * @param workspaceId - Workspace ID
9645
+ * @param tailorDBInputs - Deploy inputs, used to resolve namespace gqlOperations for the snapshot
9646
+ * @param executorUsedTypes - Types used by executors (drives publishRecordEvents default)
9647
+ * @returns {Promise<void>} Promise that resolves when rollback attempts complete
9648
+ */
9649
+ async function rollbackSingleMigrationPrePhase(client, changeSet, migration, workspaceId, tailorDBInputs, executorUsedTypes) {
9650
+ if (migration.number <= 0) return;
9651
+ const namespaceTypes = getAffectedTypeNames(migration);
9652
+ for (const create of changeSet.type.creates) {
9653
+ const name = create.request.tailordbType?.name;
9654
+ if (create.request.namespaceName === migration.namespace && name) namespaceTypes.add(name);
9655
+ }
9656
+ for (const update of changeSet.type.updates) {
9657
+ const name = update.request.tailordbType?.name;
9658
+ if (update.request.namespaceName === migration.namespace && name) namespaceTypes.add(name);
9659
+ }
9660
+ const applied = new Set([...processedTypes.created, ...processedTypes.updated]);
9661
+ const rollbackTypes = new Set([...namespaceTypes].filter((name) => applied.has(name)));
9662
+ if (rollbackTypes.size === 0) return;
9663
+ const priorSnapshot = reconstructSnapshotFromMigrations(migration.migrationsDir, migration.number - 1);
9664
+ if (!priorSnapshot) {
9665
+ logger.warn(`Cannot roll back migration ${migration.namespace}/${formatMigrationNumber(migration.number)}: prior snapshot (migration ${formatMigrationNumber(migration.number - 1)}) could not be reconstructed. Leaving schema as-is; manual repair may be required.`);
9666
+ return;
9667
+ }
9668
+ const input = tailorDBInputs.find((i) => i.namespace === migration.namespace);
9669
+ logger.warn(`Migration ${migration.namespace}/${formatMigrationNumber(migration.number)} failed; rolling back its pre-migration schema changes.`);
9670
+ for (const typeName of rollbackTypes) {
9671
+ const priorType = priorSnapshot.types[typeName];
9672
+ try {
9673
+ if (priorType) {
9674
+ const manifest = generateTailorDBTypeManifestFromSnapshot(priorType, {
9675
+ publishRecordEvents: executorUsedTypes.has(priorType.name),
9676
+ namespaceGqlOperations: input?.config.gqlOperations
9677
+ });
9678
+ await client.updateTailorDBType({
9679
+ workspaceId,
9680
+ namespaceName: migration.namespace,
9681
+ tailordbType: manifest
9682
+ });
9683
+ } else {
9684
+ await client.deleteTailorDBGQLPermission({
9685
+ workspaceId,
9686
+ namespaceName: migration.namespace,
9687
+ typeName
9688
+ }).catch(() => void 0);
9689
+ await client.deleteTailorDBType({
9690
+ workspaceId,
9691
+ namespaceName: migration.namespace,
9692
+ tailordbTypeName: typeName
9693
+ });
9694
+ }
9695
+ } catch (rollbackError) {
9696
+ logger.warn(`Failed to roll back type '${typeName}' in namespace '${migration.namespace}': ${rollbackError instanceof Error ? rollbackError.message : String(rollbackError)}`);
9697
+ }
9698
+ }
9699
+ }
9700
+ /**
9164
9701
  * Convert a runtime TailorDBService to the snapshot-shaped deploy input.
9165
9702
  * @param service - Loaded TailorDB service (after `loadTypes()`)
9166
9703
  * @returns The canonical snapshot-shaped deploy input for downstream plan/apply phases.
@@ -9579,17 +10116,7 @@ async function checkMigrationDiffs(typesByNamespace, namespacesWithMigrations) {
9579
10116
  for (const { namespace, migrationsDir } of namespacesWithMigrations) {
9580
10117
  const localTypes = typesByNamespace.get(namespace);
9581
10118
  if (!localTypes) continue;
9582
- let previousSnapshot;
9583
- try {
9584
- previousSnapshot = reconstructSnapshotFromMigrations(migrationsDir);
9585
- } catch {
9586
- results.push({
9587
- namespace,
9588
- migrationsDir,
9589
- hasDiff: false
9590
- });
9591
- continue;
9592
- }
10119
+ const previousSnapshot = reconstructSnapshotFromMigrations(migrationsDir);
9593
10120
  if (!previousSnapshot) {
9594
10121
  results.push({
9595
10122
  namespace,
@@ -9677,7 +10204,7 @@ async function applyWorkflow(client, result, phase = "create-update") {
9677
10204
  workflowId: del.workflowId
9678
10205
  })
9679
10206
  })));
9680
- await deleteAllSettled((result.jobFunctionDeletes ?? collectDeletableJobFunctions(changeSet.deletes)).map((del) => ({
10207
+ await deleteAllSettled(result.jobFunctionDeletes.map((del) => ({
9681
10208
  resourceType: "workflow job function",
9682
10209
  resourceName: del.jobFunctionName,
9683
10210
  run: () => client.deleteWorkflowJobFunction({
@@ -9704,20 +10231,6 @@ async function deleteAllSettled(operations) {
9704
10231
  const firstError = errors[0];
9705
10232
  if (firstError) throw firstError;
9706
10233
  }
9707
- function collectDeletableJobFunctions(deletes) {
9708
- const seen = /* @__PURE__ */ new Set();
9709
- const jobFunctions = [];
9710
- for (const del of deletes) for (const jobFunctionName of del.deletableJobNames) {
9711
- const key = `${del.workspaceId}\0${jobFunctionName}`;
9712
- if (seen.has(key)) continue;
9713
- seen.add(key);
9714
- jobFunctions.push({
9715
- workspaceId: del.workspaceId,
9716
- jobFunctionName
9717
- });
9718
- }
9719
- return jobFunctions;
9720
- }
9721
10234
  /**
9722
10235
  * Filter job function versions to only include those used by a workflow
9723
10236
  * @param allVersions - Map of job function names to versions
@@ -10238,6 +10751,9 @@ async function shouldForceApplyAll(client, workspaceId, application, functionEnt
10238
10751
  application.staticWebsiteServices.forEach((website) => {
10239
10752
  candidateTrns.add(resourceTrn(workspaceId, "staticwebsite", website.name));
10240
10753
  });
10754
+ application.aiGatewayServices.forEach((gateway) => {
10755
+ candidateTrns.add(resourceTrn(workspaceId, "aigateway", gateway.name));
10756
+ });
10241
10757
  application.resolverServices.forEach((pipeline) => {
10242
10758
  candidateTrns.add(resourceTrn(workspaceId, "pipeline", pipeline.namespace));
10243
10759
  });
@@ -10262,7 +10778,7 @@ async function shouldForceApplyAll(client, workspaceId, application, functionEnt
10262
10778
  });
10263
10779
  for (const trn of candidateTrns) try {
10264
10780
  const { metadata } = await client.getMetadata({ trn });
10265
- if (metadata?.labels?.["sdk-name"] !== application.name) continue;
10781
+ if (metadata?.labels["sdk-name"] !== application.name) continue;
10266
10782
  if (!hasMatchingSdkVersion(metadata.labels, desiredLabels)) return true;
10267
10783
  } catch (error) {
10268
10784
  if (error instanceof ConnectError && error.code === Code.NotFound) continue;
@@ -10316,6 +10832,7 @@ function printPlanResults(results) {
10316
10832
  const authServiceActions = extractServiceActions(results.auth.changeSet.service);
10317
10833
  results.staticWebsite.changeSet.print();
10318
10834
  results.staticWebsite.customDomainChangeSet.print();
10835
+ results.aiGateway.changeSet.print();
10319
10836
  results.app.print();
10320
10837
  printGroupedDisplaySection("TailorDB", tailorDBEntries, tailorDBServiceActions);
10321
10838
  printGroupedDisplaySection("Resolver", pipelineEntries, pipelineServiceActions);
@@ -10366,6 +10883,7 @@ function summarizePlanResults(results, displayEntries, serviceActions) {
10366
10883
  otherChanges,
10367
10884
  results.staticWebsite.changeSet,
10368
10885
  results.staticWebsite.customDomainChangeSet,
10886
+ results.aiGateway.changeSet,
10369
10887
  results.app,
10370
10888
  results.secretManager.vaultChangeSet,
10371
10889
  results.secretManager.secretChangeSet
@@ -10470,7 +10988,7 @@ async function deploy(options) {
10470
10988
  const dryRun = options?.dryRun ?? false;
10471
10989
  const yes = options?.yes ?? false;
10472
10990
  const forceApplyAll = await withSpan("plan.detectSdkVersionChange", () => shouldForceApplyAll(client, workspaceId, application, functionEntries));
10473
- const { functionRegistry, tailorDB, staticWebsite, idp, auth, pipeline, app, executor, workflow, secretManager } = await withSpan("plan", async () => {
10991
+ const { functionRegistry, tailorDB, staticWebsite, aiGateway, idp, auth, pipeline, app, executor, workflow, secretManager } = await withSpan("plan", async () => {
10474
10992
  const idpUserTriggerTargets = collectIdpUserTriggerTargets(application);
10475
10993
  const ctx = {
10476
10994
  client,
@@ -10484,9 +11002,10 @@ async function deploy(options) {
10484
11002
  };
10485
11003
  const functionRegistry = await withSpan("plan.functionRegistry", () => planFunctionRegistry(client, workspaceId, application.name, application.id, functionEntries));
10486
11004
  const unchangedWorkflowJobs = new Set(functionRegistry.changeSet.unchanged.filter((entry) => entry.name.startsWith(WORKFLOW_PREFIX)).map((entry) => entry.name.slice(WORKFLOW_PREFIX.length)));
10487
- const [tailorDB, staticWebsite, idp, auth, pipeline, app, executor, workflow, secretManager] = await Promise.all([
11005
+ const [tailorDB, staticWebsite, aiGateway, idp, auth, pipeline, app, executor, workflow, secretManager] = await Promise.all([
10488
11006
  withSpan("plan.tailorDB", () => planTailorDB(ctx)),
10489
11007
  withSpan("plan.staticWebsite", () => planStaticWebsite(ctx)),
11008
+ withSpan("plan.aiGateway", () => planAIGateway(ctx)),
10490
11009
  withSpan("plan.idp", () => planIdP(ctx)),
10491
11010
  withSpan("plan.auth", () => planAuth(ctx)),
10492
11011
  withSpan("plan.pipeline", () => planPipeline(ctx)),
@@ -10499,6 +11018,7 @@ async function deploy(options) {
10499
11018
  functionRegistry,
10500
11019
  tailorDB,
10501
11020
  staticWebsite,
11021
+ aiGateway,
10502
11022
  idp,
10503
11023
  auth,
10504
11024
  pipeline,
@@ -10513,6 +11033,7 @@ async function deploy(options) {
10513
11033
  ...functionRegistry.conflicts,
10514
11034
  ...tailorDB.conflicts,
10515
11035
  ...staticWebsite.conflicts,
11036
+ ...aiGateway.conflicts,
10516
11037
  ...idp.conflicts,
10517
11038
  ...auth.conflicts,
10518
11039
  ...pipeline.conflicts,
@@ -10525,6 +11046,7 @@ async function deploy(options) {
10525
11046
  ...functionRegistry.unmanaged,
10526
11047
  ...tailorDB.unmanaged,
10527
11048
  ...staticWebsite.unmanaged,
11049
+ ...aiGateway.unmanaged,
10528
11050
  ...idp.unmanaged,
10529
11051
  ...auth.unmanaged,
10530
11052
  ...pipeline.unmanaged,
@@ -10541,6 +11063,10 @@ async function deploy(options) {
10541
11063
  resourceType: "StaticWebsite",
10542
11064
  resourceName: del.name
10543
11065
  });
11066
+ for (const del of aiGateway.changeSet.deletes) importantDeletions.push({
11067
+ resourceType: "AIGateway",
11068
+ resourceName: del.name
11069
+ });
10544
11070
  for (const del of auth.changeSet.oauth2Client.deletes) importantDeletions.push({
10545
11071
  resourceType: "OAuth2 client",
10546
11072
  resourceName: del.name
@@ -10568,6 +11094,7 @@ async function deploy(options) {
10568
11094
  ...functionRegistry.resourceOwners,
10569
11095
  ...tailorDB.resourceOwners,
10570
11096
  ...staticWebsite.resourceOwners,
11097
+ ...aiGateway.resourceOwners,
10571
11098
  ...idp.resourceOwners,
10572
11099
  ...auth.resourceOwners,
10573
11100
  ...pipeline.resourceOwners,
@@ -10589,6 +11116,7 @@ async function deploy(options) {
10589
11116
  functionRegistry,
10590
11117
  tailorDB,
10591
11118
  staticWebsite,
11119
+ aiGateway,
10592
11120
  idp,
10593
11121
  auth,
10594
11122
  pipeline,
@@ -10618,6 +11146,7 @@ async function deploy(options) {
10618
11146
  await applySecretManager(client, secretManager, "create-update", application);
10619
11147
  await applyFunctionRegistry(client, workspaceId, functionRegistry, "create-update");
10620
11148
  await applyStaticWebsite(client, staticWebsite, "create-update");
11149
+ await applyAIGateway(client, aiGateway, "create-update");
10621
11150
  await applyIdP(client, idp, "create-update");
10622
11151
  await applyAuth(client, auth, "create-update");
10623
11152
  await applyTailorDB(client, tailorDB, "create-update");
@@ -10637,6 +11166,7 @@ async function deploy(options) {
10637
11166
  await applyWorkflow(client, workflow, "delete");
10638
11167
  await applyExecutor(client, executor, "delete");
10639
11168
  await applyStaticWebsite(client, staticWebsite, "delete");
11169
+ await applyAIGateway(client, aiGateway, "delete");
10640
11170
  await applySecretManager(client, secretManager, "delete");
10641
11171
  });
10642
11172
  await withSpan("apply.deleteApplication", () => applyApplication(client, app, "delete"));
@@ -10803,7 +11333,7 @@ function formatSubjectEvent(subject, eventTypes) {
10803
11333
  }
10804
11334
  function formatTypedEventTrigger(config) {
10805
11335
  const typedConfig = config.typedConfig;
10806
- if (!typedConfig || typedConfig.case === void 0) return null;
11336
+ if (typedConfig.case === void 0) return null;
10807
11337
  switch (typedConfig.case) {
10808
11338
  case "tailordb": return formatSubjectEvent(typedConfig.value.typeName, typedConfig.value.eventTypes);
10809
11339
  case "pipeline": return formatSubjectEvent(typedConfig.value.resolverName, typedConfig.value.eventTypes);
@@ -10875,7 +11405,7 @@ function formatTriggerConfig(executor) {
10875
11405
  }
10876
11406
  function formatEventTriggerConfig(config) {
10877
11407
  const typedConfig = config.typedConfig;
10878
- if (!typedConfig || typedConfig.case === void 0) return {
11408
+ if (typedConfig.case === void 0) return {
10879
11409
  eventType: config.eventType,
10880
11410
  condition: config.condition?.expr || ""
10881
11411
  };
@@ -11587,6 +12117,11 @@ async function startWorkflowCore(options) {
11587
12117
  }
11588
12118
  }
11589
12119
  async function startWorkflowByName(options) {
12120
+ const machineUser = await loadMachineUserName({
12121
+ machineUser: options.machineUser,
12122
+ profile: options.profile
12123
+ });
12124
+ if (!machineUser) throw new Error("Machine user is required. Specify --machine-user, set TAILOR_PLATFORM_MACHINE_USER_NAME, or set a profile default with 'tailor-sdk profile update <profile> --machine-user <name>'.");
11590
12125
  const client = await initOperatorClient(await loadAccessToken({ profile: options.profile }));
11591
12126
  const workspaceId = await loadWorkspaceId({
11592
12127
  workspaceId: options.workspaceId,
@@ -11604,7 +12139,7 @@ async function startWorkflowByName(options) {
11604
12139
  workflowName: options.name,
11605
12140
  authInvoker: {
11606
12141
  namespace: application.authNamespace,
11607
- machineUserName: options.machineUser
12142
+ machineUserName: machineUser
11608
12143
  },
11609
12144
  arg: options.arg,
11610
12145
  interval: options.interval
@@ -11630,10 +12165,10 @@ const startCommand = defineAppCommand({
11630
12165
  args: z.object({
11631
12166
  ...deploymentArgs,
11632
12167
  ...nameArgs,
11633
- "machine-user": arg(z.string(), {
12168
+ "machine-user": arg(z.string().optional(), {
11634
12169
  alias: "m",
11635
12170
  hiddenAlias: "machineuser",
11636
- description: "Machine user name",
12171
+ description: "Machine user name. Falls back to the active profile's default machine user.",
11637
12172
  env: "TAILOR_PLATFORM_MACHINE_USER_NAME"
11638
12173
  }),
11639
12174
  arg: arg(z.string().optional(), {
@@ -13458,6 +13993,11 @@ const listCommand$7 = defineAppCommand({
13458
13993
  * @returns Machine user token info
13459
13994
  */
13460
13995
  async function getMachineUserToken(options) {
13996
+ const name = await loadMachineUserName({
13997
+ machineUser: options.name,
13998
+ profile: options.profile
13999
+ });
14000
+ if (!name) throw new Error("Machine user is required. Provide the NAME positional argument, set TAILOR_PLATFORM_MACHINE_USER_NAME, or set a profile default with 'tailor-sdk profile update <profile> --machine-user <name>'.");
13461
14001
  const client = await initOperatorClient(await loadAccessToken({ profile: options.profile }));
13462
14002
  const workspaceId = await loadWorkspaceId({
13463
14003
  workspaceId: options.workspaceId,
@@ -13472,9 +14012,9 @@ async function getMachineUserToken(options) {
13472
14012
  const { machineUser } = await client.getAuthMachineUser({
13473
14013
  workspaceId,
13474
14014
  authNamespace: application.authNamespace,
13475
- name: options.name
14015
+ name
13476
14016
  });
13477
- if (!machineUser) throw new Error(`Machine user ${options.name} not found.`);
14017
+ if (!machineUser) throw new Error(`Machine user ${name} not found.`);
13478
14018
  const resp = await fetchMachineUserToken(application.url, machineUser.clientId, machineUser.clientSecret);
13479
14019
  const expiresAt = /* @__PURE__ */ new Date();
13480
14020
  expiresAt.setSeconds(expiresAt.getSeconds() + resp.expires_in);
@@ -13489,9 +14029,10 @@ const tokenCommand = defineAppCommand({
13489
14029
  description: "Get an access token for a machine user.",
13490
14030
  args: z.object({
13491
14031
  ...deploymentArgs,
13492
- name: arg(z.string(), {
14032
+ name: arg(z.string().optional(), {
13493
14033
  positional: true,
13494
- description: "Machine user name"
14034
+ description: "Machine user name. Falls back to the active profile's default machine user.",
14035
+ env: "TAILOR_PLATFORM_MACHINE_USER_NAME"
13495
14036
  })
13496
14037
  }).strict(),
13497
14038
  run: async (args) => {
@@ -14168,6 +14709,7 @@ async function execRemove(client, workspaceId, application, config, confirm) {
14168
14709
  };
14169
14710
  const tailorDB = await planTailorDB(ctx);
14170
14711
  const staticWebsite = await planStaticWebsite(ctx);
14712
+ const aiGateway = await planAIGateway(ctx);
14171
14713
  const idp = await planIdP(ctx);
14172
14714
  const auth = await planAuth(ctx);
14173
14715
  const pipeline = await planPipeline(ctx);
@@ -14178,6 +14720,7 @@ async function execRemove(client, workspaceId, application, config, confirm) {
14178
14720
  const secretManager = await planSecretManager(ctx);
14179
14721
  functionRegistry.changeSet.print();
14180
14722
  staticWebsite.changeSet.print();
14723
+ aiGateway.changeSet.print();
14181
14724
  app.print();
14182
14725
  tailorDB.changeSet.service.print();
14183
14726
  tailorDB.changeSet.type.print();
@@ -14200,11 +14743,12 @@ async function execRemove(client, workspaceId, application, config, confirm) {
14200
14743
  auth.changeSet.connection.print();
14201
14744
  secretManager.vaultChangeSet.print();
14202
14745
  secretManager.secretChangeSet.print();
14203
- 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;
14746
+ if (tailorDB.changeSet.service.deletes.length === 0 && staticWebsite.changeSet.deletes.length === 0 && aiGateway.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;
14204
14747
  if (confirm) await confirm();
14205
14748
  await applyWorkflow(client, workflow, "delete");
14206
14749
  await applyExecutor(client, executor, "delete");
14207
14750
  await applyStaticWebsite(client, staticWebsite, "delete");
14751
+ await applyAIGateway(client, aiGateway, "delete");
14208
14752
  await applyApplication(client, app, "delete");
14209
14753
  await applyPipeline(client, pipeline, "delete-resources");
14210
14754
  await applyPipeline(client, pipeline, "delete-services");
@@ -14486,13 +15030,13 @@ function extractBreakingChangeFields(diff) {
14486
15030
  const optionalToRequired = /* @__PURE__ */ new Map();
14487
15031
  const addedRequiredFields = /* @__PURE__ */ new Map();
14488
15032
  const enumValueChanges = /* @__PURE__ */ new Map();
14489
- for (const change of diff.changes) if (change.kind === "field_modified" && change.fieldName) {
15033
+ for (const change of diff.changes) if (change.kind === "field_modified") {
14490
15034
  const { before, after } = change;
14491
- if (before && after && !before.required && after.required) {
15035
+ if (!before.required && after.required) {
14492
15036
  if (!optionalToRequired.has(change.typeName)) optionalToRequired.set(change.typeName, /* @__PURE__ */ new Set());
14493
15037
  assertDefined(optionalToRequired.get(change.typeName), "optionalToRequired entry missing").add(change.fieldName);
14494
15038
  }
14495
- if (before && after && before.type === "enum" && after.type === "enum" && before.allowedValues && after.allowedValues) {
15039
+ if (before.type === "enum" && after.type === "enum" && before.allowedValues && after.allowedValues) {
14496
15040
  const beforeValues = before.allowedValues.map((v) => v.value);
14497
15041
  const afterValues = after.allowedValues.map((v) => v.value);
14498
15042
  const beforeSet = new Set(beforeValues);
@@ -14505,9 +15049,9 @@ function extractBreakingChangeFields(diff) {
14505
15049
  });
14506
15050
  }
14507
15051
  }
14508
- } else if (change.kind === "field_added" && change.fieldName) {
15052
+ } else if (change.kind === "field_added") {
14509
15053
  const { after } = change;
14510
- if (after && after.required) {
15054
+ if (after.required) {
14511
15055
  if (!addedRequiredFields.has(change.typeName)) addedRequiredFields.set(change.typeName, /* @__PURE__ */ new Map());
14512
15056
  assertDefined(addedRequiredFields.get(change.typeName), "addedRequiredFields entry missing").set(change.fieldName, after);
14513
15057
  }
@@ -14991,7 +15535,7 @@ async function generate(options) {
14991
15535
  if (options.init) await handleInitOption(namespacesWithMigrations, options.yes);
14992
15536
  let pluginManager;
14993
15537
  if (plugins.length > 0) pluginManager = new PluginManager(plugins);
14994
- const { defineApplication } = await import("./application-DSXntqnV.mjs");
15538
+ const { defineApplication } = await import("./application-nTydHJm8.mjs");
14995
15539
  const application = defineApplication({
14996
15540
  config,
14997
15541
  pluginManager
@@ -15008,10 +15552,7 @@ async function generate(options) {
15008
15552
  await tailordbService.processNamespacePlugins();
15009
15553
  const localTypesObj = tailordbService.types;
15010
15554
  const currentSnapshot = createSnapshotFromLocalTypes(localTypesObj, namespace);
15011
- let previousSnapshot = null;
15012
- try {
15013
- previousSnapshot = reconstructSnapshotFromMigrations(migrationsDir);
15014
- } catch {}
15555
+ const previousSnapshot = reconstructSnapshotFromMigrations(migrationsDir);
15015
15556
  if (!previousSnapshot) await generateInitialSnapshot(currentSnapshot, migrationsDir);
15016
15557
  else await generateDiffFromSnapshot(previousSnapshot, currentSnapshot, migrationsDir, options);
15017
15558
  }
@@ -16577,7 +17118,7 @@ const queryBaseOptionsSchema = z.object({
16577
17118
  profile: z.string().optional(),
16578
17119
  configPath: z.string().optional(),
16579
17120
  engine: queryEngineSchema,
16580
- machineUser: z.string()
17121
+ machineUser: z.string().optional()
16581
17122
  });
16582
17123
  const queryOptionsSchema = queryBaseOptionsSchema.extend({ query: z.string() });
16583
17124
  async function getNamespaceFromSqlQuery(workspaceId, query, client, namespaces) {
@@ -16600,6 +17141,11 @@ async function getNamespaceFromSqlQuery(workspaceId, query, client, namespaces)
16600
17141
  async function loadOptions(options) {
16601
17142
  const result = queryBaseOptionsSchema.safeParse(options);
16602
17143
  if (!result.success) throw new Error(assertDefined(result.error.issues[0], "validation error missing issues").message);
17144
+ const machineUser = await loadMachineUserName({
17145
+ machineUser: result.data.machineUser,
17146
+ profile: result.data.profile
17147
+ });
17148
+ if (!machineUser) throw new Error("Machine user is required. Specify --machine-user, set TAILOR_PLATFORM_MACHINE_USER_NAME, or set a profile default with 'tailor-sdk profile update <profile> --machine-user <name>'.");
16603
17149
  const client = await initOperatorClient(await loadAccessToken({ profile: result.data.profile }));
16604
17150
  const workspaceId = await loadWorkspaceId({
16605
17151
  workspaceId: result.data.workspaceId,
@@ -16615,9 +17161,9 @@ async function loadOptions(options) {
16615
17161
  const { machineUser: machineUserResource } = await client.getAuthMachineUser({
16616
17162
  workspaceId,
16617
17163
  authNamespace: application.authNamespace,
16618
- name: result.data.machineUser
17164
+ name: machineUser
16619
17165
  });
16620
- if (!machineUserResource) throw new Error(`Machine user ${result.data.machineUser} not found.`);
17166
+ if (!machineUserResource) throw new Error(`Machine user ${machineUser} not found.`);
16621
17167
  return {
16622
17168
  engine: result.data.engine,
16623
17169
  client,
@@ -16767,7 +17313,7 @@ async function prepareQueryExecutor(options) {
16767
17313
  error,
16768
17314
  engine,
16769
17315
  namespace,
16770
- machineUser: options.machineUser
17316
+ machineUser: machineUserResource.name
16771
17317
  });
16772
17318
  }
16773
17319
  };
@@ -16981,10 +17527,10 @@ const queryCommand = defineAppCommand({
16981
17527
  description: "Read query string from file; omit to start REPL mode"
16982
17528
  }),
16983
17529
  edit: arg(z.boolean().default(false), { description: "Open a temporary file in your editor; omit to start REPL mode" }),
16984
- "machine-user": arg(z.string(), {
17530
+ "machine-user": arg(z.string().optional(), {
16985
17531
  alias: "m",
16986
17532
  hiddenAlias: "machineuser",
16987
- description: "Machine user name for query execution",
17533
+ description: "Machine user name for query execution. Falls back to the active profile's default machine user.",
16988
17534
  env: "TAILOR_PLATFORM_MACHINE_USER_NAME"
16989
17535
  }),
16990
17536
  "newline-on-enter": arg(z.boolean().optional(), { description: "REPL: when true, Enter inserts a newline and Shift+Enter submits. Use --no-newline-on-enter to swap." })
@@ -17150,4 +17696,4 @@ function isDeno() {
17150
17696
 
17151
17697
  //#endregion
17152
17698
  export { listCommand$5 as $, INITIAL_SCHEMA_NUMBER as $t, truncate as A, commonArgs as An, startCommand as At, logBetaWarning as B, getExecutor as Bt, listCommand$2 as C, PluginManager as Cn, triggerExecutor as Ct, resumeWorkflow as D, apiCall as Dn, jobsCommand as Dt, resumeCommand as E, apiCommand as En, getExecutorJob as Et, writeDbTypesFile as F, pagedLogArgs as Fn, getWorkflowExecution as Ft, organizationTree as G, MIGRATION_LABEL_KEY as Gt, removeCommand$1 as H, executeScript as Ht, getConfiguredEditorCommand as I, paginationArgs as In, listWorkflowExecutions as It, listOrganizations as J, compareSnapshotWithRemote as Jt, treeCommand as K, handleOptionalToRequiredError as Kt, openInConfiguredEditor as L, toPageDirection as Ln, functionExecutionStatusToString as Lt, generate as M, confirmationArgs as Mn, getCommand$5 as Mt, generateCommand as N, deploymentArgs as Nn, getWorkflow as Nt, listCommand$3 as O, assertWritable as On, listExecutorJobs as Ot, generateMigrationScript as P, isVerbose as Pn, executionsCommand as Pt, updateFolder as Q, DIFF_FILE_NAME as Qt, show as R, workspaceArgs as Rn, formatKeyValueTable as Rt, listApps as S, sdkNameLabelKey as Sn, triggerCommand as St, healthCommand as T, prompt 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, ensureConfigId 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, configArg as jn, startWorkflow as jt, listWorkflows as k, defineAppCommand 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, generateUserTypes as wn, listCommand$9 as wt, createWorkspace as x, resourceTrn as xn, webhookCommand as xt, deleteWorkspace as y, getNamespacesWithMigrations as yn, getFunctionRegistry as yt, showCommand as z, getCommand$6 as zt };
17153
- //# sourceMappingURL=runtime-CW3jcQCc.mjs.map
17699
+ //# sourceMappingURL=runtime-2nzOZCUb.mjs.map