@tailor-platform/sdk 0.8.6 → 0.10.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.
@@ -21,6 +21,7 @@ import * as os from "node:os";
21
21
  import { parseTOML, parseYAML, stringifyYAML } from "confbox";
22
22
  import { xdgConfig } from "xdg-basedir";
23
23
  import { fromJson } from "@bufbuild/protobuf";
24
+ import chalk from "chalk";
24
25
  import { spawn } from "node:child_process";
25
26
  import { glob } from "node:fs/promises";
26
27
  import chokidar from "chokidar";
@@ -155,7 +156,7 @@ const FunctionOperationSchema = z.object({
155
156
  });
156
157
  const GqlOperationSchema = z.object({
157
158
  kind: z.literal("graphql"),
158
- appName: z.string(),
159
+ appName: z.string().optional(),
159
160
  query: z.string(),
160
161
  variables: functionSchema.optional(),
161
162
  invoker: InvokerSchema.optional()
@@ -190,6 +191,7 @@ var ExecutorService = class {
190
191
  this.config = config;
191
192
  }
192
193
  async loadExecutors() {
194
+ if (Object.keys(this.executors).length > 0) return this.executors;
193
195
  if (!this.config.files || this.config.files.length === 0) return;
194
196
  const executorFiles = loadFilesWithIgnores(this.config);
195
197
  console.log("");
@@ -275,6 +277,7 @@ var ResolverService = class {
275
277
  this.config = config;
276
278
  }
277
279
  async loadResolvers() {
280
+ if (Object.keys(this.resolvers).length > 0) return;
278
281
  if (!this.config.files || this.config.files.length === 0) return;
279
282
  const resolverFiles = loadFilesWithIgnores(this.config);
280
283
  console.log("");
@@ -464,9 +467,11 @@ var Application = class {
464
467
  _subgraphs = [];
465
468
  _executorService = void 0;
466
469
  _staticWebsiteServices = [];
470
+ _env = {};
467
471
  constructor(name, config) {
468
472
  this.name = name;
469
473
  this.config = config;
474
+ this._env = config.env || {};
470
475
  }
471
476
  addSubgraph(type, name) {
472
477
  this._subgraphs.push({
@@ -495,6 +500,9 @@ var Application = class {
495
500
  get staticWebsiteServices() {
496
501
  return this._staticWebsiteServices;
497
502
  }
503
+ get env() {
504
+ return this._env;
505
+ }
498
506
  get applications() {
499
507
  return [this];
500
508
  }
@@ -1576,13 +1584,20 @@ async function loadConfig(configPath) {
1576
1584
  function extractAttributesFromConfig(config) {
1577
1585
  return collectAttributesFromConfig(config);
1578
1586
  }
1579
- function generateTypeDefinition(attributeMap, attributeList) {
1587
+ function generateTypeDefinition(attributeMap, attributeList, env) {
1580
1588
  const mapFields = attributeMap ? Object.entries(attributeMap).map(([key, value]) => ` ${key}: ${value};`).join("\n") : "";
1581
1589
  const mapBody = !attributeMap || Object.keys(attributeMap).length === 0 ? "{}" : `{
1582
1590
  ${mapFields}
1583
1591
  }`;
1584
1592
  const listBody = `{
1585
1593
  __tuple?: ${attributeList ? `[${attributeList.map(() => "string").join(", ")}]` : "[]"};
1594
+ }`;
1595
+ const envFields = env ? Object.entries(env).map(([key, value]) => {
1596
+ const valueType = typeof value === "string" ? `"${value}"` : String(value);
1597
+ return ` ${key}: ${valueType};`;
1598
+ }).join("\n") : "";
1599
+ const envBody = !env || Object.keys(env).length === 0 ? "{}" : `{
1600
+ ${envFields}
1586
1601
  }`;
1587
1602
  return ml`
1588
1603
  // This file is auto-generated by @tailor-platform/sdk
@@ -1593,6 +1608,7 @@ declare global {
1593
1608
  namespace TailorSDK {
1594
1609
  interface AttributeMap ${mapBody}
1595
1610
  interface AttributeList ${listBody}
1611
+ interface Env ${envBody}
1596
1612
  }
1597
1613
  }
1598
1614
 
@@ -1637,13 +1653,12 @@ function resolveTypeDefinitionPath(configPath) {
1637
1653
  async function generateUserTypes(config, configPath) {
1638
1654
  try {
1639
1655
  const { attributeMap, attributeList } = extractAttributesFromConfig(config);
1640
- if (!attributeMap && !attributeList) {
1641
- console.log(styleText("cyan", "No attributes found in configuration"));
1642
- return;
1643
- }
1656
+ if (!attributeMap && !attributeList) console.log(styleText("cyan", "No attributes found in configuration"));
1644
1657
  if (attributeMap) console.log("Extracted AttributeMap:", attributeMap);
1645
1658
  if (attributeList) console.log("Extracted AttributeList:", attributeList);
1646
- const typeDefContent = generateTypeDefinition(attributeMap, attributeList);
1659
+ const env = config.env;
1660
+ if (env) console.log("Extracted Env:", env);
1661
+ const typeDefContent = generateTypeDefinition(attributeMap, attributeList, env);
1647
1662
  const outputPath = resolveTypeDefinitionPath(configPath);
1648
1663
  fs.mkdirSync(path.dirname(outputPath), { recursive: true });
1649
1664
  fs.writeFileSync(outputPath, typeDefContent);
@@ -2254,6 +2269,15 @@ const file_tailor_v1_service = /* @__PURE__ */ fileDesc("Chd0YWlsb3IvdjEvc2Vydml
2254
2269
  */
2255
2270
  const OperatorService = /* @__PURE__ */ serviceDesc(file_tailor_v1_service, 0);
2256
2271
 
2272
+ //#endregion
2273
+ //#region src/cli/package-json.ts
2274
+ let packageJson = null;
2275
+ async function readPackageJson() {
2276
+ if (packageJson) return packageJson;
2277
+ packageJson = await readPackageJSON(import.meta.url);
2278
+ return packageJson;
2279
+ }
2280
+
2257
2281
  //#endregion
2258
2282
  //#region src/cli/client.ts
2259
2283
  const baseUrl = process.env.PLATFORM_URL ?? "https://api.tailor.tech";
@@ -2278,7 +2302,7 @@ async function userAgentInterceptor() {
2278
2302
  };
2279
2303
  }
2280
2304
  async function userAgent() {
2281
- return `tailor-sdk/${(await readPackageJSON(import.meta.url)).version ?? "unknown"}`;
2305
+ return `tailor-sdk/${(await readPackageJson()).version ?? "unknown"}`;
2282
2306
  }
2283
2307
  async function bearerTokenInterceptor(accessToken) {
2284
2308
  return (next) => async (req) => {
@@ -2540,6 +2564,24 @@ function loadConfigPath(configPath) {
2540
2564
  return "tailor.config.ts";
2541
2565
  }
2542
2566
 
2567
+ //#endregion
2568
+ //#region src/cli/apply/services/label.ts
2569
+ function trnPrefix(workspaceId) {
2570
+ return `trn:v1:workspace:${workspaceId}`;
2571
+ }
2572
+ const sdkNameLabelKey = "sdk-name";
2573
+ async function buildMetaRequest(trn$7, appName) {
2574
+ const packageJson$1 = await readPackageJson();
2575
+ const sdkVersion = packageJson$1.version ? `v${packageJson$1.version.replace(/\./g, "-")}` : "unknown";
2576
+ return {
2577
+ trn: trn$7,
2578
+ labels: {
2579
+ [sdkNameLabelKey]: appName,
2580
+ "sdk-version": sdkVersion
2581
+ }
2582
+ };
2583
+ }
2584
+
2543
2585
  //#endregion
2544
2586
  //#region src/cli/apply/services/index.ts
2545
2587
  var ChangeSet = class {
@@ -2569,14 +2611,21 @@ var ChangeSet = class {
2569
2611
  async function applyApplication(client, changeSet, phase = "create-update") {
2570
2612
  if (phase === "create-update") await Promise.all([...changeSet.creates.map(async (create) => {
2571
2613
  create.request.cors = await resolveStaticWebsiteUrls(client, create.request.workspaceId, create.request.cors, "CORS");
2572
- return client.createApplication(create.request);
2614
+ await client.createApplication(create.request);
2615
+ await client.setMetadata(create.metaRequest);
2573
2616
  }), ...changeSet.updates.map(async (update) => {
2574
2617
  update.request.cors = await resolveStaticWebsiteUrls(client, update.request.workspaceId, update.request.cors, "CORS");
2575
- return client.updateApplication(update.request);
2618
+ await client.updateApplication(update.request);
2619
+ await client.setMetadata(update.metaRequest);
2576
2620
  })]);
2577
- else if (phase === "delete") await Promise.all(changeSet.deletes.map((del) => client.deleteApplication(del.request)));
2621
+ else if (phase === "delete") await Promise.all(changeSet.deletes.map(async (del) => {
2622
+ await client.deleteApplication(del.request);
2623
+ }));
2578
2624
  }
2579
- async function planApplication(client, workspaceId, application) {
2625
+ function trn$6(workspaceId, name) {
2626
+ return `trn:v1:workspace:${workspaceId}:application:${name}`;
2627
+ }
2628
+ async function planApplication({ client, workspaceId, application }) {
2580
2629
  const changeSet = new ChangeSet("Applications");
2581
2630
  const existingApplications = await fetchAll(async (pageToken) => {
2582
2631
  try {
@@ -2590,55 +2639,41 @@ async function planApplication(client, workspaceId, application) {
2590
2639
  throw error;
2591
2640
  }
2592
2641
  });
2593
- const existingNameSet = /* @__PURE__ */ new Set();
2594
- existingApplications.forEach((application$1) => {
2595
- existingNameSet.add(application$1.name);
2642
+ let authNamespace;
2643
+ let authIdpConfigName;
2644
+ if (application.authService && application.authService.config) {
2645
+ authNamespace = application.authService.config.name;
2646
+ const idProvider = application.authService.config.idProvider;
2647
+ if (idProvider) authIdpConfigName = idProvider.name;
2648
+ }
2649
+ const metaRequest = await buildMetaRequest(trn$6(workspaceId, application.name), application.name);
2650
+ if (existingApplications.some((app) => app.name === application.name)) changeSet.updates.push({
2651
+ name: application.name,
2652
+ request: {
2653
+ workspaceId,
2654
+ applicationName: application.name,
2655
+ authNamespace,
2656
+ authIdpConfigName,
2657
+ cors: application.config.cors,
2658
+ subgraphs: application.subgraphs.map((subgraph) => protoSubgraph(subgraph)),
2659
+ allowedIpAddresses: application.config.allowedIPAddresses,
2660
+ disableIntrospection: application.config.disableIntrospection
2661
+ },
2662
+ metaRequest
2596
2663
  });
2597
- for (const app of application.applications) {
2598
- let authNamespace;
2599
- let authIdpConfigName;
2600
- if (app.authService && app.authService.config) {
2601
- authNamespace = app.authService.config.name;
2602
- const idProvider = app.authService.config.idProvider;
2603
- if (idProvider) authIdpConfigName = idProvider.name;
2604
- }
2605
- if (existingNameSet.has(app.name)) {
2606
- changeSet.updates.push({
2607
- name: app.name,
2608
- request: {
2609
- workspaceId,
2610
- applicationName: app.name,
2611
- authNamespace,
2612
- authIdpConfigName,
2613
- cors: app.config.cors,
2614
- subgraphs: app.subgraphs.map((subgraph) => protoSubgraph(subgraph)),
2615
- allowedIpAddresses: app.config.allowedIPAddresses,
2616
- disableIntrospection: app.config.disableIntrospection
2617
- }
2618
- });
2619
- existingNameSet.delete(app.name);
2620
- } else changeSet.creates.push({
2621
- name: app.name,
2622
- request: {
2623
- workspaceId,
2624
- applicationName: app.name,
2625
- authNamespace,
2626
- authIdpConfigName,
2627
- cors: app.config.cors,
2628
- subgraphs: app.subgraphs.map((subgraph) => protoSubgraph(subgraph)),
2629
- allowedIpAddresses: app.config.allowedIPAddresses,
2630
- disableIntrospection: app.config.disableIntrospection
2631
- }
2632
- });
2633
- }
2634
- existingNameSet.forEach((name) => {
2635
- changeSet.deletes.push({
2636
- name,
2637
- request: {
2638
- workspaceId,
2639
- applicationName: name
2640
- }
2641
- });
2664
+ else changeSet.creates.push({
2665
+ name: application.name,
2666
+ request: {
2667
+ workspaceId,
2668
+ applicationName: application.name,
2669
+ authNamespace,
2670
+ authIdpConfigName,
2671
+ cors: application.config.cors,
2672
+ subgraphs: application.subgraphs.map((subgraph) => protoSubgraph(subgraph)),
2673
+ allowedIpAddresses: application.config.allowedIPAddresses,
2674
+ disableIntrospection: application.config.disableIntrospection
2675
+ },
2676
+ metaRequest
2642
2677
  });
2643
2678
  changeSet.print();
2644
2679
  return changeSet;
@@ -2674,9 +2709,16 @@ function idpClientVaultName(namespaceName, clientName) {
2674
2709
  function idpClientSecretName(namespaceName, clientName) {
2675
2710
  return `client-secret-${namespaceName}-${clientName}`;
2676
2711
  }
2677
- async function applyIdP(client, changeSet, phase = "create-update") {
2712
+ async function applyIdP(client, result, phase = "create-update") {
2713
+ const { changeSet } = result;
2678
2714
  if (phase === "create-update") {
2679
- await Promise.all([...changeSet.service.creates.map((create) => client.createIdPService(create.request)), ...changeSet.service.updates.map((update) => client.updateIdPService(update.request))]);
2715
+ await Promise.all([...changeSet.service.creates.map(async (create) => {
2716
+ await client.createIdPService(create.request);
2717
+ await client.setMetadata(create.metaRequest);
2718
+ }), ...changeSet.service.updates.map(async (update) => {
2719
+ await client.updateIdPService(update.request);
2720
+ await client.setMetadata(update.metaRequest);
2721
+ })]);
2680
2722
  await Promise.all([...changeSet.client.creates.map(async (create) => {
2681
2723
  const resp = await client.createIdPClient(create.request);
2682
2724
  const vaultName = idpClientVaultName(create.request.namespaceName, create.request.client?.name || "");
@@ -2715,7 +2757,7 @@ async function applyIdP(client, changeSet, phase = "create-update") {
2715
2757
  });
2716
2758
  })]);
2717
2759
  } else if (phase === "delete") {
2718
- await Promise.all(changeSet.client.deletes.filter((del) => del.tag === "client-deleted").map(async (del) => {
2760
+ await Promise.all(changeSet.client.deletes.map(async (del) => {
2719
2761
  await client.deleteIdPClient(del.request);
2720
2762
  const vaultName = `idp-${del.request.namespaceName}-${del.request.name}`;
2721
2763
  await client.deleteSecretManagerVault({
@@ -2726,22 +2768,32 @@ async function applyIdP(client, changeSet, phase = "create-update") {
2726
2768
  await Promise.all(changeSet.service.deletes.map((del) => client.deleteIdPService(del.request)));
2727
2769
  }
2728
2770
  }
2729
- async function planIdP(client, workspaceId, application) {
2730
- const idps = [];
2731
- for (const app of application.applications) idps.push(...app.idpServices);
2732
- const serviceChangeSet = await planServices$3(client, workspaceId, idps);
2771
+ async function planIdP({ client, workspaceId, application }) {
2772
+ const idps = application.idpServices;
2773
+ const { changeSet: serviceChangeSet, conflicts, unmanaged, resourceOwners } = await planServices$3(client, workspaceId, application.name, idps);
2733
2774
  const deletedServices = serviceChangeSet.deletes.map((del) => del.name);
2734
2775
  const clientChangeSet = await planClients(client, workspaceId, idps, deletedServices);
2735
2776
  serviceChangeSet.print();
2736
2777
  clientChangeSet.print();
2737
2778
  return {
2738
- service: serviceChangeSet,
2739
- client: clientChangeSet
2779
+ changeSet: {
2780
+ service: serviceChangeSet,
2781
+ client: clientChangeSet
2782
+ },
2783
+ conflicts,
2784
+ unmanaged,
2785
+ resourceOwners
2740
2786
  };
2741
2787
  }
2742
- async function planServices$3(client, workspaceId, idps) {
2788
+ function trn$5(workspaceId, name) {
2789
+ return `trn:v1:workspace:${workspaceId}:idp:${name}`;
2790
+ }
2791
+ async function planServices$3(client, workspaceId, appName, idps) {
2743
2792
  const changeSet = new ChangeSet("IdP services");
2744
- const existingServices = await fetchAll(async (pageToken) => {
2793
+ const conflicts = [];
2794
+ const unmanaged = [];
2795
+ const resourceOwners = /* @__PURE__ */ new Set();
2796
+ const withoutLabel = await fetchAll(async (pageToken) => {
2745
2797
  try {
2746
2798
  const { idpServices, nextPageToken } = await client.listIdPServices({
2747
2799
  workspaceId,
@@ -2753,13 +2805,19 @@ async function planServices$3(client, workspaceId, idps) {
2753
2805
  throw error;
2754
2806
  }
2755
2807
  });
2756
- const existingNameSet = /* @__PURE__ */ new Set();
2757
- existingServices.forEach((service) => {
2758
- const name = service.namespace?.name;
2759
- if (name) existingNameSet.add(name);
2760
- });
2808
+ const existingServices = {};
2809
+ await Promise.all(withoutLabel.map(async (resource) => {
2810
+ if (!resource.namespace?.name) return;
2811
+ const { metadata } = await client.getMetadata({ trn: trn$5(workspaceId, resource.namespace.name) });
2812
+ existingServices[resource.namespace.name] = {
2813
+ resource,
2814
+ label: metadata?.labels[sdkNameLabelKey]
2815
+ };
2816
+ }));
2761
2817
  for (const idp of idps) {
2762
2818
  const namespaceName = idp.name;
2819
+ const existing = existingServices[namespaceName];
2820
+ const metaRequest = await buildMetaRequest(trn$5(workspaceId, namespaceName), appName);
2763
2821
  let authorization;
2764
2822
  switch (idp.authorization) {
2765
2823
  case "insecure":
@@ -2772,27 +2830,40 @@ async function planServices$3(client, workspaceId, idps) {
2772
2830
  authorization = idp.authorization.cel;
2773
2831
  break;
2774
2832
  }
2775
- if (existingNameSet.has(namespaceName)) {
2833
+ if (existing) {
2834
+ if (!existing.label) unmanaged.push({
2835
+ resourceType: "IdP service",
2836
+ resourceName: idp.name
2837
+ });
2838
+ else if (existing.label !== appName) conflicts.push({
2839
+ resourceType: "IdP service",
2840
+ resourceName: idp.name,
2841
+ currentOwner: existing.label
2842
+ });
2776
2843
  changeSet.updates.push({
2777
2844
  name: namespaceName,
2778
2845
  request: {
2779
2846
  workspaceId,
2780
2847
  namespaceName,
2781
2848
  authorization
2782
- }
2849
+ },
2850
+ metaRequest
2783
2851
  });
2784
- existingNameSet.delete(namespaceName);
2852
+ delete existingServices[namespaceName];
2785
2853
  } else changeSet.creates.push({
2786
2854
  name: namespaceName,
2787
2855
  request: {
2788
2856
  workspaceId,
2789
2857
  namespaceName,
2790
2858
  authorization
2791
- }
2859
+ },
2860
+ metaRequest
2792
2861
  });
2793
2862
  }
2794
- existingNameSet.forEach((namespaceName) => {
2795
- changeSet.deletes.push({
2863
+ Object.entries(existingServices).forEach(([namespaceName]) => {
2864
+ const label = existingServices[namespaceName]?.label;
2865
+ if (label && label !== appName) resourceOwners.add(label);
2866
+ if (label === appName) changeSet.deletes.push({
2796
2867
  name: namespaceName,
2797
2868
  request: {
2798
2869
  workspaceId,
@@ -2800,7 +2871,12 @@ async function planServices$3(client, workspaceId, idps) {
2800
2871
  }
2801
2872
  });
2802
2873
  });
2803
- return changeSet;
2874
+ return {
2875
+ changeSet,
2876
+ conflicts,
2877
+ unmanaged,
2878
+ resourceOwners
2879
+ };
2804
2880
  }
2805
2881
  async function planClients(client, workspaceId, idps, deletedServices) {
2806
2882
  const changeSet = new ChangeSet("IdP clients");
@@ -2844,7 +2920,6 @@ async function planClients(client, workspaceId, idps, deletedServices) {
2844
2920
  });
2845
2921
  existingNameMap.forEach((name) => {
2846
2922
  changeSet.deletes.push({
2847
- tag: "client-deleted",
2848
2923
  name,
2849
2924
  request: {
2850
2925
  workspaceId,
@@ -2856,8 +2931,12 @@ async function planClients(client, workspaceId, idps, deletedServices) {
2856
2931
  }
2857
2932
  for (const namespaceName of deletedServices) (await fetchClients(namespaceName)).forEach((client$1) => {
2858
2933
  changeSet.deletes.push({
2859
- tag: "service-deleted",
2860
- name: client$1.name
2934
+ name: client$1.name,
2935
+ request: {
2936
+ workspaceId,
2937
+ namespaceName,
2938
+ name: client$1.name
2939
+ }
2861
2940
  });
2862
2941
  });
2863
2942
  return changeSet;
@@ -2865,9 +2944,13 @@ async function planClients(client, workspaceId, idps, deletedServices) {
2865
2944
 
2866
2945
  //#endregion
2867
2946
  //#region src/cli/apply/services/auth.ts
2868
- async function applyAuth(client, changeSet, phase = "create-update") {
2947
+ async function applyAuth(client, result, phase = "create-update") {
2948
+ const { changeSet } = result;
2869
2949
  if (phase === "create-update") {
2870
- await Promise.all(changeSet.service.creates.map((create) => client.createAuthService(create.request)));
2950
+ await Promise.all([...changeSet.service.creates.map(async (create) => {
2951
+ await client.createAuthService(create.request);
2952
+ await client.setMetadata(create.metaRequest);
2953
+ }), ...changeSet.service.updates.map((update) => client.setMetadata(update.metaRequest))]);
2871
2954
  await Promise.all([...changeSet.idpConfig.creates.map(async (create) => {
2872
2955
  if (create.idpConfig.kind === "BuiltInIdP") create.request.idpConfig.config = await protoBuiltinIdPConfig(client, create.request.workspaceId, create.idpConfig);
2873
2956
  return client.createAuthIDPConfig(create.request);
@@ -2888,23 +2971,23 @@ async function applyAuth(client, changeSet, phase = "create-update") {
2888
2971
  await Promise.all([...changeSet.scim.creates.map((create) => client.createAuthSCIMConfig(create.request)), ...changeSet.scim.updates.map((update) => client.updateAuthSCIMConfig(update.request))]);
2889
2972
  await Promise.all([...changeSet.scimResource.creates.map((create) => client.createAuthSCIMResource(create.request)), ...changeSet.scimResource.updates.map((update) => client.updateAuthSCIMResource(update.request))]);
2890
2973
  } else if (phase === "delete") {
2891
- await Promise.all(changeSet.scimResource.deletes.filter((del) => del.tag === "scim-resource-deleted").map((del) => client.deleteAuthSCIMResource(del.request)));
2892
- await Promise.all(changeSet.scim.deletes.filter((del) => del.tag === "scim-config-deleted").map((del) => client.deleteAuthSCIMConfig(del.request)));
2893
- await Promise.all(changeSet.oauth2Client.deletes.filter((del) => del.tag === "oauth2-client-deleted").map((del) => client.deleteAuthOAuth2Client(del.request)));
2894
- await Promise.all(changeSet.machineUser.deletes.filter((del) => del.tag === "machine-user-deleted").map((del) => client.deleteAuthMachineUser(del.request)));
2895
- await Promise.all(changeSet.tenantConfig.deletes.filter((del) => del.tag === "tenant-config-deleted").map((del) => client.deleteTenantConfig(del.request)));
2896
- await Promise.all(changeSet.userProfileConfig.deletes.filter((del) => del.tag === "user-profile-config-deleted").map((del) => client.deleteUserProfileConfig(del.request)));
2897
- await Promise.all(changeSet.idpConfig.deletes.filter((del) => del.tag === "idp-config-deleted").map((del) => client.deleteAuthIDPConfig(del.request)));
2974
+ await Promise.all(changeSet.scimResource.deletes.map((del) => client.deleteAuthSCIMResource(del.request)));
2975
+ await Promise.all(changeSet.scim.deletes.map((del) => client.deleteAuthSCIMConfig(del.request)));
2976
+ await Promise.all(changeSet.oauth2Client.deletes.map((del) => client.deleteAuthOAuth2Client(del.request)));
2977
+ await Promise.all(changeSet.machineUser.deletes.map((del) => client.deleteAuthMachineUser(del.request)));
2978
+ await Promise.all(changeSet.tenantConfig.deletes.map((del) => client.deleteTenantConfig(del.request)));
2979
+ await Promise.all(changeSet.userProfileConfig.deletes.map((del) => client.deleteUserProfileConfig(del.request)));
2980
+ await Promise.all(changeSet.idpConfig.deletes.map((del) => client.deleteAuthIDPConfig(del.request)));
2898
2981
  await Promise.all(changeSet.service.deletes.map((del) => client.deleteAuthService(del.request)));
2899
2982
  }
2900
2983
  }
2901
- async function planAuth(client, workspaceId, application) {
2984
+ async function planAuth({ client, workspaceId, application }) {
2902
2985
  const auths = [];
2903
- for (const app of application.applications) if (app.authService) {
2904
- await app.authService.resolveNamespaces();
2905
- auths.push(app.authService);
2986
+ if (application.authService) {
2987
+ await application.authService.resolveNamespaces();
2988
+ auths.push(application.authService);
2906
2989
  }
2907
- const serviceChangeSet = await planServices$2(client, workspaceId, auths);
2990
+ const { changeSet: serviceChangeSet, conflicts, unmanaged, resourceOwners } = await planServices$2(client, workspaceId, application.name, auths);
2908
2991
  const deletedServices = serviceChangeSet.deletes.map((del) => del.name);
2909
2992
  const idpConfigChangeSet = await planIdPConfigs(client, workspaceId, auths, deletedServices);
2910
2993
  const userProfileConfigChangeSet = await planUserProfileConfigs(client, workspaceId, auths, deletedServices);
@@ -2922,19 +3005,30 @@ async function planAuth(client, workspaceId, application) {
2922
3005
  scimChangeSet.print();
2923
3006
  scimResourceChangeSet.print();
2924
3007
  return {
2925
- service: serviceChangeSet,
2926
- idpConfig: idpConfigChangeSet,
2927
- userProfileConfig: userProfileConfigChangeSet,
2928
- tenantConfig: tenantConfigChangeSet,
2929
- machineUser: machineUserChangeSet,
2930
- oauth2Client: oauth2ClientChangeSet,
2931
- scim: scimChangeSet,
2932
- scimResource: scimResourceChangeSet
3008
+ changeSet: {
3009
+ service: serviceChangeSet,
3010
+ idpConfig: idpConfigChangeSet,
3011
+ userProfileConfig: userProfileConfigChangeSet,
3012
+ tenantConfig: tenantConfigChangeSet,
3013
+ machineUser: machineUserChangeSet,
3014
+ oauth2Client: oauth2ClientChangeSet,
3015
+ scim: scimChangeSet,
3016
+ scimResource: scimResourceChangeSet
3017
+ },
3018
+ conflicts,
3019
+ unmanaged,
3020
+ resourceOwners
2933
3021
  };
2934
3022
  }
2935
- async function planServices$2(client, workspaceId, auths) {
3023
+ function trn$4(workspaceId, name) {
3024
+ return `trn:v1:workspace:${workspaceId}:auth:${name}`;
3025
+ }
3026
+ async function planServices$2(client, workspaceId, appName, auths) {
2936
3027
  const changeSet = new ChangeSet("Auth services");
2937
- const existingServices = await fetchAll(async (pageToken) => {
3028
+ const conflicts = [];
3029
+ const unmanaged = [];
3030
+ const resourceOwners = /* @__PURE__ */ new Set();
3031
+ const withoutLabel = await fetchAll(async (pageToken) => {
2938
3032
  try {
2939
3033
  const { authServices, nextPageToken } = await client.listAuthServices({
2940
3034
  workspaceId,
@@ -2946,23 +3040,46 @@ async function planServices$2(client, workspaceId, auths) {
2946
3040
  throw error;
2947
3041
  }
2948
3042
  });
2949
- const existingNameSet = /* @__PURE__ */ new Set();
2950
- existingServices.forEach((service) => {
2951
- const name = service.namespace?.name;
2952
- if (name) existingNameSet.add(name);
2953
- });
2954
- for (const { config } of auths) if (existingNameSet.has(config.name)) {
2955
- changeSet.updates.push({ name: config.name });
2956
- existingNameSet.delete(config.name);
2957
- } else changeSet.creates.push({
2958
- name: config.name,
2959
- request: {
2960
- workspaceId,
2961
- namespaceName: config.name
2962
- }
2963
- });
2964
- existingNameSet.forEach((namespaceName) => {
2965
- changeSet.deletes.push({
3043
+ const existingServices = {};
3044
+ await Promise.all(withoutLabel.map(async (resource) => {
3045
+ if (!resource.namespace?.name) return;
3046
+ const { metadata } = await client.getMetadata({ trn: trn$4(workspaceId, resource.namespace.name) });
3047
+ existingServices[resource.namespace.name] = {
3048
+ resource,
3049
+ label: metadata?.labels[sdkNameLabelKey]
3050
+ };
3051
+ }));
3052
+ for (const { config } of auths) {
3053
+ const existing = existingServices[config.name];
3054
+ const metaRequest = await buildMetaRequest(trn$4(workspaceId, config.name), appName);
3055
+ if (existing) {
3056
+ if (!existing.label) unmanaged.push({
3057
+ resourceType: "Auth service",
3058
+ resourceName: config.name
3059
+ });
3060
+ else if (existing.label !== appName) conflicts.push({
3061
+ resourceType: "Auth service",
3062
+ resourceName: config.name,
3063
+ currentOwner: existing.label
3064
+ });
3065
+ changeSet.updates.push({
3066
+ name: config.name,
3067
+ metaRequest
3068
+ });
3069
+ delete existingServices[config.name];
3070
+ } else changeSet.creates.push({
3071
+ name: config.name,
3072
+ request: {
3073
+ workspaceId,
3074
+ namespaceName: config.name
3075
+ },
3076
+ metaRequest
3077
+ });
3078
+ }
3079
+ Object.entries(existingServices).forEach(([namespaceName]) => {
3080
+ const label = existingServices[namespaceName]?.label;
3081
+ if (label && label !== appName) resourceOwners.add(label);
3082
+ if (label === appName) changeSet.deletes.push({
2966
3083
  name: namespaceName,
2967
3084
  request: {
2968
3085
  workspaceId,
@@ -2970,7 +3087,12 @@ async function planServices$2(client, workspaceId, auths) {
2970
3087
  }
2971
3088
  });
2972
3089
  });
2973
- return changeSet;
3090
+ return {
3091
+ changeSet,
3092
+ conflicts,
3093
+ unmanaged,
3094
+ resourceOwners
3095
+ };
2974
3096
  }
2975
3097
  async function planIdPConfigs(client, workspaceId, auths, deletedServices) {
2976
3098
  const changeSet = new ChangeSet("Auth idpConfigs");
@@ -3018,7 +3140,6 @@ async function planIdPConfigs(client, workspaceId, auths, deletedServices) {
3018
3140
  });
3019
3141
  existingNameSet.forEach((name) => {
3020
3142
  changeSet.deletes.push({
3021
- tag: "idp-config-deleted",
3022
3143
  name,
3023
3144
  request: {
3024
3145
  workspaceId,
@@ -3030,8 +3151,12 @@ async function planIdPConfigs(client, workspaceId, auths, deletedServices) {
3030
3151
  }
3031
3152
  for (const namespaceName of deletedServices) (await fetchIdPConfigs(namespaceName)).forEach((idpConfig) => {
3032
3153
  changeSet.deletes.push({
3033
- tag: "service-deleted",
3034
- name: idpConfig.name
3154
+ name: idpConfig.name,
3155
+ request: {
3156
+ workspaceId,
3157
+ namespaceName,
3158
+ name: idpConfig.name
3159
+ }
3035
3160
  });
3036
3161
  });
3037
3162
  return changeSet;
@@ -3157,7 +3282,6 @@ async function planUserProfileConfigs(client, workspaceId, auths, deletedService
3157
3282
  }
3158
3283
  });
3159
3284
  else changeSet.deletes.push({
3160
- tag: "user-profile-config-deleted",
3161
3285
  name,
3162
3286
  request: {
3163
3287
  workspaceId,
@@ -3176,8 +3300,11 @@ async function planUserProfileConfigs(client, workspaceId, auths, deletedService
3176
3300
  throw error;
3177
3301
  }
3178
3302
  changeSet.deletes.push({
3179
- tag: "service-deleted",
3180
- name: `${namespaceName}-user-profile-config`
3303
+ name: `${namespaceName}-user-profile-config`,
3304
+ request: {
3305
+ workspaceId,
3306
+ namespaceName
3307
+ }
3181
3308
  });
3182
3309
  }
3183
3310
  return changeSet;
@@ -3232,7 +3359,6 @@ async function planTenantConfigs(client, workspaceId, auths, deletedServices) {
3232
3359
  }
3233
3360
  });
3234
3361
  else changeSet.deletes.push({
3235
- tag: "tenant-config-deleted",
3236
3362
  name,
3237
3363
  request: {
3238
3364
  workspaceId,
@@ -3251,8 +3377,11 @@ async function planTenantConfigs(client, workspaceId, auths, deletedServices) {
3251
3377
  throw error;
3252
3378
  }
3253
3379
  changeSet.deletes.push({
3254
- tag: "service-deleted",
3255
- name: `${namespaceName}-tenant-config`
3380
+ name: `${namespaceName}-tenant-config`,
3381
+ request: {
3382
+ workspaceId,
3383
+ namespaceName
3384
+ }
3256
3385
  });
3257
3386
  }
3258
3387
  return changeSet;
@@ -3321,7 +3450,6 @@ async function planMachineUsers(client, workspaceId, auths, deletedServices) {
3321
3450
  }
3322
3451
  existingNameSet.forEach((name) => {
3323
3452
  changeSet.deletes.push({
3324
- tag: "machine-user-deleted",
3325
3453
  name,
3326
3454
  request: {
3327
3455
  workspaceId,
@@ -3333,8 +3461,12 @@ async function planMachineUsers(client, workspaceId, auths, deletedServices) {
3333
3461
  }
3334
3462
  for (const namespaceName of deletedServices) (await fetchMachineUsers(namespaceName)).forEach((machineUser) => {
3335
3463
  changeSet.deletes.push({
3336
- tag: "service-deleted",
3337
- name: machineUser.name
3464
+ name: machineUser.name,
3465
+ request: {
3466
+ workspaceId,
3467
+ authNamespace: namespaceName,
3468
+ name: machineUser.name
3469
+ }
3338
3470
  });
3339
3471
  });
3340
3472
  return changeSet;
@@ -3391,7 +3523,6 @@ async function planOAuth2Clients(client, workspaceId, auths, deletedServices) {
3391
3523
  }
3392
3524
  existingNameSet.forEach((name) => {
3393
3525
  changeSet.deletes.push({
3394
- tag: "oauth2-client-deleted",
3395
3526
  name,
3396
3527
  request: {
3397
3528
  workspaceId,
@@ -3403,8 +3534,12 @@ async function planOAuth2Clients(client, workspaceId, auths, deletedServices) {
3403
3534
  }
3404
3535
  for (const namespaceName of deletedServices) (await fetchOAuth2Clients(namespaceName)).forEach((oauth2Client) => {
3405
3536
  changeSet.deletes.push({
3406
- tag: "service-deleted",
3407
- name: oauth2Client.name
3537
+ name: oauth2Client.name,
3538
+ request: {
3539
+ workspaceId,
3540
+ namespaceName,
3541
+ name: oauth2Client.name
3542
+ }
3408
3543
  });
3409
3544
  });
3410
3545
  return changeSet;
@@ -3460,7 +3595,6 @@ async function planSCIMConfigs(client, workspaceId, auths, deletedServices) {
3460
3595
  }
3461
3596
  });
3462
3597
  else changeSet.deletes.push({
3463
- tag: "scim-config-deleted",
3464
3598
  name,
3465
3599
  request: {
3466
3600
  workspaceId,
@@ -3479,8 +3613,11 @@ async function planSCIMConfigs(client, workspaceId, auths, deletedServices) {
3479
3613
  throw error;
3480
3614
  }
3481
3615
  changeSet.deletes.push({
3482
- tag: "service-deleted",
3483
- name: `${namespaceName}-scim-config`
3616
+ name: `${namespaceName}-scim-config`,
3617
+ request: {
3618
+ workspaceId,
3619
+ namespaceName
3620
+ }
3484
3621
  });
3485
3622
  }
3486
3623
  return changeSet;
@@ -3548,7 +3685,6 @@ async function planSCIMResources(client, workspaceId, auths, deletedServices) {
3548
3685
  });
3549
3686
  existingNameSet.forEach((name) => {
3550
3687
  changeSet.deletes.push({
3551
- tag: "scim-resource-deleted",
3552
3688
  name,
3553
3689
  request: {
3554
3690
  workspaceId,
@@ -3560,8 +3696,12 @@ async function planSCIMResources(client, workspaceId, auths, deletedServices) {
3560
3696
  }
3561
3697
  for (const namespaceName of deletedServices) (await fetchSCIMResources(namespaceName)).forEach((scimResource) => {
3562
3698
  changeSet.deletes.push({
3563
- tag: "service-deleted",
3564
- name: scimResource.name
3699
+ name: scimResource.name,
3700
+ request: {
3701
+ workspaceId,
3702
+ namespaceName,
3703
+ name: scimResource.name
3704
+ }
3565
3705
  });
3566
3706
  });
3567
3707
  return changeSet;
@@ -3640,15 +3780,91 @@ function protoSCIMAttribute(attr) {
3640
3780
  };
3641
3781
  }
3642
3782
 
3783
+ //#endregion
3784
+ //#region src/cli/apply/services/confirm.ts
3785
+ async function confirmOwnerConflict(conflicts, appName, yes) {
3786
+ if (conflicts.length === 0) return;
3787
+ const currentOwners = [...new Set(conflicts.map((c) => c.currentOwner))];
3788
+ consola.warn("Application name mismatch detected:");
3789
+ console.log(` ${chalk.yellow("Current application(s)")}: ${currentOwners.map((o) => chalk.bold(`"${o}"`)).join(", ")}`);
3790
+ console.log(` ${chalk.green("New application")}: ${chalk.bold(`"${appName}"`)}`);
3791
+ console.log("");
3792
+ console.log(` ${chalk.cyan("Resources")}:`);
3793
+ for (const c of conflicts) console.log(` • ${chalk.bold(c.resourceType)} ${chalk.cyan(`"${c.resourceName}"`)}`);
3794
+ if (yes) {
3795
+ consola.success("Updating resources (--yes flag specified)...");
3796
+ return;
3797
+ }
3798
+ const promptMessage = currentOwners.length === 1 ? `Update these resources to be managed by "${appName}"?\n${chalk.gray("(Common when renaming your application)")}` : `Update these resources to be managed by "${appName}"?`;
3799
+ if (!await consola.prompt(promptMessage, {
3800
+ type: "confirm",
3801
+ initial: false
3802
+ })) throw new Error(ml`
3803
+ Apply cancelled. Resources remain managed by their current applications.
3804
+ To override, run again and confirm, or use --yes flag.
3805
+ `);
3806
+ }
3807
+ async function confirmUnmanagedResources(resources, appName, yes) {
3808
+ if (resources.length === 0) return;
3809
+ consola.warn("Unmanaged resources detected:");
3810
+ console.log(` ${chalk.cyan("Resources")}:`);
3811
+ for (const r of resources) console.log(` • ${chalk.bold(r.resourceType)} ${chalk.cyan(`"${r.resourceName}"`)}`);
3812
+ console.log("");
3813
+ console.log(" These resources are not managed by any application.");
3814
+ if (yes) {
3815
+ consola.success(`Adding to "${appName}" (--yes flag specified)...`);
3816
+ return;
3817
+ }
3818
+ if (!await consola.prompt(`Add these resources to "${appName}"?`, {
3819
+ type: "confirm",
3820
+ initial: false
3821
+ })) throw new Error(ml`
3822
+ Apply cancelled. Resources remain unmanaged.
3823
+ To override, run again and confirm, or use --yes flag.
3824
+ `);
3825
+ }
3826
+ async function confirmImportantResourceDeletion(resources, yes) {
3827
+ if (resources.length === 0) return;
3828
+ consola.warn("The following resources will be deleted:");
3829
+ console.log(` ${chalk.cyan("Resources")}:`);
3830
+ for (const r of resources) console.log(` • ${chalk.bold(r.resourceType)} ${chalk.red(`"${r.resourceName}"`)}`);
3831
+ console.log("");
3832
+ console.log(chalk.yellow(" Deleting these resources will permanently remove all associated data."));
3833
+ if (yes) {
3834
+ consola.success("Deleting resources (--yes flag specified)...");
3835
+ return;
3836
+ }
3837
+ if (!await consola.prompt("Are you sure you want to delete these resources?", {
3838
+ type: "confirm",
3839
+ initial: false
3840
+ })) throw new Error(ml`
3841
+ Apply cancelled. Resources will not be deleted.
3842
+ To override, run again and confirm, or use --yes flag.
3843
+ `);
3844
+ }
3845
+
3643
3846
  //#endregion
3644
3847
  //#region src/cli/apply/services/executor.ts
3645
- async function applyExecutor(client, changeSet, phase = "create-update") {
3646
- if (phase === "create-update") await Promise.all([...changeSet.creates.map((create) => client.createExecutorExecutor(create.request)), ...changeSet.updates.map((update) => client.updateExecutorExecutor(update.request))]);
3848
+ async function applyExecutor(client, result, phase = "create-update") {
3849
+ const { changeSet } = result;
3850
+ if (phase === "create-update") await Promise.all([...changeSet.creates.map(async (create) => {
3851
+ await client.createExecutorExecutor(create.request);
3852
+ await client.setMetadata(create.metaRequest);
3853
+ }), ...changeSet.updates.map(async (update) => {
3854
+ await client.updateExecutorExecutor(update.request);
3855
+ await client.setMetadata(update.metaRequest);
3856
+ })]);
3647
3857
  else if (phase === "delete") await Promise.all(changeSet.deletes.map((del) => client.deleteExecutorExecutor(del.request)));
3648
3858
  }
3649
- async function planExecutor(client, workspaceId, application) {
3859
+ function trn$3(workspaceId, name) {
3860
+ return `trn:v1:workspace:${workspaceId}:executor:${name}`;
3861
+ }
3862
+ async function planExecutor({ client, workspaceId, application }) {
3650
3863
  const changeSet = new ChangeSet("Executors");
3651
- const existingExecutors = await fetchAll(async (pageToken) => {
3864
+ const conflicts = [];
3865
+ const unmanaged = [];
3866
+ const resourceOwners = /* @__PURE__ */ new Set();
3867
+ const withoutLabel = await fetchAll(async (pageToken) => {
3652
3868
  try {
3653
3869
  const { executors: executors$1, nextPageToken } = await client.listExecutorExecutors({
3654
3870
  workspaceId,
@@ -3660,29 +3876,50 @@ async function planExecutor(client, workspaceId, application) {
3660
3876
  throw error;
3661
3877
  }
3662
3878
  });
3663
- const existingNameSet = /* @__PURE__ */ new Set();
3664
- existingExecutors.forEach((executor) => {
3665
- existingNameSet.add(executor.name);
3666
- });
3879
+ const existingExecutors = {};
3880
+ await Promise.all(withoutLabel.map(async (resource) => {
3881
+ const { metadata } = await client.getMetadata({ trn: trn$3(workspaceId, resource.name) });
3882
+ existingExecutors[resource.name] = {
3883
+ resource,
3884
+ label: metadata?.labels[sdkNameLabelKey]
3885
+ };
3886
+ }));
3667
3887
  const executors = await application.executorService?.loadExecutors() ?? {};
3668
- for (const executor of Object.values(executors)) if (existingNameSet.has(executor.name)) {
3669
- changeSet.updates.push({
3888
+ for (const executor of Object.values(executors)) {
3889
+ const existing = existingExecutors[executor.name];
3890
+ const metaRequest = await buildMetaRequest(trn$3(workspaceId, executor.name), application.name);
3891
+ if (existing) {
3892
+ if (!existing.label) unmanaged.push({
3893
+ resourceType: "Executor",
3894
+ resourceName: executor.name
3895
+ });
3896
+ else if (existing.label !== application.name) conflicts.push({
3897
+ resourceType: "Executor",
3898
+ resourceName: executor.name,
3899
+ currentOwner: existing.label
3900
+ });
3901
+ changeSet.updates.push({
3902
+ name: executor.name,
3903
+ request: {
3904
+ workspaceId,
3905
+ executor: protoExecutor(application.name, executor, application.env)
3906
+ },
3907
+ metaRequest
3908
+ });
3909
+ delete existingExecutors[executor.name];
3910
+ } else changeSet.creates.push({
3670
3911
  name: executor.name,
3671
3912
  request: {
3672
3913
  workspaceId,
3673
- executor: protoExecutor(executor)
3674
- }
3914
+ executor: protoExecutor(application.name, executor, application.env)
3915
+ },
3916
+ metaRequest
3675
3917
  });
3676
- existingNameSet.delete(executor.name);
3677
- } else changeSet.creates.push({
3678
- name: executor.name,
3679
- request: {
3680
- workspaceId,
3681
- executor: protoExecutor(executor)
3682
- }
3683
- });
3684
- existingNameSet.forEach((name) => {
3685
- changeSet.deletes.push({
3918
+ }
3919
+ Object.entries(existingExecutors).forEach(([name]) => {
3920
+ const label = existingExecutors[name]?.label;
3921
+ if (label && label !== application.name) resourceOwners.add(label);
3922
+ if (label === application.name) changeSet.deletes.push({
3686
3923
  name,
3687
3924
  request: {
3688
3925
  workspaceId,
@@ -3691,9 +3928,14 @@ async function planExecutor(client, workspaceId, application) {
3691
3928
  });
3692
3929
  });
3693
3930
  changeSet.print();
3694
- return changeSet;
3931
+ return {
3932
+ changeSet,
3933
+ conflicts,
3934
+ unmanaged,
3935
+ resourceOwners
3936
+ };
3695
3937
  }
3696
- function protoExecutor(executor) {
3938
+ function protoExecutor(appName, executor, env) {
3697
3939
  const trigger = executor.trigger;
3698
3940
  let triggerType;
3699
3941
  let triggerConfig;
@@ -3782,7 +4024,7 @@ function protoExecutor(executor) {
3782
4024
  targetConfig = { config: {
3783
4025
  case: "tailorGraphql",
3784
4026
  value: {
3785
- appName: target.appName,
4027
+ appName: target.appName ?? appName,
3786
4028
  query: target.query,
3787
4029
  variables: target.variables ? { expr: `(${target.variables.toString()})(args)` } : void 0,
3788
4030
  invoker: target.invoker ? {
@@ -3803,7 +4045,7 @@ function protoExecutor(executor) {
3803
4045
  value: {
3804
4046
  name: `${executor.name}__target`,
3805
4047
  script,
3806
- variables: { expr: "({ ...args, appNamespace: args.namespaceName })" },
4048
+ variables: { expr: `({ ...args, appNamespace: args.namespaceName, env: ${JSON.stringify(env)} })` },
3807
4049
  invoker: target.invoker ? {
3808
4050
  namespace: target.invoker.authName,
3809
4051
  machineUserName: target.invoker.machineUser
@@ -3861,35 +4103,53 @@ const SCALAR_TYPE_MAP = {
3861
4103
  name: "Time"
3862
4104
  }
3863
4105
  };
3864
- async function applyPipeline(client, changeSet, phase = "create-update") {
4106
+ async function applyPipeline(client, result, phase = "create-update") {
4107
+ const { changeSet } = result;
3865
4108
  if (phase === "create-update") {
3866
- await Promise.all([...changeSet.service.creates.map((create) => client.createPipelineService(create.request)), ...changeSet.service.updates.map((update) => client.updatePipelineService(update.request))]);
4109
+ await Promise.all([...changeSet.service.creates.map(async (create) => {
4110
+ await client.createPipelineService(create.request);
4111
+ await client.setMetadata(create.metaRequest);
4112
+ }), ...changeSet.service.updates.map(async (update) => {
4113
+ await client.updatePipelineService(update.request);
4114
+ await client.setMetadata(update.metaRequest);
4115
+ })]);
3867
4116
  await Promise.all([...changeSet.resolver.creates.map((create) => client.createPipelineResolver(create.request)), ...changeSet.resolver.updates.map((update) => client.updatePipelineResolver(update.request))]);
3868
4117
  } else if (phase === "delete") {
3869
- await Promise.all(changeSet.resolver.deletes.filter((del) => del.tag === "resolver-deleted").map((del) => client.deletePipelineResolver(del.request)));
4118
+ await Promise.all(changeSet.resolver.deletes.map((del) => client.deletePipelineResolver(del.request)));
3870
4119
  await Promise.all(changeSet.service.deletes.map((del) => client.deletePipelineService(del.request)));
3871
4120
  }
3872
4121
  }
3873
- async function planPipeline(client, workspaceId, application) {
4122
+ async function planPipeline({ client, workspaceId, application }) {
3874
4123
  const pipelines = [];
3875
- for (const app of application.applications) for (const pipeline of app.resolverServices) {
4124
+ for (const pipeline of application.resolverServices) {
3876
4125
  await pipeline.loadResolvers();
3877
4126
  pipelines.push(pipeline);
3878
4127
  }
3879
4128
  const executors = Object.values(await application.executorService?.loadExecutors() ?? {});
3880
- const serviceChangeSet = await planServices$1(client, workspaceId, pipelines);
4129
+ const { changeSet: serviceChangeSet, conflicts, unmanaged, resourceOwners } = await planServices$1(client, workspaceId, application.name, pipelines);
3881
4130
  const deletedServices = serviceChangeSet.deletes.map((del) => del.name);
3882
- const resolverChangeSet = await planResolvers(client, workspaceId, pipelines, executors, deletedServices);
4131
+ const resolverChangeSet = await planResolvers(client, workspaceId, pipelines, executors, deletedServices, application.env);
3883
4132
  serviceChangeSet.print();
3884
4133
  resolverChangeSet.print();
3885
4134
  return {
3886
- service: serviceChangeSet,
3887
- resolver: resolverChangeSet
4135
+ changeSet: {
4136
+ service: serviceChangeSet,
4137
+ resolver: resolverChangeSet
4138
+ },
4139
+ conflicts,
4140
+ unmanaged,
4141
+ resourceOwners
3888
4142
  };
3889
4143
  }
3890
- async function planServices$1(client, workspaceId, pipelines) {
4144
+ function trn$2(workspaceId, name) {
4145
+ return `trn:v1:workspace:${workspaceId}:pipeline:${name}`;
4146
+ }
4147
+ async function planServices$1(client, workspaceId, appName, pipelines) {
3891
4148
  const changeSet = new ChangeSet("Pipeline services");
3892
- const existingServices = await fetchAll(async (pageToken) => {
4149
+ const conflicts = [];
4150
+ const unmanaged = [];
4151
+ const resourceOwners = /* @__PURE__ */ new Set();
4152
+ const withoutLabel = await fetchAll(async (pageToken) => {
3893
4153
  try {
3894
4154
  const { pipelineServices, nextPageToken } = await client.listPipelineServices({
3895
4155
  workspaceId,
@@ -3901,29 +4161,50 @@ async function planServices$1(client, workspaceId, pipelines) {
3901
4161
  throw error;
3902
4162
  }
3903
4163
  });
3904
- const existingNameSet = /* @__PURE__ */ new Set();
3905
- existingServices.forEach((service) => {
3906
- const name = service.namespace?.name;
3907
- if (name) existingNameSet.add(name);
3908
- });
3909
- for (const pipeline of pipelines) if (existingNameSet.has(pipeline.namespace)) {
3910
- changeSet.updates.push({
4164
+ const existingServices = {};
4165
+ await Promise.all(withoutLabel.map(async (resource) => {
4166
+ if (!resource.namespace?.name) return;
4167
+ const { metadata } = await client.getMetadata({ trn: trn$2(workspaceId, resource.namespace.name) });
4168
+ existingServices[resource.namespace.name] = {
4169
+ resource,
4170
+ label: metadata?.labels[sdkNameLabelKey]
4171
+ };
4172
+ }));
4173
+ for (const pipeline of pipelines) {
4174
+ const existing = existingServices[pipeline.namespace];
4175
+ const metaRequest = await buildMetaRequest(trn$2(workspaceId, pipeline.namespace), appName);
4176
+ if (existing) {
4177
+ if (!existing.label) unmanaged.push({
4178
+ resourceType: "Pipeline service",
4179
+ resourceName: pipeline.namespace
4180
+ });
4181
+ else if (existing.label !== appName) conflicts.push({
4182
+ resourceType: "Pipeline service",
4183
+ resourceName: pipeline.namespace,
4184
+ currentOwner: existing.label
4185
+ });
4186
+ changeSet.updates.push({
4187
+ name: pipeline.namespace,
4188
+ request: {
4189
+ workspaceId,
4190
+ namespaceName: pipeline.namespace
4191
+ },
4192
+ metaRequest
4193
+ });
4194
+ delete existingServices[pipeline.namespace];
4195
+ } else changeSet.creates.push({
3911
4196
  name: pipeline.namespace,
3912
4197
  request: {
3913
4198
  workspaceId,
3914
4199
  namespaceName: pipeline.namespace
3915
- }
4200
+ },
4201
+ metaRequest
3916
4202
  });
3917
- existingNameSet.delete(pipeline.namespace);
3918
- } else changeSet.creates.push({
3919
- name: pipeline.namespace,
3920
- request: {
3921
- workspaceId,
3922
- namespaceName: pipeline.namespace
3923
- }
3924
- });
3925
- existingNameSet.forEach((namespaceName) => {
3926
- changeSet.deletes.push({
4203
+ }
4204
+ Object.entries(existingServices).forEach(([namespaceName]) => {
4205
+ const label = existingServices[namespaceName]?.label;
4206
+ if (label && label !== appName) resourceOwners.add(label);
4207
+ if (label === appName) changeSet.deletes.push({
3927
4208
  name: namespaceName,
3928
4209
  request: {
3929
4210
  workspaceId,
@@ -3931,9 +4212,14 @@ async function planServices$1(client, workspaceId, pipelines) {
3931
4212
  }
3932
4213
  });
3933
4214
  });
3934
- return changeSet;
4215
+ return {
4216
+ changeSet,
4217
+ conflicts,
4218
+ unmanaged,
4219
+ resourceOwners
4220
+ };
3935
4221
  }
3936
- async function planResolvers(client, workspaceId, pipelines, executors, deletedServices) {
4222
+ async function planResolvers(client, workspaceId, pipelines, executors, deletedServices, env) {
3937
4223
  const changeSet = new ChangeSet("Pipeline resolvers");
3938
4224
  const fetchResolvers = (namespaceName) => {
3939
4225
  return fetchAll(async (pageToken) => {
@@ -3964,7 +4250,7 @@ async function planResolvers(client, workspaceId, pipelines, executors, deletedS
3964
4250
  request: {
3965
4251
  workspaceId,
3966
4252
  namespaceName: pipeline.namespace,
3967
- pipelineResolver: processResolver(resolver, executorUsedResolvers)
4253
+ pipelineResolver: processResolver(resolver, executorUsedResolvers, env)
3968
4254
  }
3969
4255
  });
3970
4256
  existingNameSet.delete(resolver.name);
@@ -3973,12 +4259,11 @@ async function planResolvers(client, workspaceId, pipelines, executors, deletedS
3973
4259
  request: {
3974
4260
  workspaceId,
3975
4261
  namespaceName: pipeline.namespace,
3976
- pipelineResolver: processResolver(resolver, executorUsedResolvers)
4262
+ pipelineResolver: processResolver(resolver, executorUsedResolvers, env)
3977
4263
  }
3978
4264
  });
3979
4265
  existingNameSet.forEach((name) => {
3980
4266
  changeSet.deletes.push({
3981
- tag: "resolver-deleted",
3982
4267
  name,
3983
4268
  request: {
3984
4269
  workspaceId,
@@ -3990,13 +4275,17 @@ async function planResolvers(client, workspaceId, pipelines, executors, deletedS
3990
4275
  }
3991
4276
  for (const namespaceName of deletedServices) (await fetchResolvers(namespaceName)).forEach((resolver) => {
3992
4277
  changeSet.deletes.push({
3993
- tag: "service-deleted",
3994
- name: resolver.name
4278
+ name: resolver.name,
4279
+ request: {
4280
+ workspaceId,
4281
+ namespaceName,
4282
+ resolverName: resolver.name
4283
+ }
3995
4284
  });
3996
4285
  });
3997
4286
  return changeSet;
3998
4287
  }
3999
- function processResolver(resolver, executorUsedResolvers) {
4288
+ function processResolver(resolver, executorUsedResolvers, env) {
4000
4289
  const functionPath = path.join(getDistDir(), "functions", `${resolver.name}__body.js`);
4001
4290
  let functionCode = "";
4002
4291
  try {
@@ -4010,7 +4299,7 @@ function processResolver(resolver, executorUsedResolvers) {
4010
4299
  description: `${resolver.name} function body`,
4011
4300
  operationType: PipelineResolver_OperationType.FUNCTION,
4012
4301
  operationSource: functionCode,
4013
- operationHook: { expr: `({ ...context.pipeline, input: context.args, user: ${tailorUserMap} });` },
4302
+ operationHook: { expr: `({ ...context.pipeline, input: context.args, user: ${tailorUserMap}, env: ${JSON.stringify(env)} });` },
4014
4303
  postScript: `args.body`
4015
4304
  }];
4016
4305
  const typeBaseName = inflection.camelize(resolver.name);
@@ -4065,13 +4354,26 @@ function protoFields(fields, baseName, isInput) {
4065
4354
 
4066
4355
  //#endregion
4067
4356
  //#region src/cli/apply/services/staticwebsite.ts
4068
- async function applyStaticWebsite(client, changeSet, phase = "create-update") {
4069
- if (phase === "create-update") await Promise.all([...changeSet.creates.map((create) => client.createStaticWebsite(create.request)), ...changeSet.updates.map((update) => client.updateStaticWebsite(update.request))]);
4357
+ async function applyStaticWebsite(client, result, phase = "create-update") {
4358
+ const { changeSet } = result;
4359
+ if (phase === "create-update") await Promise.all([...changeSet.creates.map(async (create) => {
4360
+ await client.createStaticWebsite(create.request);
4361
+ await client.setMetadata(create.metaRequest);
4362
+ }), ...changeSet.updates.map(async (update) => {
4363
+ await client.updateStaticWebsite(update.request);
4364
+ await client.setMetadata(update.metaRequest);
4365
+ })]);
4070
4366
  else if (phase === "delete") await Promise.all(changeSet.deletes.map((del) => client.deleteStaticWebsite(del.request)));
4071
4367
  }
4072
- async function planStaticWebsite(client, workspaceId, application) {
4368
+ function trn$1(workspaceId, name) {
4369
+ return `trn:v1:workspace:${workspaceId}:staticwebsite:${name}`;
4370
+ }
4371
+ async function planStaticWebsite({ client, workspaceId, application }) {
4073
4372
  const changeSet = new ChangeSet("StaticWebsites");
4074
- const existingWebsites = await fetchAll(async (pageToken) => {
4373
+ const conflicts = [];
4374
+ const unmanaged = [];
4375
+ const resourceOwners = /* @__PURE__ */ new Set();
4376
+ const withoutLabel = await fetchAll(async (pageToken) => {
4075
4377
  try {
4076
4378
  const { staticwebsites, nextPageToken } = await client.listStaticWebsites({
4077
4379
  workspaceId,
@@ -4083,14 +4385,29 @@ async function planStaticWebsite(client, workspaceId, application) {
4083
4385
  throw error;
4084
4386
  }
4085
4387
  });
4086
- const existingNameSet = /* @__PURE__ */ new Set();
4087
- existingWebsites.forEach((website) => {
4088
- existingNameSet.add(website.name);
4089
- });
4388
+ const existingWebsites = {};
4389
+ await Promise.all(withoutLabel.map(async (resource) => {
4390
+ const { metadata } = await client.getMetadata({ trn: trn$1(workspaceId, resource.name) });
4391
+ existingWebsites[resource.name] = {
4392
+ resource,
4393
+ label: metadata?.labels[sdkNameLabelKey]
4394
+ };
4395
+ }));
4090
4396
  for (const websiteService of application.staticWebsiteServices) {
4091
4397
  const config = websiteService;
4092
4398
  const name = websiteService.name;
4093
- if (existingNameSet.has(name)) {
4399
+ const existing = existingWebsites[name];
4400
+ const metaRequest = await buildMetaRequest(trn$1(workspaceId, name), application.name);
4401
+ if (existing) {
4402
+ if (!existing.label) unmanaged.push({
4403
+ resourceType: "StaticWebsite",
4404
+ resourceName: name
4405
+ });
4406
+ else if (existing.label !== application.name) conflicts.push({
4407
+ resourceType: "StaticWebsite",
4408
+ resourceName: name,
4409
+ currentOwner: existing.label
4410
+ });
4094
4411
  changeSet.updates.push({
4095
4412
  name,
4096
4413
  request: {
@@ -4100,9 +4417,10 @@ async function planStaticWebsite(client, workspaceId, application) {
4100
4417
  description: config.description || "",
4101
4418
  allowedIpAddresses: config.allowedIpAddresses || []
4102
4419
  }
4103
- }
4420
+ },
4421
+ metaRequest
4104
4422
  });
4105
- existingNameSet.delete(name);
4423
+ delete existingWebsites[name];
4106
4424
  } else changeSet.creates.push({
4107
4425
  name,
4108
4426
  request: {
@@ -4112,11 +4430,14 @@ async function planStaticWebsite(client, workspaceId, application) {
4112
4430
  description: config.description || "",
4113
4431
  allowedIpAddresses: config.allowedIpAddresses || []
4114
4432
  }
4115
- }
4433
+ },
4434
+ metaRequest
4116
4435
  });
4117
4436
  }
4118
- existingNameSet.forEach((name) => {
4119
- changeSet.deletes.push({
4437
+ Object.entries(existingWebsites).forEach(([name]) => {
4438
+ const label = existingWebsites[name]?.label;
4439
+ if (label && label !== application.name) resourceOwners.add(label);
4440
+ if (label === application.name) changeSet.deletes.push({
4120
4441
  name,
4121
4442
  request: {
4122
4443
  workspaceId,
@@ -4125,30 +4446,39 @@ async function planStaticWebsite(client, workspaceId, application) {
4125
4446
  });
4126
4447
  });
4127
4448
  changeSet.print();
4128
- return changeSet;
4449
+ return {
4450
+ changeSet,
4451
+ conflicts,
4452
+ unmanaged,
4453
+ resourceOwners
4454
+ };
4129
4455
  }
4130
4456
 
4131
4457
  //#endregion
4132
4458
  //#region src/cli/apply/services/tailordb.ts
4133
- async function applyTailorDB(client, changeSet, phase = "create-update") {
4459
+ async function applyTailorDB(client, result, phase = "create-update") {
4460
+ const { changeSet } = result;
4134
4461
  if (phase === "create-update") {
4135
- await Promise.all(changeSet.service.creates.map((create) => client.createTailorDBService(create.request)));
4462
+ await Promise.all([...changeSet.service.creates.map(async (create) => {
4463
+ await client.createTailorDBService(create.request);
4464
+ await client.setMetadata(create.metaRequest);
4465
+ }), ...changeSet.service.updates.map((update) => client.setMetadata(update.metaRequest))]);
4136
4466
  await Promise.all([...changeSet.type.creates.map((create) => client.createTailorDBType(create.request)), ...changeSet.type.updates.map((update) => client.updateTailorDBType(update.request))]);
4137
4467
  await Promise.all([...changeSet.gqlPermission.creates.map((create) => client.createTailorDBGQLPermission(create.request)), ...changeSet.gqlPermission.updates.map((update) => client.updateTailorDBGQLPermission(update.request))]);
4138
4468
  } else if (phase === "delete") {
4139
- await Promise.all(changeSet.gqlPermission.deletes.filter((del) => del.tag === "gql-permission-deleted").map((del) => client.deleteTailorDBGQLPermission(del.request)));
4140
- await Promise.all(changeSet.type.deletes.filter((del) => del.tag === "type-deleted").map((del) => client.deleteTailorDBType(del.request)));
4469
+ await Promise.all(changeSet.gqlPermission.deletes.map((del) => client.deleteTailorDBGQLPermission(del.request)));
4470
+ await Promise.all(changeSet.type.deletes.map((del) => client.deleteTailorDBType(del.request)));
4141
4471
  await Promise.all(changeSet.service.deletes.map((del) => client.deleteTailorDBService(del.request)));
4142
4472
  }
4143
4473
  }
4144
- async function planTailorDB(client, workspaceId, application) {
4474
+ async function planTailorDB({ client, workspaceId, application }) {
4145
4475
  const tailordbs = [];
4146
- for (const app of application.applications) for (const tailordb of app.tailorDBServices) {
4476
+ for (const tailordb of application.tailorDBServices) {
4147
4477
  await tailordb.loadTypes();
4148
4478
  tailordbs.push(tailordb);
4149
4479
  }
4150
4480
  const executors = Object.values(await application.executorService?.loadExecutors() ?? {});
4151
- const serviceChangeSet = await planServices(client, workspaceId, tailordbs);
4481
+ const { changeSet: serviceChangeSet, conflicts, unmanaged, resourceOwners } = await planServices(client, workspaceId, application.name, tailordbs);
4152
4482
  const deletedServices = serviceChangeSet.deletes.map((del) => del.name);
4153
4483
  const typeChangeSet = await planTypes(client, workspaceId, tailordbs, executors, deletedServices);
4154
4484
  const gqlPermissionChangeSet = await planGqlPermissions(client, workspaceId, tailordbs, deletedServices);
@@ -4156,14 +4486,25 @@ async function planTailorDB(client, workspaceId, application) {
4156
4486
  typeChangeSet.print();
4157
4487
  gqlPermissionChangeSet.print();
4158
4488
  return {
4159
- service: serviceChangeSet,
4160
- type: typeChangeSet,
4161
- gqlPermission: gqlPermissionChangeSet
4489
+ changeSet: {
4490
+ service: serviceChangeSet,
4491
+ type: typeChangeSet,
4492
+ gqlPermission: gqlPermissionChangeSet
4493
+ },
4494
+ conflicts,
4495
+ unmanaged,
4496
+ resourceOwners
4162
4497
  };
4163
4498
  }
4164
- async function planServices(client, workspaceId, tailordbs) {
4499
+ function trn(workspaceId, name) {
4500
+ return `${trnPrefix(workspaceId)}:tailordb:${name}`;
4501
+ }
4502
+ async function planServices(client, workspaceId, appName, tailordbs) {
4165
4503
  const changeSet = new ChangeSet("TailorDB services");
4166
- const existingServices = await fetchAll(async (pageToken) => {
4504
+ const conflicts = [];
4505
+ const unmanaged = [];
4506
+ const resourceOwners = /* @__PURE__ */ new Set();
4507
+ const withoutLabel = await fetchAll(async (pageToken) => {
4167
4508
  try {
4168
4509
  const { tailordbServices, nextPageToken } = await client.listTailorDBServices({
4169
4510
  workspaceId,
@@ -4175,24 +4516,47 @@ async function planServices(client, workspaceId, tailordbs) {
4175
4516
  throw error;
4176
4517
  }
4177
4518
  });
4178
- const existingNameSet = /* @__PURE__ */ new Set();
4179
- existingServices.forEach((service) => {
4180
- const name = service.namespace?.name;
4181
- if (name) existingNameSet.add(name);
4182
- });
4183
- for (const tailordb of tailordbs) if (existingNameSet.has(tailordb.namespace)) {
4184
- changeSet.updates.push({ name: tailordb.namespace });
4185
- existingNameSet.delete(tailordb.namespace);
4186
- } else changeSet.creates.push({
4187
- name: tailordb.namespace,
4188
- request: {
4189
- workspaceId,
4190
- namespaceName: tailordb.namespace,
4191
- defaultTimezone: "UTC"
4192
- }
4193
- });
4194
- existingNameSet.forEach((namespaceName) => {
4195
- changeSet.deletes.push({
4519
+ const existingServices = {};
4520
+ await Promise.all(withoutLabel.map(async (resource) => {
4521
+ if (!resource.namespace?.name) return;
4522
+ const { metadata } = await client.getMetadata({ trn: trn(workspaceId, resource.namespace.name) });
4523
+ existingServices[resource.namespace.name] = {
4524
+ resource,
4525
+ label: metadata?.labels[sdkNameLabelKey]
4526
+ };
4527
+ }));
4528
+ for (const tailordb of tailordbs) {
4529
+ const existing = existingServices[tailordb.namespace];
4530
+ const metaRequest = await buildMetaRequest(trn(workspaceId, tailordb.namespace), appName);
4531
+ if (existing) {
4532
+ if (!existing.label) unmanaged.push({
4533
+ resourceType: "TailorDB service",
4534
+ resourceName: tailordb.namespace
4535
+ });
4536
+ else if (existing.label !== appName) conflicts.push({
4537
+ resourceType: "TailorDB service",
4538
+ resourceName: tailordb.namespace,
4539
+ currentOwner: existing.label
4540
+ });
4541
+ changeSet.updates.push({
4542
+ name: tailordb.namespace,
4543
+ metaRequest
4544
+ });
4545
+ delete existingServices[tailordb.namespace];
4546
+ } else changeSet.creates.push({
4547
+ name: tailordb.namespace,
4548
+ request: {
4549
+ workspaceId,
4550
+ namespaceName: tailordb.namespace,
4551
+ defaultTimezone: "UTC"
4552
+ },
4553
+ metaRequest
4554
+ });
4555
+ }
4556
+ Object.entries(existingServices).forEach(([namespaceName]) => {
4557
+ const label = existingServices[namespaceName]?.label;
4558
+ if (label && label !== appName) resourceOwners.add(label);
4559
+ if (label === appName) changeSet.deletes.push({
4196
4560
  name: namespaceName,
4197
4561
  request: {
4198
4562
  workspaceId,
@@ -4200,7 +4564,12 @@ async function planServices(client, workspaceId, tailordbs) {
4200
4564
  }
4201
4565
  });
4202
4566
  });
4203
- return changeSet;
4567
+ return {
4568
+ changeSet,
4569
+ conflicts,
4570
+ unmanaged,
4571
+ resourceOwners
4572
+ };
4204
4573
  }
4205
4574
  async function planTypes(client, workspaceId, tailordbs, executors, deletedServices) {
4206
4575
  const changeSet = new ChangeSet("TailorDB types");
@@ -4249,7 +4618,6 @@ async function planTypes(client, workspaceId, tailordbs, executors, deletedServi
4249
4618
  }
4250
4619
  existingNameSet.forEach((name) => {
4251
4620
  changeSet.deletes.push({
4252
- tag: "type-deleted",
4253
4621
  name,
4254
4622
  request: {
4255
4623
  workspaceId,
@@ -4261,8 +4629,12 @@ async function planTypes(client, workspaceId, tailordbs, executors, deletedServi
4261
4629
  }
4262
4630
  for (const namespaceName of deletedServices) (await fetchTypes(namespaceName)).forEach((typ) => {
4263
4631
  changeSet.deletes.push({
4264
- tag: "service-deleted",
4265
- name: typ.name
4632
+ name: typ.name,
4633
+ request: {
4634
+ workspaceId,
4635
+ namespaceName,
4636
+ tailordbTypeName: typ.name
4637
+ }
4266
4638
  });
4267
4639
  });
4268
4640
  return changeSet;
@@ -4520,7 +4892,6 @@ async function planGqlPermissions(client, workspaceId, tailordbs, deletedService
4520
4892
  }
4521
4893
  existingNameSet.forEach((name) => {
4522
4894
  changeSet.deletes.push({
4523
- tag: "gql-permission-deleted",
4524
4895
  name,
4525
4896
  request: {
4526
4897
  workspaceId,
@@ -4532,8 +4903,12 @@ async function planGqlPermissions(client, workspaceId, tailordbs, deletedService
4532
4903
  }
4533
4904
  for (const namespaceName of deletedServices) (await fetchGqlPermissions(namespaceName)).forEach((gqlPermission) => {
4534
4905
  changeSet.deletes.push({
4535
- tag: "service-deleted",
4536
- name: gqlPermission.typeName
4906
+ name: gqlPermission.typeName,
4907
+ request: {
4908
+ workspaceId,
4909
+ namespaceName,
4910
+ typeName: gqlPermission.typeName
4911
+ }
4537
4912
  });
4538
4913
  });
4539
4914
  return changeSet;
@@ -4628,6 +5003,7 @@ async function apply(options) {
4628
5003
  const configPath = loadConfigPath(options?.configPath);
4629
5004
  const { config } = await loadConfig(configPath);
4630
5005
  const dryRun = options?.dryRun ?? false;
5006
+ const yes = options?.yes ?? false;
4631
5007
  const buildOnly = options?.buildOnly ?? false;
4632
5008
  await generateUserTypes(config, configPath);
4633
5009
  const application = defineApplication(config);
@@ -4643,13 +5019,66 @@ async function apply(options) {
4643
5019
  workspaceId: options?.workspaceId,
4644
5020
  profile: options?.profile
4645
5021
  });
4646
- const tailorDB = await planTailorDB(client, workspaceId, application);
4647
- const staticWebsite = await planStaticWebsite(client, workspaceId, application);
4648
- const idp = await planIdP(client, workspaceId, application);
4649
- const auth = await planAuth(client, workspaceId, application);
4650
- const pipeline = await planPipeline(client, workspaceId, application);
4651
- const app = await planApplication(client, workspaceId, application);
4652
- const executor = await planExecutor(client, workspaceId, application);
5022
+ for (const tailordb of application.tailorDBServices) await tailordb.loadTypes();
5023
+ for (const pipeline$1 of application.resolverServices) await pipeline$1.loadResolvers();
5024
+ if (application.executorService) await application.executorService.loadExecutors();
5025
+ console.log("");
5026
+ const ctx = {
5027
+ client,
5028
+ workspaceId,
5029
+ application
5030
+ };
5031
+ const tailorDB = await planTailorDB(ctx);
5032
+ const staticWebsite = await planStaticWebsite(ctx);
5033
+ const idp = await planIdP(ctx);
5034
+ const auth = await planAuth(ctx);
5035
+ const pipeline = await planPipeline(ctx);
5036
+ const app = await planApplication(ctx);
5037
+ const executor = await planExecutor(ctx);
5038
+ const allConflicts = [
5039
+ ...tailorDB.conflicts,
5040
+ ...staticWebsite.conflicts,
5041
+ ...idp.conflicts,
5042
+ ...auth.conflicts,
5043
+ ...pipeline.conflicts,
5044
+ ...executor.conflicts
5045
+ ];
5046
+ await confirmOwnerConflict(allConflicts, application.name, yes);
5047
+ const allUnmanaged = [
5048
+ ...tailorDB.unmanaged,
5049
+ ...staticWebsite.unmanaged,
5050
+ ...idp.unmanaged,
5051
+ ...auth.unmanaged,
5052
+ ...pipeline.unmanaged,
5053
+ ...executor.unmanaged
5054
+ ];
5055
+ await confirmUnmanagedResources(allUnmanaged, application.name, yes);
5056
+ const importantDeletions = [];
5057
+ for (const del of tailorDB.changeSet.type.deletes) importantDeletions.push({
5058
+ resourceType: "TailorDB type",
5059
+ resourceName: del.name
5060
+ });
5061
+ for (const del of staticWebsite.changeSet.deletes) importantDeletions.push({
5062
+ resourceType: "StaticWebsite",
5063
+ resourceName: del.name
5064
+ });
5065
+ await confirmImportantResourceDeletion(importantDeletions, yes);
5066
+ const resourceOwners = new Set([
5067
+ ...tailorDB.resourceOwners,
5068
+ ...staticWebsite.resourceOwners,
5069
+ ...idp.resourceOwners,
5070
+ ...auth.resourceOwners,
5071
+ ...pipeline.resourceOwners,
5072
+ ...executor.resourceOwners
5073
+ ]);
5074
+ const emptyApps = [...new Set(allConflicts.map((c) => c.currentOwner))].filter((owner) => !resourceOwners.has(owner));
5075
+ for (const emptyApp of emptyApps) app.deletes.push({
5076
+ name: emptyApp,
5077
+ request: {
5078
+ workspaceId,
5079
+ applicationName: emptyApp
5080
+ }
5081
+ });
4653
5082
  if (dryRun) {
4654
5083
  console.log("Dry run enabled. No changes applied.");
4655
5084
  return;
@@ -4724,6 +5153,11 @@ const applyCommand = defineCommand({
4724
5153
  type: "boolean",
4725
5154
  description: "Run the command without making any changes",
4726
5155
  alias: "d"
5156
+ },
5157
+ yes: {
5158
+ type: "boolean",
5159
+ description: "Skip all confirmation prompts",
5160
+ alias: "y"
4727
5161
  }
4728
5162
  },
4729
5163
  run: withCommonArgs(async (args) => {
@@ -4731,7 +5165,8 @@ const applyCommand = defineCommand({
4731
5165
  workspaceId: args["workspace-id"],
4732
5166
  profile: args.profile,
4733
5167
  configPath: args.config,
4734
- dryRun: args.dryRun
5168
+ dryRun: args.dryRun,
5169
+ yes: args.yes
4735
5170
  });
4736
5171
  })
4737
5172
  });
@@ -5855,4 +6290,4 @@ const tokenCommand = defineCommand({
5855
6290
  });
5856
6291
 
5857
6292
  //#endregion
5858
- export { PATScope, apply, applyCommand, commonArgs, createCommand, deleteCommand, fetchAll, fetchLatestToken, formatArgs, generate, generateCommand, generateUserTypes, initOperatorClient, listCommand, listCommand$1, loadAccessToken, loadConfig, loadConfigPath, loadWorkspaceId, machineUserList, machineUserToken, parseFormat, printWithFormat, readPlatformConfig, show, showCommand, tokenCommand, userAgent, withCommonArgs, workspaceCreate, workspaceDelete, workspaceList, writePlatformConfig };
6293
+ export { PATScope, apply, applyCommand, commonArgs, createCommand, deleteCommand, fetchAll, fetchLatestToken, formatArgs, generate, generateCommand, generateUserTypes, initOperatorClient, listCommand, listCommand$1, loadAccessToken, loadConfig, loadConfigPath, loadWorkspaceId, machineUserList, machineUserToken, parseFormat, printWithFormat, readPackageJson, readPlatformConfig, show, showCommand, tokenCommand, userAgent, withCommonArgs, workspaceCreate, workspaceDelete, workspaceList, writePlatformConfig };