@tailor-platform/sdk 1.47.1 → 1.48.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 +79 -0
- package/dist/{actor-jk4-f0yp.d.mts → actor-BeIEiPYM.d.mts} +2 -2
- package/dist/application-BNkNt47b.mjs +4 -0
- package/dist/{application-C7H7y0hS.mjs → application-DUENhx4Y.mjs} +80 -17
- package/dist/application-DUENhx4Y.mjs.map +1 -0
- package/dist/cli/index.mjs +12 -12
- package/dist/cli/index.mjs.map +1 -1
- package/dist/cli/lib.d.mts +6 -6
- package/dist/cli/lib.mjs +4 -4
- package/dist/{client-DCqdtFte.mjs → client-CPW1N1Rs.mjs} +1 -1
- package/dist/{client-DbyKSN1F.mjs → client-_kHh0Pip.mjs} +2 -2
- package/dist/{client-DbyKSN1F.mjs.map → client-_kHh0Pip.mjs.map} +1 -1
- package/dist/configure/index.d.mts +4 -4
- package/dist/configure/index.mjs +51 -3
- package/dist/configure/index.mjs.map +1 -1
- package/dist/{crashreport-CNSw_BrJ.mjs → crashreport-CvmdFs4i.mjs} +5 -5
- package/dist/crashreport-CvmdFs4i.mjs.map +1 -0
- package/dist/{crashreport-DXGFd16F.mjs → crashreport-DHJuSmUc.mjs} +1 -1
- package/dist/{errors-wNQxQQBH.mjs → errors-pMPXghkO.mjs} +1 -1
- package/dist/{errors-wNQxQQBH.mjs.map → errors-pMPXghkO.mjs.map} +1 -1
- package/dist/index-BQ4oi0AI.d.mts +48 -0
- package/dist/{index-BbOTbZFf.d.mts → index-BjXN1SdY.d.mts} +2 -2
- package/dist/{index-DB8EapT-.d.mts → index-C--7W0UO.d.mts} +5 -5
- package/dist/{index-BRvNi5q9.d.mts → index-VJW98BSy.d.mts} +2 -2
- package/dist/{index-iy-hNfGp.d.mts → index-nV4ZC_Ve.d.mts} +2 -2
- package/dist/{interceptor-CBsqEWDK.mjs → interceptor-DTNS0EtF.mjs} +1 -1
- package/dist/{interceptor-CBsqEWDK.mjs.map → interceptor-DTNS0EtF.mjs.map} +1 -1
- package/dist/{job-R5C2Hfcc.mjs → job-M3Avv_SV.mjs} +4 -3
- package/dist/{job-R5C2Hfcc.mjs.map → job-M3Avv_SV.mjs.map} +1 -1
- package/dist/{mock-BP-9O5On.mjs → mock-BfL09ULZ.mjs} +1 -1
- package/dist/{mock-BP-9O5On.mjs.map → mock-BfL09ULZ.mjs.map} +1 -1
- 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/builtin/seed/index.mjs +1 -1
- package/dist/plugin/index.d.mts +2 -2
- package/dist/{repl-editor-CZpLlOBj.mjs → repl-editor-jZ493eQI.mjs} +1 -1
- package/dist/{repl-editor-CZpLlOBj.mjs.map → repl-editor-jZ493eQI.mjs.map} +1 -1
- package/dist/{runtime-XjP6JMmP.mjs → runtime-CNg0w27y.mjs} +396 -125
- package/dist/runtime-CNg0w27y.mjs.map +1 -0
- package/dist/{tailordb-DjlNUV6u.mjs → schema-C5QjYEc-.mjs} +2 -42
- package/dist/schema-C5QjYEc-.mjs.map +1 -0
- package/dist/secret-file-BHpxGyNf.mjs +65 -0
- package/dist/secret-file-BHpxGyNf.mjs.map +1 -0
- package/dist/{seed-DrKY5yIF.mjs → seed-DjfAn0BC.mjs} +44 -19
- package/dist/seed-DjfAn0BC.mjs.map +1 -0
- package/dist/{service-obEU5gSM.mjs → service-DCgJxdg1.mjs} +2 -2
- package/dist/{service-obEU5gSM.mjs.map → service-DCgJxdg1.mjs.map} +1 -1
- package/dist/{tailor-db-field-Bn8ZC5lK.d.mts → tailor-db-field-4bMLe25-.d.mts} +5 -1
- package/dist/telemetry-C13VIFpT.mjs +4 -0
- package/dist/{telemetry-DcL8Fsm_.mjs → telemetry-C1Y56L5E.mjs} +1 -1
- package/dist/{telemetry-DcL8Fsm_.mjs.map → telemetry-C1Y56L5E.mjs.map} +1 -1
- package/dist/utils/test/index.d.mts +3 -3
- package/dist/utils/test/index.mjs +1 -1
- package/dist/vitest/environment.mjs +1 -1
- package/dist/vitest/index.mjs +1 -1
- package/dist/vitest/setup.mjs +1 -1
- package/dist/{workflow.generated-i7PK4fg-.d.mts → workflow.generated-OYAu_6zX.d.mts} +12 -2
- package/docs/cli/application.md +4 -0
- package/docs/configuration.md +4 -0
- package/docs/generator/builtin.md +35 -4
- package/package.json +11 -11
- package/postinstall.mjs +1 -1
- package/dist/application-C7H7y0hS.mjs.map +0 -1
- package/dist/application-Csq5jxYP.mjs +0 -4
- package/dist/crashreport-CNSw_BrJ.mjs.map +0 -1
- package/dist/index-BXyS7xKC.d.mts +0 -21
- package/dist/runtime-XjP6JMmP.mjs.map +0 -1
- package/dist/seed-DrKY5yIF.mjs.map +0 -1
- package/dist/tailordb-DjlNUV6u.mjs.map +0 -1
- package/dist/telemetry-21afNV9_.mjs +0 -4
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
|
|
2
|
-
import {
|
|
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-
|
|
2
|
+
import { t as db } from "./schema-C5QjYEc-.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-_kHh0Pip.mjs";
|
|
4
4
|
import { a as parseBoolean, i as symbols, n as logger, r as styles, t as CIPromptError } from "./logger-DTNAMYGy.mjs";
|
|
5
|
-
import { C as
|
|
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-DUENhx4Y.mjs";
|
|
6
6
|
import { t as multiline } from "./multiline-e3IpANmS.mjs";
|
|
7
7
|
import { t as readPackageJson } from "./package-json-6Px8bDpG.mjs";
|
|
8
|
-
import { n as isCLIError, t as createCLIError } from "./errors-
|
|
9
|
-
import { r as withSpan } from "./telemetry-
|
|
8
|
+
import { n as isCLIError, t as createCLIError } from "./errors-pMPXghkO.mjs";
|
|
9
|
+
import { r as withSpan } from "./telemetry-C1Y56L5E.mjs";
|
|
10
10
|
import { arg, createDefineCommand, defineCommand, runCommand } from "politty";
|
|
11
11
|
import { z } from "zod";
|
|
12
12
|
import * as fs$1 from "node:fs";
|
|
@@ -23,7 +23,7 @@ import { xdgConfig } from "xdg-basedir";
|
|
|
23
23
|
import { Code, ConnectError } from "@connectrpc/connect";
|
|
24
24
|
import { resolveTSConfig } from "pkg-types";
|
|
25
25
|
import { ScalarType, create, fromJson, toJson } from "@bufbuild/protobuf";
|
|
26
|
-
import * as crypto from "node:crypto";
|
|
26
|
+
import * as crypto$1 from "node:crypto";
|
|
27
27
|
import { createHash } from "node:crypto";
|
|
28
28
|
import { ExitPromptError } from "@inquirer/core";
|
|
29
29
|
import { confirm, input, password } from "@inquirer/prompts";
|
|
@@ -31,6 +31,7 @@ import { isCI } from "std-env";
|
|
|
31
31
|
import * as rolldown from "rolldown";
|
|
32
32
|
import * as fs from "node:fs/promises";
|
|
33
33
|
import { glob } from "node:fs/promises";
|
|
34
|
+
import { parseSync } from "oxc-parser";
|
|
34
35
|
import * as inflection from "inflection";
|
|
35
36
|
import { setTimeout as setTimeout$1 } from "timers/promises";
|
|
36
37
|
import { spawn } from "node:child_process";
|
|
@@ -1443,6 +1444,11 @@ function trnPrefix(workspaceId) {
|
|
|
1443
1444
|
}
|
|
1444
1445
|
const sdkNameLabelKey = "sdk-name";
|
|
1445
1446
|
const sdkVersionLabelKey = "sdk-version";
|
|
1447
|
+
const sdkAppIdLabelKey = "sdk-app-id";
|
|
1448
|
+
const appIdLabelPrefix = "app-";
|
|
1449
|
+
function toAppIdLabelValue(appId) {
|
|
1450
|
+
return `${appIdLabelPrefix}${appId}`;
|
|
1451
|
+
}
|
|
1446
1452
|
/**
|
|
1447
1453
|
* Check whether existing metadata was produced by the current SDK version.
|
|
1448
1454
|
* @param existingLabels - Labels currently stored on the remote resource
|
|
@@ -1453,13 +1459,33 @@ function hasMatchingSdkVersion(existingLabels, desiredLabels) {
|
|
|
1453
1459
|
return existingLabels?.[sdkVersionLabelKey] === desiredLabels?.[sdkVersionLabelKey];
|
|
1454
1460
|
}
|
|
1455
1461
|
/**
|
|
1462
|
+
* Determine whether a remote resource is owned by the given application.
|
|
1463
|
+
* When the resource carries an `sdk-app-id`, ownership is decided strictly
|
|
1464
|
+
* by id match — a resource explicitly tagged with another app's id is
|
|
1465
|
+
* NOT ours even if the legacy sdk-name happens to match. Resources without
|
|
1466
|
+
* `sdk-app-id` (legacy) fall back to sdk-name comparison.
|
|
1467
|
+
* @param labels - Labels currently stored on the remote resource
|
|
1468
|
+
* @param appName - Application name from the local config
|
|
1469
|
+
* @param appId - Stable application id from the local config (when present)
|
|
1470
|
+
* @returns True when the resource is owned by the application
|
|
1471
|
+
*/
|
|
1472
|
+
function isOwnedByApp(labels, appName, appId) {
|
|
1473
|
+
if (!labels) return false;
|
|
1474
|
+
const labelAppId = labels[sdkAppIdLabelKey];
|
|
1475
|
+
if (labelAppId) return appId !== void 0 && labelAppId === toAppIdLabelValue(appId);
|
|
1476
|
+
return labels[sdkNameLabelKey] === appName;
|
|
1477
|
+
}
|
|
1478
|
+
/**
|
|
1456
1479
|
* Build metadata request with SDK labels.
|
|
1457
|
-
* @param
|
|
1458
|
-
* @param
|
|
1459
|
-
* @param
|
|
1480
|
+
* @param params - Parameters for building the metadata request
|
|
1481
|
+
* @param params.trn - Target TRN
|
|
1482
|
+
* @param params.appName - Application name label
|
|
1483
|
+
* @param params.appId - Stable application id label (when managed by SDK)
|
|
1484
|
+
* @param params.existingLabels - Existing labels to preserve (optional)
|
|
1460
1485
|
* @returns Metadata request
|
|
1461
1486
|
*/
|
|
1462
|
-
async function buildMetaRequest(
|
|
1487
|
+
async function buildMetaRequest(params) {
|
|
1488
|
+
const { trn, appName, appId, existingLabels } = params;
|
|
1463
1489
|
const packageJson = await readPackageJson();
|
|
1464
1490
|
const sdkVersion = packageJson.version ? `v${packageJson.version.replace(/\./g, "-")}` : "unknown";
|
|
1465
1491
|
return {
|
|
@@ -1467,7 +1493,8 @@ async function buildMetaRequest(trn, appName, existingLabels) {
|
|
|
1467
1493
|
labels: {
|
|
1468
1494
|
...existingLabels ?? {},
|
|
1469
1495
|
[sdkNameLabelKey]: appName,
|
|
1470
|
-
[sdkVersionLabelKey]: sdkVersion
|
|
1496
|
+
[sdkVersionLabelKey]: sdkVersion,
|
|
1497
|
+
...appId ? { [sdkAppIdLabelKey]: toAppIdLabelValue(appId) } : {}
|
|
1471
1498
|
}
|
|
1472
1499
|
};
|
|
1473
1500
|
}
|
|
@@ -1568,11 +1595,20 @@ async function planApplication(context) {
|
|
|
1568
1595
|
}
|
|
1569
1596
|
});
|
|
1570
1597
|
if (forRemoval) {
|
|
1571
|
-
|
|
1572
|
-
|
|
1598
|
+
const ownedAppNames = /* @__PURE__ */ new Set();
|
|
1599
|
+
if (existingApplications.some((app) => app.name === application.name)) ownedAppNames.add(application.name);
|
|
1600
|
+
if (application.id) {
|
|
1601
|
+
const others = existingApplications.filter((app) => !ownedAppNames.has(app.name));
|
|
1602
|
+
const owned = await Promise.all(others.map(async (app) => {
|
|
1603
|
+
return isOwnedByApp(await fetchAppLabels(client, workspaceId, app.name), application.name, application.id) ? app.name : null;
|
|
1604
|
+
}));
|
|
1605
|
+
for (const name of owned) if (name) ownedAppNames.add(name);
|
|
1606
|
+
}
|
|
1607
|
+
for (const name of ownedAppNames) changeSet.deletes.push({
|
|
1608
|
+
name,
|
|
1573
1609
|
request: {
|
|
1574
1610
|
workspaceId,
|
|
1575
|
-
applicationName:
|
|
1611
|
+
applicationName: name
|
|
1576
1612
|
}
|
|
1577
1613
|
});
|
|
1578
1614
|
return changeSet;
|
|
@@ -1602,7 +1638,11 @@ async function planApplication(context) {
|
|
|
1602
1638
|
});
|
|
1603
1639
|
if (idpConfigs.length > 0) authIdpConfigName = idpConfigs[0].name;
|
|
1604
1640
|
}
|
|
1605
|
-
const metaRequest = await buildMetaRequest(
|
|
1641
|
+
const metaRequest = await buildMetaRequest({
|
|
1642
|
+
trn: trn$6(workspaceId, application.name),
|
|
1643
|
+
appName: application.name,
|
|
1644
|
+
appId: application.id
|
|
1645
|
+
});
|
|
1606
1646
|
const expectedLocalWebsites = new Set(application.staticWebsiteServices.map((website) => website.name));
|
|
1607
1647
|
const resolvedCors = await resolveStaticWebsiteUrls(client, workspaceId, application.config.cors, "CORS", { expectedLocalNames: expectedLocalWebsites });
|
|
1608
1648
|
const desired = normalizeComparableApplication(application, authNamespace, authIdpConfigName, resolvedCors);
|
|
@@ -1617,9 +1657,22 @@ async function planApplication(context) {
|
|
|
1617
1657
|
disableIntrospection: application.config.disableIntrospection
|
|
1618
1658
|
};
|
|
1619
1659
|
const existing = existingApplications.find((app) => app.name === application.name);
|
|
1660
|
+
if (application.id) {
|
|
1661
|
+
const otherApps = existingApplications.filter((app) => app.name !== application.name);
|
|
1662
|
+
const renamedAway = await Promise.all(otherApps.map(async (app) => {
|
|
1663
|
+
return isOwnedByApp(await fetchAppLabels(client, workspaceId, app.name), application.name, application.id) ? app.name : null;
|
|
1664
|
+
}));
|
|
1665
|
+
for (const name of renamedAway) if (name) changeSet.deletes.push({
|
|
1666
|
+
name,
|
|
1667
|
+
request: {
|
|
1668
|
+
workspaceId,
|
|
1669
|
+
applicationName: name
|
|
1670
|
+
}
|
|
1671
|
+
});
|
|
1672
|
+
}
|
|
1620
1673
|
if (existing) {
|
|
1621
|
-
const
|
|
1622
|
-
if (
|
|
1674
|
+
const labels = await fetchAppLabels(client, workspaceId, application.name);
|
|
1675
|
+
if (isOwnedByApp(labels, application.name, application.id) && hasMatchingSdkVersion(labels, metaRequest.labels) && areApplicationsEqual(existing, desired)) changeSet.unchanged.push({ name: application.name });
|
|
1623
1676
|
else changeSet.updates.push({
|
|
1624
1677
|
name: application.name,
|
|
1625
1678
|
request,
|
|
@@ -1632,6 +1685,15 @@ async function planApplication(context) {
|
|
|
1632
1685
|
});
|
|
1633
1686
|
return changeSet;
|
|
1634
1687
|
}
|
|
1688
|
+
async function fetchAppLabels(client, workspaceId, appName) {
|
|
1689
|
+
try {
|
|
1690
|
+
const { metadata } = await client.getMetadata({ trn: trn$6(workspaceId, appName) });
|
|
1691
|
+
return metadata?.labels;
|
|
1692
|
+
} catch (error) {
|
|
1693
|
+
if (error instanceof ConnectError && error.code === Code.NotFound) return;
|
|
1694
|
+
throw error;
|
|
1695
|
+
}
|
|
1696
|
+
}
|
|
1635
1697
|
function protoSubgraph(subgraph) {
|
|
1636
1698
|
let serviceType;
|
|
1637
1699
|
switch (subgraph.Type) {
|
|
@@ -1757,10 +1819,11 @@ function hasNonSecretFieldChanged(existing, desired) {
|
|
|
1757
1819
|
* @param client - Operator client instance
|
|
1758
1820
|
* @param workspaceId - Workspace ID
|
|
1759
1821
|
* @param appName - Application name for ownership
|
|
1822
|
+
* @param appId - Stable application id (when managed by SDK)
|
|
1760
1823
|
* @param auths - Auth services with connection configs
|
|
1761
1824
|
* @returns Planned changes for auth connections
|
|
1762
1825
|
*/
|
|
1763
|
-
async function planAuthConnections(client, workspaceId, appName, auths) {
|
|
1826
|
+
async function planAuthConnections(client, workspaceId, appName, appId, auths) {
|
|
1764
1827
|
const changeSet = createChangeSet("Auth connections");
|
|
1765
1828
|
const conflicts = [];
|
|
1766
1829
|
const unmanaged = [];
|
|
@@ -1787,7 +1850,8 @@ async function planAuthConnections(client, workspaceId, appName, auths) {
|
|
|
1787
1850
|
const { metadata } = await client.getMetadata({ trn: connectionTrn(workspaceId, resource.name) });
|
|
1788
1851
|
existingConnections[resource.name] = {
|
|
1789
1852
|
resource,
|
|
1790
|
-
label: metadata?.labels[sdkNameLabelKey]
|
|
1853
|
+
label: metadata?.labels[sdkNameLabelKey],
|
|
1854
|
+
allLabels: metadata?.labels
|
|
1791
1855
|
};
|
|
1792
1856
|
} catch (error) {
|
|
1793
1857
|
if (error instanceof ConnectError && error.code === Code.InvalidArgument) {
|
|
@@ -1802,17 +1866,23 @@ async function planAuthConnections(client, workspaceId, appName, auths) {
|
|
|
1802
1866
|
const state = loadSecretsState();
|
|
1803
1867
|
for (const [name, config] of Object.entries(desiredConnections)) {
|
|
1804
1868
|
const existing = existingConnections[name];
|
|
1805
|
-
const metaRequest = metadataSupported ? await buildMetaRequest(
|
|
1869
|
+
const metaRequest = metadataSupported ? await buildMetaRequest({
|
|
1870
|
+
trn: connectionTrn(workspaceId, name),
|
|
1871
|
+
appName,
|
|
1872
|
+
appId
|
|
1873
|
+
}) : void 0;
|
|
1806
1874
|
if (existing) {
|
|
1807
|
-
if (
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1875
|
+
if (!isOwnedByApp(existing.allLabels, appName, appId)) {
|
|
1876
|
+
if (metadataSupported && !existing.label) unmanaged.push({
|
|
1877
|
+
resourceType: "Auth connection",
|
|
1878
|
+
resourceName: name
|
|
1879
|
+
});
|
|
1880
|
+
else if (existing.label) conflicts.push({
|
|
1881
|
+
resourceType: "Auth connection",
|
|
1882
|
+
resourceName: name,
|
|
1883
|
+
currentOwner: existing.label
|
|
1884
|
+
});
|
|
1885
|
+
}
|
|
1816
1886
|
const currentHash = hashConnectionConfig(config);
|
|
1817
1887
|
const storedHash = state.connections?.[name];
|
|
1818
1888
|
if (hasNonSecretFieldChanged(existing.resource, config) || currentHash !== storedHash) changeSet.replaces.push({
|
|
@@ -1834,11 +1904,12 @@ async function planAuthConnections(client, workspaceId, appName, auths) {
|
|
|
1834
1904
|
}
|
|
1835
1905
|
for (const [name, entry] of Object.entries(existingConnections)) {
|
|
1836
1906
|
if (!entry) continue;
|
|
1837
|
-
|
|
1907
|
+
const owned = isOwnedByApp(entry.allLabels, appName, appId);
|
|
1908
|
+
if (entry.label && !owned) {
|
|
1838
1909
|
resourceOwners.add(entry.label);
|
|
1839
1910
|
continue;
|
|
1840
1911
|
}
|
|
1841
|
-
if (
|
|
1912
|
+
if (owned || !metadataSupported) changeSet.deletes.push({
|
|
1842
1913
|
name,
|
|
1843
1914
|
request: {
|
|
1844
1915
|
workspaceId,
|
|
@@ -1934,7 +2005,7 @@ const CHUNK_SIZE = 64 * 1024;
|
|
|
1934
2005
|
* @returns Hex-encoded SHA-256 hash
|
|
1935
2006
|
*/
|
|
1936
2007
|
function computeContentHash(content) {
|
|
1937
|
-
return crypto.createHash("sha256").update(content, "utf-8").digest("hex");
|
|
2008
|
+
return crypto$1.createHash("sha256").update(content, "utf-8").digest("hex");
|
|
1938
2009
|
}
|
|
1939
2010
|
function functionRegistryTrn$1(workspaceId, name) {
|
|
1940
2011
|
return `trn:v1:workspace:${workspaceId}:function_registry:${name}`;
|
|
@@ -2103,10 +2174,11 @@ function filterBundledWorkflowJobs(jobs, usedJobNames) {
|
|
|
2103
2174
|
* @param client - Operator client instance
|
|
2104
2175
|
* @param workspaceId - Workspace ID
|
|
2105
2176
|
* @param appName - Application name
|
|
2177
|
+
* @param appId - Stable application id (when managed by SDK)
|
|
2106
2178
|
* @param entries - Desired function entries
|
|
2107
2179
|
* @returns Planned changes
|
|
2108
2180
|
*/
|
|
2109
|
-
async function planFunctionRegistry(client, workspaceId, appName, entries) {
|
|
2181
|
+
async function planFunctionRegistry(client, workspaceId, appName, appId, entries) {
|
|
2110
2182
|
const changeSet = createChangeSet("Function registry");
|
|
2111
2183
|
const conflicts = [];
|
|
2112
2184
|
const unmanaged = [];
|
|
@@ -2138,19 +2210,23 @@ async function planFunctionRegistry(client, workspaceId, appName, entries) {
|
|
|
2138
2210
|
}));
|
|
2139
2211
|
for (const entry of entries) {
|
|
2140
2212
|
const existing = existingMap[entry.name];
|
|
2141
|
-
const metaRequest = await buildMetaRequest(
|
|
2213
|
+
const metaRequest = await buildMetaRequest({
|
|
2214
|
+
trn: functionRegistryTrn$1(workspaceId, entry.name),
|
|
2215
|
+
appName,
|
|
2216
|
+
appId
|
|
2217
|
+
});
|
|
2142
2218
|
if (existing) {
|
|
2143
|
-
const
|
|
2144
|
-
if (!existing.label) unmanaged.push({
|
|
2219
|
+
const owned = isOwnedByApp(existing.allLabels, appName, appId);
|
|
2220
|
+
if (!owned) if (!existing.label) unmanaged.push({
|
|
2145
2221
|
resourceType: "Function registry",
|
|
2146
2222
|
resourceName: entry.name
|
|
2147
2223
|
});
|
|
2148
|
-
else
|
|
2224
|
+
else conflicts.push({
|
|
2149
2225
|
resourceType: "Function registry",
|
|
2150
2226
|
resourceName: entry.name,
|
|
2151
2227
|
currentOwner: existing.label
|
|
2152
2228
|
});
|
|
2153
|
-
if (existing.resource.contentHash === entry.contentHash &&
|
|
2229
|
+
if (existing.resource.contentHash === entry.contentHash && owned && hasMatchingSdkVersion(existing.allLabels, metaRequest.labels)) changeSet.unchanged.push({ name: entry.name });
|
|
2154
2230
|
else changeSet.updates.push({
|
|
2155
2231
|
name: entry.name,
|
|
2156
2232
|
entry,
|
|
@@ -2166,8 +2242,9 @@ async function planFunctionRegistry(client, workspaceId, appName, entries) {
|
|
|
2166
2242
|
for (const [name, existing] of Object.entries(existingMap)) {
|
|
2167
2243
|
if (!existing) continue;
|
|
2168
2244
|
const label = existing.label;
|
|
2169
|
-
|
|
2170
|
-
if (label
|
|
2245
|
+
const owned = isOwnedByApp(existing.allLabels, appName, appId);
|
|
2246
|
+
if (label && !owned) resourceOwners.add(label);
|
|
2247
|
+
if (owned) changeSet.deletes.push({
|
|
2171
2248
|
name,
|
|
2172
2249
|
workspaceId
|
|
2173
2250
|
});
|
|
@@ -2659,7 +2736,7 @@ async function applyIdP(client, result, phase = "create-update") {
|
|
|
2659
2736
|
async function planIdP(context) {
|
|
2660
2737
|
const { client, workspaceId, application, forRemoval, forceApplyAll = false, idpUserTriggerTargets } = context;
|
|
2661
2738
|
const idps = forRemoval ? [] : application.idpServices;
|
|
2662
|
-
const { changeSet: serviceChangeSet, conflicts, unmanaged, resourceOwners } = await planServices$3(client, workspaceId, application.name, idps, idpUserTriggerTargets ?? /* @__PURE__ */ new Set());
|
|
2739
|
+
const { changeSet: serviceChangeSet, conflicts, unmanaged, resourceOwners } = await planServices$3(client, workspaceId, application.name, application.id, idps, idpUserTriggerTargets ?? /* @__PURE__ */ new Set());
|
|
2663
2740
|
return {
|
|
2664
2741
|
changeSet: {
|
|
2665
2742
|
service: serviceChangeSet,
|
|
@@ -2746,7 +2823,7 @@ function areIdPServicesEqual(existing, desired) {
|
|
|
2746
2823
|
permission: normalizeComparablePermission(existing.permission)
|
|
2747
2824
|
}), desired);
|
|
2748
2825
|
}
|
|
2749
|
-
async function planServices$3(client, workspaceId, appName, idps, idpUserTriggerTargets) {
|
|
2826
|
+
async function planServices$3(client, workspaceId, appName, appId, idps, idpUserTriggerTargets) {
|
|
2750
2827
|
const changeSet = createChangeSet("IdP services");
|
|
2751
2828
|
const conflicts = [];
|
|
2752
2829
|
const unmanaged = [];
|
|
@@ -2777,7 +2854,11 @@ async function planServices$3(client, workspaceId, appName, idps, idpUserTrigger
|
|
|
2777
2854
|
for (const idp of idps) {
|
|
2778
2855
|
const namespaceName = idp.name;
|
|
2779
2856
|
const existing = existingServices[namespaceName];
|
|
2780
|
-
const metaRequest = await buildMetaRequest(
|
|
2857
|
+
const metaRequest = await buildMetaRequest({
|
|
2858
|
+
trn: trn$5(workspaceId, namespaceName),
|
|
2859
|
+
appName,
|
|
2860
|
+
appId
|
|
2861
|
+
});
|
|
2781
2862
|
let authorization;
|
|
2782
2863
|
switch (idp.authorization) {
|
|
2783
2864
|
case "insecure":
|
|
@@ -2823,17 +2904,17 @@ async function planServices$3(client, workspaceId, appName, idps, idpUserTrigger
|
|
|
2823
2904
|
permission: protoPermission
|
|
2824
2905
|
};
|
|
2825
2906
|
if (existing) {
|
|
2826
|
-
const
|
|
2827
|
-
if (!existing.label) unmanaged.push({
|
|
2907
|
+
const owned = isOwnedByApp(existing.allLabels, appName, appId);
|
|
2908
|
+
if (!owned) if (!existing.label) unmanaged.push({
|
|
2828
2909
|
resourceType: "IdP service",
|
|
2829
2910
|
resourceName: idp.name
|
|
2830
2911
|
});
|
|
2831
|
-
else
|
|
2912
|
+
else conflicts.push({
|
|
2832
2913
|
resourceType: "IdP service",
|
|
2833
2914
|
resourceName: idp.name,
|
|
2834
2915
|
currentOwner: existing.label
|
|
2835
2916
|
});
|
|
2836
|
-
if (
|
|
2917
|
+
if (owned && hasMatchingSdkVersion(existing.allLabels, metaRequest.labels) && areIdPServicesEqual(existing.resource, desired)) changeSet.unchanged.push({ name: namespaceName });
|
|
2837
2918
|
else changeSet.updates.push({
|
|
2838
2919
|
name: namespaceName,
|
|
2839
2920
|
request,
|
|
@@ -2847,9 +2928,11 @@ async function planServices$3(client, workspaceId, appName, idps, idpUserTrigger
|
|
|
2847
2928
|
});
|
|
2848
2929
|
}
|
|
2849
2930
|
Object.entries(existingServices).forEach(([namespaceName]) => {
|
|
2850
|
-
const
|
|
2851
|
-
|
|
2852
|
-
|
|
2931
|
+
const entry = existingServices[namespaceName];
|
|
2932
|
+
const label = entry?.label;
|
|
2933
|
+
const owned = isOwnedByApp(entry?.allLabels, appName, appId);
|
|
2934
|
+
if (label && !owned) resourceOwners.add(label);
|
|
2935
|
+
if (owned) changeSet.deletes.push({
|
|
2853
2936
|
name: namespaceName,
|
|
2854
2937
|
request: {
|
|
2855
2938
|
workspaceId,
|
|
@@ -3097,7 +3180,7 @@ async function planAuth(context) {
|
|
|
3097
3180
|
await application.authService.resolveNamespaces();
|
|
3098
3181
|
auths.push(application.authService);
|
|
3099
3182
|
}
|
|
3100
|
-
const { changeSet: serviceChangeSet, conflicts, unmanaged, resourceOwners } = await planServices$2(client, workspaceId, application.name, auths, forceApplyAll);
|
|
3183
|
+
const { changeSet: serviceChangeSet, conflicts, unmanaged, resourceOwners } = await planServices$2(client, workspaceId, application.name, application.id, auths, forceApplyAll);
|
|
3101
3184
|
const deletedServices = serviceChangeSet.deletes.map((del) => del.name);
|
|
3102
3185
|
const expectedLocalWebsites = new Set(application.staticWebsiteServices.map((website) => website.name));
|
|
3103
3186
|
const [idpConfigChangeSet, userProfileConfigChangeSet, tenantConfigChangeSet, machineUserChangeSet, authHookChangeSet, oauth2ClientChangeSet, scimChangeSet, scimResourceChangeSet, connectionResult] = await Promise.all([
|
|
@@ -3109,7 +3192,7 @@ async function planAuth(context) {
|
|
|
3109
3192
|
planOAuth2Clients(client, workspaceId, auths, deletedServices, expectedLocalWebsites, forceApplyAll),
|
|
3110
3193
|
planSCIMConfigs(client, workspaceId, auths, deletedServices),
|
|
3111
3194
|
planSCIMResources(client, workspaceId, auths, deletedServices),
|
|
3112
|
-
planAuthConnections(client, workspaceId, application.name, auths)
|
|
3195
|
+
planAuthConnections(client, workspaceId, application.name, application.id, auths)
|
|
3113
3196
|
]);
|
|
3114
3197
|
return {
|
|
3115
3198
|
changeSet: {
|
|
@@ -3132,7 +3215,7 @@ async function planAuth(context) {
|
|
|
3132
3215
|
function trn$4(workspaceId, name) {
|
|
3133
3216
|
return `trn:v1:workspace:${workspaceId}:auth:${name}`;
|
|
3134
3217
|
}
|
|
3135
|
-
async function planServices$2(client, workspaceId, appName, auths, forceApplyAll = false) {
|
|
3218
|
+
async function planServices$2(client, workspaceId, appName, appId, auths, forceApplyAll = false) {
|
|
3136
3219
|
const changeSet = createChangeSet("Auth services");
|
|
3137
3220
|
const conflicts = [];
|
|
3138
3221
|
const unmanaged = [];
|
|
@@ -3156,30 +3239,35 @@ async function planServices$2(client, workspaceId, appName, auths, forceApplyAll
|
|
|
3156
3239
|
const { metadata } = await client.getMetadata({ trn: trn$4(workspaceId, resource.namespace.name) });
|
|
3157
3240
|
existingServices[resource.namespace.name] = {
|
|
3158
3241
|
resource,
|
|
3159
|
-
label: metadata?.labels[sdkNameLabelKey]
|
|
3242
|
+
label: metadata?.labels[sdkNameLabelKey],
|
|
3243
|
+
allLabels: metadata?.labels
|
|
3160
3244
|
};
|
|
3161
3245
|
}));
|
|
3162
3246
|
for (const auth of auths) {
|
|
3163
3247
|
const { parsedConfig: config } = auth;
|
|
3164
3248
|
const existing = existingServices[config.name];
|
|
3165
|
-
const metaRequest = await buildMetaRequest(
|
|
3249
|
+
const metaRequest = await buildMetaRequest({
|
|
3250
|
+
trn: trn$4(workspaceId, config.name),
|
|
3251
|
+
appName,
|
|
3252
|
+
appId
|
|
3253
|
+
});
|
|
3166
3254
|
const request = {
|
|
3167
3255
|
workspaceId,
|
|
3168
3256
|
namespaceName: config.name,
|
|
3169
3257
|
publishSessionEvents: config.publishSessionEvents
|
|
3170
3258
|
};
|
|
3171
3259
|
if (existing) {
|
|
3172
|
-
const
|
|
3173
|
-
if (!existing.label) unmanaged.push({
|
|
3260
|
+
const owned = isOwnedByApp(existing.allLabels, appName, appId);
|
|
3261
|
+
if (!owned) if (!existing.label) unmanaged.push({
|
|
3174
3262
|
resourceType: "Auth service",
|
|
3175
3263
|
resourceName: config.name
|
|
3176
3264
|
});
|
|
3177
|
-
else
|
|
3265
|
+
else conflicts.push({
|
|
3178
3266
|
resourceType: "Auth service",
|
|
3179
3267
|
resourceName: config.name,
|
|
3180
3268
|
currentOwner: existing.label
|
|
3181
3269
|
});
|
|
3182
|
-
if (!forceApplyAll && existing.resource.publishSessionEvents === (config.publishSessionEvents ?? false) &&
|
|
3270
|
+
if (!forceApplyAll && existing.resource.publishSessionEvents === (config.publishSessionEvents ?? false) && owned) changeSet.unchanged.push({ name: config.name });
|
|
3183
3271
|
else changeSet.updates.push({
|
|
3184
3272
|
name: config.name,
|
|
3185
3273
|
request,
|
|
@@ -3193,9 +3281,11 @@ async function planServices$2(client, workspaceId, appName, auths, forceApplyAll
|
|
|
3193
3281
|
});
|
|
3194
3282
|
}
|
|
3195
3283
|
Object.entries(existingServices).forEach(([namespaceName]) => {
|
|
3196
|
-
const
|
|
3197
|
-
|
|
3198
|
-
|
|
3284
|
+
const entry = existingServices[namespaceName];
|
|
3285
|
+
const label = entry?.label;
|
|
3286
|
+
const owned = isOwnedByApp(entry?.allLabels, appName, appId);
|
|
3287
|
+
if (label && !owned) resourceOwners.add(label);
|
|
3288
|
+
if (owned) changeSet.deletes.push({
|
|
3199
3289
|
name: namespaceName,
|
|
3200
3290
|
request: {
|
|
3201
3291
|
workspaceId,
|
|
@@ -4159,10 +4249,99 @@ async function planAuthHooks(client, workspaceId, auths, deletedServices, forceA
|
|
|
4159
4249
|
return changeSet;
|
|
4160
4250
|
}
|
|
4161
4251
|
|
|
4252
|
+
//#endregion
|
|
4253
|
+
//#region src/cli/commands/deploy/config-id-injector.ts
|
|
4254
|
+
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
4255
|
+
function findDefineConfigCalls(node, results) {
|
|
4256
|
+
if (!node || typeof node !== "object") return;
|
|
4257
|
+
const n = node;
|
|
4258
|
+
if (n.type === "CallExpression") {
|
|
4259
|
+
const ce = n;
|
|
4260
|
+
if (ce.callee.type === "Identifier" && ce.callee.name === "defineConfig") {
|
|
4261
|
+
const arg = ce.arguments[0];
|
|
4262
|
+
const configObj = arg && arg.type === "ObjectExpression" ? arg : null;
|
|
4263
|
+
results.push({
|
|
4264
|
+
callExpr: ce,
|
|
4265
|
+
configObj
|
|
4266
|
+
});
|
|
4267
|
+
}
|
|
4268
|
+
}
|
|
4269
|
+
for (const key of Object.keys(n)) {
|
|
4270
|
+
const child = n[key];
|
|
4271
|
+
if (Array.isArray(child)) for (const c of child) findDefineConfigCalls(c, results);
|
|
4272
|
+
else if (child && typeof child === "object") findDefineConfigCalls(child, results);
|
|
4273
|
+
}
|
|
4274
|
+
}
|
|
4275
|
+
function findIdProperty(obj) {
|
|
4276
|
+
for (const prop of obj.properties) {
|
|
4277
|
+
if (prop.type !== "Property") continue;
|
|
4278
|
+
if ((prop.key.type === "Identifier" ? prop.key.name : prop.key.type === "Literal" ? prop.key.value : null) === "id") return prop;
|
|
4279
|
+
}
|
|
4280
|
+
return null;
|
|
4281
|
+
}
|
|
4282
|
+
/**
|
|
4283
|
+
* Ensure `tailor.config.ts` has an `id` property on the `defineConfig({...})`
|
|
4284
|
+
* argument. Generates a UUID when missing and writes it back to the file.
|
|
4285
|
+
* Returns null when the file does not contain a `defineConfig()` call (e.g.
|
|
4286
|
+
* a wrapper that re-exports another config).
|
|
4287
|
+
* @param configPath - Absolute path to the config file
|
|
4288
|
+
* @returns Resolved id and whether it was newly injected, or null if skipped
|
|
4289
|
+
*/
|
|
4290
|
+
async function ensureConfigId(configPath) {
|
|
4291
|
+
const source = await fs$1.promises.readFile(configPath, "utf-8");
|
|
4292
|
+
const { program } = parseSync(configPath, source);
|
|
4293
|
+
const calls = [];
|
|
4294
|
+
findDefineConfigCalls(program, calls);
|
|
4295
|
+
if (calls.length === 0) return null;
|
|
4296
|
+
if (calls.length > 1) throw new Error(`Multiple defineConfig() calls found in ${configPath}. Only one is supported.`);
|
|
4297
|
+
const { configObj } = calls[0];
|
|
4298
|
+
if (!configObj) throw new Error(`defineConfig() argument must be an inline object literal in ${configPath} so the SDK can manage the 'id' field.`);
|
|
4299
|
+
const idProp = findIdProperty(configObj);
|
|
4300
|
+
if (idProp) {
|
|
4301
|
+
const value = idProp.value;
|
|
4302
|
+
if (value.type !== "Literal") throw new Error(`'id' field in ${configPath} must be a string literal. To use this config for a separate app, delete it.`);
|
|
4303
|
+
const literalValue = value.value;
|
|
4304
|
+
if (typeof literalValue !== "string" || literalValue === "") throw new Error(`'id' field in ${configPath} must be a non-empty string literal. To use this config for a separate app, delete it.`);
|
|
4305
|
+
if (!uuidRegex.test(literalValue)) throw new Error(`'id' field in ${configPath} must be a UUID. To use this config for a separate app, delete it.`);
|
|
4306
|
+
return {
|
|
4307
|
+
id: literalValue,
|
|
4308
|
+
injected: false
|
|
4309
|
+
};
|
|
4310
|
+
}
|
|
4311
|
+
const id = crypto.randomUUID();
|
|
4312
|
+
const newSource = insertIdProperty(source, configObj, id);
|
|
4313
|
+
await fs$1.promises.writeFile(configPath, newSource, "utf-8");
|
|
4314
|
+
logger.info(`Generated app id and wrote to ${configPath}: ${id}`);
|
|
4315
|
+
return {
|
|
4316
|
+
id,
|
|
4317
|
+
injected: true
|
|
4318
|
+
};
|
|
4319
|
+
}
|
|
4320
|
+
const idComment = "// SDK-managed app id — do not edit, except when copying this config to a separate app.";
|
|
4321
|
+
function insertIdProperty(source, configObj, id) {
|
|
4322
|
+
const idLiteral = `id: ${JSON.stringify(id)}`;
|
|
4323
|
+
if (configObj.properties.length > 0) {
|
|
4324
|
+
const firstProp = configObj.properties[0];
|
|
4325
|
+
const lineStart = source.lastIndexOf("\n", firstProp.start - 1) + 1;
|
|
4326
|
+
const indent = source.slice(lineStart, firstProp.start);
|
|
4327
|
+
const insertion = `${idComment}\n${indent}${idLiteral},\n${indent}`;
|
|
4328
|
+
return source.slice(0, firstProp.start) + insertion + source.slice(firstProp.start);
|
|
4329
|
+
}
|
|
4330
|
+
const openBracePos = configObj.start + 1;
|
|
4331
|
+
const braceLineStart = source.lastIndexOf("\n", configObj.start) + 1;
|
|
4332
|
+
const baseIndent = source.slice(braceLineStart).match(/^[\t ]*/)?.[0] ?? "";
|
|
4333
|
+
const innerIndent = `${baseIndent} `;
|
|
4334
|
+
const insertion = `\n${innerIndent}${idComment}\n${innerIndent}${idLiteral},\n${baseIndent}`;
|
|
4335
|
+
return source.slice(0, openBracePos) + insertion + source.slice(openBracePos);
|
|
4336
|
+
}
|
|
4337
|
+
|
|
4162
4338
|
//#endregion
|
|
4163
4339
|
//#region src/cli/commands/deploy/confirm.ts
|
|
4164
4340
|
/**
|
|
4165
4341
|
* Confirm reassignment of resources when owner conflicts are detected.
|
|
4342
|
+
* Splits into two scenarios: id regeneration (same sdk-name, different
|
|
4343
|
+
* sdk-app-id) and name mismatch (different sdk-name). Each gets its own
|
|
4344
|
+
* prompt because the user-facing meaning is different.
|
|
4166
4345
|
* @param conflicts - Detected owner conflicts
|
|
4167
4346
|
* @param appName - Target application name
|
|
4168
4347
|
* @param yes - Whether to auto-confirm without prompting
|
|
@@ -4170,6 +4349,30 @@ async function planAuthHooks(client, workspaceId, auths, deletedServices, forceA
|
|
|
4170
4349
|
*/
|
|
4171
4350
|
async function confirmOwnerConflict(conflicts, appName, yes) {
|
|
4172
4351
|
if (conflicts.length === 0) return;
|
|
4352
|
+
const idRegenerated = conflicts.filter((c) => c.currentOwner === appName);
|
|
4353
|
+
const nameMismatches = conflicts.filter((c) => c.currentOwner !== appName);
|
|
4354
|
+
if (idRegenerated.length > 0) await confirmIdRegeneration(idRegenerated, appName, yes);
|
|
4355
|
+
if (nameMismatches.length > 0) await confirmNameMismatch(nameMismatches, appName, yes);
|
|
4356
|
+
}
|
|
4357
|
+
async function confirmIdRegeneration(conflicts, appName, yes) {
|
|
4358
|
+
logger.warn(`Application id was regenerated for "${appName}":`);
|
|
4359
|
+
logger.log(" These resources still carry the previous id.");
|
|
4360
|
+
logger.newline();
|
|
4361
|
+
logger.log(` ${styles.info("Resources")}:`);
|
|
4362
|
+
for (const c of conflicts) logger.log(` • ${styles.bold(c.resourceType)} ${styles.info(`"${c.resourceName}"`)}`);
|
|
4363
|
+
if (yes) {
|
|
4364
|
+
logger.success("Re-tagging resources with the new id (--yes flag specified)...", { mode: "plain" });
|
|
4365
|
+
return;
|
|
4366
|
+
}
|
|
4367
|
+
if (!await prompt.confirm({
|
|
4368
|
+
message: `Re-tag these resources with the new id for "${appName}"?\n${styles.dim("(The id in tailor.config.ts was removed since the previous deploy, so a new one was generated)")}`,
|
|
4369
|
+
default: false
|
|
4370
|
+
})) throw new Error(multiline`
|
|
4371
|
+
Apply cancelled. Resources remain tagged with the previous id.
|
|
4372
|
+
To override, run again and confirm, or use --yes flag.
|
|
4373
|
+
`);
|
|
4374
|
+
}
|
|
4375
|
+
async function confirmNameMismatch(conflicts, appName, yes) {
|
|
4173
4376
|
const currentOwners = [...new Set(conflicts.map((c) => c.currentOwner))];
|
|
4174
4377
|
logger.warn("Application name mismatch detected:");
|
|
4175
4378
|
logger.log(` ${styles.warning("Current application(s)")}: ${currentOwners.map((o) => styles.bold(`"${o}"`)).join(", ")}`);
|
|
@@ -4329,19 +4532,24 @@ async function planExecutor(context) {
|
|
|
4329
4532
|
const executors = forRemoval ? {} : await application.executorService?.loadExecutors() ?? {};
|
|
4330
4533
|
for (const executor of Object.values(executors)) {
|
|
4331
4534
|
const existing = existingExecutors[executor.name];
|
|
4332
|
-
const metaRequest = await buildMetaRequest(
|
|
4535
|
+
const metaRequest = await buildMetaRequest({
|
|
4536
|
+
trn: trn$3(workspaceId, executor.name),
|
|
4537
|
+
appName: application.name,
|
|
4538
|
+
appId: application.id
|
|
4539
|
+
});
|
|
4333
4540
|
const desiredExecutor = protoExecutor(application, executor);
|
|
4334
4541
|
if (existing) {
|
|
4335
|
-
|
|
4542
|
+
const owned = isOwnedByApp(existing.allLabels, application.name, application.id);
|
|
4543
|
+
if (!owned) if (!existing.label) unmanaged.push({
|
|
4336
4544
|
resourceType: "Executor",
|
|
4337
4545
|
resourceName: executor.name
|
|
4338
4546
|
});
|
|
4339
|
-
else
|
|
4547
|
+
else conflicts.push({
|
|
4340
4548
|
resourceType: "Executor",
|
|
4341
4549
|
resourceName: executor.name,
|
|
4342
4550
|
currentOwner: existing.label
|
|
4343
4551
|
});
|
|
4344
|
-
if (
|
|
4552
|
+
if (owned && hasMatchingSdkVersion(existing.allLabels, metaRequest.labels) && areExecutorsEqual(existing.resource, desiredExecutor)) changeSet.unchanged.push({ name: executor.name });
|
|
4345
4553
|
else changeSet.updates.push({
|
|
4346
4554
|
name: executor.name,
|
|
4347
4555
|
request: {
|
|
@@ -4361,9 +4569,11 @@ async function planExecutor(context) {
|
|
|
4361
4569
|
});
|
|
4362
4570
|
}
|
|
4363
4571
|
Object.entries(existingExecutors).forEach(([name]) => {
|
|
4364
|
-
const
|
|
4365
|
-
|
|
4366
|
-
|
|
4572
|
+
const entry = existingExecutors[name];
|
|
4573
|
+
const label = entry?.label;
|
|
4574
|
+
const owned = isOwnedByApp(entry?.allLabels, application.name, application.id);
|
|
4575
|
+
if (label && !owned) resourceOwners.add(label);
|
|
4576
|
+
if (owned) changeSet.deletes.push({
|
|
4367
4577
|
name,
|
|
4368
4578
|
request: {
|
|
4369
4579
|
workspaceId,
|
|
@@ -4722,7 +4932,7 @@ async function planPipeline(context) {
|
|
|
4722
4932
|
pipelines.push(pipeline);
|
|
4723
4933
|
}
|
|
4724
4934
|
const executors = forRemoval ? [] : Object.values(await application.executorService?.loadExecutors() ?? {});
|
|
4725
|
-
const { changeSet: serviceChangeSet, conflicts, unmanaged, resourceOwners } = await planServices$1(client, workspaceId, application.name, pipelines);
|
|
4935
|
+
const { changeSet: serviceChangeSet, conflicts, unmanaged, resourceOwners } = await planServices$1(client, workspaceId, application.name, application.id, pipelines);
|
|
4726
4936
|
const { changeSet: resolverChangeSet } = await planResolvers(client, workspaceId, pipelines, executors, serviceChangeSet.deletes.map((del) => del.name), application.env, application.authService?.config.name, forceApplyAll);
|
|
4727
4937
|
return {
|
|
4728
4938
|
changeSet: {
|
|
@@ -4737,7 +4947,7 @@ async function planPipeline(context) {
|
|
|
4737
4947
|
function trn$2(workspaceId, name) {
|
|
4738
4948
|
return `trn:v1:workspace:${workspaceId}:pipeline:${name}`;
|
|
4739
4949
|
}
|
|
4740
|
-
async function planServices$1(client, workspaceId, appName, pipelines) {
|
|
4950
|
+
async function planServices$1(client, workspaceId, appName, appId, pipelines) {
|
|
4741
4951
|
const changeSet = createChangeSet("Pipeline services");
|
|
4742
4952
|
const conflicts = [];
|
|
4743
4953
|
const unmanaged = [];
|
|
@@ -4767,18 +4977,23 @@ async function planServices$1(client, workspaceId, appName, pipelines) {
|
|
|
4767
4977
|
}));
|
|
4768
4978
|
for (const pipeline of pipelines) {
|
|
4769
4979
|
const existing = existingServices[pipeline.namespace];
|
|
4770
|
-
const metaRequest = await buildMetaRequest(
|
|
4980
|
+
const metaRequest = await buildMetaRequest({
|
|
4981
|
+
trn: trn$2(workspaceId, pipeline.namespace),
|
|
4982
|
+
appName,
|
|
4983
|
+
appId
|
|
4984
|
+
});
|
|
4771
4985
|
if (existing) {
|
|
4772
|
-
|
|
4986
|
+
const owned = isOwnedByApp(existing.allLabels, appName, appId);
|
|
4987
|
+
if (!owned) if (!existing.label) unmanaged.push({
|
|
4773
4988
|
resourceType: "Pipeline service",
|
|
4774
4989
|
resourceName: pipeline.namespace
|
|
4775
4990
|
});
|
|
4776
|
-
else
|
|
4991
|
+
else conflicts.push({
|
|
4777
4992
|
resourceType: "Pipeline service",
|
|
4778
4993
|
resourceName: pipeline.namespace,
|
|
4779
4994
|
currentOwner: existing.label
|
|
4780
4995
|
});
|
|
4781
|
-
if (
|
|
4996
|
+
if (owned && hasMatchingSdkVersion(existing.allLabels, metaRequest.labels)) changeSet.unchanged.push({ name: pipeline.namespace });
|
|
4782
4997
|
else changeSet.updates.push({
|
|
4783
4998
|
name: pipeline.namespace,
|
|
4784
4999
|
request: {
|
|
@@ -4798,9 +5013,11 @@ async function planServices$1(client, workspaceId, appName, pipelines) {
|
|
|
4798
5013
|
});
|
|
4799
5014
|
}
|
|
4800
5015
|
Object.entries(existingServices).forEach(([namespaceName]) => {
|
|
4801
|
-
const
|
|
4802
|
-
|
|
4803
|
-
|
|
5016
|
+
const entry = existingServices[namespaceName];
|
|
5017
|
+
const label = entry?.label;
|
|
5018
|
+
const owned = isOwnedByApp(entry?.allLabels, appName, appId);
|
|
5019
|
+
if (label && !owned) resourceOwners.add(label);
|
|
5020
|
+
if (owned) changeSet.deletes.push({
|
|
4804
5021
|
name: namespaceName,
|
|
4805
5022
|
request: {
|
|
4806
5023
|
workspaceId,
|
|
@@ -5062,17 +5279,22 @@ async function planSecretManager(context) {
|
|
|
5062
5279
|
const vaultName = vault.vaultName;
|
|
5063
5280
|
const existing = existingVaults[vaultName];
|
|
5064
5281
|
if (existing) {
|
|
5065
|
-
const metaRequest = await buildMetaRequest(
|
|
5066
|
-
|
|
5282
|
+
const metaRequest = await buildMetaRequest({
|
|
5283
|
+
trn: vaultTrn$1(workspaceId, vaultName),
|
|
5284
|
+
appName: application.name,
|
|
5285
|
+
appId: application.id
|
|
5286
|
+
});
|
|
5287
|
+
const owned = isOwnedByApp(existing.allLabels, application.name, application.id);
|
|
5288
|
+
if (!owned) if (!existing.label) unmanaged.push({
|
|
5067
5289
|
resourceType: "Secret Manager vault",
|
|
5068
5290
|
resourceName: vaultName
|
|
5069
5291
|
});
|
|
5070
|
-
else
|
|
5292
|
+
else conflicts.push({
|
|
5071
5293
|
resourceType: "Secret Manager vault",
|
|
5072
5294
|
resourceName: vaultName,
|
|
5073
5295
|
currentOwner: existing.label
|
|
5074
5296
|
});
|
|
5075
|
-
if (
|
|
5297
|
+
if (owned && hasMatchingSdkVersion(existing.allLabels, metaRequest.labels)) vaultChangeSet.unchanged.push({ name: vaultName });
|
|
5076
5298
|
else vaultChangeSet.updates.push({
|
|
5077
5299
|
name: vaultName,
|
|
5078
5300
|
workspaceId
|
|
@@ -5133,8 +5355,9 @@ async function planSecretManager(context) {
|
|
|
5133
5355
|
for (const [name, entry] of Object.entries(existingVaults)) {
|
|
5134
5356
|
if (!entry) continue;
|
|
5135
5357
|
const label = entry.label;
|
|
5136
|
-
|
|
5137
|
-
if (label
|
|
5358
|
+
const owned = isOwnedByApp(entry.allLabels, application.name, application.id);
|
|
5359
|
+
if (label && !owned) resourceOwners.add(label);
|
|
5360
|
+
if (owned) {
|
|
5138
5361
|
const secrets = await fetchAll(async (pageToken, maxPageSize) => {
|
|
5139
5362
|
try {
|
|
5140
5363
|
const { secrets, nextPageToken } = await client.listSecretManagerSecrets({
|
|
@@ -5190,12 +5413,20 @@ async function applySecretManager(client, result, phase = "create-update", appli
|
|
|
5190
5413
|
secretmanagerVaultName: create.name
|
|
5191
5414
|
});
|
|
5192
5415
|
if (application) {
|
|
5193
|
-
const metaRequest = await buildMetaRequest(
|
|
5416
|
+
const metaRequest = await buildMetaRequest({
|
|
5417
|
+
trn: vaultTrn$1(create.workspaceId, create.name),
|
|
5418
|
+
appName: application.name,
|
|
5419
|
+
appId: application.id
|
|
5420
|
+
});
|
|
5194
5421
|
await client.setMetadata(metaRequest);
|
|
5195
5422
|
}
|
|
5196
5423
|
}));
|
|
5197
5424
|
if (application) await Promise.all(vaultChangeSet.updates.map(async (update) => {
|
|
5198
|
-
const metaRequest = await buildMetaRequest(
|
|
5425
|
+
const metaRequest = await buildMetaRequest({
|
|
5426
|
+
trn: vaultTrn$1(update.workspaceId, update.name),
|
|
5427
|
+
appName: application.name,
|
|
5428
|
+
appId: application.id
|
|
5429
|
+
});
|
|
5199
5430
|
await client.setMetadata(metaRequest);
|
|
5200
5431
|
}));
|
|
5201
5432
|
await Promise.all(secretChangeSet.creates.map((create) => client.createSecretManagerSecret({
|
|
@@ -5316,7 +5547,11 @@ async function planStaticWebsite(context) {
|
|
|
5316
5547
|
const config = websiteService;
|
|
5317
5548
|
const name = websiteService.name;
|
|
5318
5549
|
const existing = existingWebsites[name];
|
|
5319
|
-
const metaRequest = await buildMetaRequest(
|
|
5550
|
+
const metaRequest = await buildMetaRequest({
|
|
5551
|
+
trn: trn$1(workspaceId, name),
|
|
5552
|
+
appName: application.name,
|
|
5553
|
+
appId: application.id
|
|
5554
|
+
});
|
|
5320
5555
|
const desired = normalizeComparableStaticWebsite(config);
|
|
5321
5556
|
const request = {
|
|
5322
5557
|
workspaceId,
|
|
@@ -5327,17 +5562,17 @@ async function planStaticWebsite(context) {
|
|
|
5327
5562
|
}
|
|
5328
5563
|
};
|
|
5329
5564
|
if (existing) {
|
|
5330
|
-
const
|
|
5331
|
-
if (!existing.label) unmanaged.push({
|
|
5565
|
+
const owned = isOwnedByApp(existing.allLabels, application.name, application.id);
|
|
5566
|
+
if (!owned) if (!existing.label) unmanaged.push({
|
|
5332
5567
|
resourceType: "StaticWebsite",
|
|
5333
5568
|
resourceName: name
|
|
5334
5569
|
});
|
|
5335
|
-
else
|
|
5570
|
+
else conflicts.push({
|
|
5336
5571
|
resourceType: "StaticWebsite",
|
|
5337
5572
|
resourceName: name,
|
|
5338
5573
|
currentOwner: existing.label
|
|
5339
5574
|
});
|
|
5340
|
-
if (
|
|
5575
|
+
if (owned && hasMatchingSdkVersion(existing.allLabels, metaRequest.labels) && areStaticWebsitesEqual(existing.resource, desired)) changeSet.unchanged.push({ name });
|
|
5341
5576
|
else changeSet.updates.push({
|
|
5342
5577
|
name,
|
|
5343
5578
|
request,
|
|
@@ -5351,9 +5586,11 @@ async function planStaticWebsite(context) {
|
|
|
5351
5586
|
});
|
|
5352
5587
|
}
|
|
5353
5588
|
Object.entries(existingWebsites).forEach(([name]) => {
|
|
5354
|
-
const
|
|
5355
|
-
|
|
5356
|
-
|
|
5589
|
+
const entry = existingWebsites[name];
|
|
5590
|
+
const label = entry?.label;
|
|
5591
|
+
const owned = isOwnedByApp(entry?.allLabels, application.name, application.id);
|
|
5592
|
+
if (label && !owned) resourceOwners.add(label);
|
|
5593
|
+
if (owned) changeSet.deletes.push({
|
|
5357
5594
|
name,
|
|
5358
5595
|
request: {
|
|
5359
5596
|
workspaceId,
|
|
@@ -7657,7 +7894,7 @@ async function planTailorDB(context) {
|
|
|
7657
7894
|
tailordbs.push(tailordb);
|
|
7658
7895
|
}
|
|
7659
7896
|
const executors = forRemoval ? [] : Object.values(await application.executorService?.loadExecutors() ?? {});
|
|
7660
|
-
const { changeSet: serviceChangeSet, conflicts, unmanaged, resourceOwners } = await planServices(client, workspaceId, application.name, tailordbs);
|
|
7897
|
+
const { changeSet: serviceChangeSet, conflicts, unmanaged, resourceOwners } = await planServices(client, workspaceId, application.name, application.id, tailordbs);
|
|
7661
7898
|
const deletedServices = serviceChangeSet.deletes.map((del) => del.name);
|
|
7662
7899
|
const [typeChangeSet, gqlPermissionChangeSet] = await Promise.all([planTypes(client, workspaceId, tailordbs, executors, deletedServices, void 0, forceApplyAll), planGqlPermissions(client, workspaceId, tailordbs, deletedServices, forceApplyAll)]);
|
|
7663
7900
|
return {
|
|
@@ -7731,7 +7968,7 @@ function areTailorDBServicesEqual(existing, desired) {
|
|
|
7731
7968
|
defaultTimezone: "UTC"
|
|
7732
7969
|
}));
|
|
7733
7970
|
}
|
|
7734
|
-
async function planServices(client, workspaceId, appName, tailordbs) {
|
|
7971
|
+
async function planServices(client, workspaceId, appName, appId, tailordbs) {
|
|
7735
7972
|
const changeSet = createChangeSet("TailorDB services");
|
|
7736
7973
|
const conflicts = [];
|
|
7737
7974
|
const unmanaged = [];
|
|
@@ -7761,18 +7998,24 @@ async function planServices(client, workspaceId, appName, tailordbs) {
|
|
|
7761
7998
|
}));
|
|
7762
7999
|
for (const tailordb of tailordbs) {
|
|
7763
8000
|
const existing = existingServices[tailordb.namespace];
|
|
7764
|
-
const metaRequest = await buildMetaRequest(
|
|
8001
|
+
const metaRequest = await buildMetaRequest({
|
|
8002
|
+
trn: trn(workspaceId, tailordb.namespace),
|
|
8003
|
+
appName,
|
|
8004
|
+
appId,
|
|
8005
|
+
existingLabels: existing?.allLabels
|
|
8006
|
+
});
|
|
7765
8007
|
if (existing) {
|
|
7766
|
-
|
|
8008
|
+
const owned = isOwnedByApp(existing.allLabels, appName, appId);
|
|
8009
|
+
if (!owned) if (!existing.label) unmanaged.push({
|
|
7767
8010
|
resourceType: "TailorDB service",
|
|
7768
8011
|
resourceName: tailordb.namespace
|
|
7769
8012
|
});
|
|
7770
|
-
else
|
|
8013
|
+
else conflicts.push({
|
|
7771
8014
|
resourceType: "TailorDB service",
|
|
7772
8015
|
resourceName: tailordb.namespace,
|
|
7773
8016
|
currentOwner: existing.label
|
|
7774
8017
|
});
|
|
7775
|
-
if (
|
|
8018
|
+
if (owned && hasMatchingSdkVersion(existing.allLabels, metaRequest.labels) && areTailorDBServicesEqual(existing.resource, tailordb)) changeSet.unchanged.push({ name: tailordb.namespace });
|
|
7776
8019
|
else changeSet.updates.push({
|
|
7777
8020
|
name: tailordb.namespace,
|
|
7778
8021
|
metaRequest
|
|
@@ -7789,9 +8032,11 @@ async function planServices(client, workspaceId, appName, tailordbs) {
|
|
|
7789
8032
|
});
|
|
7790
8033
|
}
|
|
7791
8034
|
Object.entries(existingServices).forEach(([namespaceName]) => {
|
|
7792
|
-
const
|
|
7793
|
-
|
|
7794
|
-
|
|
8035
|
+
const entry = existingServices[namespaceName];
|
|
8036
|
+
const label = entry?.label;
|
|
8037
|
+
const owned = isOwnedByApp(entry?.allLabels, appName, appId);
|
|
8038
|
+
if (label && !owned) resourceOwners.add(label);
|
|
8039
|
+
if (owned) changeSet.deletes.push({
|
|
7795
8040
|
name: namespaceName,
|
|
7796
8041
|
request: {
|
|
7797
8042
|
workspaceId,
|
|
@@ -8434,9 +8679,9 @@ function formatMigrationCheckResults(results) {
|
|
|
8434
8679
|
* @returns Promise that resolves when workflows are applied
|
|
8435
8680
|
*/
|
|
8436
8681
|
async function applyWorkflow(client, result, phase = "create-update") {
|
|
8437
|
-
const { changeSet, appName } = result;
|
|
8682
|
+
const { changeSet, appName, appId } = result;
|
|
8438
8683
|
if (phase === "create-update") {
|
|
8439
|
-
const jobFunctionVersions = await registerJobFunctions(client, changeSet, appName, result.unchangedWorkflowJobNames);
|
|
8684
|
+
const jobFunctionVersions = await registerJobFunctions(client, changeSet, appName, appId, result.unchangedWorkflowJobNames);
|
|
8440
8685
|
await Promise.all([...changeSet.creates.map(async (create) => {
|
|
8441
8686
|
const filteredVersions = filterJobFunctionVersions(jobFunctionVersions, create.usedJobNames);
|
|
8442
8687
|
await client.createWorkflow({
|
|
@@ -8484,10 +8729,11 @@ function filterJobFunctionVersions(allVersions, usedJobNames) {
|
|
|
8484
8729
|
* @param client - Operator client instance
|
|
8485
8730
|
* @param changeSet - Workflow change set
|
|
8486
8731
|
* @param appName - Application name
|
|
8732
|
+
* @param appId
|
|
8487
8733
|
* @param unchangedWorkflowJobNames - Job function names used by unchanged workflows
|
|
8488
8734
|
* @returns Map of job function names to versions
|
|
8489
8735
|
*/
|
|
8490
|
-
async function registerJobFunctions(client, changeSet, appName, unchangedWorkflowJobNames = /* @__PURE__ */ new Set()) {
|
|
8736
|
+
async function registerJobFunctions(client, changeSet, appName, appId, unchangedWorkflowJobNames = /* @__PURE__ */ new Set()) {
|
|
8491
8737
|
const jobFunctionVersions = {};
|
|
8492
8738
|
const firstWorkflow = changeSet.creates[0] || changeSet.updates[0] || changeSet.deletes[0];
|
|
8493
8739
|
if (!firstWorkflow) return jobFunctionVersions;
|
|
@@ -8515,7 +8761,11 @@ async function registerJobFunctions(client, changeSet, appName, unchangedWorkflo
|
|
|
8515
8761
|
jobFunctionName: jobName,
|
|
8516
8762
|
scriptRef: workflowJobFunctionName(jobName)
|
|
8517
8763
|
});
|
|
8518
|
-
await client.setMetadata(await buildMetaRequest(
|
|
8764
|
+
await client.setMetadata(await buildMetaRequest({
|
|
8765
|
+
trn: jobFunctionTrn(workspaceId, jobName),
|
|
8766
|
+
appName,
|
|
8767
|
+
appId
|
|
8768
|
+
}));
|
|
8519
8769
|
return {
|
|
8520
8770
|
jobName,
|
|
8521
8771
|
version: response.jobFunction?.version
|
|
@@ -8526,7 +8776,7 @@ async function registerJobFunctions(client, changeSet, appName, unchangedWorkflo
|
|
|
8526
8776
|
const unusedJobFunctions = existingJobFunctions.filter((jobName) => !allUsedJobNames.has(jobName));
|
|
8527
8777
|
await Promise.all(unusedJobFunctions.map(async (jobName) => {
|
|
8528
8778
|
const { metadata } = await client.getMetadata({ trn: jobFunctionTrn(workspaceId, jobName) });
|
|
8529
|
-
if (metadata?.labels
|
|
8779
|
+
if (isOwnedByApp(metadata?.labels, appName, appId)) await client.setMetadata({
|
|
8530
8780
|
trn: jobFunctionTrn(workspaceId, jobName),
|
|
8531
8781
|
labels: { [sdkNameLabelKey]: "" }
|
|
8532
8782
|
});
|
|
@@ -8564,12 +8814,13 @@ function jobFunctionTrn(workspaceId, name) {
|
|
|
8564
8814
|
* @param client - Operator client instance
|
|
8565
8815
|
* @param workspaceId - Workspace ID
|
|
8566
8816
|
* @param appName - Application name
|
|
8817
|
+
* @param appId
|
|
8567
8818
|
* @param workflows - Parsed workflows
|
|
8568
8819
|
* @param mainJobDeps - Main job dependencies by workflow
|
|
8569
8820
|
* @param unchangedJobFunctions - Job functions already proven unchanged by function registry plan
|
|
8570
8821
|
* @returns Planned workflow changes
|
|
8571
8822
|
*/
|
|
8572
|
-
async function planWorkflow(client, workspaceId, appName, workflows, mainJobDeps, unchangedJobFunctions = /* @__PURE__ */ new Set()) {
|
|
8823
|
+
async function planWorkflow(client, workspaceId, appName, appId, workflows, mainJobDeps, unchangedJobFunctions = /* @__PURE__ */ new Set()) {
|
|
8573
8824
|
const changeSet = createChangeSet("Workflows");
|
|
8574
8825
|
const conflicts = [];
|
|
8575
8826
|
const unmanaged = [];
|
|
@@ -8594,20 +8845,25 @@ async function planWorkflow(client, workspaceId, appName, workflows, mainJobDeps
|
|
|
8594
8845
|
}));
|
|
8595
8846
|
for (const workflow of Object.values(workflows)) {
|
|
8596
8847
|
const existing = existingWorkflows[workflow.name];
|
|
8597
|
-
const metaRequest = await buildMetaRequest(
|
|
8848
|
+
const metaRequest = await buildMetaRequest({
|
|
8849
|
+
trn: workflowTrn$1(workspaceId, workflow.name),
|
|
8850
|
+
appName,
|
|
8851
|
+
appId
|
|
8852
|
+
});
|
|
8598
8853
|
const usedJobNames = mainJobDeps[workflow.mainJob.name];
|
|
8599
8854
|
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}", ... })`);
|
|
8600
8855
|
if (existing) {
|
|
8601
|
-
|
|
8856
|
+
const owned = isOwnedByApp(existing.allLabels, appName, appId);
|
|
8857
|
+
if (!owned) if (!existing.label) unmanaged.push({
|
|
8602
8858
|
resourceType: "Workflow",
|
|
8603
8859
|
resourceName: workflow.name
|
|
8604
8860
|
});
|
|
8605
|
-
else
|
|
8861
|
+
else conflicts.push({
|
|
8606
8862
|
resourceType: "Workflow",
|
|
8607
8863
|
resourceName: workflow.name,
|
|
8608
8864
|
currentOwner: existing.label
|
|
8609
8865
|
});
|
|
8610
|
-
if (
|
|
8866
|
+
if (owned && hasMatchingSdkVersion(existing.allLabels, metaRequest.labels) && canTreatWorkflowAsUnchanged(existing.resource, workflow, usedJobNames, unchangedJobFunctions)) {
|
|
8611
8867
|
changeSet.unchanged.push({ name: workflow.name });
|
|
8612
8868
|
for (const jobName of usedJobNames) unchangedWorkflowJobNames.add(jobName);
|
|
8613
8869
|
} else changeSet.updates.push({
|
|
@@ -8629,8 +8885,9 @@ async function planWorkflow(client, workspaceId, appName, workflows, mainJobDeps
|
|
|
8629
8885
|
Object.values(existingWorkflows).forEach((existing) => {
|
|
8630
8886
|
if (!existing) return;
|
|
8631
8887
|
const label = existing.label;
|
|
8632
|
-
|
|
8633
|
-
if (label
|
|
8888
|
+
const owned = isOwnedByApp(existing.allLabels, appName, appId);
|
|
8889
|
+
if (label && !owned) resourceOwners.add(label);
|
|
8890
|
+
if (owned) changeSet.deletes.push({
|
|
8634
8891
|
name: existing.resource.name,
|
|
8635
8892
|
workspaceId,
|
|
8636
8893
|
workflowId: existing.resource.id,
|
|
@@ -8643,6 +8900,7 @@ async function planWorkflow(client, workspaceId, appName, workflows, mainJobDeps
|
|
|
8643
8900
|
unmanaged,
|
|
8644
8901
|
resourceOwners,
|
|
8645
8902
|
appName,
|
|
8903
|
+
appId,
|
|
8646
8904
|
unchangedWorkflowJobNames
|
|
8647
8905
|
};
|
|
8648
8906
|
}
|
|
@@ -8765,7 +9023,11 @@ function collectIdpUserTriggerTargets(application) {
|
|
|
8765
9023
|
return targets;
|
|
8766
9024
|
}
|
|
8767
9025
|
async function shouldForceApplyAll(client, workspaceId, application, functionEntries) {
|
|
8768
|
-
const desiredLabels = (await buildMetaRequest(
|
|
9026
|
+
const desiredLabels = (await buildMetaRequest({
|
|
9027
|
+
trn: applicationTrn(workspaceId, application.name),
|
|
9028
|
+
appName: application.name,
|
|
9029
|
+
appId: application.id
|
|
9030
|
+
})).labels;
|
|
8769
9031
|
const candidateTrns = /* @__PURE__ */ new Set();
|
|
8770
9032
|
if (application.subgraphs.length > 0) candidateTrns.add(applicationTrn(workspaceId, application.name));
|
|
8771
9033
|
application.staticWebsiteServices.forEach((website) => {
|
|
@@ -8902,9 +9164,16 @@ async function deploy(options) {
|
|
|
8902
9164
|
return withSpan("deploy", async (rootSpan) => {
|
|
8903
9165
|
rootSpan.setAttribute("deploy.dry_run", options?.dryRun ?? false);
|
|
8904
9166
|
const { config, application, workflowBuildResult, bundledScripts, buildOnly } = await withSpan("build", async () => {
|
|
8905
|
-
const { config, plugins } = await withSpan("build.loadConfig", () => loadConfig(options?.configPath));
|
|
8906
9167
|
const dryRun = options?.dryRun ?? false;
|
|
8907
9168
|
const buildOnly = options?.buildOnly ?? parseBoolean(process.env.TAILOR_PLATFORM_SDK_BUILD_ONLY) === true;
|
|
9169
|
+
const { config, plugins } = await withSpan("build.loadConfig", async () => {
|
|
9170
|
+
const foundPath = loadConfigPath(options?.configPath);
|
|
9171
|
+
if (foundPath && !dryRun && !buildOnly) {
|
|
9172
|
+
const resolvedPath = path.resolve(process.cwd(), foundPath);
|
|
9173
|
+
if (fs$1.existsSync(resolvedPath)) await ensureConfigId(resolvedPath);
|
|
9174
|
+
}
|
|
9175
|
+
return loadConfig(options?.configPath);
|
|
9176
|
+
});
|
|
8908
9177
|
const noCache = options?.noCache ?? false;
|
|
8909
9178
|
const packageJson = await readPackageJson();
|
|
8910
9179
|
const cacheDir = path.resolve(getDistDir(), "cache");
|
|
@@ -8982,7 +9251,7 @@ async function deploy(options) {
|
|
|
8982
9251
|
forceApplyAll,
|
|
8983
9252
|
idpUserTriggerTargets
|
|
8984
9253
|
};
|
|
8985
|
-
const functionRegistry = await withSpan("plan.functionRegistry", () => planFunctionRegistry(client, workspaceId, application.name, functionEntries));
|
|
9254
|
+
const functionRegistry = await withSpan("plan.functionRegistry", () => planFunctionRegistry(client, workspaceId, application.name, application.id, functionEntries));
|
|
8986
9255
|
const unchangedWorkflowJobs = new Set(functionRegistry.changeSet.unchanged.filter((entry) => entry.name.startsWith(WORKFLOW_PREFIX)).map((entry) => entry.name.slice(WORKFLOW_PREFIX.length)));
|
|
8987
9256
|
const [tailorDB, staticWebsite, idp, auth, pipeline, app, executor, workflow, secretManager] = await Promise.all([
|
|
8988
9257
|
withSpan("plan.tailorDB", () => planTailorDB(ctx)),
|
|
@@ -8992,7 +9261,7 @@ async function deploy(options) {
|
|
|
8992
9261
|
withSpan("plan.pipeline", () => planPipeline(ctx)),
|
|
8993
9262
|
withSpan("plan.application", () => planApplication(ctx)),
|
|
8994
9263
|
withSpan("plan.executor", () => planExecutor(ctx)),
|
|
8995
|
-
withSpan("plan.workflow", () => planWorkflow(client, workspaceId, application.name, workflowService?.workflows ?? {}, workflowBuildResult?.mainJobDeps ?? {}, unchangedWorkflowJobs)),
|
|
9264
|
+
withSpan("plan.workflow", () => planWorkflow(client, workspaceId, application.name, application.id, workflowService?.workflows ?? {}, workflowBuildResult?.mainJobDeps ?? {}, unchangedWorkflowJobs)),
|
|
8996
9265
|
withSpan("plan.secretManager", () => planSecretManager(ctx))
|
|
8997
9266
|
]);
|
|
8998
9267
|
return {
|
|
@@ -11820,7 +12089,9 @@ function createGenerationManager(params) {
|
|
|
11820
12089
|
*/
|
|
11821
12090
|
async function generate$1(options) {
|
|
11822
12091
|
return withSpan("generate", async (rootSpan) => {
|
|
11823
|
-
const { config, generators, plugins } = await withSpan("generate.loadConfig", async () =>
|
|
12092
|
+
const { config, generators, plugins } = await withSpan("generate.loadConfig", async () => {
|
|
12093
|
+
return loadConfig(options?.configPath);
|
|
12094
|
+
});
|
|
11824
12095
|
const watch = options?.watch ?? false;
|
|
11825
12096
|
rootSpan.setAttribute("generate.watch", watch);
|
|
11826
12097
|
rootSpan.setAttribute("generate.generators.count", generators.length);
|
|
@@ -12648,8 +12919,8 @@ async function execRemove(client, workspaceId, application, config, confirm) {
|
|
|
12648
12919
|
const pipeline = await planPipeline(ctx);
|
|
12649
12920
|
const app = await planApplication(ctx);
|
|
12650
12921
|
const executor = await planExecutor(ctx);
|
|
12651
|
-
const workflow = await planWorkflow(client, workspaceId, application.name, {}, {});
|
|
12652
|
-
const functionRegistry = await planFunctionRegistry(client, workspaceId, application.name, []);
|
|
12922
|
+
const workflow = await planWorkflow(client, workspaceId, application.name, application.id, {}, {});
|
|
12923
|
+
const functionRegistry = await planFunctionRegistry(client, workspaceId, application.name, application.id, []);
|
|
12653
12924
|
const secretManager = await planSecretManager(ctx);
|
|
12654
12925
|
functionRegistry.changeSet.print();
|
|
12655
12926
|
staticWebsite.changeSet.print();
|
|
@@ -13372,7 +13643,7 @@ async function generate(options) {
|
|
|
13372
13643
|
if (options.init) await handleInitOption(namespacesWithMigrations, options.yes);
|
|
13373
13644
|
let pluginManager;
|
|
13374
13645
|
if (plugins.length > 0) pluginManager = new PluginManager(plugins);
|
|
13375
|
-
const { defineApplication } = await import("./application-
|
|
13646
|
+
const { defineApplication } = await import("./application-BNkNt47b.mjs");
|
|
13376
13647
|
const application = defineApplication({
|
|
13377
13648
|
config,
|
|
13378
13649
|
pluginManager
|
|
@@ -15187,7 +15458,7 @@ async function runRepl(options) {
|
|
|
15187
15458
|
const execute = await prepareQueryExecutor(options);
|
|
15188
15459
|
const historyPath = getReplHistoryPath(options.engine, options.profile, options.workspaceId);
|
|
15189
15460
|
const validate = createReplValidator(options.engine);
|
|
15190
|
-
const { highlightSqlLine, highlightGraphqlLine, replTransform } = await import("./repl-editor-
|
|
15461
|
+
const { highlightSqlLine, highlightGraphqlLine, replTransform } = await import("./repl-editor-jZ493eQI.mjs");
|
|
15191
15462
|
const highlight = options.engine === "sql" ? highlightSqlLine : highlightGraphqlLine;
|
|
15192
15463
|
const prompt = createPrompt({
|
|
15193
15464
|
prefix: "",
|
|
@@ -15521,4 +15792,4 @@ function isDeno() {
|
|
|
15521
15792
|
|
|
15522
15793
|
//#endregion
|
|
15523
15794
|
export { deleteCommand$1 as $, getMigrationDirPath as $t, truncate as A, executionsCommand as At, updateOrganization as B, MIGRATION_LABEL_KEY as Bt, listCommand$2 as C, toPageDirection as Cn, jobsCommand as Ct, resumeWorkflow as D, startWorkflow as Dt, resumeCommand as E, startCommand as Et, showCommand as F, getCommand$6 as Ft, getCommand$1 as G, INITIAL_SCHEMA_NUMBER as Gt, treeCommand as H, bundleMigrationScript as Ht, logBetaWarning as I, getExecutor as It, updateFolder as J, compareLocalTypesWithSnapshot as Jt, getOrganization as K, MIGRATE_FILE_NAME as Kt, remove as L, deploy as Lt, generate as M, listWorkflowExecutions as Mt, generateCommand as N, functionExecutionStatusToString as Nt, listCommand$3 as O, getCommand$5 as Ot, show as P, formatKeyValueTable as Pt, getFolder as Q, getLatestMigrationNumber as Qt, removeCommand$1 as R, executeScript as Rt, listApps as S, paginationArgs as Sn, getExecutorJob as St, healthCommand as T, watchExecutorJob as Tt, listCommand$4 as U, DB_TYPES_FILE_NAME as Ut, organizationTree as V, parseMigrationLabelNumber as Vt, listOrganizations as W, DIFF_FILE_NAME as Wt, listFolders as X, createSnapshotFromLocalTypes as Xt, listCommand$5 as Y, compareSnapshots as Yt, getCommand$2 as Z, formatMigrationNumber as Zt, getWorkspace as _, commonArgs as _n, webhookCommand as _t, updateUser as a, reconstructSnapshotFromMigrations as an, getCommand$3 as at, createCommand as b, isVerbose as bn, listCommand$9 as bt, listCommand as c, hasChanges as cn, tokenCommand as ct, inviteUser as d, trnPrefix as dn, generate$1 as dt, getMigrationFilePath as en, deleteFolder as et, restoreCommand as f, generateUserTypes as fn, listCommand$8 as ft, getCommand as g, defineAppCommand as gn, listWebhookExecutors as gt, listWorkspaces as h, apiCall as hn, getFunctionRegistry as ht, updateCommand as i, loadDiff as in, listOAuth2Clients as it, truncateCommand as j, getWorkflowExecution as jt, listWorkflows as k, getWorkflow as kt, listUsers as l, getNamespacesWithMigrations as ln, listCommand$7 as lt, listCommand$1 as m, apiCommand as mn, getCommand$4 as mt, query as n, getNextMigrationNumber as nn, createFolder as nt, removeCommand as o, formatDiffSummary as on, getOAuth2Client as ot, restoreWorkspace as p, prompt as pn, listFunctionRegistries as pt, updateCommand$2 as q, SCHEMA_FILE_NAME as qt, queryCommand as r, isValidMigrationNumber as rn, listCommand$6 as rt, removeUser as s, formatMigrationDiff as sn, getMachineUserToken as st, isNativeTypeScriptRuntime as t, getMigrationFiles as tn, createCommand$1 as tt, inviteCommand as u, sdkNameLabelKey as un, listMachineUsers as ut, deleteCommand as v, confirmationArgs as vn, triggerCommand as vt, getAppHealth as w, workspaceArgs as wn, listExecutorJobs as wt, createWorkspace as x, pagedLogArgs as xn, listExecutors as xt, deleteWorkspace as y, deploymentArgs as yn, triggerExecutor as yt, updateCommand$1 as z, waitForExecution$1 as zt };
|
|
15524
|
-
//# sourceMappingURL=runtime-
|
|
15795
|
+
//# sourceMappingURL=runtime-CNg0w27y.mjs.map
|