@tailor-platform/sdk 1.54.3 → 1.55.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/dist/{actor-Cjae_LGD.d.mts → actor-J2gJ0eK5.d.mts} +2 -2
  3. package/dist/application-DM8q9GDI.mjs +4 -0
  4. package/dist/{application-BfGje3iZ.mjs → application-DzUlASfA.mjs} +333 -4
  5. package/dist/application-DzUlASfA.mjs.map +1 -0
  6. package/dist/brand-DlnJ375c.mjs.map +1 -1
  7. package/dist/cli/index.mjs +101 -38
  8. package/dist/cli/index.mjs.map +1 -1
  9. package/dist/cli/lib.d.mts +1334 -176
  10. package/dist/cli/lib.mjs +3 -3
  11. package/dist/{client-CGO7gniI.mjs → client-DLPEPJ_s.mjs} +24 -19
  12. package/dist/client-DLPEPJ_s.mjs.map +1 -0
  13. package/dist/{client-yfFdZU9s.mjs → client-DrzwCD1W.mjs} +1 -1
  14. package/dist/configure/index.d.mts +5 -4
  15. package/dist/configure/index.mjs +47 -1
  16. package/dist/configure/index.mjs.map +1 -1
  17. package/dist/{crashreport-DGdAgX8Y.mjs → crashreport-Bm2mN5tg.mjs} +2 -2
  18. package/dist/{crashreport-DGdAgX8Y.mjs.map → crashreport-Bm2mN5tg.mjs.map} +1 -1
  19. package/dist/{crashreport-DnwIxpzF.mjs → crashreport-C5oHvHUC.mjs} +1 -1
  20. package/dist/{index-qQYMbkT-.d.mts → index-BE-fpxIo.d.mts} +2 -2
  21. package/dist/{index-DJUoIn_v.d.mts → index-BLsnrEtc.d.mts} +97 -5
  22. package/dist/{index-DrYHpTja.d.mts → index-D9xG-a6Y.d.mts} +2 -2
  23. package/dist/{index-CyyoHrPK.d.mts → index-S6-FtUpA.d.mts} +2 -2
  24. package/dist/{index-Cf1Lo_XT.d.mts → index-cHqh66cF.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-BuE5ZOnW.d.mts +634 -0
  31. package/dist/{runtime-DpbAj_8a.mjs → runtime-CgGeIoxi.mjs} +366 -164
  32. package/dist/runtime-CgGeIoxi.mjs.map +1 -0
  33. package/dist/seed-DfLyRh63.mjs.map +1 -1
  34. package/dist/tailordb-BlBGmQK-.d.mts +863 -0
  35. package/dist/utils/test/index.d.mts +3 -3
  36. package/dist/vitest/index.d.mts +25 -1
  37. package/dist/vitest/index.mjs +57 -12
  38. package/dist/vitest/index.mjs.map +1 -1
  39. package/dist/{workflow.generated-CWi2rivQ.d.mts → workflow.generated-CQg1_Ami.d.mts} +183 -8
  40. package/docs/cli-reference.md +12 -0
  41. package/docs/services/http-adapter.md +100 -0
  42. package/package.json +11 -11
  43. package/dist/application-BfGje3iZ.mjs.map +0 -1
  44. package/dist/application-BsipSxp3.mjs +0 -4
  45. package/dist/client-CGO7gniI.mjs.map +0 -1
  46. package/dist/runtime-DpbAj_8a.mjs.map +0 -1
  47. package/dist/tailor-db-field-D0qg8s4U.d.mts +0 -1639
@@ -1,8 +1,8 @@
1
1
 
2
2
  import { t as db } from "./schema-DKsNhbav.mjs";
3
- import { $ as FilterSchema, A as FunctionExecution_Status, B as AuthOAuth2Client_GrantType, C as TailorDBType_Permission_Operator, D as IdPLang, E as PipelineResolver_OperationType, F as AuthConnection_Type, H as AuthSCIMAttribute_Type, I as AuthHookPoint, J as GetApplicationSchemaHealthResponse_ApplicationSchemaHealthStatus, K as TenantProviderConfig_TenantProviderType, L as AuthIDPConfig_AuthType, M as ExecutorJobStatus, N as ExecutorTargetType, O as IdPPermissionOperator, P as ExecutorTriggerType, Q as Condition_Operator, R as AuthInvokerSchema, S as TailorDBGQLPermission_Permit, T as TailorDBType_PermitAction, U as AuthSCIMAttribute_Uniqueness, V as AuthSCIMAttribute_Mutability, W as AuthSCIMConfig_AuthorizationType, X as Subgraph_ServiceType, Y as ApplicationSchemaUpdateAttemptStatus, Z as ConditionSchema, _ as WorkspacePlatformUserRole, a as fetchMachineUserToken, b as TailorDBGQLPermission_Action, d as initOperatorClient, et as PageDirection, g as OperatorService, h as userAgent, i as fetchAll, k as IdPPermissionPermit, m as resolveStaticWebsiteUrls, o as fetchPaged, p as platformBaseUrl, q as UserProfileProviderConfig_UserProfileProviderType, v as WorkflowExecution_Status, w as TailorDBType_Permission_Permit, x as TailorDBGQLPermission_Operator, y as WorkflowJobExecution_Status, z as AuthOAuth2Client_ClientType } from "./client-CGO7gniI.mjs";
3
+ import { $ as FilterSchema, A as FunctionExecution_Status, B as AuthOAuth2Client_GrantType, C as TailorDBType_Permission_Operator, D as IdPLang, E as PipelineResolver_OperationType, F as AuthConnection_Type, H as AuthSCIMAttribute_Type, I as AuthHookPoint, J as GetApplicationSchemaHealthResponse_ApplicationSchemaHealthStatus, K as TenantProviderConfig_TenantProviderType, L as AuthIDPConfig_AuthType, M as ExecutorJobStatus, N as ExecutorTargetType, O as IdPPermissionOperator, P as ExecutorTriggerType, Q as Condition_Operator, R as AuthInvokerSchema, S as TailorDBGQLPermission_Permit, T as TailorDBType_PermitAction, U as AuthSCIMAttribute_Uniqueness, V as AuthSCIMAttribute_Mutability, W as AuthSCIMConfig_AuthorizationType, X as Subgraph_ServiceType, Y as ApplicationSchemaUpdateAttemptStatus, Z as ConditionSchema, _ as WorkspacePlatformUserRole, a as fetchMachineUserToken, b as TailorDBGQLPermission_Action, d as initOperatorClient, et as PageDirection, g as OperatorService, h as userAgent, i as fetchAll, k as IdPPermissionPermit, m as resolveStaticWebsiteUrls, o as fetchPaged, p as platformBaseUrl, q as UserProfileProviderConfig_UserProfileProviderType, v as WorkflowExecution_Status, w as TailorDBType_Permission_Permit, x as TailorDBGQLPermission_Operator, y as WorkflowJobExecution_Status, z as AuthOAuth2Client_ClientType } from "./client-DLPEPJ_s.mjs";
4
4
  import { a as parseBoolean, i as symbols, n as logger, r as styles, t as CIPromptError } from "./logger-DpJyJvNz.mjs";
5
- import { C as loadConfigPath, O as writePlatformConfig, S as loadAccessToken, T as readPlatformConfig, _ as getDistDir, d as buildResolverOperationHookExpr, f as OAuth2ClientSchema, g as createBundleCache, h as loadFilesWithIgnores, m as stringifyFunction, n as generatePluginFilesIfNeeded, p as TailorDBTypeSchema, r as loadApplication, s as createExecutorService, t as defineApplication, u as buildExecutorArgsExpr, v as hashFile, w as loadWorkspaceId, y as loadConfig } from "./application-BfGje3iZ.mjs";
5
+ import { C as loadAccessToken, E as readPlatformConfig, T as loadWorkspaceId, _ as createBundleCache, b as loadConfig, c as createExecutorService, d as buildExecutorArgsExpr, f as buildResolverOperationHookExpr, g as loadFilesWithIgnores, h as stringifyFunction, k as writePlatformConfig, m as TailorDBTypeSchema, n as generatePluginFilesIfNeeded, p as OAuth2ClientSchema, r as loadApplication, s as HTTP_METHODS, t as defineApplication, v as getDistDir, w as loadConfigPath, y as hashFile } from "./application-DzUlASfA.mjs";
6
6
  import { t as multiline } from "./multiline-Cf9ODpr1.mjs";
7
7
  import { t as readPackageJson } from "./package-json-DcQApfPQ.mjs";
8
8
  import { n as isCLIError, t as createCLIError } from "./errors-EsY4XO6O.mjs";
@@ -717,6 +717,34 @@ function coerceFieldValue(field, raw) {
717
717
  }
718
718
  return raw;
719
719
  }
720
+ /**
721
+ * Collapse top-level body keys that address a known input field by its
722
+ * protobuf name (snake_case) or JSON name to the field's `localName`. protojson
723
+ * accepts every alias, so converging them here lets the presence checks below
724
+ * reason in a single namespace — otherwise a `--body` written as
725
+ * `{"workspace_id": ...}` slips past the camelCase check and we inject a second
726
+ * `workspaceId`, which the server rejects as a duplicate field. When both forms
727
+ * are present the canonical key wins and the alias is dropped.
728
+ * @param body - The parsed body object to mutate
729
+ * @param fields - The target endpoint's input fields
730
+ * @returns Whether any key was rewritten
731
+ */
732
+ function normalizeBodyFieldKeys(body, fields) {
733
+ const aliasToLocal = /* @__PURE__ */ new Map();
734
+ for (const f of fields) {
735
+ aliasToLocal.set(f.name, f.localName);
736
+ aliasToLocal.set(f.jsonName, f.localName);
737
+ }
738
+ let changed = false;
739
+ for (const key of Object.keys(body)) {
740
+ const local = aliasToLocal.get(key);
741
+ if (!local || local === key) continue;
742
+ if (!Object.hasOwn(body, local)) body[local] = body[key];
743
+ delete body[key];
744
+ changed = true;
745
+ }
746
+ return changed;
747
+ }
720
748
  const FORBIDDEN_SEGMENTS = new Set([
721
749
  "__proto__",
722
750
  "constructor",
@@ -833,15 +861,16 @@ Use \`--field key=value\` (repeatable) to set request body fields without writin
833
861
  mutated = true;
834
862
  }
835
863
  if (parsedBody && method) {
864
+ if (normalizeBodyFieldKeys(parsedBody, method.input.fields)) mutated = true;
836
865
  const fieldNames = method.input.fields.map((f) => f.localName);
837
- if (fieldNames.includes("workspaceId") && !("workspaceId" in parsedBody)) try {
866
+ if (fieldNames.includes("workspaceId") && !Object.hasOwn(parsedBody, "workspaceId")) try {
838
867
  parsedBody.workspaceId = await loadWorkspaceId({
839
868
  workspaceId: args["workspace-id"],
840
869
  profile: args.profile
841
870
  });
842
871
  mutated = true;
843
872
  } catch {}
844
- if (fieldNames.includes("namespaceName") && !("namespaceName" in parsedBody)) try {
873
+ if (fieldNames.includes("namespaceName") && !Object.hasOwn(parsedBody, "namespaceName")) try {
845
874
  const { config } = await loadConfig(args.config);
846
875
  const ns = resolveNamespaceName(methodName, config);
847
876
  if (ns) {
@@ -1608,10 +1637,14 @@ function createChangeSet(title) {
1608
1637
  print: () => {
1609
1638
  if (isEmpty()) return;
1610
1639
  logger.log(styles.bold(`${title}:`));
1611
- creates.forEach((item) => logger.log(` ${symbols.create} ${item.name}`));
1612
- deletes.forEach((item) => logger.log(` ${symbols.delete} ${item.name}`));
1613
- updates.forEach((item) => logger.log(` ${symbols.update} ${item.name}`));
1614
- replaces.forEach((item) => logger.log(` ${symbols.replace} ${item.name}`));
1640
+ const printItem = (symbol, item) => {
1641
+ logger.log(` ${symbol} ${item.name}`);
1642
+ for (const detail of item.details ?? []) logger.log(` ${detail}`);
1643
+ };
1644
+ creates.forEach((item) => printItem(symbols.create, item));
1645
+ deletes.forEach((item) => printItem(symbols.delete, item));
1646
+ updates.forEach((item) => printItem(symbols.update, item));
1647
+ replaces.forEach((item) => printItem(symbols.replace, item));
1615
1648
  }
1616
1649
  };
1617
1650
  }
@@ -1799,6 +1832,17 @@ function normalizeSubgraphs(subgraphs) {
1799
1832
  return left.serviceNamespace.localeCompare(right.serviceNamespace);
1800
1833
  });
1801
1834
  }
1835
+ function normalizeHttpAdapters(httpAdapters) {
1836
+ return [...httpAdapters ?? []].map((adapter) => ({
1837
+ name: adapter.name ?? "",
1838
+ pathPattern: adapter.pathPattern ?? "",
1839
+ methods: sortStrings(adapter.methods),
1840
+ inputScript: adapter.inputScript ?? "",
1841
+ outputScript: adapter.outputScript ?? "",
1842
+ enabled: adapter.enabled ?? true,
1843
+ priority: adapter.priority ?? 0
1844
+ })).sort((left, right) => left.name.localeCompare(right.name));
1845
+ }
1802
1846
  function toComparableApplication(input) {
1803
1847
  return {
1804
1848
  authNamespace: input.authNamespace,
@@ -1807,10 +1851,11 @@ function toComparableApplication(input) {
1807
1851
  subgraphs: [...input.subgraphs],
1808
1852
  allowedIpAddresses: sortStrings(input.allowedIpAddresses),
1809
1853
  disableIntrospection: input.disableIntrospection,
1810
- disabled: input.disabled
1854
+ disabled: input.disabled,
1855
+ httpAdapters: [...input.httpAdapters]
1811
1856
  };
1812
1857
  }
1813
- function normalizeComparableApplication(application, authNamespace, authIdpConfigName, cors) {
1858
+ function normalizeComparableApplication(application, authNamespace, authIdpConfigName, cors, httpAdapters) {
1814
1859
  return toComparableApplication({
1815
1860
  authNamespace: authNamespace ?? "",
1816
1861
  authIdpConfigName: authIdpConfigName ?? "",
@@ -1818,7 +1863,8 @@ function normalizeComparableApplication(application, authNamespace, authIdpConfi
1818
1863
  subgraphs: normalizeSubgraphs(application.subgraphs.map((subgraph) => protoSubgraph(subgraph))),
1819
1864
  allowedIpAddresses: application.config.allowedIpAddresses ?? [],
1820
1865
  disableIntrospection: application.config.disableIntrospection ?? false,
1821
- disabled: false
1866
+ disabled: false,
1867
+ httpAdapters: normalizeHttpAdapters(httpAdapters)
1822
1868
  });
1823
1869
  }
1824
1870
  function normalizeComparableExistingApplication(app) {
@@ -1829,7 +1875,8 @@ function normalizeComparableExistingApplication(app) {
1829
1875
  subgraphs: normalizeSubgraphs(app.subgraphs),
1830
1876
  allowedIpAddresses: app.allowedIpAddresses,
1831
1877
  disableIntrospection: app.disableIntrospection,
1832
- disabled: app.disabled
1878
+ disabled: app.disabled,
1879
+ httpAdapters: normalizeHttpAdapters(app.httpAdapters)
1833
1880
  });
1834
1881
  }
1835
1882
  function areApplicationsEqual(existing, desired) {
@@ -1838,9 +1885,10 @@ function areApplicationsEqual(existing, desired) {
1838
1885
  /**
1839
1886
  * Plan application changes based on current and desired state.
1840
1887
  * @param context - Planning context
1888
+ * @param httpAdapterBuildResult - Bundled HTTP adapter scripts to embed on the Application
1841
1889
  * @returns Planned changes
1842
1890
  */
1843
- async function planApplication(context) {
1891
+ async function planApplication(context, httpAdapterBuildResult) {
1844
1892
  const { client, workspaceId, application, forRemoval } = context;
1845
1893
  const changeSet = createChangeSet("Applications");
1846
1894
  const existingApplications = await fetchAll(async (pageToken, maxPageSize) => {
@@ -1902,7 +1950,8 @@ async function planApplication(context) {
1902
1950
  });
1903
1951
  const expectedLocalWebsites = new Set(application.staticWebsiteServices.map((website) => website.name));
1904
1952
  const resolvedCors = await resolveStaticWebsiteUrls(client, workspaceId, application.config.cors, "CORS", { expectedLocalNames: expectedLocalWebsites });
1905
- const desired = normalizeComparableApplication(application, authNamespace, authIdpConfigName, resolvedCors);
1953
+ const httpAdapters = buildHttpAdapters(application, httpAdapterBuildResult);
1954
+ const desired = normalizeComparableApplication(application, authNamespace, authIdpConfigName, resolvedCors, httpAdapters);
1906
1955
  const request = {
1907
1956
  workspaceId,
1908
1957
  applicationName: application.name,
@@ -1911,7 +1960,8 @@ async function planApplication(context) {
1911
1960
  cors: application.config.cors,
1912
1961
  subgraphs: application.subgraphs.map((subgraph) => protoSubgraph(subgraph)),
1913
1962
  allowedIpAddresses: application.config.allowedIpAddresses,
1914
- disableIntrospection: application.config.disableIntrospection
1963
+ disableIntrospection: application.config.disableIntrospection,
1964
+ httpAdapters
1915
1965
  };
1916
1966
  const existing = existingApplications.find((app) => app.name === application.name);
1917
1967
  if (application.id) {
@@ -1935,12 +1985,20 @@ async function planApplication(context) {
1935
1985
  metaRequest
1936
1986
  };
1937
1987
  if (isOwnedByApp(labels, application.name, application.id) && hasMatchingSdkVersion(labels, metaRequest.labels) && areApplicationsEqual(existing, desired)) changeSet.unchanged.push(update);
1938
- else changeSet.updates.push(update);
1939
- } else changeSet.creates.push({
1940
- name: application.name,
1941
- request,
1942
- metaRequest
1943
- });
1988
+ else {
1989
+ const details = diffHttpAdapterDisplay(existing.httpAdapters, httpAdapters);
1990
+ if (details.length > 0) update.details = details;
1991
+ changeSet.updates.push(update);
1992
+ }
1993
+ } else {
1994
+ const details = diffHttpAdapterDisplay(void 0, httpAdapters);
1995
+ changeSet.creates.push({
1996
+ name: application.name,
1997
+ request,
1998
+ metaRequest,
1999
+ details: details.length > 0 ? details : void 0
2000
+ });
2001
+ }
1944
2002
  return changeSet;
1945
2003
  }
1946
2004
  async function fetchAppLabels(client, workspaceId, appName) {
@@ -1952,6 +2010,59 @@ async function fetchAppLabels(client, workspaceId, appName) {
1952
2010
  throw error;
1953
2011
  }
1954
2012
  }
2013
+ /**
2014
+ * Build per-adapter diff lines for the application plan display. The platform
2015
+ * models HTTP adapters as an embedded Application field (no dedicated RPC), so
2016
+ * adapter changes surface as an Application update; these lines show which
2017
+ * adapter actually changed instead of just `~ <app>`.
2018
+ * @param existingAdapters - HTTP adapters currently deployed on the application
2019
+ * @param desiredAdapters - HTTP adapters built from the local config
2020
+ * @returns Indented diff lines (`+`/`~`/`-` per adapter), sorted by name
2021
+ */
2022
+ function diffHttpAdapterDisplay(existingAdapters, desiredAdapters) {
2023
+ const existingByName = new Map((existingAdapters ?? []).map((a) => [a.name ?? "", a]));
2024
+ const desiredByName = new Map(desiredAdapters.map((a) => [a.name ?? "", a]));
2025
+ const entries = [];
2026
+ for (const [name, desired] of desiredByName) {
2027
+ const existing = existingByName.get(name);
2028
+ if (!existing) entries.push({
2029
+ name,
2030
+ symbol: symbols.create
2031
+ });
2032
+ else if (!areNormalizedEqual(normalizeHttpAdapters([existing])[0], normalizeHttpAdapters([desired])[0])) entries.push({
2033
+ name,
2034
+ symbol: symbols.update
2035
+ });
2036
+ }
2037
+ for (const name of existingByName.keys()) if (!desiredByName.has(name)) entries.push({
2038
+ name,
2039
+ symbol: symbols.delete
2040
+ });
2041
+ return entries.sort((left, right) => left.name.localeCompare(right.name)).map((entry) => `${entry.symbol} ${entry.name} (httpAdapter)`);
2042
+ }
2043
+ function buildHttpAdapters(application, httpAdapterBuildResult) {
2044
+ const adapters = application.httpAdapterService?.adapters ?? [];
2045
+ if (adapters.length === 0) return [];
2046
+ return adapters.map((loaded) => {
2047
+ const inputScript = httpAdapterBuildResult?.bundledInputs.get(loaded.adapter.name);
2048
+ if (!inputScript) throw new Error(`HTTP adapter "${loaded.adapter.name}" was loaded but no bundled input script is available`);
2049
+ let outputScript = "";
2050
+ if (loaded.hasOutput) {
2051
+ const bundled = httpAdapterBuildResult?.bundledOutputs.get(loaded.adapter.name);
2052
+ if (!bundled) throw new Error(`HTTP adapter "${loaded.adapter.name}" declares an output handler but no bundled output script is available`);
2053
+ outputScript = bundled;
2054
+ }
2055
+ return {
2056
+ name: loaded.adapter.name,
2057
+ pathPattern: loaded.adapter.pathPattern,
2058
+ methods: loaded.methods.map((m) => HTTP_METHODS[m]),
2059
+ inputScript,
2060
+ outputScript,
2061
+ enabled: loaded.adapter.enabled,
2062
+ priority: loaded.adapter.priority
2063
+ };
2064
+ });
2065
+ }
1955
2066
  function protoSubgraph(subgraph) {
1956
2067
  let serviceType;
1957
2068
  switch (subgraph.Type) {
@@ -4732,6 +4843,88 @@ function normalizeAuthInvoker(authInvoker, authNamespace, context) {
4732
4843
  return authInvoker;
4733
4844
  }
4734
4845
 
4846
+ //#endregion
4847
+ //#region src/cli/commands/deploy/owned-resource.ts
4848
+ /**
4849
+ * Fetch a workspace-scoped resource list and attach SDK ownership metadata.
4850
+ * @template T
4851
+ * @param params - Resource fetch parameters
4852
+ * @param params.client - Operator client instance
4853
+ * @param params.workspaceId - Workspace ID
4854
+ * @param params.fetchPage - Function that fetches one resource page
4855
+ * @param params.getName - Function that extracts the resource name
4856
+ * @param params.getTrn - Function that builds the resource TRN
4857
+ * @returns Existing resources keyed by resource name, with SDK labels attached
4858
+ */
4859
+ async function fetchExistingResourcesWithLabels(params) {
4860
+ const { client, workspaceId, fetchPage, getName, getTrn } = params;
4861
+ const withoutLabel = await fetchAll(async (pageToken, maxPageSize) => {
4862
+ try {
4863
+ return await fetchPage(pageToken, maxPageSize);
4864
+ } catch (error) {
4865
+ if (error instanceof ConnectError && error.code === Code.NotFound) return [[], ""];
4866
+ throw error;
4867
+ }
4868
+ });
4869
+ const existingResources = {};
4870
+ await Promise.all(withoutLabel.map(async (resource) => {
4871
+ const name = getName(resource);
4872
+ if (!name) return;
4873
+ const { metadata } = await client.getMetadata({ trn: getTrn(workspaceId, name) });
4874
+ existingResources[name] = {
4875
+ resource,
4876
+ label: metadata?.labels[sdkNameLabelKey],
4877
+ allLabels: metadata?.labels
4878
+ };
4879
+ }));
4880
+ return existingResources;
4881
+ }
4882
+ /**
4883
+ * Determine whether a same-named existing resource is managed by this app.
4884
+ * Records the user-facing confirmation data when ownership does not match.
4885
+ * @param params - Ownership classification inputs
4886
+ * @param params.labels - Existing resource labels
4887
+ * @param params.ownerLabel - Existing `sdk-name` label, when present
4888
+ * @param params.appName - Current application name
4889
+ * @param params.appId - Current application id, when present
4890
+ * @param params.resourceType - Resource kind for confirmation messages
4891
+ * @param params.resourceName - Resource name for confirmation messages
4892
+ * @param params.conflicts - Conflict accumulator
4893
+ * @param params.unmanaged - Unmanaged-resource accumulator
4894
+ * @returns True when the resource is owned by the current app
4895
+ */
4896
+ function trackDesiredResourceOwnership(params) {
4897
+ const { labels, ownerLabel, appName, appId, resourceType, resourceName, conflicts, unmanaged } = params;
4898
+ const owned = isOwnedByApp(labels, appName, appId);
4899
+ if (!owned) if (!ownerLabel) unmanaged.push({
4900
+ resourceType,
4901
+ resourceName
4902
+ });
4903
+ else conflicts.push({
4904
+ resourceType,
4905
+ resourceName,
4906
+ currentOwner: ownerLabel
4907
+ });
4908
+ return owned;
4909
+ }
4910
+ /**
4911
+ * Determine whether a remote-only resource is still owned by this app.
4912
+ * Also records other SDK owners so renamed-empty applications can be handled.
4913
+ * @param params - Ownership classification inputs
4914
+ * @param params.labels - Existing resource labels
4915
+ * @param params.ownerLabel - Existing `sdk-name` label, when present
4916
+ * @param params.appName - Current application name
4917
+ * @param params.appId - Current application id, when present
4918
+ * @param params.resourceOwners - Other-owner accumulator
4919
+ * @returns True when the resource is owned by the current app
4920
+ */
4921
+ function trackRemainingResourceOwner(params) {
4922
+ const { labels, ownerLabel, appName, appId, resourceOwners } = params;
4923
+ const owned = isOwnedByApp(labels, appName, appId);
4924
+ if (ownerLabel && !owned) resourceOwners.add(ownerLabel);
4925
+ return owned;
4926
+ }
4927
+
4735
4928
  //#endregion
4736
4929
  //#region src/cli/commands/deploy/executor.ts
4737
4930
  /**
@@ -4766,28 +4959,20 @@ async function planExecutor(context) {
4766
4959
  const conflicts = [];
4767
4960
  const unmanaged = [];
4768
4961
  const resourceOwners = /* @__PURE__ */ new Set();
4769
- const withoutLabel = await fetchAll(async (pageToken, maxPageSize) => {
4770
- try {
4962
+ const existingExecutors = await fetchExistingResourcesWithLabels({
4963
+ client,
4964
+ workspaceId,
4965
+ fetchPage: async (pageToken, pageSize) => {
4771
4966
  const { executors, nextPageToken } = await client.listExecutorExecutors({
4772
4967
  workspaceId,
4773
4968
  pageToken,
4774
- pageSize: maxPageSize
4969
+ pageSize
4775
4970
  });
4776
4971
  return [executors, nextPageToken];
4777
- } catch (error) {
4778
- if (error instanceof ConnectError && error.code === Code.NotFound) return [[], ""];
4779
- throw error;
4780
- }
4972
+ },
4973
+ getName: (resource) => resource.name,
4974
+ getTrn: trn$3
4781
4975
  });
4782
- const existingExecutors = {};
4783
- await Promise.all(withoutLabel.map(async (resource) => {
4784
- const { metadata } = await client.getMetadata({ trn: trn$3(workspaceId, resource.name) });
4785
- existingExecutors[resource.name] = {
4786
- resource,
4787
- label: metadata?.labels[sdkNameLabelKey],
4788
- allLabels: metadata?.labels
4789
- };
4790
- }));
4791
4976
  const executors = forRemoval ? {} : await application.executorService?.loadExecutors() ?? {};
4792
4977
  for (const executor of Object.values(executors)) {
4793
4978
  const existing = existingExecutors[executor.name];
@@ -4798,17 +4983,16 @@ async function planExecutor(context) {
4798
4983
  });
4799
4984
  const desiredExecutor = protoExecutor(application, executor);
4800
4985
  if (existing) {
4801
- const owned = isOwnedByApp(existing.allLabels, application.name, application.id);
4802
- if (!owned) if (!existing.label) unmanaged.push({
4803
- resourceType: "Executor",
4804
- resourceName: executor.name
4805
- });
4806
- else conflicts.push({
4986
+ if (trackDesiredResourceOwnership({
4987
+ labels: existing.allLabels,
4988
+ ownerLabel: existing.label,
4989
+ appName: application.name,
4990
+ appId: application.id,
4807
4991
  resourceType: "Executor",
4808
4992
  resourceName: executor.name,
4809
- currentOwner: existing.label
4810
- });
4811
- if (owned && hasMatchingSdkVersion(existing.allLabels, metaRequest.labels) && areExecutorsEqual(existing.resource, desiredExecutor)) changeSet.unchanged.push({ name: executor.name });
4993
+ conflicts,
4994
+ unmanaged
4995
+ }) && hasMatchingSdkVersion(existing.allLabels, metaRequest.labels) && areExecutorsEqual(existing.resource, desiredExecutor)) changeSet.unchanged.push({ name: executor.name });
4812
4996
  else changeSet.updates.push({
4813
4997
  name: executor.name,
4814
4998
  request: {
@@ -4830,9 +5014,13 @@ async function planExecutor(context) {
4830
5014
  Object.entries(existingExecutors).forEach(([name]) => {
4831
5015
  const entry = existingExecutors[name];
4832
5016
  const label = entry?.label;
4833
- const owned = isOwnedByApp(entry?.allLabels, application.name, application.id);
4834
- if (label && !owned) resourceOwners.add(label);
4835
- if (owned) changeSet.deletes.push({
5017
+ if (trackRemainingResourceOwner({
5018
+ labels: entry?.allLabels,
5019
+ ownerLabel: label,
5020
+ appName: application.name,
5021
+ appId: application.id,
5022
+ resourceOwners
5023
+ })) changeSet.deletes.push({
4836
5024
  name,
4837
5025
  request: {
4838
5026
  workspaceId,
@@ -5779,28 +5967,20 @@ async function planStaticWebsite(context) {
5779
5967
  const conflicts = [];
5780
5968
  const unmanaged = [];
5781
5969
  const resourceOwners = /* @__PURE__ */ new Set();
5782
- const withoutLabel = await fetchAll(async (pageToken, maxPageSize) => {
5783
- try {
5970
+ const existingWebsites = await fetchExistingResourcesWithLabels({
5971
+ client,
5972
+ workspaceId,
5973
+ fetchPage: async (pageToken, pageSize) => {
5784
5974
  const { staticwebsites, nextPageToken } = await client.listStaticWebsites({
5785
5975
  workspaceId,
5786
5976
  pageToken,
5787
- pageSize: maxPageSize
5977
+ pageSize
5788
5978
  });
5789
5979
  return [staticwebsites, nextPageToken];
5790
- } catch (error) {
5791
- if (error instanceof ConnectError && error.code === Code.NotFound) return [[], ""];
5792
- throw error;
5793
- }
5980
+ },
5981
+ getName: (resource) => resource.name,
5982
+ getTrn: trn$1
5794
5983
  });
5795
- const existingWebsites = {};
5796
- await Promise.all(withoutLabel.map(async (resource) => {
5797
- const { metadata } = await client.getMetadata({ trn: trn$1(workspaceId, resource.name) });
5798
- existingWebsites[resource.name] = {
5799
- resource,
5800
- label: metadata?.labels[sdkNameLabelKey],
5801
- allLabels: metadata?.labels
5802
- };
5803
- }));
5804
5984
  const staticWebsiteServices = forRemoval ? [] : application.staticWebsiteServices;
5805
5985
  for (const websiteService of staticWebsiteServices) {
5806
5986
  const config = websiteService;
@@ -5821,17 +6001,16 @@ async function planStaticWebsite(context) {
5821
6001
  }
5822
6002
  };
5823
6003
  if (existing) {
5824
- const owned = isOwnedByApp(existing.allLabels, application.name, application.id);
5825
- if (!owned) if (!existing.label) unmanaged.push({
5826
- resourceType: "StaticWebsite",
5827
- resourceName: name
5828
- });
5829
- else conflicts.push({
6004
+ if (trackDesiredResourceOwnership({
6005
+ labels: existing.allLabels,
6006
+ ownerLabel: existing.label,
6007
+ appName: application.name,
6008
+ appId: application.id,
5830
6009
  resourceType: "StaticWebsite",
5831
6010
  resourceName: name,
5832
- currentOwner: existing.label
5833
- });
5834
- if (owned && hasMatchingSdkVersion(existing.allLabels, metaRequest.labels) && areStaticWebsitesEqual(existing.resource, desired)) changeSet.unchanged.push({ name });
6011
+ conflicts,
6012
+ unmanaged
6013
+ }) && hasMatchingSdkVersion(existing.allLabels, metaRequest.labels) && areStaticWebsitesEqual(existing.resource, desired)) changeSet.unchanged.push({ name });
5835
6014
  else changeSet.updates.push({
5836
6015
  name,
5837
6016
  request,
@@ -5847,9 +6026,13 @@ async function planStaticWebsite(context) {
5847
6026
  Object.entries(existingWebsites).forEach(([name]) => {
5848
6027
  const entry = existingWebsites[name];
5849
6028
  const label = entry?.label;
5850
- const owned = isOwnedByApp(entry?.allLabels, application.name, application.id);
5851
- if (label && !owned) resourceOwners.add(label);
5852
- if (owned) changeSet.deletes.push({
6029
+ if (trackRemainingResourceOwner({
6030
+ labels: entry?.allLabels,
6031
+ ownerLabel: label,
6032
+ appName: application.name,
6033
+ appId: application.id,
6034
+ resourceOwners
6035
+ })) changeSet.deletes.push({
5853
6036
  name,
5854
6037
  request: {
5855
6038
  workspaceId,
@@ -5939,19 +6122,11 @@ function formatDiffChange(change) {
5939
6122
  case "type_removed": return ` - [Type] ${change.typeName} (removed)`;
5940
6123
  case "type_modified": return ` ~ [Type] ${change.typeName}: ${change.reason}`;
5941
6124
  case "field_added": {
5942
- const field = change.after;
5943
- const typeStr = formatFieldType(field);
6125
+ const typeStr = formatFieldType(change.after);
5944
6126
  return ` + ${change.fieldName}: ${typeStr}`;
5945
6127
  }
5946
- case "field_removed": {
5947
- const field = change.before;
5948
- return ` - ${change.fieldName}: ${field.type}`;
5949
- }
5950
- case "field_modified": {
5951
- const before = change.before;
5952
- const after = change.after;
5953
- return ` ~ ${change.fieldName}: ${formatFieldModification(before, after)}`;
5954
- }
6128
+ case "field_removed": return ` - ${change.fieldName}: ${change.before.type}`;
6129
+ case "field_modified": return ` ~ ${change.fieldName}: ${formatFieldModification(change.before, change.after)}`;
5955
6130
  case "index_added": return ` + [Index] ${change.indexName}`;
5956
6131
  case "index_removed": return ` - [Index] ${change.indexName}`;
5957
6132
  case "index_modified": return ` ~ [Index] ${change.indexName}: ${change.reason ?? "modified"}`;
@@ -5962,7 +6137,10 @@ function formatDiffChange(change) {
5962
6137
  case "relationship_removed": return ` - [Relationship${change.relationshipType ? ` (${change.relationshipType})` : ""}] ${change.relationshipName}`;
5963
6138
  case "relationship_modified": return ` ~ [Relationship${change.relationshipType ? ` (${change.relationshipType})` : ""}] ${change.relationshipName}: ${change.reason ?? "modified"}`;
5964
6139
  case "permission_modified": return ` ~ [Permission] ${change.reason ?? "modified"}`;
5965
- default: return ` ? ${change.typeName}.${change.fieldName ?? ""}`;
6140
+ default: {
6141
+ const unknown = change;
6142
+ return ` ? ${unknown.typeName}.${unknown.fieldName ?? ""}`;
6143
+ }
5966
6144
  }
5967
6145
  }
5968
6146
  /**
@@ -6066,6 +6244,28 @@ function formatDiffSummary(diff) {
6066
6244
  return parts.length > 0 ? parts.join(", ") : "No changes";
6067
6245
  }
6068
6246
 
6247
+ //#endregion
6248
+ //#region src/cli/commands/tailordb/migrate/migration-number.ts
6249
+ /**
6250
+ * Format migration number as 4-digit string.
6251
+ * @param num - Migration number
6252
+ * @returns 4-digit padded string
6253
+ */
6254
+ function formatMigrationNumber(num) {
6255
+ return num.toString().padStart(4, "0");
6256
+ }
6257
+
6258
+ //#endregion
6259
+ //#region src/cli/commands/tailordb/migrate/snapshot-types.ts
6260
+ /**
6261
+ * Type guard: is the operand a field-reference (object) operand?
6262
+ * @param {SnapshotPermissionOperand} operand - Operand to test
6263
+ * @returns {boolean} True if operand is a field-ref (not a value operand)
6264
+ */
6265
+ function isSnapshotFieldRefOperand(operand) {
6266
+ return typeof operand === "object" && operand !== null && !Array.isArray(operand);
6267
+ }
6268
+
6069
6269
  //#endregion
6070
6270
  //#region src/cli/commands/tailordb/migrate/snapshot.ts
6071
6271
  /**
@@ -6121,14 +6321,6 @@ function normalizeSnapshotType(type) {
6121
6321
  for (const field of Object.values(type.fields)) normalizeSnapshotField(field);
6122
6322
  }
6123
6323
  /**
6124
- * Type guard: is the operand a field-reference (object) operand?
6125
- * @param {SnapshotPermissionOperand} operand - Operand to test
6126
- * @returns {boolean} True if operand is a field-ref (not a value operand)
6127
- */
6128
- function isSnapshotFieldRefOperand(operand) {
6129
- return typeof operand === "object" && operand !== null && !Array.isArray(operand);
6130
- }
6131
- /**
6132
6324
  * Validate that a migration number follows the expected format (4-digit number)
6133
6325
  * @param {string} numberStr - Migration number string to validate
6134
6326
  * @returns {boolean} True if number matches expected format
@@ -6137,14 +6329,6 @@ function isValidMigrationNumber(numberStr) {
6137
6329
  return MIGRATION_NUMBER_PATTERN.test(numberStr);
6138
6330
  }
6139
6331
  /**
6140
- * Format migration number as 4-digit string
6141
- * @param {number} num - Migration number
6142
- * @returns {string} 4-digit padded string (e.g., "0001")
6143
- */
6144
- function formatMigrationNumber(num) {
6145
- return num.toString().padStart(4, "0");
6146
- }
6147
- /**
6148
6332
  * Map of migration file types to their file names
6149
6333
  */
6150
6334
  const MIGRATION_FILE_NAMES = {
@@ -7359,6 +7543,15 @@ const PRE_MIGRATION_FIELD_KINDS = new Set([
7359
7543
  "field_removed"
7360
7544
  ]);
7361
7545
  /**
7546
+ * Type guard: is the change a field-level change that needs pre-migration
7547
+ * schema adjustment?
7548
+ * @param {DiffChange} change - Diff change to test
7549
+ * @returns {boolean} True if the change is a field-level change
7550
+ */
7551
+ function isPreMigrationFieldChange(change) {
7552
+ return PRE_MIGRATION_FIELD_KINDS.has(change.kind);
7553
+ }
7554
+ /**
7362
7555
  * Build a map of field changes that require pre-migration schema adjustment.
7363
7556
  * @param {PendingMigration[]} pendingMigrations - Pending migrations to scan
7364
7557
  * @returns {PreMigrationChangesMap} Map of changes keyed by typeName/fieldName
@@ -7366,7 +7559,7 @@ const PRE_MIGRATION_FIELD_KINDS = new Set([
7366
7559
  function buildPreMigrationChangesMap(pendingMigrations) {
7367
7560
  const map = /* @__PURE__ */ new Map();
7368
7561
  for (const migration of pendingMigrations) for (const change of migration.diff.changes) {
7369
- if (!PRE_MIGRATION_FIELD_KINDS.has(change.kind)) continue;
7562
+ if (!isPreMigrationFieldChange(change)) continue;
7370
7563
  if (!change.fieldName) continue;
7371
7564
  const perType = map.get(change.typeName) ?? /* @__PURE__ */ new Map();
7372
7565
  perType.set(change.fieldName, change);
@@ -7385,24 +7578,21 @@ function buildPreMigrationChangesMap(pendingMigrations) {
7385
7578
  * - Modified fields keep the looser side of unique/required/enum.
7386
7579
  *
7387
7580
  * @param {Record<string, MessageInitShape<typeof TailorDBType_FieldConfigSchema>>} fields - Field map to adjust (mutated in place)
7388
- * @param {Map<string, DiffChange>} typeChanges - Changes for this type, keyed by fieldName
7581
+ * @param {Map<string, FieldDiffChange>} typeChanges - Changes for this type, keyed by fieldName
7389
7582
  */
7390
7583
  function applyPreMigrationFieldAdjustments(fields, typeChanges) {
7391
7584
  for (const [fieldName, change] of typeChanges) {
7392
7585
  if (change.kind === "field_removed") {
7393
- const before = change.before;
7394
- if (before) fields[fieldName] = convertFieldConfigToProto(before);
7586
+ if (change.before) fields[fieldName] = convertFieldConfigToProto(change.before);
7395
7587
  continue;
7396
7588
  }
7397
7589
  const field = fields[fieldName];
7398
7590
  if (!field) continue;
7399
- const before = change.before;
7400
- const after = change.after;
7401
- if (change.kind === "field_added" && after?.required) {
7402
- field.required = false;
7591
+ if (change.kind === "field_added") {
7592
+ if (change.after?.required) field.required = false;
7403
7593
  continue;
7404
7594
  }
7405
- if (change.kind !== "field_modified") continue;
7595
+ const { before, after } = change;
7406
7596
  if (!before?.required && after?.required) field.required = false;
7407
7597
  if (!(before?.unique ?? false) && (after?.unique ?? false)) field.unique = false;
7408
7598
  if (before?.allowedValues && after?.allowedValues) {
@@ -9403,23 +9593,20 @@ async function planWorkflow(client, workspaceId, appName, appId, workflows, main
9403
9593
  const unmanaged = [];
9404
9594
  const resourceOwners = /* @__PURE__ */ new Set();
9405
9595
  const unchangedWorkflowJobNames = /* @__PURE__ */ new Set();
9406
- const withoutLabel = await fetchAll(async (pageToken, maxPageSize) => {
9407
- const response = await client.listWorkflows({
9408
- workspaceId,
9409
- pageToken,
9410
- pageSize: maxPageSize
9411
- });
9412
- return [response.workflows, response.nextPageToken];
9596
+ const existingWorkflows = await fetchExistingResourcesWithLabels({
9597
+ client,
9598
+ workspaceId,
9599
+ fetchPage: async (pageToken, pageSize) => {
9600
+ const response = await client.listWorkflows({
9601
+ workspaceId,
9602
+ pageToken,
9603
+ pageSize
9604
+ });
9605
+ return [response.workflows, response.nextPageToken];
9606
+ },
9607
+ getName: (resource) => resource.name,
9608
+ getTrn: workflowTrn$1
9413
9609
  });
9414
- const existingWorkflows = {};
9415
- await Promise.all(withoutLabel.map(async (resource) => {
9416
- const { metadata } = await client.getMetadata({ trn: workflowTrn$1(workspaceId, resource.name) });
9417
- existingWorkflows[resource.name] = {
9418
- resource,
9419
- label: metadata?.labels[sdkNameLabelKey],
9420
- allLabels: metadata?.labels
9421
- };
9422
- }));
9423
9610
  for (const workflow of Object.values(workflows)) {
9424
9611
  const existing = existingWorkflows[workflow.name];
9425
9612
  const metaRequest = await buildMetaRequest({
@@ -9430,17 +9617,16 @@ async function planWorkflow(client, workspaceId, appName, appId, workflows, main
9430
9617
  const usedJobNames = mainJobDeps[workflow.mainJob.name];
9431
9618
  if (!usedJobNames) throw new Error(`Job "${workflow.mainJob.name}" (mainJob of workflow "${workflow.name}") was not found.\n\nPossible causes:\n - The job is not exported as a named export\n - The file containing the job is not included in workflow.files glob pattern\n\nSolution:\n export const ${workflow.mainJob.name} = createWorkflowJob({ name: "${workflow.mainJob.name}", ... })`);
9432
9619
  if (existing) {
9433
- const owned = isOwnedByApp(existing.allLabels, appName, appId);
9434
- if (!owned) if (!existing.label) unmanaged.push({
9435
- resourceType: "Workflow",
9436
- resourceName: workflow.name
9437
- });
9438
- else conflicts.push({
9620
+ if (trackDesiredResourceOwnership({
9621
+ labels: existing.allLabels,
9622
+ ownerLabel: existing.label,
9623
+ appName,
9624
+ appId,
9439
9625
  resourceType: "Workflow",
9440
9626
  resourceName: workflow.name,
9441
- currentOwner: existing.label
9442
- });
9443
- if (owned && hasMatchingSdkVersion(existing.allLabels, metaRequest.labels) && canTreatWorkflowAsUnchanged(existing.resource, workflow, usedJobNames, unchangedJobFunctions)) {
9627
+ conflicts,
9628
+ unmanaged
9629
+ }) && hasMatchingSdkVersion(existing.allLabels, metaRequest.labels) && canTreatWorkflowAsUnchanged(existing.resource, workflow, usedJobNames, unchangedJobFunctions)) {
9444
9630
  changeSet.unchanged.push({ name: workflow.name });
9445
9631
  for (const jobName of usedJobNames) unchangedWorkflowJobNames.add(jobName);
9446
9632
  } else changeSet.updates.push({
@@ -9461,10 +9647,13 @@ async function planWorkflow(client, workspaceId, appName, appId, workflows, main
9461
9647
  }
9462
9648
  Object.values(existingWorkflows).forEach((existing) => {
9463
9649
  if (!existing) return;
9464
- const label = existing.label;
9465
- const owned = isOwnedByApp(existing.allLabels, appName, appId);
9466
- if (label && !owned) resourceOwners.add(label);
9467
- if (owned) changeSet.deletes.push({
9650
+ if (trackRemainingResourceOwner({
9651
+ labels: existing.allLabels,
9652
+ ownerLabel: existing.label,
9653
+ appName,
9654
+ appId,
9655
+ resourceOwners
9656
+ })) changeSet.deletes.push({
9468
9657
  name: existing.resource.name,
9469
9658
  workspaceId,
9470
9659
  workflowId: existing.resource.id,
@@ -9754,7 +9943,7 @@ function summarizePlanResults(results, displayEntries, serviceActions) {
9754
9943
  async function deploy(options) {
9755
9944
  return withSpan("deploy", async (rootSpan) => {
9756
9945
  rootSpan.setAttribute("deploy.dry_run", options?.dryRun ?? false);
9757
- const { config, application, workflowBuildResult, bundledScripts, buildOnly } = await withSpan("build", async () => {
9946
+ const { config, application, workflowBuildResult, httpAdapterBuildResult, bundledScripts, buildOnly } = await withSpan("build", async () => {
9758
9947
  const dryRun = options?.dryRun ?? false;
9759
9948
  const buildOnly = options?.buildOnly ?? parseBoolean(process.env.TAILOR_PLATFORM_SDK_BUILD_ONLY) === true;
9760
9949
  const { config, plugins } = await withSpan("build.loadConfig", async () => {
@@ -9791,6 +9980,7 @@ async function deploy(options) {
9791
9980
  }));
9792
9981
  let application;
9793
9982
  let workflowBuildResult;
9983
+ let httpAdapterBuildResult;
9794
9984
  let bundledScripts;
9795
9985
  try {
9796
9986
  const result = await withSpan("build.loadApplication", () => loadApplication({
@@ -9800,6 +9990,7 @@ async function deploy(options) {
9800
9990
  }));
9801
9991
  application = result.application;
9802
9992
  workflowBuildResult = result.workflowBuildResult;
9993
+ httpAdapterBuildResult = result.httpAdapterBuildResult;
9803
9994
  bundledScripts = result.bundledScripts;
9804
9995
  } finally {
9805
9996
  cacheManager.finalize();
@@ -9809,6 +10000,7 @@ async function deploy(options) {
9809
10000
  plugins,
9810
10001
  application,
9811
10002
  workflowBuildResult,
10003
+ httpAdapterBuildResult,
9812
10004
  bundledScripts,
9813
10005
  dryRun,
9814
10006
  buildOnly
@@ -9850,7 +10042,7 @@ async function deploy(options) {
9850
10042
  withSpan("plan.idp", () => planIdP(ctx)),
9851
10043
  withSpan("plan.auth", () => planAuth(ctx)),
9852
10044
  withSpan("plan.pipeline", () => planPipeline(ctx)),
9853
- withSpan("plan.application", () => planApplication(ctx)),
10045
+ withSpan("plan.application", () => planApplication(ctx, httpAdapterBuildResult)),
9854
10046
  withSpan("plan.executor", () => planExecutor(ctx)),
9855
10047
  withSpan("plan.workflow", () => planWorkflow(client, workspaceId, application.name, application.id, workflowService?.workflows ?? {}, workflowBuildResult?.mainJobDeps ?? {}, unchangedWorkflowJobs)),
9856
10048
  withSpan("plan.secretManager", () => planSecretManager(ctx))
@@ -10972,10 +11164,11 @@ const startCommand = defineAppCommand({
10972
11164
  configPath: args.config,
10973
11165
  interval: parseDuration(args.interval)
10974
11166
  });
11167
+ const jsonOutput = logger.jsonMode;
10975
11168
  logger.info(`Execution ID: ${executionId}`, { mode: "stream" });
10976
11169
  if (args.wait) {
10977
- const result = await wait({ showProgress: true });
10978
- if (args.logs && !args.json) {
11170
+ const result = await wait({ showProgress: !jsonOutput });
11171
+ if (args.logs && !jsonOutput) {
10979
11172
  const { execution } = await getWorkflowExecution({
10980
11173
  executionId,
10981
11174
  workspaceId: args["workspace-id"],
@@ -11406,6 +11599,7 @@ const listCommand$9 = defineAppCommand({
11406
11599
  ...paginationArgs()
11407
11600
  }).strict(),
11408
11601
  run: async (args) => {
11602
+ const jsonOutput = logger.jsonMode;
11409
11603
  const executors = await listExecutors({
11410
11604
  workspaceId: args["workspace-id"],
11411
11605
  profile: args.profile,
@@ -11414,10 +11608,11 @@ const listCommand$9 = defineAppCommand({
11414
11608
  });
11415
11609
  if (executors.length === 0) {
11416
11610
  logger.info("No executors found.");
11611
+ if (jsonOutput) logger.out([]);
11417
11612
  return;
11418
11613
  }
11419
11614
  logger.out(executors, { display: { disabled: (v) => v ? styles.warning("true") : styles.dim("false") } });
11420
- if (!args.json) {
11615
+ if (!jsonOutput) {
11421
11616
  if (executors.some((e) => e.triggerType === "webhook")) logger.info("To see webhook URLs, run: tailor-sdk executor webhook list");
11422
11617
  }
11423
11618
  }
@@ -11674,6 +11869,7 @@ const listWebhookCommand = defineAppCommand({
11674
11869
  ...paginationArgs()
11675
11870
  }).strict(),
11676
11871
  run: async (args) => {
11872
+ const jsonOutput = logger.jsonMode;
11677
11873
  const executors = await listWebhookExecutors({
11678
11874
  workspaceId: args["workspace-id"],
11679
11875
  profile: args.profile,
@@ -11682,10 +11878,11 @@ const listWebhookCommand = defineAppCommand({
11682
11878
  });
11683
11879
  if (executors.length === 0) {
11684
11880
  logger.info("No webhook executors found.");
11881
+ if (jsonOutput) logger.out([]);
11685
11882
  return;
11686
11883
  }
11687
11884
  logger.out(executors, { display: { disabled: (v) => v ? styles.warning("true") : styles.dim("false") } });
11688
- if (!args.json) logger.info("To test a webhook, run: tailor-sdk executor trigger <name> -d '{\"key\":\"value\"}'");
11885
+ if (!jsonOutput) logger.info("To test a webhook, run: tailor-sdk executor trigger <name> -d '{\"key\":\"value\"}'");
11689
11886
  }
11690
11887
  });
11691
11888
  const webhookCommand = defineCommand({
@@ -11833,13 +12030,14 @@ const listCommand$8 = defineAppCommand({
11833
12030
  ...paginationArgs()
11834
12031
  }).strict(),
11835
12032
  run: async (args) => {
12033
+ const jsonOutput = logger.jsonMode;
11836
12034
  const registries = await listFunctionRegistries({
11837
12035
  workspaceId: args["workspace-id"],
11838
12036
  profile: args.profile,
11839
12037
  order: args.order,
11840
12038
  limit: args.limit
11841
12039
  });
11842
- const formatted = args.json ? registries : registries.map(({ createdAt, updatedAt, ...rest }) => ({
12040
+ const formatted = jsonOutput ? registries : registries.map(({ createdAt, updatedAt, ...rest }) => ({
11843
12041
  ...rest,
11844
12042
  createdAt: humanizeRelativeTime(createdAt),
11845
12043
  updatedAt: humanizeRelativeTime(updatedAt)
@@ -13752,8 +13950,7 @@ function extractBreakingChangeFields(diff) {
13752
13950
  const addedRequiredFields = /* @__PURE__ */ new Map();
13753
13951
  const enumValueChanges = /* @__PURE__ */ new Map();
13754
13952
  for (const change of diff.changes) if (change.kind === "field_modified" && change.fieldName) {
13755
- const before = change.before;
13756
- const after = change.after;
13953
+ const { before, after } = change;
13757
13954
  if (before && after && !before.required && after.required) {
13758
13955
  if (!optionalToRequired.has(change.typeName)) optionalToRequired.set(change.typeName, /* @__PURE__ */ new Set());
13759
13956
  optionalToRequired.get(change.typeName).add(change.fieldName);
@@ -13772,7 +13969,7 @@ function extractBreakingChangeFields(diff) {
13772
13969
  }
13773
13970
  }
13774
13971
  } else if (change.kind === "field_added" && change.fieldName) {
13775
- const after = change.after;
13972
+ const { after } = change;
13776
13973
  if (after && after.required) {
13777
13974
  if (!addedRequiredFields.has(change.typeName)) addedRequiredFields.set(change.typeName, /* @__PURE__ */ new Map());
13778
13975
  addedRequiredFields.get(change.typeName).set(change.fieldName, after);
@@ -14127,8 +14324,7 @@ function generateChangeScript(change) {
14127
14324
  return null;
14128
14325
  }
14129
14326
  if (change.kind !== "field_modified") return null;
14130
- const before = change.before;
14131
- const after = change.after;
14327
+ const { before, after } = change;
14132
14328
  if (!before.required && after.required) return ` // Set ${change.fieldName} for ${change.typeName} records where it is null
14133
14329
  await trx
14134
14330
  .updateTable("${change.typeName}")
@@ -14160,8 +14356,8 @@ function generateChangeScript(change) {
14160
14356
  }
14161
14357
  }`;
14162
14358
  if (before.type === "enum" && after.type === "enum") {
14163
- const beforeValues = before.allowedValues ?? [];
14164
- const afterValues = after.allowedValues ?? [];
14359
+ const beforeValues = (before.allowedValues ?? []).map((v) => v.value);
14360
+ const afterValues = (after.allowedValues ?? []).map((v) => v.value);
14165
14361
  const removedValues = beforeValues.filter((v) => !afterValues.includes(v));
14166
14362
  if (removedValues.length > 0) {
14167
14363
  const defaultValue = afterValues[0] ?? "NEW_VALUE";
@@ -14258,7 +14454,7 @@ async function generate(options) {
14258
14454
  if (options.init) await handleInitOption(namespacesWithMigrations, options.yes);
14259
14455
  let pluginManager;
14260
14456
  if (plugins.length > 0) pluginManager = new PluginManager(plugins);
14261
- const { defineApplication } = await import("./application-BsipSxp3.mjs");
14457
+ const { defineApplication } = await import("./application-DM8q9GDI.mjs");
14262
14458
  const application = defineApplication({
14263
14459
  config,
14264
14460
  pluginManager
@@ -14665,15 +14861,16 @@ const listCommand$3 = defineAppCommand({
14665
14861
  ...paginationArgs()
14666
14862
  }).strict(),
14667
14863
  run: async (args) => {
14864
+ const jsonOutput = logger.jsonMode;
14668
14865
  const workflows = await listWorkflows({
14669
14866
  workspaceId: args["workspace-id"],
14670
14867
  profile: args.profile,
14671
14868
  order: args.order,
14672
14869
  limit: args.limit
14673
14870
  });
14674
- if (workflows.length === 0 && !args.json) {
14871
+ if (workflows.length === 0) {
14675
14872
  logger.info("No workflows found.");
14676
- return;
14873
+ if (!jsonOutput) return;
14677
14874
  }
14678
14875
  logger.out(workflows);
14679
14876
  }
@@ -14898,13 +15095,14 @@ const listCommand$2 = defineAppCommand({
14898
15095
  ...paginationArgs()
14899
15096
  }).strict(),
14900
15097
  run: async (args) => {
15098
+ const jsonOutput = logger.jsonMode;
14901
15099
  const apps = await listApps({
14902
15100
  workspaceId: args["workspace-id"],
14903
15101
  profile: args.profile,
14904
15102
  order: args.order,
14905
15103
  limit: args.limit
14906
15104
  });
14907
- const formattedApps = args.json ? apps : apps.map(({ updatedAt: _, createdAt, ...rest }) => ({
15105
+ const formattedApps = jsonOutput ? apps : apps.map(({ updatedAt: _, createdAt, ...rest }) => ({
14908
15106
  ...rest,
14909
15107
  createdAt: humanizeRelativeTime(createdAt)
14910
15108
  }));
@@ -15862,9 +16060,13 @@ async function loadTypeFieldOrder(config, namespace) {
15862
16060
  return fieldOrder;
15863
16061
  }
15864
16062
 
16063
+ //#endregion
16064
+ //#region src/cli/query/types.ts
16065
+ const queryEngines = ["sql", "gql"];
16066
+
15865
16067
  //#endregion
15866
16068
  //#region src/cli/query/index.ts
15867
- const queryEngineSchema = z.enum(["sql", "gql"]);
16069
+ const queryEngineSchema = z.enum(queryEngines);
15868
16070
  const queryBaseOptionsSchema = z.object({
15869
16071
  workspaceId: z.string().optional(),
15870
16072
  profile: z.string().optional(),
@@ -16444,5 +16646,5 @@ function isDeno() {
16444
16646
  }
16445
16647
 
16446
16648
  //#endregion
16447
- export { listCommand$5 as $, compareSnapshots as $t, truncate as A, workspaceArgs as An, startCommand as At, logBetaWarning as B, getExecutor as Bt, listCommand$2 as C, configArg as Cn, triggerExecutor as Ct, resumeWorkflow as D, pagedLogArgs as Dn, jobsCommand as Dt, resumeCommand as E, isVerbose 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, paginationArgs 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, commonArgs as Sn, triggerCommand as St, healthCommand as T, deploymentArgs 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 _, prompt as _n, listFunctionRegistries as _t, updateUser as a, getMigrationFiles as an, createCommand$1 as at, createCommand as b, assertWritable as bn, listWebhookExecutors as bt, listCommand as c, loadDiff 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, generateUserTypes as gn, listCommand$8 as gt, listWorkspaces as h, trnPrefix as hn, generate$1 as ht, updateCommand as i, getMigrationFilePath as in, deleteFolder as it, truncateCommand as j, startWorkflow as jt, listWorkflows as k, toPageDirection as kn, watchExecutorJob as kt, listUsers as l, reconstructSnapshotFromMigrations as ln, getCommand$3 as lt, listCommand$1 as m, sdkNameLabelKey as mn, listMachineUsers as mt, query as n, getLatestMigrationNumber as nn, getFolder as nt, removeCommand as o, getNextMigrationNumber 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, getMigrationDirPath as rn, deleteCommand$1 as rt, removeUser as s, isValidMigrationNumber as sn, listCommand$6 as st, isNativeTypeScriptRuntime as t, formatMigrationNumber as tn, getCommand$2 as tt, inviteCommand as u, formatDiffSummary as un, getOAuth2Client as ut, deleteCommand as v, apiCommand as vn, getCommand$4 as vt, getAppHealth as w, confirmationArgs as wn, listCommand$9 as wt, createWorkspace as x, defineAppCommand as xn, webhookCommand as xt, deleteWorkspace as y, apiCall as yn, getFunctionRegistry as yt, showCommand as z, getCommand$6 as zt };
16448
- //# sourceMappingURL=runtime-DpbAj_8a.mjs.map
16649
+ export { listCommand$5 as $, compareSnapshots as $t, truncate as A, workspaceArgs as An, startCommand as At, logBetaWarning as B, getExecutor as Bt, listCommand$2 as C, configArg as Cn, triggerExecutor as Ct, resumeWorkflow as D, pagedLogArgs as Dn, jobsCommand as Dt, resumeCommand as E, isVerbose 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, paginationArgs 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, commonArgs as Sn, triggerCommand as St, healthCommand as T, deploymentArgs 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 _, prompt as _n, listFunctionRegistries as _t, updateUser as a, getNextMigrationNumber as an, createCommand$1 as at, createCommand as b, assertWritable 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, generateUserTypes as gn, listCommand$8 as gt, listWorkspaces as h, trnPrefix as hn, generate$1 as ht, updateCommand as i, getMigrationFiles as in, deleteFolder as it, truncateCommand as j, startWorkflow as jt, listWorkflows as k, toPageDirection as kn, watchExecutorJob as kt, listUsers as l, formatMigrationNumber as ln, getCommand$3 as lt, listCommand$1 as m, sdkNameLabelKey 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, apiCommand as vn, getCommand$4 as vt, getAppHealth as w, confirmationArgs as wn, listCommand$9 as wt, createWorkspace as x, defineAppCommand as xn, webhookCommand as xt, deleteWorkspace as y, apiCall as yn, getFunctionRegistry as yt, showCommand as z, getCommand$6 as zt };
16650
+ //# sourceMappingURL=runtime-CgGeIoxi.mjs.map