@microagi/alchemy-gcp 0.11.7 → 0.11.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (151) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/lib/ArtifactRegistry/Operations.d.ts +1 -1
  3. package/lib/ArtifactRegistry/Repository.d.ts +2 -2
  4. package/lib/ArtifactRegistry/Repository.d.ts.map +1 -1
  5. package/lib/ArtifactRegistry/Repository.js +5 -5
  6. package/lib/ArtifactRegistry/Repository.js.map +1 -1
  7. package/lib/ArtifactRegistry/RepositoryIamMember.d.ts +2 -1
  8. package/lib/ArtifactRegistry/RepositoryIamMember.d.ts.map +1 -1
  9. package/lib/ArtifactRegistry/RepositoryIamMember.js +1 -1
  10. package/lib/CloudResourceManager/Project.d.ts +2 -1
  11. package/lib/CloudResourceManager/Project.d.ts.map +1 -1
  12. package/lib/CloudResourceManager/Project.js +6 -6
  13. package/lib/CloudResourceManager/Project.js.map +1 -1
  14. package/lib/Compute/Address.d.ts +2 -1
  15. package/lib/Compute/Address.d.ts.map +1 -1
  16. package/lib/Compute/Address.js +4 -4
  17. package/lib/Compute/Address.js.map +1 -1
  18. package/lib/Compute/Firewall.d.ts +2 -1
  19. package/lib/Compute/Firewall.d.ts.map +1 -1
  20. package/lib/Compute/Firewall.js +1 -1
  21. package/lib/Compute/ForwardingRule.d.ts +2 -1
  22. package/lib/Compute/ForwardingRule.d.ts.map +1 -1
  23. package/lib/Compute/ForwardingRule.js +4 -4
  24. package/lib/Compute/ForwardingRule.js.map +1 -1
  25. package/lib/Compute/GlobalAddress.d.ts +2 -1
  26. package/lib/Compute/GlobalAddress.d.ts.map +1 -1
  27. package/lib/Compute/GlobalAddress.js +4 -4
  28. package/lib/Compute/GlobalAddress.js.map +1 -1
  29. package/lib/Compute/Network.d.ts +2 -1
  30. package/lib/Compute/Network.d.ts.map +1 -1
  31. package/lib/Compute/Network.js +1 -1
  32. package/lib/Compute/Operations.d.ts +1 -1
  33. package/lib/Compute/ProjectDefaultNetworkTier.d.ts +2 -1
  34. package/lib/Compute/ProjectDefaultNetworkTier.d.ts.map +1 -1
  35. package/lib/Compute/ProjectDefaultNetworkTier.js +1 -1
  36. package/lib/Compute/SharedVpcHost.d.ts +2 -1
  37. package/lib/Compute/SharedVpcHost.d.ts.map +1 -1
  38. package/lib/Compute/SharedVpcHost.js +1 -1
  39. package/lib/Compute/SharedVpcServiceProject.d.ts +2 -1
  40. package/lib/Compute/SharedVpcServiceProject.d.ts.map +1 -1
  41. package/lib/Compute/SharedVpcServiceProject.js +1 -1
  42. package/lib/Compute/Subnetwork.d.ts +2 -1
  43. package/lib/Compute/Subnetwork.d.ts.map +1 -1
  44. package/lib/Compute/Subnetwork.js +2 -2
  45. package/lib/Compute/Subnetwork.js.map +1 -1
  46. package/lib/Container/Cluster.d.ts +4 -2
  47. package/lib/Container/Cluster.d.ts.map +1 -1
  48. package/lib/Container/Cluster.js +28 -10
  49. package/lib/Container/Cluster.js.map +1 -1
  50. package/lib/Container/NodePool.d.ts +2 -2
  51. package/lib/Container/NodePool.d.ts.map +1 -1
  52. package/lib/Container/NodePool.js +22 -12
  53. package/lib/Container/NodePool.js.map +1 -1
  54. package/lib/Container/Operations.d.ts +1 -1
  55. package/lib/Iam/Operations.d.ts +1 -1
  56. package/lib/Iam/ServiceAccount.d.ts +2 -1
  57. package/lib/Iam/ServiceAccount.d.ts.map +1 -1
  58. package/lib/Iam/ServiceAccount.js +1 -1
  59. package/lib/Iam/ServiceAccountKey.d.ts +2 -1
  60. package/lib/Iam/ServiceAccountKey.d.ts.map +1 -1
  61. package/lib/Iam/ServiceAccountKey.js +1 -1
  62. package/lib/Iam/WorkloadIdentityPool.d.ts +2 -1
  63. package/lib/Iam/WorkloadIdentityPool.d.ts.map +1 -1
  64. package/lib/Iam/WorkloadIdentityPool.js +1 -1
  65. package/lib/Iam/WorkloadIdentityPoolProvider.d.ts +2 -1
  66. package/lib/Iam/WorkloadIdentityPoolProvider.d.ts.map +1 -1
  67. package/lib/Iam/WorkloadIdentityPoolProvider.js +4 -4
  68. package/lib/Iam/WorkloadIdentityPoolProvider.js.map +1 -1
  69. package/lib/Kubernetes/Secret.d.ts.map +1 -1
  70. package/lib/Kubernetes/Secret.js.map +1 -1
  71. package/lib/ManagedLustre/Instance.d.ts +2 -1
  72. package/lib/ManagedLustre/Instance.d.ts.map +1 -1
  73. package/lib/ManagedLustre/Instance.js +6 -6
  74. package/lib/ManagedLustre/Instance.js.map +1 -1
  75. package/lib/Run/IamSync.d.ts +1 -1
  76. package/lib/Run/Job.d.ts +3 -3
  77. package/lib/Run/Job.d.ts.map +1 -1
  78. package/lib/Run/Job.js +5 -5
  79. package/lib/Run/Job.js.map +1 -1
  80. package/lib/Run/Operations.d.ts +1 -1
  81. package/lib/Run/Service.d.ts +2 -2
  82. package/lib/Run/Service.d.ts.map +1 -1
  83. package/lib/Run/Service.js +9 -7
  84. package/lib/Run/Service.js.map +1 -1
  85. package/lib/Run/index.d.ts +2 -2
  86. package/lib/ServiceNetworking/PsaConnection.d.ts +2 -1
  87. package/lib/ServiceNetworking/PsaConnection.d.ts.map +1 -1
  88. package/lib/ServiceNetworking/PsaConnection.js +1 -1
  89. package/lib/ServiceUsage/ApiEnable.d.ts +2 -1
  90. package/lib/ServiceUsage/ApiEnable.d.ts.map +1 -1
  91. package/lib/ServiceUsage/ApiEnable.js +1 -1
  92. package/lib/Sqladmin/Database.d.ts +2 -1
  93. package/lib/Sqladmin/Database.d.ts.map +1 -1
  94. package/lib/Sqladmin/Database.js +1 -1
  95. package/lib/Sqladmin/Instance.d.ts +2 -1
  96. package/lib/Sqladmin/Instance.d.ts.map +1 -1
  97. package/lib/Sqladmin/Instance.js +7 -7
  98. package/lib/Sqladmin/Instance.js.map +1 -1
  99. package/lib/Sqladmin/Operations.d.ts +1 -1
  100. package/lib/Sqladmin/User.d.ts +2 -1
  101. package/lib/Sqladmin/User.d.ts.map +1 -1
  102. package/lib/Sqladmin/User.js +1 -1
  103. package/lib/Storage/Bucket.d.ts +2 -2
  104. package/lib/Storage/Bucket.d.ts.map +1 -1
  105. package/lib/Storage/Bucket.js +1 -1
  106. package/lib/Storage/StorageBucketIamMember.d.ts +2 -1
  107. package/lib/Storage/StorageBucketIamMember.d.ts.map +1 -1
  108. package/lib/Storage/StorageBucketIamMember.js +1 -1
  109. package/lib/Tags.d.ts +3 -1
  110. package/lib/Tags.d.ts.map +1 -1
  111. package/lib/Tags.js +9 -1
  112. package/lib/Tags.js.map +1 -1
  113. package/package.json +9 -9
  114. package/src/ArtifactRegistry/Operations.ts +1 -1
  115. package/src/ArtifactRegistry/Repository.ts +5 -5
  116. package/src/ArtifactRegistry/RepositoryIamMember.ts +1 -1
  117. package/src/CloudResourceManager/Project.ts +6 -6
  118. package/src/Compute/Address.ts +4 -4
  119. package/src/Compute/Firewall.ts +1 -1
  120. package/src/Compute/ForwardingRule.ts +4 -4
  121. package/src/Compute/GlobalAddress.ts +4 -4
  122. package/src/Compute/Network.ts +1 -1
  123. package/src/Compute/Operations.ts +1 -1
  124. package/src/Compute/ProjectDefaultNetworkTier.ts +1 -1
  125. package/src/Compute/SharedVpcHost.ts +1 -1
  126. package/src/Compute/SharedVpcServiceProject.ts +1 -1
  127. package/src/Compute/Subnetwork.ts +2 -2
  128. package/src/Container/Cluster.ts +36 -11
  129. package/src/Container/NodePool.ts +30 -13
  130. package/src/Container/Operations.ts +1 -1
  131. package/src/Iam/Operations.ts +1 -1
  132. package/src/Iam/ServiceAccount.ts +1 -1
  133. package/src/Iam/ServiceAccountKey.ts +1 -1
  134. package/src/Iam/WorkloadIdentityPool.ts +1 -1
  135. package/src/Iam/WorkloadIdentityPoolProvider.ts +7 -3
  136. package/src/Kubernetes/Secret.ts +4 -1
  137. package/src/ManagedLustre/Instance.ts +6 -6
  138. package/src/Run/IamSync.ts +1 -1
  139. package/src/Run/Job.ts +6 -6
  140. package/src/Run/Operations.ts +1 -1
  141. package/src/Run/Service.ts +9 -7
  142. package/src/Run/index.ts +2 -2
  143. package/src/ServiceNetworking/PsaConnection.ts +1 -1
  144. package/src/ServiceUsage/ApiEnable.ts +1 -1
  145. package/src/Sqladmin/Database.ts +1 -1
  146. package/src/Sqladmin/Instance.ts +13 -7
  147. package/src/Sqladmin/Operations.ts +1 -1
  148. package/src/Sqladmin/User.ts +1 -1
  149. package/src/Storage/Bucket.ts +1 -1
  150. package/src/Storage/StorageBucketIamMember.ts +1 -1
  151. package/src/Tags.ts +16 -1
@@ -123,7 +123,10 @@ type SecretObject = {
123
123
  namespace?: string;
124
124
  uid?: string;
125
125
  resourceVersion?: string;
126
- labels?: Record<string, string>;
126
+ // Distilled's generated `…ObjectMetaLabelsMap` index signature includes
127
+ // `undefined`, so the observed object is only assignable to this local
128
+ // subset if we mirror that.
129
+ labels?: Record<string, string | undefined>;
127
130
  };
128
131
  type?: string;
129
132
  };
@@ -1,5 +1,5 @@
1
1
  import { ConfigError } from "@distilled.cloud/gcp";
2
- import * as lustre from "@distilled.cloud/gcp/lustre-v1";
2
+ import * as lustre from "@distilled.cloud/gcp/lustre_v1";
3
3
  import { Resource } from "alchemy";
4
4
  import { Unowned } from "alchemy/AdoptPolicy";
5
5
  import type { ScopedPlanStatusSession } from "alchemy/Cli/Cli";
@@ -11,7 +11,7 @@ import * as Duration from "effect/Duration";
11
11
  import * as Effect from "effect/Effect";
12
12
  import * as Schedule from "effect/Schedule";
13
13
  import type { NetworkRefById } from "../Compute/Network.ts";
14
- import { gcpInternalLabels, hasAlchemyLabels } from "../Tags.ts";
14
+ import { gcpInternalLabels, hasAlchemyLabels, normalizeStringMap } from "../Tags.ts";
15
15
  import type * as GCP from "../Providers.ts";
16
16
 
17
17
  /**
@@ -221,7 +221,7 @@ const toAttributes = (
221
221
  perUnitStorageThroughput: i.perUnitStorageThroughput,
222
222
  gkeSupportEnabled: i.gkeSupportEnabled,
223
223
  kmsKey: i.kmsKey,
224
- labels: { ...(i.labels ?? {}) },
224
+ labels: normalizeStringMap(i.labels) ?? {},
225
225
  });
226
226
 
227
227
  export const ManagedLustreInstanceProvider = () =>
@@ -295,7 +295,7 @@ export const ManagedLustreInstanceProvider = () =>
295
295
  if ((args.observed.description ?? undefined) !== args.desired.description) {
296
296
  updateMaskFields.push("description");
297
297
  }
298
- const observedLabels = { ...(args.observed.labels ?? {}) };
298
+ const observedLabels = normalizeStringMap(args.observed.labels) ?? {};
299
299
  const labelDiff = diffTags(observedLabels, args.desired.labels);
300
300
  if (labelDiff.removed.length > 0 || labelDiff.upsert.length > 0) {
301
301
  updateMaskFields.push("labels");
@@ -434,7 +434,7 @@ export const ManagedLustreInstanceProvider = () =>
434
434
  ),
435
435
  );
436
436
  for (const candidate of page?.instances ?? []) {
437
- if (yield* hasAlchemyLabels(id, candidate.labels)) {
437
+ if (yield* hasAlchemyLabels(id, normalizeStringMap(candidate.labels))) {
438
438
  observed = candidate;
439
439
  break;
440
440
  }
@@ -450,7 +450,7 @@ export const ManagedLustreInstanceProvider = () =>
450
450
  instanceId,
451
451
  network,
452
452
  });
453
- return (yield* hasAlchemyLabels(id, observed.labels))
453
+ return (yield* hasAlchemyLabels(id, normalizeStringMap(observed.labels)))
454
454
  ? attrs
455
455
  : Unowned(attrs);
456
456
  }),
@@ -1,4 +1,4 @@
1
- import type * as run from "@distilled.cloud/gcp/run-v2";
1
+ import type * as run from "@distilled.cloud/gcp/run_v2";
2
2
  import type { ResourceBinding } from "alchemy/Resource";
3
3
  import * as Duration from "effect/Duration";
4
4
  import * as Effect from "effect/Effect";
package/src/Run/Job.ts CHANGED
@@ -1,4 +1,4 @@
1
- import * as run from "@distilled.cloud/gcp/run-v2";
1
+ import * as run from "@distilled.cloud/gcp/run_v2";
2
2
  import { Resource } from "alchemy";
3
3
  import { Unowned } from "alchemy/AdoptPolicy";
4
4
  import type { ScopedPlanStatusSession } from "alchemy/Cli/Cli";
@@ -10,7 +10,7 @@ import * as Duration from "effect/Duration";
10
10
  import * as Effect from "effect/Effect";
11
11
  import * as Schedule from "effect/Schedule";
12
12
  import type * as GCP from "../Providers.ts";
13
- import { gcpInternalLabels, hasAlchemyLabels } from "../Tags.ts";
13
+ import { gcpInternalLabels, hasAlchemyLabels, normalizeStringMap } from "../Tags.ts";
14
14
  import { makeSyncIam, type RunIamBindingContract } from "./IamSync.ts";
15
15
  import { makeAwaitOperation } from "./Operations.ts";
16
16
  import {
@@ -34,7 +34,7 @@ import {
34
34
  * converge-to-desired-state model) and is left to user-side code:
35
35
  *
36
36
  * ```typescript
37
- * import * as run from "@distilled.cloud/gcp/run-v2";
37
+ * import * as run from "@distilled.cloud/gcp/run_v2";
38
38
  * const job = yield* GCP.Job("Nightly", { ... });
39
39
  * const runJob = yield* run.runProjectsLocationsJobs;
40
40
  * yield* runJob({
@@ -234,7 +234,7 @@ const toAttributes = (
234
234
  latestCreatedExecution: j.latestCreatedExecution,
235
235
  reconciling: j.reconciling,
236
236
  etag: j.etag,
237
- labels: { ...(j.labels ?? {}) },
237
+ labels: normalizeStringMap(j.labels) ?? {},
238
238
  createTime: j.createTime,
239
239
  updateTime: j.updateTime,
240
240
  });
@@ -260,7 +260,7 @@ const jobMutated = (
260
260
  desiredLabels: Record<string, string>,
261
261
  ): boolean => {
262
262
  const labelDiff = diffTags(
263
- { ...(observed.labels ?? {}) },
263
+ normalizeStringMap(observed.labels) ?? {},
264
264
  desiredLabels,
265
265
  );
266
266
  if (labelDiff.removed.length > 0 || labelDiff.upsert.length > 0) return true;
@@ -448,7 +448,7 @@ export const JobProvider = () =>
448
448
  const observed = yield* observe(project, location, name);
449
449
  if (!observed) return undefined;
450
450
  const attrs = toAttributes(observed, { project, location, name });
451
- return (yield* hasAlchemyLabels(id, observed.labels))
451
+ return (yield* hasAlchemyLabels(id, normalizeStringMap(observed.labels)))
452
452
  ? attrs
453
453
  : Unowned(attrs);
454
454
  }),
@@ -1,5 +1,5 @@
1
1
  import { ConfigError } from "@distilled.cloud/gcp";
2
- import * as run from "@distilled.cloud/gcp/run-v2";
2
+ import * as run from "@distilled.cloud/gcp/run_v2";
3
3
  import type { ScopedPlanStatusSession } from "alchemy/Cli/Cli";
4
4
  import * as Duration from "effect/Duration";
5
5
  import * as Effect from "effect/Effect";
@@ -1,4 +1,4 @@
1
- import * as run from "@distilled.cloud/gcp/run-v2";
1
+ import * as run from "@distilled.cloud/gcp/run_v2";
2
2
  import { Resource } from "alchemy";
3
3
  import { Unowned } from "alchemy/AdoptPolicy";
4
4
  import type { ScopedPlanStatusSession } from "alchemy/Cli/Cli";
@@ -10,7 +10,7 @@ import * as Duration from "effect/Duration";
10
10
  import * as Effect from "effect/Effect";
11
11
  import * as Schedule from "effect/Schedule";
12
12
  import type * as GCP from "../Providers.ts";
13
- import { gcpInternalLabels, hasAlchemyLabels } from "../Tags.ts";
13
+ import { gcpInternalLabels, hasAlchemyLabels, normalizeStringMap } from "../Tags.ts";
14
14
  import { makeSyncIam, type RunIamBindingContract } from "./IamSync.ts";
15
15
  import { makeAwaitOperation } from "./Operations.ts";
16
16
  import {
@@ -245,8 +245,10 @@ const toServiceBody = (
245
245
  ? { defaultUriDisabled: news.defaultUriDisabled }
246
246
  : {}),
247
247
  ...(news.scaling ? { scaling: news.scaling } : {}),
248
- ...(news.traffic ? { traffic: news.traffic } : {}),
249
- ...(news.customAudiences ? { customAudiences: news.customAudiences } : {}),
248
+ ...(news.traffic ? { traffic: [...news.traffic] } : {}),
249
+ ...(news.customAudiences
250
+ ? { customAudiences: [...news.customAudiences] }
251
+ : {}),
250
252
  ...(news.binaryAuthorization
251
253
  ? { binaryAuthorization: news.binaryAuthorization }
252
254
  : {}),
@@ -271,7 +273,7 @@ const toAttributes = (
271
273
  terminalCondition: s.terminalCondition,
272
274
  trafficStatuses: s.trafficStatuses ?? [],
273
275
  etag: s.etag,
274
- labels: { ...(s.labels ?? {}) },
276
+ labels: normalizeStringMap(s.labels) ?? {},
275
277
  createTime: s.createTime,
276
278
  updateTime: s.updateTime,
277
279
  });
@@ -314,7 +316,7 @@ export const ServiceProvider = () =>
314
316
  updateMaskFields.push("description");
315
317
  }
316
318
  const labelDiff = diffTags(
317
- { ...(args.observed.labels ?? {}) },
319
+ normalizeStringMap(args.observed.labels) ?? {},
318
320
  args.desiredLabels,
319
321
  );
320
322
  if (labelDiff.removed.length > 0 || labelDiff.upsert.length > 0) {
@@ -536,7 +538,7 @@ export const ServiceProvider = () =>
536
538
  const observed = yield* observe(project, location, name);
537
539
  if (!observed) return undefined;
538
540
  const attrs = toAttributes(observed, { project, location, name });
539
- return (yield* hasAlchemyLabels(id, observed.labels))
541
+ return (yield* hasAlchemyLabels(id, normalizeStringMap(observed.labels)))
540
542
  ? attrs
541
543
  : Unowned(attrs);
542
544
  }),
package/src/Run/index.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type * as run from "@distilled.cloud/gcp/run-v2";
1
+ import type * as run from "@distilled.cloud/gcp/run_v2";
2
2
 
3
3
  export { Job, JobProvider } from "./Job.ts";
4
4
  export type { JobAttributes, JobProps } from "./Job.ts";
@@ -9,7 +9,7 @@ export type { ServiceAttributes, ServiceProps } from "./Service.ts";
9
9
 
10
10
  /**
11
11
  * Clean aliases for the most commonly-used Cloud Run v2 SDK types,
12
- * re-exported from `@distilled.cloud/gcp/run-v2` so consumers don't
12
+ * re-exported from `@distilled.cloud/gcp/run_v2` so consumers don't
13
13
  * need to import from the underlying SDK directly. The aliases are
14
14
  * type-only — they share identity with the distilled types, so values
15
15
  * are interchangeable.
@@ -1,5 +1,5 @@
1
1
  import { ConfigError } from "@distilled.cloud/gcp";
2
- import * as sn from "@distilled.cloud/gcp/servicenetworking-v1";
2
+ import * as sn from "@distilled.cloud/gcp/servicenetworking_v1";
3
3
  import { Resource } from "alchemy";
4
4
  import type { ScopedPlanStatusSession } from "alchemy/Cli/Cli";
5
5
  import { deepEqual, isResolved } from "alchemy/Diff";
@@ -1,5 +1,5 @@
1
1
  import { ConfigError } from "@distilled.cloud/gcp";
2
- import * as su from "@distilled.cloud/gcp/serviceusage-v1";
2
+ import * as su from "@distilled.cloud/gcp/serviceusage_v1";
3
3
  import { Resource } from "alchemy";
4
4
  import type { ScopedPlanStatusSession } from "alchemy/Cli/Cli";
5
5
  import { isResolved } from "alchemy/Diff";
@@ -1,4 +1,4 @@
1
- import * as sql from "@distilled.cloud/gcp/sqladmin-v1";
1
+ import * as sql from "@distilled.cloud/gcp/sqladmin_v1";
2
2
  import { Resource } from "alchemy";
3
3
  import { isResolved, somePropsAreDifferent } from "alchemy/Diff";
4
4
  import * as Provider from "alchemy/Provider";
@@ -1,4 +1,4 @@
1
- import * as sql from "@distilled.cloud/gcp/sqladmin-v1";
1
+ import * as sql from "@distilled.cloud/gcp/sqladmin_v1";
2
2
  import { Resource } from "alchemy";
3
3
  import { Unowned } from "alchemy/AdoptPolicy";
4
4
  import type { ScopedPlanStatusSession } from "alchemy/Cli/Cli";
@@ -11,7 +11,7 @@ import * as Effect from "effect/Effect";
11
11
  import * as Redacted from "effect/Redacted";
12
12
  import * as Schedule from "effect/Schedule";
13
13
  import type * as GCP from "../Providers.ts";
14
- import { gcpInternalLabels, hasAlchemyLabels } from "../Tags.ts";
14
+ import { gcpInternalLabels, hasAlchemyLabels, normalizeStringMap } from "../Tags.ts";
15
15
  import { makeAwaitOperation } from "./Operations.ts";
16
16
  import type {
17
17
  PostgresVersion,
@@ -289,7 +289,7 @@ const toAttributes = (
289
289
  }
290
290
  : undefined,
291
291
  settingsVersion: i.settings?.settingsVersion,
292
- labels: { ...(i.settings?.userLabels ?? {}) },
292
+ labels: normalizeStringMap(i.settings?.userLabels) ?? {},
293
293
  };
294
294
  };
295
295
 
@@ -341,7 +341,7 @@ const toSettingsBody = (
341
341
  }
342
342
  : {}),
343
343
  ...(s.backupConfiguration ? { backupConfiguration: s.backupConfiguration } : {}),
344
- ...(s.databaseFlags ? { databaseFlags: s.databaseFlags } : {}),
344
+ ...(s.databaseFlags ? { databaseFlags: [...s.databaseFlags] } : {}),
345
345
  ...(s.deletionProtectionEnabled !== undefined
346
346
  ? { deletionProtectionEnabled: s.deletionProtectionEnabled }
347
347
  : {}),
@@ -454,7 +454,7 @@ export const SqlInstanceProvider = () =>
454
454
  );
455
455
 
456
456
  const labelDiff = diffTags(
457
- { ...(obsSettings.userLabels ?? {}) },
457
+ normalizeStringMap(obsSettings.userLabels) ?? {},
458
458
  args.desiredLabels,
459
459
  );
460
460
  if (labelDiff.removed.length > 0 || labelDiff.upsert.length > 0) {
@@ -631,7 +631,10 @@ export const SqlInstanceProvider = () =>
631
631
  );
632
632
  for (const candidate of page?.items ?? []) {
633
633
  if (
634
- yield* hasAlchemyLabels(id, candidate.settings?.userLabels)
634
+ yield* hasAlchemyLabels(
635
+ id,
636
+ normalizeStringMap(candidate.settings?.userLabels),
637
+ )
635
638
  ) {
636
639
  observed = candidate;
637
640
  break;
@@ -644,7 +647,10 @@ export const SqlInstanceProvider = () =>
644
647
  region,
645
648
  name: observed.name,
646
649
  });
647
- return (yield* hasAlchemyLabels(id, observed.settings?.userLabels))
650
+ return (yield* hasAlchemyLabels(
651
+ id,
652
+ normalizeStringMap(observed.settings?.userLabels),
653
+ ))
648
654
  ? attrs
649
655
  : Unowned(attrs);
650
656
  }),
@@ -1,5 +1,5 @@
1
1
  import { ConfigError } from "@distilled.cloud/gcp";
2
- import * as sql from "@distilled.cloud/gcp/sqladmin-v1";
2
+ import * as sql from "@distilled.cloud/gcp/sqladmin_v1";
3
3
  import type { ScopedPlanStatusSession } from "alchemy/Cli/Cli";
4
4
  import * as Duration from "effect/Duration";
5
5
  import * as Effect from "effect/Effect";
@@ -1,4 +1,4 @@
1
- import * as sql from "@distilled.cloud/gcp/sqladmin-v1";
1
+ import * as sql from "@distilled.cloud/gcp/sqladmin_v1";
2
2
  import { Resource } from "alchemy";
3
3
  import { isResolved, somePropsAreDifferent } from "alchemy/Diff";
4
4
  import * as Provider from "alchemy/Provider";
@@ -1,5 +1,5 @@
1
1
  import { ConfigError } from "@distilled.cloud/gcp";
2
- import * as storage from "@distilled.cloud/gcp/storage-v1";
2
+ import * as storage from "@distilled.cloud/gcp/storage_v1";
3
3
  import { Resource } from "alchemy";
4
4
  import { Unowned } from "alchemy/AdoptPolicy";
5
5
  import { isResolved } from "alchemy/Diff";
@@ -1,5 +1,5 @@
1
1
  import { ConfigError } from "@distilled.cloud/gcp";
2
- import * as storage from "@distilled.cloud/gcp/storage-v1";
2
+ import * as storage from "@distilled.cloud/gcp/storage_v1";
3
3
  import { Resource } from "alchemy";
4
4
  import { isResolved } from "alchemy/Diff";
5
5
  import * as Provider from "alchemy/Provider";
package/src/Tags.ts CHANGED
@@ -28,6 +28,18 @@ const sanitizeLabelValue = (raw: string): string => {
28
28
  return replaced.slice(0, 63);
29
29
  };
30
30
 
31
+ /** Normalize an SDK string map by omitting absent values at the boundary. */
32
+ export const normalizeStringMap = (
33
+ value: Record<string, string | undefined> | undefined,
34
+ ): Record<string, string> | undefined =>
35
+ value === undefined
36
+ ? undefined
37
+ : Object.fromEntries(
38
+ Object.entries(value).filter(
39
+ (entry): entry is [string, string] => entry[1] !== undefined,
40
+ ),
41
+ );
42
+
31
43
  /**
32
44
  * Compute the alchemy-internal label set for a Resource. Merge the
33
45
  * result with user-provided labels (user wins on key collision is
@@ -50,7 +62,10 @@ export const gcpInternalLabels = Effect.fnUntraced(function* (id: string) {
50
62
  */
51
63
  export const hasAlchemyLabels = Effect.fnUntraced(function* (
52
64
  id: string,
53
- labels: Record<string, string> | undefined,
65
+ // Distilled's generated Kubernetes/GCP map types have index signatures that
66
+ // include `undefined` (`{ [k: string]: string | undefined }`), so accept the
67
+ // wider shape — the equality checks below are unaffected.
68
+ labels: Record<string, string | undefined> | undefined,
54
69
  ) {
55
70
  if (!labels) return false;
56
71
  const expected = yield* gcpInternalLabels(id);