@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.
- package/CHANGELOG.md +51 -0
- package/dist/{actor-J2gJ0eK5.d.mts → actor-D_2aJjYO.d.mts} +2 -2
- package/dist/{application-BezXGbrU.mjs → application-DGDmL8i_.mjs} +72 -9
- package/dist/application-DGDmL8i_.mjs.map +1 -0
- package/dist/application-nTydHJm8.mjs +4 -0
- package/dist/cli/index.mjs +66 -22
- package/dist/cli/index.mjs.map +1 -1
- package/dist/cli/lib.d.mts +375 -375
- package/dist/cli/lib.mjs +3 -3
- package/dist/{client-CobIRHl-.mjs → client-F0a4cWUM.mjs} +3 -2
- package/dist/client-F0a4cWUM.mjs.map +1 -0
- package/dist/{client-C68VWo4g.mjs → client-boxXYevx.mjs} +1 -1
- package/dist/completion/zsh-worker.zsh +4043 -0
- package/dist/configure/index.d.mts +5 -5
- package/dist/configure/index.mjs +17 -1
- package/dist/configure/index.mjs.map +1 -1
- package/dist/{crashreport-BhD0y14F.mjs → crashreport-0EHy-ayY.mjs} +2 -2
- package/dist/{crashreport-BhD0y14F.mjs.map → crashreport-0EHy-ayY.mjs.map} +1 -1
- package/dist/{crashreport-D1wKBJ8N.mjs → crashreport-Bf6uT6mf.mjs} +1 -1
- package/dist/{index-CLxubakC.d.mts → index-BdLqzJDu.d.mts} +19 -6
- package/dist/{index-CfRFkXIO.d.mts → index-Bhjep8cS.d.mts} +2 -2
- package/dist/{index-DUupuPhZ.d.mts → index-CZ2r3qiO.d.mts} +2 -2
- package/dist/{index-CPRnOjjt.d.mts → index-Db2RvnEH.d.mts} +2 -2
- package/dist/{index-CQZVJ5SX.d.mts → index-QpC0TNbH.d.mts} +2 -2
- package/dist/plugin/builtin/enum-constants/index.d.mts +1 -1
- package/dist/plugin/builtin/file-utils/index.d.mts +1 -1
- package/dist/plugin/builtin/kysely-type/index.d.mts +1 -1
- package/dist/plugin/builtin/seed/index.d.mts +1 -1
- package/dist/plugin/index.d.mts +2 -2
- package/dist/{plugin-C_FyVSdl.d.mts → plugin-DylAsA4Z.d.mts} +2 -2
- package/dist/{runtime-CW3jcQCc.mjs → runtime-2nzOZCUb.mjs} +728 -182
- package/dist/runtime-2nzOZCUb.mjs.map +1 -0
- package/dist/{tailordb-BlBGmQK-.d.mts → tailordb-C-ar4XCX.d.mts} +4 -4
- package/dist/utils/test/index.d.mts +3 -3
- package/dist/{workflow.generated-Bf1tWylx.d.mts → workflow.generated--1Qc15Et.d.mts} +62 -7
- package/docs/cli/auth.md +4 -4
- package/docs/cli/completion.md +3 -0
- package/docs/cli/function.md +8 -8
- package/docs/cli/query.md +1 -1
- package/docs/cli/workflow.md +10 -10
- package/docs/cli/workspace.md +14 -10
- package/docs/cli-reference.md +1 -1
- package/docs/services/aigateway.md +97 -0
- package/docs/services/auth.md +19 -0
- package/docs/services/idp.md +96 -0
- package/docs/services/tailordb-migration.md +17 -6
- package/package.json +12 -12
- package/dist/application-BezXGbrU.mjs.map +0 -1
- package/dist/application-DSXntqnV.mjs +0 -4
- package/dist/client-CobIRHl-.mjs.map +0 -1
- 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-
|
|
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,
|
|
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]
|
|
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
|
-
|
|
6624
|
-
|
|
6625
|
-
|
|
6626
|
-
|
|
6627
|
-
|
|
6628
|
-
|
|
6629
|
-
|
|
6630
|
-
|
|
6631
|
-
|
|
6632
|
-
|
|
6633
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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 &&
|
|
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
|
|
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 &&
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
8569
|
+
if (change.after.required) field.required = false;
|
|
8114
8570
|
continue;
|
|
8115
8571
|
}
|
|
8116
8572
|
const { before, after } = change;
|
|
8117
|
-
if (!before
|
|
8118
|
-
if (!(before
|
|
8119
|
-
if (before
|
|
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
|
-
|
|
8889
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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(
|
|
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
|
|
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 (
|
|
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 (
|
|
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:
|
|
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
|
|
14015
|
+
name
|
|
13476
14016
|
});
|
|
13477
|
-
if (!machineUser) throw new Error(`Machine user ${
|
|
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"
|
|
15033
|
+
for (const change of diff.changes) if (change.kind === "field_modified") {
|
|
14490
15034
|
const { before, after } = change;
|
|
14491
|
-
if (
|
|
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
|
|
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"
|
|
15052
|
+
} else if (change.kind === "field_added") {
|
|
14509
15053
|
const { after } = change;
|
|
14510
|
-
if (after
|
|
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-
|
|
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
|
-
|
|
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:
|
|
17164
|
+
name: machineUser
|
|
16619
17165
|
});
|
|
16620
|
-
if (!machineUserResource) throw new Error(`Machine user ${
|
|
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:
|
|
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-
|
|
17699
|
+
//# sourceMappingURL=runtime-2nzOZCUb.mjs.map
|