@alienplatform/core 3.3.11 → 3.3.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -4563,7 +4563,7 @@ z$2.object({
4563
4563
  * Do not edit manually.
4564
4564
  */
4565
4565
  /**
4566
- * @description Email infrastructure for sending and receiving mail on customer-owned\ndomains. On AWS this is backed by SES: a shared configuration set, optional\ninbound/event wiring, and one email identity (Easy DKIM) per seed domain.\n\n# Infrastructure vs runtime data\n\nThis resource owns the email *infrastructure* and the capability to use it,\nnot the domain lifecycle. Deployment manages the configuration set, the\nevent topology, the inbound receipt topology, and any seed identities\nlisted in `domains`. Email identities created at runtime through the\n`email/manage-identities` grant are application data: they are not tracked\nby the deployment, are not removed when the stack is deleted, and their\nlifecycle — including deletion — belongs to the application.\n\nThe operator (or the application, for runtime-created identities) owns DNS:\nthe per-domain DKIM CNAME records surfaced in [`EmailOutputs`] must be\ncreated before SES verifies a domain and allows sending from it.\n\n# Inbound mail (AWS)\n\nWhen `inbound` is set, a SES receipt rule set is provisioned that writes\nraw incoming mail into the linked Storage bucket. The receipt rule is a\ncatch-all (no recipient filter), so mail for identities verified at runtime\nlands in the bucket without any infrastructure change.\n\nAlien activates the provisioned receipt rule set as part of setup. Because\nSES permits only one active receipt rule set per AWS account and region, an\nAWS stack may contain only one email resource with inbound delivery, and\ninstalling it makes its rule set the account\'s active rule set. SES email\nreceiving is available only in a subset of AWS regions; deploying `inbound`\nto an unsupported region fails during setup.\n\n# Update semantics\n\n`domains` is append-friendly: adding a domain provisions a new identity,\nremoving a domain deletes its identity (and its DKIM verification state).\nThe list may be empty. `inbound` and `events` may be added, removed, or\nrepointed; removing them tears down the corresponding receipt rule set /\nevent destination wiring.
4566
+ * @description Email infrastructure for sending and receiving mail on customer-owned\ndomains. On AWS this is backed by SES: a shared configuration set, optional\ninbound/event wiring, and one email identity (Easy DKIM) per seed domain.\n\n# Infrastructure vs runtime data\n\nThis resource owns the email *infrastructure* and the capability to use it,\nnot the domain lifecycle. Deployment manages the configuration set, the\nevent topology, the inbound receipt topology, and any seed identities\nlisted in `domains`. Email identities created at runtime through the\n`email/manage-identities` grant are application data: they are not tracked\nby the deployment, are not removed when the stack is deleted, and their\nlifecycle — including deletion — belongs to the application.\n\nThe operator (or the application, for runtime-created identities) owns DNS:\nthe per-domain DKIM CNAME records surfaced in [`EmailOutputs`] must be\ncreated before SES verifies a domain and allows sending from it.\n\n# Inbound mail (AWS)\n\nWhen `inbound` is set, a SES receipt rule set is provisioned that writes\nraw incoming mail into the linked Storage bucket. The receipt rule is a\ncatch-all (no recipient filter), so mail for identities verified at runtime\nlands in the bucket without any infrastructure change.\n\nAlien activates the provisioned receipt rule set as part of setup. Because\nSES permits only one active receipt rule set per AWS account and region, an\nAWS stack may contain only one email resource with inbound delivery. The\nresource requires exclusive ownership of SES receiving in its account and\nregion: setup refuses to replace an active rule set it does not own. Choose\nan unused region when the account already receives email through SES. SES email\nreceiving is available only in a subset of AWS regions; deploying `inbound`\nto an unsupported region fails during setup.\n\n# Update semantics\n\n`domains` is append-friendly: adding a domain provisions a new identity,\nremoving a domain deletes its identity (and its DKIM verification state).\nThe list may be empty. `inbound` and `events` may be added, removed, or\nrepointed; removing them tears down the corresponding receipt rule set /\nevent destination wiring.
4567
4567
  */
4568
4568
  const EmailSchema = z$2.object({
4569
4569
  "domains": z$2.optional(z$2.array(z$2.string()).describe("Seed mail domains provisioned at deploy time (one SES identity each).\nUseful for day-0 bootstrap and products with a static domain set.\nMay be empty (the default): products that create and verify domains\ndynamically should manage identities at runtime through the\n`email/manage-identities` grant instead of listing them here.")),
@@ -4574,7 +4574,7 @@ const EmailSchema = z$2.object({
4574
4574
  get "inbound"() {
4575
4575
  return z$2.union([EmailInboundSchema, z$2.null()]).optional();
4576
4576
  }
4577
- }).describe("Email infrastructure for sending and receiving mail on customer-owned\ndomains. On AWS this is backed by SES: a shared configuration set, optional\ninbound/event wiring, and one email identity (Easy DKIM) per seed domain.\n\n# Infrastructure vs runtime data\n\nThis resource owns the email *infrastructure* and the capability to use it,\nnot the domain lifecycle. Deployment manages the configuration set, the\nevent topology, the inbound receipt topology, and any seed identities\nlisted in `domains`. Email identities created at runtime through the\n`email/manage-identities` grant are application data: they are not tracked\nby the deployment, are not removed when the stack is deleted, and their\nlifecycle — including deletion — belongs to the application.\n\nThe operator (or the application, for runtime-created identities) owns DNS:\nthe per-domain DKIM CNAME records surfaced in [`EmailOutputs`] must be\ncreated before SES verifies a domain and allows sending from it.\n\n# Inbound mail (AWS)\n\nWhen `inbound` is set, a SES receipt rule set is provisioned that writes\nraw incoming mail into the linked Storage bucket. The receipt rule is a\ncatch-all (no recipient filter), so mail for identities verified at runtime\nlands in the bucket without any infrastructure change.\n\nAlien activates the provisioned receipt rule set as part of setup. Because\nSES permits only one active receipt rule set per AWS account and region, an\nAWS stack may contain only one email resource with inbound delivery, and\ninstalling it makes its rule set the account's active rule set. SES email\nreceiving is available only in a subset of AWS regions; deploying `inbound`\nto an unsupported region fails during setup.\n\n# Update semantics\n\n`domains` is append-friendly: adding a domain provisions a new identity,\nremoving a domain deletes its identity (and its DKIM verification state).\nThe list may be empty. `inbound` and `events` may be added, removed, or\nrepointed; removing them tears down the corresponding receipt rule set /\nevent destination wiring.");
4577
+ }).describe("Email infrastructure for sending and receiving mail on customer-owned\ndomains. On AWS this is backed by SES: a shared configuration set, optional\ninbound/event wiring, and one email identity (Easy DKIM) per seed domain.\n\n# Infrastructure vs runtime data\n\nThis resource owns the email *infrastructure* and the capability to use it,\nnot the domain lifecycle. Deployment manages the configuration set, the\nevent topology, the inbound receipt topology, and any seed identities\nlisted in `domains`. Email identities created at runtime through the\n`email/manage-identities` grant are application data: they are not tracked\nby the deployment, are not removed when the stack is deleted, and their\nlifecycle — including deletion — belongs to the application.\n\nThe operator (or the application, for runtime-created identities) owns DNS:\nthe per-domain DKIM CNAME records surfaced in [`EmailOutputs`] must be\ncreated before SES verifies a domain and allows sending from it.\n\n# Inbound mail (AWS)\n\nWhen `inbound` is set, a SES receipt rule set is provisioned that writes\nraw incoming mail into the linked Storage bucket. The receipt rule is a\ncatch-all (no recipient filter), so mail for identities verified at runtime\nlands in the bucket without any infrastructure change.\n\nAlien activates the provisioned receipt rule set as part of setup. Because\nSES permits only one active receipt rule set per AWS account and region, an\nAWS stack may contain only one email resource with inbound delivery. The\nresource requires exclusive ownership of SES receiving in its account and\nregion: setup refuses to replace an active rule set it does not own. Choose\nan unused region when the account already receives email through SES. SES email\nreceiving is available only in a subset of AWS regions; deploying `inbound`\nto an unsupported region fails during setup.\n\n# Update semantics\n\n`domains` is append-friendly: adding a domain provisions a new identity,\nremoving a domain deletes its identity (and its DKIM verification state).\nThe list may be empty. `inbound` and `events` may be added, removed, or\nrepointed; removing them tears down the corresponding receipt rule set /\nevent destination wiring.");
4578
4578
  //#endregion
4579
4579
  //#region src/generated/zod/response-handling-schema.ts
4580
4580
  /**
@@ -5242,7 +5242,7 @@ const ImportedResourceSchema = z$2.object({
5242
5242
  * @description Certificate publication or reference mode for Kubernetes public endpoints.
5243
5243
  */
5244
5244
  const KubernetesCertificateModeSchema = z$2.union([
5245
- z$2.lazy(() => KubernetesTlsSecretRefSchema).and(z$2.object({ "mode": z$2.enum(["tlsSecretRef"]) })),
5245
+ z$2.lazy(() => KubernetesTlsSecretRefSchema).and(z$2.object({ "mode": z$2.enum(["tlsSecretRef"]) })).describe("Namespace-scoped Kubernetes TLS Secret reference."),
5246
5246
  z$2.object({
5247
5247
  "mode": z$2.enum(["managedAcmImport"]),
5248
5248
  "region": z$2.string().describe("ACM region. Defaults to the deployment region when omitted.").nullish(),
@@ -5483,7 +5483,7 @@ const KubernetesIngressRouteProfileSchema = z$2.object({
5483
5483
  /**
5484
5484
  * @description Kubernetes route API selected for public endpoints.
5485
5485
  */
5486
- const KubernetesRouteProfileSchema = z$2.union([z$2.lazy(() => KubernetesIngressRouteProfileSchema).and(z$2.object({ "routeApi": z$2.enum(["ingress"]) })), z$2.lazy(() => KubernetesGatewayRouteProfileSchema).and(z$2.object({ "routeApi": z$2.enum(["gateway"]) }))]).describe("Kubernetes route API selected for public endpoints.");
5486
+ const KubernetesRouteProfileSchema = z$2.union([z$2.lazy(() => KubernetesIngressRouteProfileSchema).and(z$2.object({ "routeApi": z$2.enum(["ingress"]) })).describe("Shared Ingress route profile values."), z$2.lazy(() => KubernetesGatewayRouteProfileSchema).and(z$2.object({ "routeApi": z$2.enum(["gateway"]) })).describe("Shared Gateway API route profile values.")]).describe("Kubernetes route API selected for public endpoints.");
5487
5487
  //#endregion
5488
5488
  //#region src/generated/zod/kubernetes-exposure-settings-schema.ts
5489
5489
  /**
@@ -5807,9 +5807,9 @@ const LocalWorkerHeartbeatDataSchema = z$2.object({
5807
5807
  * @description Management configuration for different cloud platforms.\n\nPlatform-derived configuration for cross-account/cross-tenant access.\nThis is NOT user-specified - it\'s derived from the Manager\'s ServiceAccount.
5808
5808
  */
5809
5809
  const ManagementConfigSchema = z$2.union([
5810
- z$2.lazy(() => AwsManagementConfigSchema).and(z$2.object({ "platform": z$2.enum(["aws"]) })),
5811
- z$2.lazy(() => GcpManagementConfigSchema).and(z$2.object({ "platform": z$2.enum(["gcp"]) })),
5812
- z$2.lazy(() => AzureManagementConfigSchema).and(z$2.object({ "platform": z$2.enum(["azure"]) })),
5810
+ z$2.lazy(() => AwsManagementConfigSchema).and(z$2.object({ "platform": z$2.enum(["aws"]) })).describe("AWS management configuration extracted from stack settings"),
5811
+ z$2.lazy(() => GcpManagementConfigSchema).and(z$2.object({ "platform": z$2.enum(["gcp"]) })).describe("GCP management configuration extracted from stack settings"),
5812
+ z$2.lazy(() => AzureManagementConfigSchema).and(z$2.object({ "platform": z$2.enum(["azure"]) })).describe("Azure management configuration extracted from stack settings"),
5813
5813
  z$2.object({ "platform": z$2.enum(["kubernetes"]) })
5814
5814
  ]).describe("Management configuration for different cloud platforms.\n\nPlatform-derived configuration for cross-account/cross-tenant access.\nThis is NOT user-specified - it's derived from the Manager's ServiceAccount.");
5815
5815
  //#endregion
@@ -6064,10 +6064,10 @@ const PostgresBackendSchema = z$2.object({ "type": z$2.enum(["auroraServerlessV2
6064
6064
  * Do not edit manually.
6065
6065
  */
6066
6066
  const PostgresHeartbeatDataSchema = z$2.union([
6067
- z$2.lazy(() => AuroraPostgresHeartbeatDataSchema).and(z$2.object({ "backend": z$2.enum(["aurora"]) })),
6068
- z$2.lazy(() => GcpCloudSqlPostgresHeartbeatDataSchema).and(z$2.object({ "backend": z$2.enum(["cloudSql"]) })),
6069
- z$2.lazy(() => AzureFlexibleServerPostgresHeartbeatDataSchema).and(z$2.object({ "backend": z$2.enum(["flexibleServer"]) })),
6070
- z$2.lazy(() => LocalPostgresHeartbeatDataSchema).and(z$2.object({ "backend": z$2.enum(["local"]) }))
6067
+ z$2.lazy(() => AuroraPostgresHeartbeatDataSchema).and(z$2.object({ "backend": z$2.enum(["aurora"]) })).describe("AWS Aurora Serverless v2 backend."),
6068
+ z$2.lazy(() => GcpCloudSqlPostgresHeartbeatDataSchema).and(z$2.object({ "backend": z$2.enum(["cloudSql"]) })).describe("GCP Cloud SQL backend."),
6069
+ z$2.lazy(() => AzureFlexibleServerPostgresHeartbeatDataSchema).and(z$2.object({ "backend": z$2.enum(["flexibleServer"]) })).describe("Azure Flexible Server backend."),
6070
+ z$2.lazy(() => LocalPostgresHeartbeatDataSchema).and(z$2.object({ "backend": z$2.enum(["local"]) })).describe("Local embedded Postgres backend.")
6071
6071
  ]);
6072
6072
  z$2.object({
6073
6073
  "database": z$2.string().describe("The default database created for this resource. On cloud backends this is the fixed\nlabel `POSTGRES_DATABASE_NAME` (`alien`); on Local it is the resource id."),
@@ -6869,7 +6869,7 @@ const StorageSchema = z$2.object({
6869
6869
  /**
6870
6870
  * @description Request to submit a command response (from deployment)
6871
6871
  */
6872
- const SubmitResponseRequestSchema = z$2.lazy(() => CommandResponseSchema).describe("Request to submit a command response (from deployment)");
6872
+ const SubmitResponseRequestSchema = z$2.lazy(() => CommandResponseSchema).describe("Command response from deployment").describe("Request to submit a command response (from deployment)");
6873
6873
  //#endregion
6874
6874
  //#region src/generated/zod/upload-complete-request-schema.ts
6875
6875
  /**
@@ -7082,186 +7082,140 @@ var ResourceBuilder = class {
7082
7082
  }
7083
7083
  };
7084
7084
  //#endregion
7085
- //#region src/storage.ts
7085
+ //#region src/ai.ts
7086
7086
  /**
7087
- * Represents an object storage bucket.
7087
+ * Represents an AI Gateway resource that provides a unified interface to
7088
+ * managed AI inference services across cloud providers.
7088
7089
  */
7089
- var Storage = class extends ResourceBuilder {
7090
- _config = {
7091
- publicRead: false,
7092
- versioning: false,
7093
- lifecycleRules: [],
7094
- corsAllowedOrigins: []
7095
- };
7090
+ var AI = class extends ResourceBuilder {
7091
+ _config = {};
7096
7092
  /**
7097
- * Creates a new Storage builder.
7098
- * @param id ID of the storage bucket. For names with dots, each dot-separated label must be ≤ 63 characters.
7093
+ * Creates a new AI builder.
7094
+ * @param id Identifier for the AI resource. Must contain only alphanumeric characters, hyphens, and underscores ([A-Za-z0-9-_]). Maximum 64 characters.
7099
7095
  */
7100
7096
  constructor(id) {
7101
7097
  super();
7102
7098
  this._config.id = id;
7103
7099
  }
7104
7100
  /**
7105
- * Returns a ResourceType representing any storage resource.
7106
- * Used for creating permission targets that apply to all storage resources.
7107
- * @returns The "storage" resource type.
7101
+ * Returns a ResourceType representing any AI resource.
7102
+ * Used for creating permission targets that apply to all AI resources.
7103
+ * @returns The "ai" resource type.
7108
7104
  */
7109
7105
  static any() {
7110
- return "storage";
7106
+ return "ai";
7111
7107
  }
7112
7108
  /**
7113
- * Allows public read access to objects without authentication.
7114
- * Default: `false`.
7115
- * @param value Whether to allow public read access.
7116
- * @returns The Storage builder instance.
7109
+ * Builds and validates the AI configuration.
7110
+ * @returns An immutable Resource representing the configured AI Gateway.
7111
+ * @throws Error if the AI configuration is invalid.
7117
7112
  */
7118
- publicRead(value) {
7119
- this._config.publicRead = value;
7120
- return this;
7113
+ build() {
7114
+ const config = AiSchema.parse(this._config);
7115
+ return this.resource({
7116
+ type: "ai",
7117
+ ...config
7118
+ });
7121
7119
  }
7120
+ };
7121
+ //#endregion
7122
+ //#region src/artifact-registry.ts
7123
+ /**
7124
+ * Represents an artifact registry for storing container images and other build artifacts.
7125
+ * This is a high-level wrapper resource that provides a cloud-agnostic interface over
7126
+ * AWS ECR, GCP Artifact Registry, and Azure Container Registry.
7127
+ */
7128
+ var ArtifactRegistry = class {
7129
+ _config = {};
7122
7130
  /**
7123
- * Enables object versioning.
7124
- * Default: `false`.
7125
- * @param value Whether to enable versioning.
7126
- * @returns The Storage builder instance.
7131
+ * Creates a new ArtifactRegistry builder.
7132
+ * @param id Identifier for the artifact registry. Must contain only alphanumeric characters, hyphens, and underscores ([A-Za-z0-9-_]). Maximum 64 characters.
7127
7133
  */
7128
- versioning(value) {
7129
- this._config.versioning = value;
7130
- return this;
7134
+ constructor(id) {
7135
+ this._config.id = id;
7131
7136
  }
7132
7137
  /**
7133
- * Defines lifecycle rules for automatic object management (e.g., expiration).
7134
- * @param rules An array of lifecycle rules.
7135
- * @returns The Storage builder instance.
7138
+ * Returns a ResourceType representing any artifact registry resource.
7139
+ * Used for creating permission targets that apply to all artifact registry resources.
7140
+ * @returns The "artifact-registry" resource type.
7136
7141
  */
7137
- lifecycleRules(rules) {
7138
- this._config.lifecycleRules = rules;
7139
- return this;
7142
+ static any() {
7143
+ return "artifact-registry";
7140
7144
  }
7141
7145
  /**
7142
- * Allows browser reads from the listed origins through signed URLs.
7143
- * Providers enable `GET` and `HEAD`; use `*` only when the signed URL itself
7144
- * is the credential and browser cookies are not involved.
7145
- * @param origins Allowed browser origins.
7146
- * @returns The Storage builder instance.
7146
+ * AWS-only: Configure ECR private image replication to additional regions.
7147
+ * Ensures images pushed in the registry's home region are automatically
7148
+ * available in these destination regions (required when Lambda or other
7149
+ * compute runs in a different region).
7150
+ * @param regions - AWS region codes to replicate to (e.g., ["us-east-2", "eu-west-1"])
7147
7151
  */
7148
- corsAllowedOrigins(origins) {
7149
- this._config.corsAllowedOrigins = origins;
7152
+ replicationRegions(regions) {
7153
+ this._config.replicationRegions = regions;
7150
7154
  return this;
7151
7155
  }
7152
7156
  /**
7153
- * Builds and validates the storage configuration.
7154
- * @returns An immutable Resource representing the configured storage bucket.
7155
- * @throws Error if the storage configuration is invalid.
7157
+ * Builds and validates the artifact registry configuration.
7158
+ * @returns An immutable Resource representing the configured artifact registry.
7159
+ * @throws Error if the artifact registry configuration is invalid.
7156
7160
  */
7157
7161
  build() {
7158
- const config = StorageSchema.parse(this._config);
7159
- return this.resource({
7160
- type: "storage",
7161
- ...config
7162
+ return new Resource({
7163
+ type: "artifact-registry",
7164
+ ...ArtifactRegistrySchema.parse(this._config)
7162
7165
  });
7163
7166
  }
7164
7167
  };
7165
7168
  //#endregion
7166
- //#region src/worker.ts
7169
+ //#region src/build.ts
7167
7170
  /**
7168
- * Represents a serverless worker that executes code in response to triggers or direct invocations.
7169
- * Workers are the primary compute resource in serverless applications, designed to be stateless and ephemeral.
7171
+ * Represents a build resource that executes bash scripts to build code.
7172
+ * Builds are designed to be stateless and can be triggered on-demand to compile,
7173
+ * test, or package application code.
7170
7174
  */
7171
- var Worker = class extends ResourceBuilder {
7175
+ var Build = class {
7172
7176
  _config = {
7173
7177
  links: [],
7174
- triggers: [],
7175
- publicEndpoints: [],
7176
7178
  environment: {}
7177
7179
  };
7178
7180
  /**
7179
- * Creates a new Worker builder.
7180
- * @param id Identifier for the worker. Must contain only alphanumeric characters, hyphens, and underscores ([A-Za-z0-9-_]). Maximum 64 characters.
7181
+ * Creates a new Build builder.
7182
+ * @param id Identifier for the build resource. Must contain only alphanumeric characters, hyphens, and underscores ([A-Za-z0-9-_]). Maximum 64 characters.
7181
7183
  */
7182
7184
  constructor(id) {
7183
- super();
7184
7185
  this._config.id = id;
7185
7186
  }
7186
7187
  /**
7187
- * Returns a ResourceType representing any worker resource.
7188
- * Used for creating permission targets that apply to all worker resources.
7189
- * @returns The "worker" resource type.
7188
+ * Returns a ResourceType representing any build resource.
7189
+ * Used for creating permission targets that apply to all build resources.
7190
+ * @returns The "build" resource type.
7190
7191
  */
7191
7192
  static any() {
7192
- return "worker";
7193
- }
7194
- /**
7195
- * Sets the code for the worker, either a pre-built image or source code to be built.
7196
- * @param code The worker code configuration.
7197
- * @returns The Worker builder instance.
7198
- */
7199
- code(code) {
7200
- this._config.code = code;
7201
- return this;
7202
- }
7203
- /**
7204
- * Sets the memory allocated to the worker in megabytes (MB).
7205
- * Constraints: 128‑32768 MB (platform-specific limits may apply).
7206
- * Default: 512 MB.
7207
- * @param mb The memory in MB.
7208
- * @returns The Worker builder instance.
7209
- */
7210
- memoryMb(mb) {
7211
- this._config.memoryMb = mb;
7212
- return this;
7213
- }
7214
- /**
7215
- * Sets the maximum execution time for the worker in seconds.
7216
- * Constraints: 1‑3600 seconds (platform-specific limits may apply).
7217
- * Default: 30 seconds.
7218
- * @param sec The timeout in seconds.
7219
- * @returns The Worker builder instance.
7220
- */
7221
- timeoutSeconds(sec) {
7222
- this._config.timeoutSeconds = sec;
7223
- return this;
7224
- }
7225
- /**
7226
- * Sets the maximum number of concurrent executions allowed for the worker.
7227
- * `null` means platform default applies.
7228
- * @param limit The concurrency limit, or `null` for platform default.
7229
- * @returns The Worker builder instance.
7230
- */
7231
- concurrencyLimit(limit) {
7232
- this._config.concurrencyLimit = limit;
7233
- return this;
7193
+ return "build";
7234
7194
  }
7235
7195
  /**
7236
- * Exposes a named public HTTP endpoint for the worker.
7237
- *
7238
- * If no public endpoint is declared, the worker is private and only reachable
7239
- * through triggers, commands, or provider invocation APIs.
7196
+ * Sets the compute type for the build.
7197
+ * @param type The compute type (small, medium, large, x-large).
7198
+ * @returns The Build builder instance.
7240
7199
  */
7241
- publicEndpoint(name, options = {}) {
7242
- if (!this._config.publicEndpoints) this._config.publicEndpoints = [];
7243
- this._config.publicEndpoints.push({
7244
- name,
7245
- hostLabel: options.hostLabel,
7246
- wildcardSubdomains: options.wildcardSubdomains ?? false
7247
- });
7200
+ computeType(type) {
7201
+ this._config.computeType = type;
7248
7202
  return this;
7249
7203
  }
7250
7204
  /**
7251
- * Sets key-value pairs as environment variables for the worker.
7205
+ * Sets key-value pairs as environment variables for the build.
7252
7206
  * @param env A map of environment variable names to their values.
7253
- * @returns The Worker builder instance.
7207
+ * @returns The Build builder instance.
7254
7208
  */
7255
7209
  environment(env) {
7256
7210
  this._config.environment = env;
7257
7211
  return this;
7258
7212
  }
7259
7213
  /**
7260
- * Links another resource (e.g., Storage, KV, Queue) to this worker.
7261
- * This makes the linked resource accessible to the worker, often by injecting
7214
+ * Links another resource (e.g., Storage, ArtifactRegistry, Role) to this build.
7215
+ * This makes the linked resource accessible to the build, often by injecting
7262
7216
  * environment variables or granting permissions.
7263
7217
  * @param resource The resource to link.
7264
- * @returns The Worker builder instance.
7218
+ * @returns The Build builder instance.
7265
7219
  */
7266
7220
  link(resource) {
7267
7221
  if (!this._config.links) this._config.links = [];
@@ -7269,99 +7223,740 @@ var Worker = class extends ResourceBuilder {
7269
7223
  return this;
7270
7224
  }
7271
7225
  /**
7272
- * Assigns a permission profile to this worker.
7273
- * The profile defines the permissions granted to this worker when interacting
7226
+ * Assigns a permission profile to this build.
7227
+ * The profile defines the permissions granted to this build when interacting
7274
7228
  * with other cloud resources.
7275
7229
  * @param permissions The permission profile name.
7276
- * @returns The Worker builder instance.
7230
+ * @returns The Build builder instance.
7277
7231
  */
7278
7232
  permissions(permissions) {
7279
7233
  this._config.permissions = permissions;
7280
7234
  return this;
7281
7235
  }
7282
7236
  /**
7283
- * Configures a readiness probe for the worker.
7284
- * The probe will be executed after provisioning/update to verify the worker is ready.
7285
- * Only works with workers that declare a public endpoint.
7286
- *
7287
- * @example
7288
- * ```typescript
7289
- * const probe: ReadinessProbe = {
7290
- * method: "GET",
7291
- * path: "/health"
7292
- * };
7293
- *
7294
- * const func = new Worker("my-api")
7295
- * .code({ type: "image", image: "my-api:latest" })
7296
- * .publicEndpoint("api")
7297
- * .readinessProbe(probe)
7298
- * .build();
7299
- * ```
7300
- *
7301
- * @param probe The readiness probe configuration.
7302
- * @returns The Worker builder instance.
7303
- */
7304
- readinessProbe(probe) {
7305
- this._config.readinessProbe = probe;
7306
- return this;
7307
- }
7308
- /**
7309
- * Enables or disables the Commands protocol for the worker.
7310
- * When enabled, the platform pushes commands into the Worker runtime, which executes registered handlers.
7311
- * Default: false.
7312
- * @param enabled Whether to enable commands for this worker.
7313
- * @returns The Worker builder instance.
7237
+ * Builds and validates the build configuration.
7238
+ * @returns An immutable Resource representing the configured build.
7239
+ * @throws Error if the build configuration is invalid.
7314
7240
  */
7315
- commandsEnabled(enabled) {
7316
- this._config.commandsEnabled = enabled;
7317
- return this;
7241
+ build() {
7242
+ return new Resource({
7243
+ type: "build",
7244
+ ...BuildSchema.parse(this._config)
7245
+ });
7318
7246
  }
7319
- /**
7320
- * Adds a trigger to the worker. Workers can have multiple triggers.
7321
- * Each trigger will independently invoke the worker when its conditions are met.
7322
- *
7323
- * @example
7324
- * ```typescript
7325
- * // Queue trigger
7326
- * const queueTrigger: WorkerTrigger = {
7327
- * type: "queue",
7328
- * queue: myQueue.ref()
7329
- * };
7330
- *
7331
- * // Schedule trigger
7332
- * const scheduleTrigg: WorkerTrigger = {
7333
- * type: "schedule",
7334
- * cron: "0 * * * *"
7335
- * };
7247
+ };
7248
+ //#endregion
7249
+ //#region src/error.ts
7250
+ /**
7251
+ * This module provides a structured error handling system similar to Rust's error types,
7252
+ * with TypeScript type safety, error chaining, and context preservation.
7253
+ *
7254
+ * @example Basic Usage
7255
+ * ```typescript
7256
+ * import { AlienError, defineError } from '@alienplatform/core'
7257
+ * import { z } from 'zod'
7258
+ *
7259
+ * // Define a type-safe error
7260
+ * const DatabaseError = defineError({
7261
+ * code: "DATABASE_CONNECTION_FAILED",
7262
+ * context: z.object({
7263
+ * host: z.string(),
7264
+ * port: z.number(),
7265
+ * reason: z.string(),
7266
+ * }),
7267
+ * message: ({ host, port, reason }) => `Failed to connect to database '${host}:${port}': ${reason}`,
7268
+ * retryable: true,
7269
+ * internal: false,
7270
+ * httpStatusCode: 502,
7271
+ * })
7272
+ *
7273
+ * // Use it
7274
+ * throw new AlienError(DatabaseError.create({
7275
+ * host: "localhost",
7276
+ * port: 5432,
7277
+ * reason: "Connection timeout"
7278
+ * }))
7279
+ * ```
7280
+ *
7281
+ * @example Error Chaining
7282
+ * ```typescript
7283
+ * try {
7284
+ * // Some operation that fails
7285
+ * throw new Error("Connection refused")
7286
+ * } catch (error) {
7287
+ * throw (await AlienError.from(error)).withContext(
7288
+ * DatabaseError.create({
7289
+ * host: "localhost",
7290
+ * port: 5432,
7291
+ * reason: "Connection refused by server"
7292
+ * })
7293
+ * )
7294
+ * }
7295
+ * ```
7296
+ *
7297
+ * @example External API Sanitization
7298
+ * ```typescript
7299
+ * const internalError = new AlienError(InternalApiError.create({
7300
+ * service: "payment-processor",
7301
+ * details: "Database password expired",
7302
+ * traceId: "trace-12345"
7303
+ * }))
7304
+ *
7305
+ * // Safe for external APIs (sanitizes internal errors)
7306
+ * const safeResponse = internalError.toExternal()
7307
+ * ```
7308
+ */
7309
+ /**
7310
+ * Helper function to create type-safe error definitions.
7311
+ *
7312
+ * This function provides a clean API for defining reusable error types
7313
+ * with full TypeScript type safety and Zod validation.
7314
+ *
7315
+ * @template TContext - Zod schema type for the error context
7316
+ * @param metadata - Error metadata including code, schema, and message generator
7317
+ * @returns Object with metadata and a create function for error instances
7318
+ *
7319
+ * @example
7320
+ * ```typescript
7321
+ * const UserNotFound = defineError({
7322
+ * code: "USER_NOT_FOUND",
7323
+ * context: z.object({
7324
+ * userId: z.string(),
7325
+ * searchMethod: z.string(),
7326
+ * }),
7327
+ * message: ({ userId, searchMethod }) =>
7328
+ * `User '${userId}' not found using method '${searchMethod}'`,
7329
+ * retryable: false,
7330
+ * internal: false,
7331
+ * httpStatusCode: 404,
7332
+ * })
7333
+ *
7334
+ * // Usage
7335
+ * const error = UserNotFound.create({
7336
+ * userId: "123",
7337
+ * searchMethod: "database_lookup"
7338
+ * })
7339
+ * ```
7340
+ */
7341
+ function defineError(metadata) {
7342
+ return {
7343
+ metadata,
7344
+ contextSchema: metadata.context,
7345
+ create: (context) => ({
7346
+ metadata,
7347
+ contextSchema: metadata.context,
7348
+ context,
7349
+ toOptions: () => ({
7350
+ code: metadata.code,
7351
+ message: metadata.message(context),
7352
+ retryable: metadata.retryable,
7353
+ internal: metadata.internal,
7354
+ httpStatusCode: metadata.httpStatusCode,
7355
+ context
7356
+ })
7357
+ })
7358
+ };
7359
+ }
7360
+ /**
7361
+ * Main AlienError class that provides structured error handling.
7362
+ *
7363
+ * This class extends the standard JavaScript Error with additional features:
7364
+ * - Type-safe context data
7365
+ * - Error chaining and source tracking
7366
+ * - Retryability and internal/external visibility flags
7367
+ * - HTTP status code mapping
7368
+ * - Sanitization for external APIs
7369
+ *
7370
+ * @template TContext - Zod schema type for the error context
7371
+ *
7372
+ * @example Basic Construction
7373
+ * ```typescript
7374
+ * const error = new AlienError(DatabaseError.create({
7375
+ * host: "localhost",
7376
+ * port: 5432,
7377
+ * reason: "Timeout"
7378
+ * }))
7379
+ * ```
7380
+ *
7381
+ * @example Converting JavaScript Errors
7382
+ * ```typescript
7383
+ * try {
7384
+ * JSON.parse("invalid json")
7385
+ * } catch (jsError) {
7386
+ * const alienError = AlienError.from(jsError)
7387
+ * console.log(alienError.code) // "GENERIC_ERROR"
7388
+ * }
7389
+ * ```
7390
+ *
7391
+ * @example Error Chaining
7392
+ * ```typescript
7393
+ * const contextualError = AlienError.from(new Error("Network timeout"))
7394
+ * .withContext(DatabaseError.create({
7395
+ * host: "localhost",
7396
+ * port: 5432,
7397
+ * reason: "Connection timeout"
7398
+ * }))
7399
+ *
7400
+ * // Check error chain
7401
+ * console.log(contextualError.hasErrorCode("DATABASE_CONNECTION_FAILED")) // true
7402
+ * console.log(contextualError.toString()) // Shows full error chain
7403
+ * ```
7404
+ */
7405
+ var AlienError = class AlienError extends Error {
7406
+ /** Unique error code identifying the error type */
7407
+ code;
7408
+ /** Whether this error can be safely retried */
7409
+ retryable;
7410
+ /** Whether this error contains sensitive internal information */
7411
+ internal;
7412
+ /** HTTP status code for API responses */
7413
+ httpStatusCode;
7414
+ /** Type-safe context data specific to this error */
7415
+ context;
7416
+ /** Optional human-facing remediation hint */
7417
+ hint;
7418
+ /** Source error that caused this error (for chaining) */
7419
+ source;
7420
+ constructor(input) {
7421
+ let options;
7422
+ if ("metadata" in input && "context" in input) {
7423
+ const { metadata, context: contextData } = input;
7424
+ const message = metadata.message(contextData);
7425
+ options = {
7426
+ code: metadata.code,
7427
+ message,
7428
+ retryable: metadata.retryable,
7429
+ internal: metadata.internal,
7430
+ httpStatusCode: metadata.httpStatusCode,
7431
+ context: contextData
7432
+ };
7433
+ } else options = input;
7434
+ const message = options.message;
7435
+ super(message, { cause: options.source });
7436
+ this.name = "AlienError";
7437
+ this.code = options.code;
7438
+ this.retryable = options.retryable;
7439
+ this.internal = options.internal;
7440
+ this.httpStatusCode = options.httpStatusCode ?? 500;
7441
+ this.context = options.context;
7442
+ this.hint = options.hint;
7443
+ this.source = void 0;
7444
+ if (options.source && typeof options.source === "object") {
7445
+ if ("code" in options.source && "message" in options.source && "retryable" in options.source && "internal" in options.source) this.source = new AlienError(options.source);
7446
+ }
7447
+ }
7448
+ /**
7449
+ * Create an AlienError from a type-safe error definition.
7450
+ *
7451
+ * @template TContext - Zod schema type for the error context
7452
+ * @param definition - Error definition with type-safe context
7453
+ * @returns New AlienError instance
7454
+ */
7455
+ static fromDefinition(definition) {
7456
+ return new AlienError(definition);
7457
+ }
7458
+ /**
7459
+ * Create an AlienError from raw options (for compatibility).
7460
+ *
7461
+ * @param options - Raw error options conforming to AlienErrorOptions schema
7462
+ * @returns New AlienError instance
7463
+ */
7464
+ static fromOptions(options) {
7465
+ return new AlienError(AlienErrorSchema.parse(options));
7466
+ }
7467
+ /**
7468
+ * Helper function to get a user-friendly type name for error context.
7469
+ *
7470
+ * @param error - Any value to get the type name for
7471
+ * @returns User-friendly type name
7472
+ */
7473
+ static getErrorTypeName(error) {
7474
+ if (error === null) return "null";
7475
+ if (error === void 0) return "undefined";
7476
+ if (error?.constructor?.name) return error.constructor.name;
7477
+ const typeofResult = typeof error;
7478
+ return typeofResult === "object" ? "Object" : typeofResult.charAt(0).toUpperCase() + typeofResult.slice(1);
7479
+ }
7480
+ /**
7481
+ * Convert a JavaScript Error or any object to a generic AlienError.
7482
+ *
7483
+ * This is equivalent to Rust's `.into_alien_error()` pattern and provides
7484
+ * a way to convert any JavaScript error into the structured AlienError format.
7485
+ *
7486
+ * @param error - Any JavaScript error or object to convert
7487
+ * @returns AlienError with GENERIC_ERROR code and preserved original error
7488
+ *
7489
+ * @example
7490
+ * ```typescript
7491
+ * try {
7492
+ * throw new TypeError("Invalid argument")
7493
+ * } catch (error) {
7494
+ * const alienError = AlienError.from(error)
7495
+ * console.log(alienError.code) // "GENERIC_ERROR"
7496
+ * console.log(alienError.context?.originalError) // Serialized TypeError
7497
+ * }
7498
+ * ```
7499
+ *
7500
+ * @example Chaining with context
7501
+ * ```typescript
7502
+ * try {
7503
+ * JSON.parse("invalid")
7504
+ * } catch (error) {
7505
+ * throw AlienError.from(error).withContext(
7506
+ * ValidationError.create({
7507
+ * input: "invalid",
7508
+ * expectedFormat: "JSON"
7509
+ * })
7510
+ * )
7511
+ * }
7512
+ * ```
7513
+ *
7514
+ * @example AxiosError conversion
7515
+ * ```typescript
7516
+ * try {
7517
+ * await axios.get('/api/resource')
7518
+ * } catch (error) {
7519
+ * // If error.response.data contains a valid AlienError structure, it will be parsed
7520
+ * const alienError = AlienError.from(error)
7521
+ * console.log(alienError.code) // Could be "REMOTE_RESOURCE_NOT_FOUND" if parsed from response
7522
+ * }
7523
+ * ```
7524
+ */
7525
+ static async from(error) {
7526
+ if (error instanceof AlienError) return error;
7527
+ if (error instanceof Response) {
7528
+ let errorBody;
7529
+ try {
7530
+ errorBody = await error.json();
7531
+ } catch {
7532
+ return new AlienError({
7533
+ code: "GENERIC_ERROR",
7534
+ message: `HTTP request failed with status ${error.status}`,
7535
+ retryable: false,
7536
+ internal: true,
7537
+ httpStatusCode: error.status,
7538
+ context: {
7539
+ url: error.url,
7540
+ status: error.status,
7541
+ statusText: error.statusText
7542
+ }
7543
+ });
7544
+ }
7545
+ const parseResult = AlienErrorSchema.safeParse(errorBody);
7546
+ if (parseResult.success) return new AlienError(parseResult.data);
7547
+ return new AlienError({
7548
+ code: "GENERIC_ERROR",
7549
+ message: errorBody?.message || `HTTP request failed with status ${error.status}`,
7550
+ retryable: false,
7551
+ internal: true,
7552
+ httpStatusCode: error.status,
7553
+ context: {
7554
+ url: error.url,
7555
+ status: error.status,
7556
+ statusText: error.statusText,
7557
+ responseBody: errorBody
7558
+ }
7559
+ });
7560
+ }
7561
+ if (error?.response?.data && typeof error.response.data === "object") {
7562
+ const parseResult = AlienErrorSchema.safeParse(error.response.data);
7563
+ if (parseResult.success) return new AlienError(parseResult.data);
7564
+ }
7565
+ const serialized = serializeError(error);
7566
+ const message = serialized?.message || String(error);
7567
+ return new AlienError({
7568
+ code: "GENERIC_ERROR",
7569
+ message,
7570
+ retryable: false,
7571
+ internal: true,
7572
+ httpStatusCode: 500,
7573
+ context: {
7574
+ originalError: serialized,
7575
+ errorType: AlienError.getErrorTypeName(error)
7576
+ }
7577
+ });
7578
+ }
7579
+ /**
7580
+ * Add context to this error, creating a new error that wraps this one.
7336
7581
  *
7337
- * const func = new Worker("my-func")
7338
- * .code({ type: "image", image: "my-image:latest" })
7339
- * .trigger(queueTrigger)
7340
- * .trigger(scheduleTrigger)
7341
- * .build();
7582
+ * This is equivalent to Rust's `.with_context()` pattern and allows
7583
+ * building error chains with increasing levels of context.
7584
+ *
7585
+ * @template TNewContext - Zod schema type for the new context
7586
+ * @param definition - Error definition to wrap this error with
7587
+ * @returns New AlienError with this error as the source
7588
+ *
7589
+ * @example
7590
+ * ```typescript
7591
+ * // Clean fluent API
7592
+ * const authError = (await AlienError.from(new Error("ECONNREFUSED")))
7593
+ * .withContext(DatabaseError.create({
7594
+ * host: "localhost",
7595
+ * port: 5432,
7596
+ * reason: "Connection refused"
7597
+ * }))
7598
+ * .withContext(AuthError.create({
7599
+ * username: "john",
7600
+ * reason: "Database unavailable"
7601
+ * }))
7602
+ *
7603
+ * // Error chain: AuthError -> DatabaseError -> GENERIC_ERROR
7604
+ * console.log(authError.toString())
7342
7605
  * ```
7606
+ */
7607
+ withContext(definition) {
7608
+ const { metadata, context: contextData } = definition;
7609
+ const message = metadata.message(contextData);
7610
+ const sourceOptions = {
7611
+ code: this.code,
7612
+ message: this.message,
7613
+ retryable: this.retryable,
7614
+ internal: this.internal,
7615
+ httpStatusCode: this.httpStatusCode,
7616
+ context: this.context,
7617
+ hint: this.hint,
7618
+ source: this.source?.toOptions()
7619
+ };
7620
+ return new AlienError({
7621
+ code: metadata.code,
7622
+ message,
7623
+ retryable: metadata.retryable,
7624
+ internal: metadata.internal,
7625
+ httpStatusCode: metadata.httpStatusCode,
7626
+ context: contextData,
7627
+ source: sourceOptions
7628
+ });
7629
+ }
7630
+ /**
7631
+ * Convert this AlienError to the wire format (AlienErrorOptions).
7343
7632
  *
7344
- * @param trigger The trigger configuration.
7345
- * @returns The Worker builder instance.
7633
+ * This method serializes the error into the standard format used
7634
+ * for transmitting errors over the network or storing them.
7635
+ *
7636
+ * @returns AlienErrorOptions object representing this error
7637
+ */
7638
+ toOptions() {
7639
+ return {
7640
+ code: this.code,
7641
+ message: this.message,
7642
+ retryable: this.retryable,
7643
+ internal: this.internal,
7644
+ httpStatusCode: this.httpStatusCode,
7645
+ context: this.context,
7646
+ hint: this.hint,
7647
+ source: this.source?.toOptions()
7648
+ };
7649
+ }
7650
+ /**
7651
+ * Get a sanitized version for external APIs (hides internal errors).
7652
+ *
7653
+ * This method is crucial for security - it prevents sensitive internal
7654
+ * error details from being exposed to external users while preserving
7655
+ * the error chain structure for non-sensitive errors.
7656
+ *
7657
+ * @returns Sanitized AlienErrorOptions safe for external consumption
7658
+ *
7659
+ * @example
7660
+ * ```typescript
7661
+ * const internalError = new AlienError(InternalApiError.create({
7662
+ * service: "payment-processor",
7663
+ * details: "Database password expired for user admin",
7664
+ * traceId: "trace-12345"
7665
+ * }))
7666
+ *
7667
+ * console.log(internalError.toOptions())
7668
+ * // Shows full details including sensitive information
7669
+ *
7670
+ * console.log(internalError.toExternal())
7671
+ * // { code: "GENERIC_ERROR", message: "Internal server error", ... }
7672
+ * ```
7673
+ */
7674
+ toExternal() {
7675
+ if (this.internal) return {
7676
+ code: "GENERIC_ERROR",
7677
+ message: "Internal server error",
7678
+ retryable: false,
7679
+ internal: false,
7680
+ httpStatusCode: 500
7681
+ };
7682
+ return {
7683
+ code: this.code,
7684
+ message: this.message,
7685
+ retryable: this.retryable,
7686
+ internal: this.internal,
7687
+ httpStatusCode: this.httpStatusCode,
7688
+ context: this.context,
7689
+ hint: this.hint,
7690
+ source: this.source?.toExternal()
7691
+ };
7692
+ }
7693
+ /**
7694
+ * Check if this error chain contains an error with a specific code.
7695
+ *
7696
+ * This method traverses the entire error chain (this error and all
7697
+ * source errors) to find if any error has the specified code.
7698
+ *
7699
+ * @param code - Error code to search for
7700
+ * @returns True if the code is found anywhere in the error chain
7701
+ *
7702
+ * @example
7703
+ * ```typescript
7704
+ * const chainedError = authError.withContext(dbError.withContext(networkError))
7705
+ *
7706
+ * console.log(chainedError.hasErrorCode("AUTH_FAILED")) // true
7707
+ * console.log(chainedError.hasErrorCode("DATABASE_CONNECTION_FAILED")) // true
7708
+ * console.log(chainedError.hasErrorCode("NETWORK_TIMEOUT")) // true
7709
+ * console.log(chainedError.hasErrorCode("NONEXISTENT_ERROR")) // false
7710
+ * ```
7711
+ */
7712
+ hasErrorCode(code) {
7713
+ if (this.code === code) return true;
7714
+ return this.source?.hasErrorCode(code) ?? false;
7715
+ }
7716
+ /**
7717
+ * Find the first error in the chain with a specific code.
7718
+ *
7719
+ * This method traverses the error chain and returns the first error
7720
+ * instance that matches the specified code, allowing access to its
7721
+ * specific context and details.
7722
+ *
7723
+ * @param code - Error code to search for
7724
+ * @returns AlienError instance with the specified code, or undefined if not found
7725
+ *
7726
+ * @example
7727
+ * ```typescript
7728
+ * const chainedError = authError.withContext(dbError)
7729
+ *
7730
+ * const dbError = chainedError.findErrorByCode("DATABASE_CONNECTION_FAILED")
7731
+ * if (dbError) {
7732
+ * console.log("Database error context:", dbError.context)
7733
+ * console.log("Host:", dbError.context?.host)
7734
+ * }
7735
+ * ```
7736
+ */
7737
+ findErrorByCode(code) {
7738
+ if (this.code === code) return this;
7739
+ return this.source?.findErrorByCode(code);
7740
+ }
7741
+ /**
7742
+ * Get a formatted string representation of the error chain.
7743
+ *
7744
+ * This method provides a human-readable representation of the entire
7745
+ * error chain, showing how errors are nested and providing context
7746
+ * for debugging and logging.
7747
+ *
7748
+ * @returns Formatted string showing the complete error chain
7749
+ *
7750
+ * @example
7751
+ * ```typescript
7752
+ * const chainedError = authError.withContext(dbError.withContext(networkError))
7753
+ * console.log(chainedError.toString())
7754
+ * // Output:
7755
+ * // AUTH_FAILED: User authentication failed for 'john'
7756
+ * // ├─▶ DATABASE_CONNECTION_FAILED: Failed to connect to database 'localhost:5432'
7757
+ * // ├─▶ GENERIC_ERROR: Connection timeout
7758
+ * ```
7759
+ */
7760
+ toString() {
7761
+ let result = `${this.code}: ${this.message}`;
7762
+ let current = this.source;
7763
+ let indent = "";
7764
+ while (current) {
7765
+ indent += " ";
7766
+ result += `\n${indent}├─▶ ${current.code}: ${current.message}`;
7767
+ current = current.source;
7768
+ }
7769
+ return result;
7770
+ }
7771
+ };
7772
+ //#endregion
7773
+ //#region src/common-errors.ts
7774
+ /**
7775
+ * Error thrown when a requested resource cannot be found in the stack state.
7776
+ * This matches the Rust alien-core error: RESOURCE_NOT_FOUND
7777
+ */
7778
+ const ResourceNotFoundError = defineError({
7779
+ code: "RESOURCE_NOT_FOUND",
7780
+ context: z$1.object({
7781
+ resourceId: z$1.string(),
7782
+ availableResources: z$1.array(z$1.string())
7783
+ }),
7784
+ message: ({ resourceId, availableResources }) => `Resource '${resourceId}' not found in stack state. Available resources: ${JSON.stringify(availableResources)}`,
7785
+ retryable: false,
7786
+ internal: false,
7787
+ httpStatusCode: 404
7788
+ });
7789
+ /**
7790
+ * Error thrown when resource outputs cannot be parsed according to their expected schema.
7791
+ * This indicates an internal system error or data corruption.
7792
+ */
7793
+ const ResourceOutputsParseError = defineError({
7794
+ code: "RESOURCE_OUTPUTS_PARSE_ERROR",
7795
+ context: z$1.object({
7796
+ resourceName: z$1.string(),
7797
+ resourceType: z$1.string(),
7798
+ validationErrors: z$1.string()
7799
+ }),
7800
+ message: ({ resourceName, resourceType, validationErrors }) => `Failed to parse outputs for resource '${resourceName}' of type '${resourceType}':\n${validationErrors}`,
7801
+ retryable: false,
7802
+ internal: true,
7803
+ httpStatusCode: 500
7804
+ });
7805
+ /**
7806
+ * Error thrown when there's a resource type mismatch during stack operations.
7807
+ * This matches the Rust alien-core error: UNEXPECTED_RESOURCE_TYPE
7808
+ */
7809
+ const UnexpectedResourceTypeError = defineError({
7810
+ code: "UNEXPECTED_RESOURCE_TYPE",
7811
+ context: z$1.object({
7812
+ resourceId: z$1.string(),
7813
+ expected: z$1.string(),
7814
+ actual: z$1.string()
7815
+ }),
7816
+ message: ({ resourceId, expected, actual }) => `Unexpected resource type for resource '${resourceId}': expected ${expected}, but got ${actual}`,
7817
+ retryable: false,
7818
+ internal: false,
7819
+ httpStatusCode: 400
7820
+ });
7821
+ /**
7822
+ * Error thrown when a binding's projected configuration is invalid.
7823
+ */
7824
+ const InvalidBindingConfigError = defineError({
7825
+ code: "INVALID_BINDING_CONFIG",
7826
+ context: z$1.object({
7827
+ message: z$1.string(),
7828
+ suggestion: z$1.string().optional()
7829
+ }),
7830
+ message: ({ message, suggestion }) => suggestion ? `${message}. ${suggestion}` : message,
7831
+ retryable: false,
7832
+ internal: false,
7833
+ httpStatusCode: 400
7834
+ });
7835
+ /**
7836
+ * Error thrown when a binding is not found.
7837
+ */
7838
+ const BindingNotFoundError = defineError({
7839
+ code: "BINDING_NOT_FOUND",
7840
+ context: z$1.object({
7841
+ bindingName: z$1.string(),
7842
+ bindingType: z$1.string()
7843
+ }),
7844
+ message: ({ bindingName, bindingType }) => `${bindingType} binding '${bindingName}' not found`,
7845
+ retryable: false,
7846
+ internal: false,
7847
+ httpStatusCode: 404
7848
+ });
7849
+ //#endregion
7850
+ //#region src/compute-cluster.ts
7851
+ /**
7852
+ * Declares a ComputeCluster — the setup-owned machine boundary for daemons and
7853
+ * containers. Each capacity group inside the cluster becomes a separate
7854
+ * Auto Scaling Group (AWS), Managed Instance Group (GCP), or VM Scale Set
7855
+ * (Azure). Daemons reference a cluster via `daemon.cluster(...)` and (when
7856
+ * the cluster has more than one capacity group) a specific group via
7857
+ * `daemon.pool(...)`.
7858
+ *
7859
+ * Application source declares portable pool requirements. Provider machine
7860
+ * names are selected later through deployment settings.
7861
+ */
7862
+ var ComputeCluster = class {
7863
+ _config = { capacityGroups: [] };
7864
+ constructor(id) {
7865
+ this._config.id = id;
7866
+ }
7867
+ /**
7868
+ * Returns the resource type for permission targets that apply to all
7869
+ * compute-cluster resources.
7346
7870
  */
7347
- trigger(trigger) {
7348
- if (!this._config.triggers) this._config.triggers = [];
7349
- this._config.triggers.push(trigger);
7871
+ static any() {
7872
+ return "compute-cluster";
7873
+ }
7874
+ pool(groupId, config) {
7875
+ const { minSize, maxSize } = selectedScaleBounds(config.scale);
7876
+ this._config.capacityGroups.push({
7877
+ groupId,
7878
+ profile: machineProfileFromRequirements(config.requirements),
7879
+ minSize,
7880
+ maxSize,
7881
+ scalePolicy: scalePolicyFromInput(config.scale),
7882
+ nestedVirtualization: config.requirements.nestedVirtualization
7883
+ });
7350
7884
  return this;
7351
7885
  }
7352
7886
  /**
7353
- * Builds and validates the worker configuration.
7354
- * @returns An immutable Resource representing the configured worker.
7355
- * @throws Error if the worker configuration is invalid (e.g., missing code).
7887
+ * Sets the container CIDR block used for inter-container networking inside
7888
+ * the cluster. Each machine gets a /24 subnet carved from this range.
7889
+ * Defaults to 10.244.0.0/16 if not specified.
7890
+ */
7891
+ containerCidr(cidr) {
7892
+ this._config.containerCidr = cidr;
7893
+ return this;
7894
+ }
7895
+ /**
7896
+ * Builds and validates the cluster configuration.
7356
7897
  */
7357
7898
  build() {
7358
- const config = WorkerSchema.parse(this._config);
7359
- return this.resource({
7360
- type: "worker",
7361
- ...config
7899
+ return new Resource({
7900
+ type: "compute-cluster",
7901
+ ...ComputeClusterSchema.parse(this._config)
7362
7902
  });
7363
7903
  }
7364
7904
  };
7905
+ function selectedScaleBounds(scale) {
7906
+ if (scale.type === "fixed") {
7907
+ const machines = defaultChoice(scale.machines);
7908
+ return {
7909
+ minSize: machines,
7910
+ maxSize: machines
7911
+ };
7912
+ }
7913
+ return {
7914
+ minSize: defaultChoice(scale.min),
7915
+ maxSize: defaultChoice(scale.max)
7916
+ };
7917
+ }
7918
+ function scalePolicyFromInput(scale) {
7919
+ if (scale.type === "fixed") return {
7920
+ type: "fixed",
7921
+ machines: choiceRange(scale.machines)
7922
+ };
7923
+ return {
7924
+ type: "autoscale",
7925
+ min: choiceRange(scale.min),
7926
+ max: choiceRange(scale.max)
7927
+ };
7928
+ }
7929
+ function choiceRange(choice) {
7930
+ if (typeof choice === "number") return {
7931
+ min: choice,
7932
+ max: choice,
7933
+ default: choice
7934
+ };
7935
+ return choice;
7936
+ }
7937
+ function defaultChoice(choice) {
7938
+ if (typeof choice === "number") return choice;
7939
+ return choice.default;
7940
+ }
7941
+ function machineProfileFromRequirements(requirements) {
7942
+ return {
7943
+ cpu: typeof requirements.cpu === "number" ? `${requirements.cpu}` : requirements.cpu,
7944
+ memoryBytes: parseQuantityBytes(requirements.memory),
7945
+ ephemeralStorageBytes: parseQuantityBytes(requirements.ephemeralStorage ?? "20Gi"),
7946
+ architecture: requirements.architecture,
7947
+ gpu: requirements.accelerators?.[0] ? {
7948
+ type: requirements.accelerators[0].type,
7949
+ count: requirements.accelerators[0].count
7950
+ } : void 0
7951
+ };
7952
+ }
7953
+ function parseQuantityBytes(value) {
7954
+ const match = value.match(/^([0-9]+(?:\.[0-9]+)?)(Ki|Mi|Gi|Ti|k|M|G|T)?$/);
7955
+ if (!match) throw new Error(`Invalid memory/storage quantity: ${value}`);
7956
+ const amount = Number(match[1]);
7957
+ const suffix = match[2];
7958
+ return Math.round(amount * (suffix === "Ti" ? 1024 ** 4 : suffix === "Gi" ? 1024 ** 3 : suffix === "Mi" ? 1024 ** 2 : suffix === "Ki" ? 1024 : suffix === "T" ? 1e3 ** 4 : suffix === "G" ? 1e3 ** 3 : suffix === "M" ? 1e3 ** 2 : suffix === "k" ? 1e3 : 1));
7959
+ }
7365
7960
  //#endregion
7366
7961
  //#region src/container.ts
7367
7962
  /**
@@ -7695,125 +8290,14 @@ var Container = class extends ResourceBuilder {
7695
8290
  * @returns An immutable Resource representing the configured container.
7696
8291
  * @throws Error if the container configuration is invalid.
7697
8292
  */
7698
- build() {
7699
- const config = ContainerSchema.parse(this._config);
7700
- return this.resource({
7701
- type: "container",
7702
- ...config
7703
- });
7704
- }
7705
- };
7706
- //#endregion
7707
- //#region src/compute-cluster.ts
7708
- /**
7709
- * Declares a ComputeCluster — the setup-owned machine boundary for daemons and
7710
- * containers. Each capacity group inside the cluster becomes a separate
7711
- * Auto Scaling Group (AWS), Managed Instance Group (GCP), or VM Scale Set
7712
- * (Azure). Daemons reference a cluster via `daemon.cluster(...)` and (when
7713
- * the cluster has more than one capacity group) a specific group via
7714
- * `daemon.pool(...)`.
7715
- *
7716
- * Application source declares portable pool requirements. Provider machine
7717
- * names are selected later through deployment settings.
7718
- */
7719
- var ComputeCluster = class {
7720
- _config = { capacityGroups: [] };
7721
- constructor(id) {
7722
- this._config.id = id;
7723
- }
7724
- /**
7725
- * Returns the resource type for permission targets that apply to all
7726
- * compute-cluster resources.
7727
- */
7728
- static any() {
7729
- return "compute-cluster";
7730
- }
7731
- pool(groupId, config) {
7732
- const { minSize, maxSize } = selectedScaleBounds(config.scale);
7733
- this._config.capacityGroups.push({
7734
- groupId,
7735
- profile: machineProfileFromRequirements(config.requirements),
7736
- minSize,
7737
- maxSize,
7738
- scalePolicy: scalePolicyFromInput(config.scale),
7739
- nestedVirtualization: config.requirements.nestedVirtualization
7740
- });
7741
- return this;
7742
- }
7743
- /**
7744
- * Sets the container CIDR block used for inter-container networking inside
7745
- * the cluster. Each machine gets a /24 subnet carved from this range.
7746
- * Defaults to 10.244.0.0/16 if not specified.
7747
- */
7748
- containerCidr(cidr) {
7749
- this._config.containerCidr = cidr;
7750
- return this;
7751
- }
7752
- /**
7753
- * Builds and validates the cluster configuration.
7754
- */
7755
- build() {
7756
- return new Resource({
7757
- type: "compute-cluster",
7758
- ...ComputeClusterSchema.parse(this._config)
8293
+ build() {
8294
+ const config = ContainerSchema.parse(this._config);
8295
+ return this.resource({
8296
+ type: "container",
8297
+ ...config
7759
8298
  });
7760
8299
  }
7761
8300
  };
7762
- function selectedScaleBounds(scale) {
7763
- if (scale.type === "fixed") {
7764
- const machines = defaultChoice(scale.machines);
7765
- return {
7766
- minSize: machines,
7767
- maxSize: machines
7768
- };
7769
- }
7770
- return {
7771
- minSize: defaultChoice(scale.min),
7772
- maxSize: defaultChoice(scale.max)
7773
- };
7774
- }
7775
- function scalePolicyFromInput(scale) {
7776
- if (scale.type === "fixed") return {
7777
- type: "fixed",
7778
- machines: choiceRange(scale.machines)
7779
- };
7780
- return {
7781
- type: "autoscale",
7782
- min: choiceRange(scale.min),
7783
- max: choiceRange(scale.max)
7784
- };
7785
- }
7786
- function choiceRange(choice) {
7787
- if (typeof choice === "number") return {
7788
- min: choice,
7789
- max: choice,
7790
- default: choice
7791
- };
7792
- return choice;
7793
- }
7794
- function defaultChoice(choice) {
7795
- if (typeof choice === "number") return choice;
7796
- return choice.default;
7797
- }
7798
- function machineProfileFromRequirements(requirements) {
7799
- return {
7800
- cpu: typeof requirements.cpu === "number" ? `${requirements.cpu}` : requirements.cpu,
7801
- memoryBytes: parseQuantityBytes(requirements.memory),
7802
- ephemeralStorageBytes: parseQuantityBytes(requirements.ephemeralStorage ?? "20Gi"),
7803
- architecture: requirements.architecture,
7804
- gpu: requirements.accelerators?.[0] ? {
7805
- type: requirements.accelerators[0].type,
7806
- count: requirements.accelerators[0].count
7807
- } : void 0
7808
- };
7809
- }
7810
- function parseQuantityBytes(value) {
7811
- const match = value.match(/^([0-9]+(?:\.[0-9]+)?)(Ki|Mi|Gi|Ti|k|M|G|T)?$/);
7812
- if (!match) throw new Error(`Invalid memory/storage quantity: ${value}`);
7813
- const amount = Number(match[1]);
7814
- const suffix = match[2];
7815
- return Math.round(amount * (suffix === "Ti" ? 1024 ** 4 : suffix === "Gi" ? 1024 ** 3 : suffix === "Mi" ? 1024 ** 2 : suffix === "Ki" ? 1024 : suffix === "T" ? 1e3 ** 4 : suffix === "G" ? 1e3 ** 3 : suffix === "M" ? 1e3 ** 2 : suffix === "k" ? 1e3 : 1));
7816
- }
7817
8301
  //#endregion
7818
8302
  //#region src/daemon.ts
7819
8303
  /**
@@ -8019,174 +8503,329 @@ var Daemon = class extends ResourceBuilder {
8019
8503
  }
8020
8504
  };
8021
8505
  //#endregion
8022
- //#region src/build.ts
8506
+ //#region src/email.ts
8023
8507
  /**
8024
- * Represents a build resource that executes bash scripts to build code.
8025
- * Builds are designed to be stateless and can be triggered on-demand to compile,
8026
- * test, or package application code.
8508
+ * Email infrastructure for sending and receiving mail on customer-owned
8509
+ * domains (AWS SES). Provisions a shared configuration set, optional inbound
8510
+ * and event wiring, and one email identity (Easy DKIM) per seed domain.
8511
+ *
8512
+ * The resource owns the email infrastructure, not the domain lifecycle. Seed
8513
+ * domains are optional: products that create and verify domains dynamically
8514
+ * should manage identities at runtime through the `email/manage-identities`
8515
+ * grant instead of listing them here. Runtime-created identities are
8516
+ * application data — they are not tracked by the deployment and survive stack
8517
+ * deletion.
8518
+ *
8519
+ * After deployment, create the per-domain DKIM CNAME records from the
8520
+ * resource outputs — SES verifies each domain once the records exist in DNS.
8521
+ *
8522
+ * When inbound mail is configured, the receipt rule is a catch-all (no
8523
+ * recipient filter), so mail for runtime-verified identities lands in the
8524
+ * bucket without redeployment. Setup activates the provisioned receipt rule
8525
+ * set automatically. SES permits one active receipt rule set per account and
8526
+ * region, so an AWS stack may contain only one Email with inbound delivery,
8527
+ * and installing it makes its rule set the account's active rule set.
8027
8528
  */
8028
- var Build = class {
8029
- _config = {
8030
- links: [],
8031
- environment: {}
8032
- };
8529
+ var Email = class extends ResourceBuilder {
8530
+ _config = { domains: [] };
8033
8531
  /**
8034
- * Creates a new Build builder.
8035
- * @param id Identifier for the build resource. Must contain only alphanumeric characters, hyphens, and underscores ([A-Za-z0-9-_]). Maximum 64 characters.
8532
+ * Creates a new Email builder.
8533
+ * @param id Identifier for the email resource. Must contain only alphanumeric characters, hyphens, and underscores ([A-Za-z0-9-_]). Maximum 64 characters.
8036
8534
  */
8037
8535
  constructor(id) {
8536
+ super();
8038
8537
  this._config.id = id;
8039
8538
  }
8040
8539
  /**
8041
- * Returns a ResourceType representing any build resource.
8042
- * Used for creating permission targets that apply to all build resources.
8043
- * @returns The "build" resource type.
8540
+ * Returns a ResourceType representing any email resource.
8541
+ * Used for creating permission targets that apply to all email resources.
8542
+ * @returns The "email" resource type.
8044
8543
  */
8045
8544
  static any() {
8046
- return "build";
8545
+ return "email";
8047
8546
  }
8048
8547
  /**
8049
- * Sets the compute type for the build.
8050
- * @param type The compute type (small, medium, large, x-large).
8051
- * @returns The Build builder instance.
8548
+ * Sets the seed mail domains provisioned at deploy time (one SES identity
8549
+ * each). Optional — omit for products that manage domains at runtime.
8550
+ * @param domains The mail domains (e.g. `["mail.example.com"]`).
8551
+ * @returns The Email builder instance.
8052
8552
  */
8053
- computeType(type) {
8054
- this._config.computeType = type;
8553
+ domains(domains) {
8554
+ this._config.domains = domains;
8055
8555
  return this;
8056
8556
  }
8057
8557
  /**
8058
- * Sets key-value pairs as environment variables for the build.
8059
- * @param env A map of environment variable names to their values.
8060
- * @returns The Build builder instance.
8558
+ * Adds a single seed mail domain.
8559
+ * @param domain The mail domain (e.g. `"mail.example.com"`).
8560
+ * @returns The Email builder instance.
8061
8561
  */
8062
- environment(env) {
8063
- this._config.environment = env;
8562
+ domain(domain) {
8563
+ this._config.domains = [...this._config.domains ?? [], domain];
8064
8564
  return this;
8065
8565
  }
8066
8566
  /**
8067
- * Links another resource (e.g., Storage, ArtifactRegistry, Role) to this build.
8068
- * This makes the linked resource accessible to the build, often by injecting
8069
- * environment variables or granting permissions.
8070
- * @param resource The resource to link.
8071
- * @returns The Build builder instance.
8567
+ * Configures inbound mail: raw incoming mail for the configured domains is
8568
+ * written to the linked Storage bucket. Note the post-deploy activation
8569
+ * step described in the class documentation.
8570
+ * @param storage The Storage resource that receives raw incoming mail.
8571
+ * @returns The Email builder instance.
8072
8572
  */
8073
- link(resource) {
8074
- if (!this._config.links) this._config.links = [];
8075
- this._config.links.push(resource.ref());
8573
+ inbound(storage) {
8574
+ this._config.inbound = { storage: storage.ref() };
8076
8575
  return this;
8077
8576
  }
8078
8577
  /**
8079
- * Assigns a permission profile to this build.
8080
- * The profile defines the permissions granted to this build when interacting
8081
- * with other cloud resources.
8082
- * @param permissions The permission profile name.
8083
- * @returns The Build builder instance.
8578
+ * Configures sending events: send / delivery / bounce / complaint /
8579
+ * delivery-delay / reject events are delivered to the linked Queue.
8580
+ * @param queue The Queue resource that receives sending events.
8581
+ * @returns The Email builder instance.
8084
8582
  */
8085
- permissions(permissions) {
8086
- this._config.permissions = permissions;
8583
+ events(queue) {
8584
+ this._config.events = { queue: queue.ref() };
8087
8585
  return this;
8088
8586
  }
8089
8587
  /**
8090
- * Builds and validates the build configuration.
8091
- * @returns An immutable Resource representing the configured build.
8092
- * @throws Error if the build configuration is invalid.
8588
+ * Builds and validates the email configuration.
8589
+ * @returns An immutable Resource representing the configured email infrastructure.
8590
+ * @throws Error if the email configuration is invalid.
8093
8591
  */
8094
8592
  build() {
8095
- return new Resource({
8096
- type: "build",
8097
- ...BuildSchema.parse(this._config)
8593
+ const config = EmailSchema.parse(this._config);
8594
+ return this.resource({
8595
+ type: "email",
8596
+ ...config
8098
8597
  });
8099
8598
  }
8100
8599
  };
8101
8600
  //#endregion
8102
- //#region src/artifact-registry.ts
8103
- /**
8104
- * Represents an artifact registry for storing container images and other build artifacts.
8105
- * This is a high-level wrapper resource that provides a cloud-agnostic interface over
8106
- * AWS ECR, GCP Artifact Registry, and Azure Container Registry.
8107
- */
8108
- var ArtifactRegistry = class {
8109
- _config = {};
8110
- /**
8111
- * Creates a new ArtifactRegistry builder.
8112
- * @param id Identifier for the artifact registry. Must contain only alphanumeric characters, hyphens, and underscores ([A-Za-z0-9-_]). Maximum 64 characters.
8113
- */
8114
- constructor(id) {
8115
- this._config.id = id;
8116
- }
8117
- /**
8118
- * Returns a ResourceType representing any artifact registry resource.
8119
- * Used for creating permission targets that apply to all artifact registry resources.
8120
- * @returns The "artifact-registry" resource type.
8121
- */
8122
- static any() {
8123
- return "artifact-registry";
8124
- }
8125
- /**
8126
- * AWS-only: Configure ECR private image replication to additional regions.
8127
- * Ensures images pushed in the registry's home region are automatically
8128
- * available in these destination regions (required when Lambda or other
8129
- * compute runs in a different region).
8130
- * @param regions - AWS region codes to replicate to (e.g., ["us-east-2", "eu-west-1"])
8131
- */
8132
- replicationRegions(regions) {
8133
- this._config.replicationRegions = regions;
8134
- return this;
8135
- }
8136
- /**
8137
- * Builds and validates the artifact registry configuration.
8138
- * @returns An immutable Resource representing the configured artifact registry.
8139
- * @throws Error if the artifact registry configuration is invalid.
8140
- */
8141
- build() {
8142
- return new Resource({
8143
- type: "artifact-registry",
8144
- ...ArtifactRegistrySchema.parse(this._config)
8145
- });
8601
+ //#region src/get-resource-outputs.ts
8602
+ const ResourceSchemaMapping = {
8603
+ function: {
8604
+ input: WorkerSchema,
8605
+ output: WorkerOutputsSchema
8606
+ },
8607
+ container: {
8608
+ input: ContainerSchema,
8609
+ output: ContainerOutputsSchema
8610
+ },
8611
+ storage: {
8612
+ input: StorageSchema,
8613
+ output: StorageOutputsSchema
8614
+ },
8615
+ kv: {
8616
+ input: KvSchema,
8617
+ output: KvOutputsSchema
8618
+ },
8619
+ queue: {
8620
+ input: QueueSchema,
8621
+ output: QueueOutputsSchema
8622
+ },
8623
+ vault: {
8624
+ input: VaultSchema,
8625
+ output: VaultOutputsSchema
8626
+ },
8627
+ build: {
8628
+ input: BuildSchema,
8629
+ output: BuildOutputsSchema
8630
+ },
8631
+ "artifact-registry": {
8632
+ input: ArtifactRegistrySchema,
8633
+ output: ArtifactRegistryOutputsSchema
8634
+ },
8635
+ "service-account": {
8636
+ input: ServiceAccountSchema,
8637
+ output: ServiceAccountOutputsSchema
8638
+ },
8639
+ "remote-stack-management": {
8640
+ input: RemoteStackManagementSchema,
8641
+ output: RemoteStackManagementOutputsSchema
8146
8642
  }
8147
8643
  };
8644
+ function getResourceOutputs(params) {
8645
+ const { state, resource } = params;
8646
+ const resourceState = state.resources[resource.name];
8647
+ if (!resourceState) throw new AlienError(ResourceNotFoundError.create({
8648
+ resourceId: resource.name,
8649
+ availableResources: Object.keys(state.resources)
8650
+ }));
8651
+ const outputs = ResourceSchemaMapping[resource.type].output.safeParse(resourceState.outputs);
8652
+ if (!outputs.success) throw new AlienError(ResourceOutputsParseError.create({
8653
+ resourceName: resource.name,
8654
+ resourceType: resource.type,
8655
+ validationErrors: z$1.prettifyError(outputs.error)
8656
+ }));
8657
+ return outputs.data;
8658
+ }
8148
8659
  //#endregion
8149
- //#region src/vault.ts
8150
- /**
8151
- * Represents a secure vault for storing secrets.
8152
- * This resource provides a platform-agnostic interface over cloud-native secret management services:
8153
- * - AWS: AWS Secrets Manager with prefixed secret names
8154
- * - GCP: Secret Manager with prefixed secret names
8155
- * - Azure: Key Vault resource
8156
- *
8157
- * The vault acts as a namespace for secrets and controls access permissions for workers and services.
8158
- */
8159
- var Vault = class extends ResourceBuilder {
8160
- _config = {};
8161
- /**
8162
- * Creates a new Vault builder.
8163
- * @param id Identifier for the vault. Must contain only alphanumeric characters, hyphens, and underscores ([A-Za-z0-9-_]). Maximum 64 characters.
8164
- */
8165
- constructor(id) {
8166
- super();
8167
- this._config.id = id;
8660
+ //#region src/input.ts
8661
+ const stackInputDraftSymbol = Symbol("alien.stackInputDraft");
8662
+ const stackInputDefinitionsSymbol = Symbol("alien.stackInputDefinitions");
8663
+ function inputs(drafts) {
8664
+ const result = {};
8665
+ const definitions = [];
8666
+ for (const [id, draft] of Object.entries(drafts)) {
8667
+ validateInputId(id);
8668
+ validateDraft(id, draft);
8669
+ result[id] = {
8670
+ id,
8671
+ kind: draft.kind
8672
+ };
8673
+ definitions.push({
8674
+ id,
8675
+ kind: draft.kind,
8676
+ providedBy: normalizeArray(draft.options.providedBy),
8677
+ required: draft.options.required,
8678
+ label: draft.options.label,
8679
+ description: draft.options.description,
8680
+ placeholder: draft.options.placeholder,
8681
+ default: toDefaultValue(draft.kind, draft.options.default),
8682
+ platforms: draft.options.platforms ? [...draft.options.platforms] : void 0,
8683
+ validation: Object.keys(draft.validation).length > 0 ? draft.validation : void 0,
8684
+ env: normalizeEnv(draft.options.env)
8685
+ });
8168
8686
  }
8169
- /**
8170
- * Returns a ResourceType representing any vault resource.
8171
- * Used for creating permission targets that apply to all vault resources.
8172
- * @returns The "vault" resource type.
8173
- */
8174
- static any() {
8175
- return "vault";
8687
+ Object.defineProperty(result, stackInputDefinitionsSymbol, {
8688
+ value: Object.freeze(definitions),
8689
+ enumerable: false
8690
+ });
8691
+ return result;
8692
+ }
8693
+ function getStackInputDefinitions(value) {
8694
+ if (Array.isArray(value)) return [...value];
8695
+ return [...value[stackInputDefinitionsSymbol]];
8696
+ }
8697
+ function defineInput(kind, options, validation = {}) {
8698
+ return {
8699
+ [stackInputDraftSymbol]: true,
8700
+ kind,
8701
+ options,
8702
+ validation
8703
+ };
8704
+ }
8705
+ function defineStringInput(options) {
8706
+ return defineInput("string", options, {
8707
+ minLength: options.minLength,
8708
+ maxLength: options.maxLength,
8709
+ pattern: options.pattern,
8710
+ format: options.format
8711
+ });
8712
+ }
8713
+ function defineSecretInput(options) {
8714
+ return defineInput("secret", options, {
8715
+ minLength: options.minLength,
8716
+ maxLength: options.maxLength,
8717
+ pattern: options.pattern,
8718
+ format: options.format
8719
+ });
8720
+ }
8721
+ function defineNumberInput(options) {
8722
+ return defineInput("number", options, {
8723
+ min: numberToString(options.min),
8724
+ max: numberToString(options.max)
8725
+ });
8726
+ }
8727
+ function defineIntegerInput(options) {
8728
+ return defineInput("integer", options, {
8729
+ min: integerToString(options.min, "min"),
8730
+ max: integerToString(options.max, "max")
8731
+ });
8732
+ }
8733
+ function defineBooleanInput(options) {
8734
+ return defineInput("boolean", options);
8735
+ }
8736
+ function defineEnumInput(values, options) {
8737
+ return defineInput("enum", options, { values: [...values] });
8738
+ }
8739
+ function defineStringListInput(options) {
8740
+ return defineInput("stringList", options, {
8741
+ minItems: options.minItems,
8742
+ maxItems: options.maxItems
8743
+ });
8744
+ }
8745
+ function normalizeArray(value) {
8746
+ return Array.isArray(value) ? [...value] : [value];
8747
+ }
8748
+ function normalizeEnv(value) {
8749
+ if (!value) return [];
8750
+ return normalizeArray(value).map((mapping) => {
8751
+ if (typeof mapping === "string") return { name: mapping };
8752
+ return {
8753
+ name: mapping.name,
8754
+ targetResources: mapping.targetResources ? [...mapping.targetResources] : void 0,
8755
+ type: mapping.type
8756
+ };
8757
+ });
8758
+ }
8759
+ function toDefaultValue(kind, value) {
8760
+ if (value === void 0) return;
8761
+ switch (kind) {
8762
+ case "string":
8763
+ case "enum": return {
8764
+ type: "string",
8765
+ value: String(value)
8766
+ };
8767
+ case "number": return {
8768
+ type: "number",
8769
+ value: numberToString(value) ?? ""
8770
+ };
8771
+ case "integer": return {
8772
+ type: "number",
8773
+ value: integerToString(value, "default") ?? ""
8774
+ };
8775
+ case "boolean": return {
8776
+ type: "boolean",
8777
+ value: Boolean(value)
8778
+ };
8779
+ case "stringList": return {
8780
+ type: "stringList",
8781
+ value: [...value]
8782
+ };
8783
+ case "secret": throw new Error("Secret stack inputs cannot declare a default value");
8176
8784
  }
8177
- /**
8178
- * Builds and validates the vault configuration.
8179
- * @returns An immutable Resource representing the configured vault.
8180
- * @throws Error if the vault configuration is invalid.
8181
- */
8182
- build() {
8183
- const config = VaultSchema.parse(this._config);
8184
- return this.resource({
8185
- type: "vault",
8186
- ...config
8187
- });
8785
+ }
8786
+ function validateDraft(id, draft) {
8787
+ if (draft?.[stackInputDraftSymbol] !== true) throw new Error(`Stack input '${id}' must be created with alien.string(), alien.secret(), or another input helper`);
8788
+ if (normalizeArray(draft.options.providedBy).length === 0) throw new Error(`Stack input '${id}' must include at least one providedBy value`);
8789
+ if (!draft.options.label.trim()) throw new Error(`Stack input '${id}' must include a label`);
8790
+ if (draft.options.required && !draft.options.description.trim()) throw new Error(`Stack input '${id}' must include a description when required is true`);
8791
+ validateValidation(id, draft.kind, draft.validation);
8792
+ for (const mapping of normalizeEnv(draft.options.env)) {
8793
+ validateEnvName(id, mapping.name);
8794
+ if (mapping.targetResources?.length === 0) throw new Error(`Stack input '${id}' env mapping '${mapping.name}' cannot use an empty targetResources list`);
8188
8795
  }
8189
- };
8796
+ }
8797
+ function validateInputId(id) {
8798
+ if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(id)) throw new Error(`Stack input '${id}' id must start with a letter or underscore and contain only letters, digits, and underscores`);
8799
+ if (!/[a-z]/.test(id)) throw new Error(`Stack input '${id}' id must not be all-caps env-var style`);
8800
+ }
8801
+ function validateEnvName(id, name) {
8802
+ if (!/^[A-Z_][A-Z0-9_]*$/.test(name)) throw new Error(`Stack input '${id}' env name '${name}' must use uppercase letters, digits, and underscores`);
8803
+ }
8804
+ function validateValidation(id, kind, validation) {
8805
+ const minLength = validation.minLength ?? void 0;
8806
+ const maxLength = validation.maxLength ?? void 0;
8807
+ const minItems = validation.minItems ?? void 0;
8808
+ const maxItems = validation.maxItems ?? void 0;
8809
+ if (minLength !== void 0 && maxLength !== void 0 && minLength > maxLength) throw new Error(`Stack input '${id}' minLength must be less than or equal to maxLength`);
8810
+ if (minItems !== void 0 && maxItems !== void 0 && minItems > maxItems) throw new Error(`Stack input '${id}' minItems must be less than or equal to maxItems`);
8811
+ if (kind === "enum" && (!validation.values || validation.values.length === 0)) throw new Error(`Stack input '${id}' enum values must not be empty`);
8812
+ if (validation.pattern) validatePortablePattern(id, validation.pattern);
8813
+ }
8814
+ function validatePortablePattern(id, pattern) {
8815
+ if (pattern.length === 0) throw new Error(`Stack input '${id}' pattern must not be empty`);
8816
+ if (pattern.startsWith("/") && pattern.endsWith("/") && pattern.length > 1) throw new Error(`Stack input '${id}' pattern must not use regex delimiters`);
8817
+ if (/\\[1-9pPk]/.test(pattern) || /\(\?/.test(pattern) || /\[[^\]]*\[/.test(pattern)) throw new Error(`Stack input '${id}' pattern is not portable across TypeScript, CloudFormation, and Terraform`);
8818
+ }
8819
+ function numberToString(value) {
8820
+ if (value === void 0) return;
8821
+ if (!Number.isFinite(value)) throw new Error("Stack input number constraints must be finite");
8822
+ return String(value);
8823
+ }
8824
+ function integerToString(value, field) {
8825
+ if (value === void 0) return;
8826
+ if (!Number.isInteger(value)) throw new Error(`Stack input integer ${field} must be an integer`);
8827
+ return String(value);
8828
+ }
8190
8829
  //#endregion
8191
8830
  //#region src/kv.ts
8192
8831
  /**
@@ -8329,53 +8968,16 @@ var Postgres = class extends ResourceBuilder {
8329
8968
  highAvailability(value = true) {
8330
8969
  this._config.highAvailability = value;
8331
8970
  return this;
8332
- }
8333
- /**
8334
- * Builds and validates the postgres configuration.
8335
- * @returns An immutable Resource representing the configured database.
8336
- * @throws Error if the configuration is invalid.
8337
- */
8338
- build() {
8339
- const config = PostgresSchema.parse(this._config);
8340
- return this.resource({
8341
- type: "postgres",
8342
- ...config
8343
- });
8344
- }
8345
- };
8346
- //#endregion
8347
- //#region src/ai.ts
8348
- /**
8349
- * Represents an AI Gateway resource that provides a unified interface to
8350
- * managed AI inference services across cloud providers.
8351
- */
8352
- var AI = class extends ResourceBuilder {
8353
- _config = {};
8354
- /**
8355
- * Creates a new AI builder.
8356
- * @param id Identifier for the AI resource. Must contain only alphanumeric characters, hyphens, and underscores ([A-Za-z0-9-_]). Maximum 64 characters.
8357
- */
8358
- constructor(id) {
8359
- super();
8360
- this._config.id = id;
8361
- }
8362
- /**
8363
- * Returns a ResourceType representing any AI resource.
8364
- * Used for creating permission targets that apply to all AI resources.
8365
- * @returns The "ai" resource type.
8366
- */
8367
- static any() {
8368
- return "ai";
8369
- }
8370
- /**
8371
- * Builds and validates the AI configuration.
8372
- * @returns An immutable Resource representing the configured AI Gateway.
8373
- * @throws Error if the AI configuration is invalid.
8971
+ }
8972
+ /**
8973
+ * Builds and validates the postgres configuration.
8974
+ * @returns An immutable Resource representing the configured database.
8975
+ * @throws Error if the configuration is invalid.
8374
8976
  */
8375
8977
  build() {
8376
- const config = AiSchema.parse(this._config);
8978
+ const config = PostgresSchema.parse(this._config);
8377
8979
  return this.resource({
8378
- type: "ai",
8980
+ type: "postgres",
8379
8981
  ...config
8380
8982
  });
8381
8983
  }
@@ -8418,101 +9020,6 @@ var Queue = class extends ResourceBuilder {
8418
9020
  }
8419
9021
  };
8420
9022
  //#endregion
8421
- //#region src/email.ts
8422
- /**
8423
- * Email infrastructure for sending and receiving mail on customer-owned
8424
- * domains (AWS SES). Provisions a shared configuration set, optional inbound
8425
- * and event wiring, and one email identity (Easy DKIM) per seed domain.
8426
- *
8427
- * The resource owns the email infrastructure, not the domain lifecycle. Seed
8428
- * domains are optional: products that create and verify domains dynamically
8429
- * should manage identities at runtime through the `email/manage-identities`
8430
- * grant instead of listing them here. Runtime-created identities are
8431
- * application data — they are not tracked by the deployment and survive stack
8432
- * deletion.
8433
- *
8434
- * After deployment, create the per-domain DKIM CNAME records from the
8435
- * resource outputs — SES verifies each domain once the records exist in DNS.
8436
- *
8437
- * When inbound mail is configured, the receipt rule is a catch-all (no
8438
- * recipient filter), so mail for runtime-verified identities lands in the
8439
- * bucket without redeployment. Setup activates the provisioned receipt rule
8440
- * set automatically. SES permits one active receipt rule set per account and
8441
- * region, so an AWS stack may contain only one Email with inbound delivery,
8442
- * and installing it makes its rule set the account's active rule set.
8443
- */
8444
- var Email = class extends ResourceBuilder {
8445
- _config = { domains: [] };
8446
- /**
8447
- * Creates a new Email builder.
8448
- * @param id Identifier for the email resource. Must contain only alphanumeric characters, hyphens, and underscores ([A-Za-z0-9-_]). Maximum 64 characters.
8449
- */
8450
- constructor(id) {
8451
- super();
8452
- this._config.id = id;
8453
- }
8454
- /**
8455
- * Returns a ResourceType representing any email resource.
8456
- * Used for creating permission targets that apply to all email resources.
8457
- * @returns The "email" resource type.
8458
- */
8459
- static any() {
8460
- return "email";
8461
- }
8462
- /**
8463
- * Sets the seed mail domains provisioned at deploy time (one SES identity
8464
- * each). Optional — omit for products that manage domains at runtime.
8465
- * @param domains The mail domains (e.g. `["mail.example.com"]`).
8466
- * @returns The Email builder instance.
8467
- */
8468
- domains(domains) {
8469
- this._config.domains = domains;
8470
- return this;
8471
- }
8472
- /**
8473
- * Adds a single seed mail domain.
8474
- * @param domain The mail domain (e.g. `"mail.example.com"`).
8475
- * @returns The Email builder instance.
8476
- */
8477
- domain(domain) {
8478
- this._config.domains = [...this._config.domains ?? [], domain];
8479
- return this;
8480
- }
8481
- /**
8482
- * Configures inbound mail: raw incoming mail for the configured domains is
8483
- * written to the linked Storage bucket. Note the post-deploy activation
8484
- * step described in the class documentation.
8485
- * @param storage The Storage resource that receives raw incoming mail.
8486
- * @returns The Email builder instance.
8487
- */
8488
- inbound(storage) {
8489
- this._config.inbound = { storage: storage.ref() };
8490
- return this;
8491
- }
8492
- /**
8493
- * Configures sending events: send / delivery / bounce / complaint /
8494
- * delivery-delay / reject events are delivered to the linked Queue.
8495
- * @param queue The Queue resource that receives sending events.
8496
- * @returns The Email builder instance.
8497
- */
8498
- events(queue) {
8499
- this._config.events = { queue: queue.ref() };
8500
- return this;
8501
- }
8502
- /**
8503
- * Builds and validates the email configuration.
8504
- * @returns An immutable Resource representing the configured email infrastructure.
8505
- * @throws Error if the email configuration is invalid.
8506
- */
8507
- build() {
8508
- const config = EmailSchema.parse(this._config);
8509
- return this.resource({
8510
- type: "email",
8511
- ...config
8512
- });
8513
- }
8514
- };
8515
- //#endregion
8516
9023
  //#region src/service-account.ts
8517
9024
  /**
8518
9025
  * Represents a non-human identity that can be assumed by compute services.
@@ -8575,203 +9082,33 @@ var ServiceAccount = class {
8575
9082
  * platforms: {
8576
9083
  * aws: [{ grant: { actions: ["s3:GetObject"] }, binding: { stack: { resources: ["*"] } } }]
8577
9084
  * }
8578
- * }
8579
- *
8580
- * const account = new ServiceAccount("custom-processor")
8581
- * .stackPermissionSet(customPermissionSet)
8582
- * .build()
8583
- * ```
8584
- *
8585
- * @param permissionSet The permission set object with platform-specific permissions
8586
- * @returns The ServiceAccount builder instance.
8587
- */
8588
- stackPermissionSet(permissionSet) {
8589
- if (!this._config.stackPermissionSets) this._config.stackPermissionSets = [];
8590
- this._config.stackPermissionSets.push(permissionSet);
8591
- return this;
8592
- }
8593
- /**
8594
- * Builds and validates the service account configuration.
8595
- * @returns An immutable Resource representing the configured service account.
8596
- * @throws Error if the service account configuration is invalid.
8597
- */
8598
- build() {
8599
- return new Resource({
8600
- type: "service-account",
8601
- ...ServiceAccountSchema.parse(this._config)
8602
- });
8603
- }
8604
- };
8605
- //#endregion
8606
- //#region src/input.ts
8607
- const stackInputDraftSymbol = Symbol("alien.stackInputDraft");
8608
- const stackInputDefinitionsSymbol = Symbol("alien.stackInputDefinitions");
8609
- function inputs(drafts) {
8610
- const result = {};
8611
- const definitions = [];
8612
- for (const [id, draft] of Object.entries(drafts)) {
8613
- validateInputId(id);
8614
- validateDraft(id, draft);
8615
- result[id] = {
8616
- id,
8617
- kind: draft.kind
8618
- };
8619
- definitions.push({
8620
- id,
8621
- kind: draft.kind,
8622
- providedBy: normalizeArray(draft.options.providedBy),
8623
- required: draft.options.required,
8624
- label: draft.options.label,
8625
- description: draft.options.description,
8626
- placeholder: draft.options.placeholder,
8627
- default: toDefaultValue(draft.kind, draft.options.default),
8628
- platforms: draft.options.platforms ? [...draft.options.platforms] : void 0,
8629
- validation: Object.keys(draft.validation).length > 0 ? draft.validation : void 0,
8630
- env: normalizeEnv(draft.options.env)
8631
- });
8632
- }
8633
- Object.defineProperty(result, stackInputDefinitionsSymbol, {
8634
- value: Object.freeze(definitions),
8635
- enumerable: false
8636
- });
8637
- return result;
8638
- }
8639
- function getStackInputDefinitions(value) {
8640
- if (Array.isArray(value)) return [...value];
8641
- return [...value[stackInputDefinitionsSymbol]];
8642
- }
8643
- function defineInput(kind, options, validation = {}) {
8644
- return {
8645
- [stackInputDraftSymbol]: true,
8646
- kind,
8647
- options,
8648
- validation
8649
- };
8650
- }
8651
- function defineStringInput(options) {
8652
- return defineInput("string", options, {
8653
- minLength: options.minLength,
8654
- maxLength: options.maxLength,
8655
- pattern: options.pattern,
8656
- format: options.format
8657
- });
8658
- }
8659
- function defineSecretInput(options) {
8660
- return defineInput("secret", options, {
8661
- minLength: options.minLength,
8662
- maxLength: options.maxLength,
8663
- pattern: options.pattern,
8664
- format: options.format
8665
- });
8666
- }
8667
- function defineNumberInput(options) {
8668
- return defineInput("number", options, {
8669
- min: numberToString(options.min),
8670
- max: numberToString(options.max)
8671
- });
8672
- }
8673
- function defineIntegerInput(options) {
8674
- return defineInput("integer", options, {
8675
- min: integerToString(options.min, "min"),
8676
- max: integerToString(options.max, "max")
8677
- });
8678
- }
8679
- function defineBooleanInput(options) {
8680
- return defineInput("boolean", options);
8681
- }
8682
- function defineEnumInput(values, options) {
8683
- return defineInput("enum", options, { values: [...values] });
8684
- }
8685
- function defineStringListInput(options) {
8686
- return defineInput("stringList", options, {
8687
- minItems: options.minItems,
8688
- maxItems: options.maxItems
8689
- });
8690
- }
8691
- function normalizeArray(value) {
8692
- return Array.isArray(value) ? [...value] : [value];
8693
- }
8694
- function normalizeEnv(value) {
8695
- if (!value) return [];
8696
- return normalizeArray(value).map((mapping) => {
8697
- if (typeof mapping === "string") return { name: mapping };
8698
- return {
8699
- name: mapping.name,
8700
- targetResources: mapping.targetResources ? [...mapping.targetResources] : void 0,
8701
- type: mapping.type
8702
- };
8703
- });
8704
- }
8705
- function toDefaultValue(kind, value) {
8706
- if (value === void 0) return;
8707
- switch (kind) {
8708
- case "string":
8709
- case "enum": return {
8710
- type: "string",
8711
- value: String(value)
8712
- };
8713
- case "number": return {
8714
- type: "number",
8715
- value: numberToString(value) ?? ""
8716
- };
8717
- case "integer": return {
8718
- type: "number",
8719
- value: integerToString(value, "default") ?? ""
8720
- };
8721
- case "boolean": return {
8722
- type: "boolean",
8723
- value: Boolean(value)
8724
- };
8725
- case "stringList": return {
8726
- type: "stringList",
8727
- value: [...value]
8728
- };
8729
- case "secret": throw new Error("Secret stack inputs cannot declare a default value");
9085
+ * }
9086
+ *
9087
+ * const account = new ServiceAccount("custom-processor")
9088
+ * .stackPermissionSet(customPermissionSet)
9089
+ * .build()
9090
+ * ```
9091
+ *
9092
+ * @param permissionSet The permission set object with platform-specific permissions
9093
+ * @returns The ServiceAccount builder instance.
9094
+ */
9095
+ stackPermissionSet(permissionSet) {
9096
+ if (!this._config.stackPermissionSets) this._config.stackPermissionSets = [];
9097
+ this._config.stackPermissionSets.push(permissionSet);
9098
+ return this;
8730
9099
  }
8731
- }
8732
- function validateDraft(id, draft) {
8733
- if (!draft || draft[stackInputDraftSymbol] !== true) throw new Error(`Stack input '${id}' must be created with alien.string(), alien.secret(), or another input helper`);
8734
- if (normalizeArray(draft.options.providedBy).length === 0) throw new Error(`Stack input '${id}' must include at least one providedBy value`);
8735
- if (!draft.options.label.trim()) throw new Error(`Stack input '${id}' must include a label`);
8736
- if (draft.options.required && !draft.options.description.trim()) throw new Error(`Stack input '${id}' must include a description when required is true`);
8737
- validateValidation(id, draft.kind, draft.validation);
8738
- for (const mapping of normalizeEnv(draft.options.env)) {
8739
- validateEnvName(id, mapping.name);
8740
- if (mapping.targetResources?.length === 0) throw new Error(`Stack input '${id}' env mapping '${mapping.name}' cannot use an empty targetResources list`);
9100
+ /**
9101
+ * Builds and validates the service account configuration.
9102
+ * @returns An immutable Resource representing the configured service account.
9103
+ * @throws Error if the service account configuration is invalid.
9104
+ */
9105
+ build() {
9106
+ return new Resource({
9107
+ type: "service-account",
9108
+ ...ServiceAccountSchema.parse(this._config)
9109
+ });
8741
9110
  }
8742
- }
8743
- function validateInputId(id) {
8744
- if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(id)) throw new Error(`Stack input '${id}' id must start with a letter or underscore and contain only letters, digits, and underscores`);
8745
- if (!/[a-z]/.test(id)) throw new Error(`Stack input '${id}' id must not be all-caps env-var style`);
8746
- }
8747
- function validateEnvName(id, name) {
8748
- if (!/^[A-Z_][A-Z0-9_]*$/.test(name)) throw new Error(`Stack input '${id}' env name '${name}' must use uppercase letters, digits, and underscores`);
8749
- }
8750
- function validateValidation(id, kind, validation) {
8751
- const minLength = validation.minLength ?? void 0;
8752
- const maxLength = validation.maxLength ?? void 0;
8753
- const minItems = validation.minItems ?? void 0;
8754
- const maxItems = validation.maxItems ?? void 0;
8755
- if (minLength !== void 0 && maxLength !== void 0 && minLength > maxLength) throw new Error(`Stack input '${id}' minLength must be less than or equal to maxLength`);
8756
- if (minItems !== void 0 && maxItems !== void 0 && minItems > maxItems) throw new Error(`Stack input '${id}' minItems must be less than or equal to maxItems`);
8757
- if (kind === "enum" && (!validation.values || validation.values.length === 0)) throw new Error(`Stack input '${id}' enum values must not be empty`);
8758
- if (validation.pattern) validatePortablePattern(id, validation.pattern);
8759
- }
8760
- function validatePortablePattern(id, pattern) {
8761
- if (pattern.length === 0) throw new Error(`Stack input '${id}' pattern must not be empty`);
8762
- if (pattern.startsWith("/") && pattern.endsWith("/") && pattern.length > 1) throw new Error(`Stack input '${id}' pattern must not use regex delimiters`);
8763
- if (/\\[1-9pPk]/.test(pattern) || /\(\?/.test(pattern) || /\[[^\]]*\[/.test(pattern)) throw new Error(`Stack input '${id}' pattern is not portable across TypeScript, CloudFormation, and Terraform`);
8764
- }
8765
- function numberToString(value) {
8766
- if (value === void 0) return;
8767
- if (!Number.isFinite(value)) throw new Error("Stack input number constraints must be finite");
8768
- return String(value);
8769
- }
8770
- function integerToString(value, field) {
8771
- if (value === void 0) return;
8772
- if (!Number.isInteger(value)) throw new Error(`Stack input integer ${field} must be an integer`);
8773
- return String(value);
8774
- }
9111
+ };
8775
9112
  //#endregion
8776
9113
  //#region src/stack.ts
8777
9114
  /**
@@ -8817,699 +9154,362 @@ var Stack = class {
8817
9154
  return this;
8818
9155
  }
8819
9156
  /**
8820
- * Configure permissions for this stack.
8821
- * @param config Permission configuration
8822
- * @returns The Stack builder instance.
8823
- */
8824
- permissions(config) {
8825
- this._config.permissions = config;
8826
- return this;
8827
- }
8828
- /**
8829
- * Configure values that must be provided before setup or deployment can proceed.
8830
- * @param inputs Stack input definitions created with alien.inputs({...}).
8831
- * @returns The Stack builder instance.
8832
- */
8833
- inputs(inputs) {
8834
- this._config.inputs = getStackInputDefinitions(inputs);
8835
- return this;
8836
- }
8837
- /**
8838
- * Gets the stack ID without building/validating the stack.
8839
- * @returns The stack ID.
8840
- */
8841
- get id() {
8842
- return this._config.id;
8843
- }
8844
- /**
8845
- * Builds and validates the stack configuration.
8846
- * @returns The complete and validated stack configuration.
8847
- * @throws Error if the stack configuration is invalid.
8848
- */
8849
- build() {
8850
- return StackSchema.parse(this._config);
8851
- }
8852
- };
8853
- //#endregion
8854
- //#region src/error.ts
8855
- /**
8856
- * This module provides a structured error handling system similar to Rust's error types,
8857
- * with TypeScript type safety, error chaining, and context preservation.
8858
- *
8859
- * @example Basic Usage
8860
- * ```typescript
8861
- * import { AlienError, defineError } from '@alienplatform/core'
8862
- * import { z } from 'zod'
8863
- *
8864
- * // Define a type-safe error
8865
- * const DatabaseError = defineError({
8866
- * code: "DATABASE_CONNECTION_FAILED",
8867
- * context: z.object({
8868
- * host: z.string(),
8869
- * port: z.number(),
8870
- * reason: z.string(),
8871
- * }),
8872
- * message: ({ host, port, reason }) => `Failed to connect to database '${host}:${port}': ${reason}`,
8873
- * retryable: true,
8874
- * internal: false,
8875
- * httpStatusCode: 502,
8876
- * })
8877
- *
8878
- * // Use it
8879
- * throw new AlienError(DatabaseError.create({
8880
- * host: "localhost",
8881
- * port: 5432,
8882
- * reason: "Connection timeout"
8883
- * }))
8884
- * ```
8885
- *
8886
- * @example Error Chaining
8887
- * ```typescript
8888
- * try {
8889
- * // Some operation that fails
8890
- * throw new Error("Connection refused")
8891
- * } catch (error) {
8892
- * throw (await AlienError.from(error)).withContext(
8893
- * DatabaseError.create({
8894
- * host: "localhost",
8895
- * port: 5432,
8896
- * reason: "Connection refused by server"
8897
- * })
8898
- * )
8899
- * }
8900
- * ```
8901
- *
8902
- * @example External API Sanitization
8903
- * ```typescript
8904
- * const internalError = new AlienError(InternalApiError.create({
8905
- * service: "payment-processor",
8906
- * details: "Database password expired",
8907
- * traceId: "trace-12345"
8908
- * }))
8909
- *
8910
- * // Safe for external APIs (sanitizes internal errors)
8911
- * const safeResponse = internalError.toExternal()
8912
- * ```
8913
- */
8914
- /**
8915
- * Helper function to create type-safe error definitions.
8916
- *
8917
- * This function provides a clean API for defining reusable error types
8918
- * with full TypeScript type safety and Zod validation.
8919
- *
8920
- * @template TContext - Zod schema type for the error context
8921
- * @param metadata - Error metadata including code, schema, and message generator
8922
- * @returns Object with metadata and a create function for error instances
8923
- *
8924
- * @example
8925
- * ```typescript
8926
- * const UserNotFound = defineError({
8927
- * code: "USER_NOT_FOUND",
8928
- * context: z.object({
8929
- * userId: z.string(),
8930
- * searchMethod: z.string(),
8931
- * }),
8932
- * message: ({ userId, searchMethod }) =>
8933
- * `User '${userId}' not found using method '${searchMethod}'`,
8934
- * retryable: false,
8935
- * internal: false,
8936
- * httpStatusCode: 404,
8937
- * })
8938
- *
8939
- * // Usage
8940
- * const error = UserNotFound.create({
8941
- * userId: "123",
8942
- * searchMethod: "database_lookup"
8943
- * })
8944
- * ```
8945
- */
8946
- function defineError(metadata) {
8947
- return {
8948
- metadata,
8949
- contextSchema: metadata.context,
8950
- create: (context) => ({
8951
- metadata,
8952
- contextSchema: metadata.context,
8953
- context,
8954
- toOptions: () => ({
8955
- code: metadata.code,
8956
- message: metadata.message(context),
8957
- retryable: metadata.retryable,
8958
- internal: metadata.internal,
8959
- httpStatusCode: metadata.httpStatusCode,
8960
- context
8961
- })
8962
- })
8963
- };
8964
- }
8965
- /**
8966
- * Main AlienError class that provides structured error handling.
8967
- *
8968
- * This class extends the standard JavaScript Error with additional features:
8969
- * - Type-safe context data
8970
- * - Error chaining and source tracking
8971
- * - Retryability and internal/external visibility flags
8972
- * - HTTP status code mapping
8973
- * - Sanitization for external APIs
8974
- *
8975
- * @template TContext - Zod schema type for the error context
8976
- *
8977
- * @example Basic Construction
8978
- * ```typescript
8979
- * const error = new AlienError(DatabaseError.create({
8980
- * host: "localhost",
8981
- * port: 5432,
8982
- * reason: "Timeout"
8983
- * }))
8984
- * ```
8985
- *
8986
- * @example Converting JavaScript Errors
8987
- * ```typescript
8988
- * try {
8989
- * JSON.parse("invalid json")
8990
- * } catch (jsError) {
8991
- * const alienError = AlienError.from(jsError)
8992
- * console.log(alienError.code) // "GENERIC_ERROR"
8993
- * }
8994
- * ```
8995
- *
8996
- * @example Error Chaining
8997
- * ```typescript
8998
- * const contextualError = AlienError.from(new Error("Network timeout"))
8999
- * .withContext(DatabaseError.create({
9000
- * host: "localhost",
9001
- * port: 5432,
9002
- * reason: "Connection timeout"
9003
- * }))
9004
- *
9005
- * // Check error chain
9006
- * console.log(contextualError.hasErrorCode("DATABASE_CONNECTION_FAILED")) // true
9007
- * console.log(contextualError.toString()) // Shows full error chain
9008
- * ```
9157
+ * Configure permissions for this stack.
9158
+ * @param config Permission configuration
9159
+ * @returns The Stack builder instance.
9160
+ */
9161
+ permissions(config) {
9162
+ this._config.permissions = config;
9163
+ return this;
9164
+ }
9165
+ /**
9166
+ * Configure values that must be provided before setup or deployment can proceed.
9167
+ * @param inputs Stack input definitions created with alien.inputs({...}).
9168
+ * @returns The Stack builder instance.
9169
+ */
9170
+ inputs(inputs) {
9171
+ this._config.inputs = getStackInputDefinitions(inputs);
9172
+ return this;
9173
+ }
9174
+ /**
9175
+ * Gets the stack ID without building/validating the stack.
9176
+ * @returns The stack ID.
9177
+ */
9178
+ get id() {
9179
+ return this._config.id;
9180
+ }
9181
+ /**
9182
+ * Builds and validates the stack configuration.
9183
+ * @returns The complete and validated stack configuration.
9184
+ * @throws Error if the stack configuration is invalid.
9185
+ */
9186
+ build() {
9187
+ return StackSchema.parse(this._config);
9188
+ }
9189
+ };
9190
+ //#endregion
9191
+ //#region src/storage.ts
9192
+ /**
9193
+ * Represents an object storage bucket.
9009
9194
  */
9010
- var AlienError = class AlienError extends Error {
9011
- /** Unique error code identifying the error type */
9012
- code;
9013
- /** Whether this error can be safely retried */
9014
- retryable;
9015
- /** Whether this error contains sensitive internal information */
9016
- internal;
9017
- /** HTTP status code for API responses */
9018
- httpStatusCode;
9019
- /** Type-safe context data specific to this error */
9020
- context;
9021
- /** Optional human-facing remediation hint */
9022
- hint;
9023
- /** Source error that caused this error (for chaining) */
9024
- source;
9025
- constructor(input) {
9026
- let options;
9027
- if ("metadata" in input && "context" in input) {
9028
- const { metadata, context: contextData } = input;
9029
- const message = metadata.message(contextData);
9030
- options = {
9031
- code: metadata.code,
9032
- message,
9033
- retryable: metadata.retryable,
9034
- internal: metadata.internal,
9035
- httpStatusCode: metadata.httpStatusCode,
9036
- context: contextData
9037
- };
9038
- } else options = input;
9039
- const message = options.message;
9040
- super(message, { cause: options.source });
9041
- this.name = "AlienError";
9042
- this.code = options.code;
9043
- this.retryable = options.retryable;
9044
- this.internal = options.internal;
9045
- this.httpStatusCode = options.httpStatusCode ?? 500;
9046
- this.context = options.context;
9047
- this.hint = options.hint;
9048
- this.source = void 0;
9049
- if (options.source && typeof options.source === "object") {
9050
- if ("code" in options.source && "message" in options.source && "retryable" in options.source && "internal" in options.source) this.source = new AlienError(options.source);
9051
- }
9195
+ var Storage = class extends ResourceBuilder {
9196
+ _config = {
9197
+ publicRead: false,
9198
+ versioning: false,
9199
+ lifecycleRules: [],
9200
+ corsAllowedOrigins: []
9201
+ };
9202
+ /**
9203
+ * Creates a new Storage builder.
9204
+ * @param id ID of the storage bucket. For names with dots, each dot-separated label must be ≤ 63 characters.
9205
+ */
9206
+ constructor(id) {
9207
+ super();
9208
+ this._config.id = id;
9052
9209
  }
9053
9210
  /**
9054
- * Create an AlienError from a type-safe error definition.
9055
- *
9056
- * @template TContext - Zod schema type for the error context
9057
- * @param definition - Error definition with type-safe context
9058
- * @returns New AlienError instance
9211
+ * Returns a ResourceType representing any storage resource.
9212
+ * Used for creating permission targets that apply to all storage resources.
9213
+ * @returns The "storage" resource type.
9059
9214
  */
9060
- static fromDefinition(definition) {
9061
- return new AlienError(definition);
9215
+ static any() {
9216
+ return "storage";
9062
9217
  }
9063
9218
  /**
9064
- * Create an AlienError from raw options (for compatibility).
9065
- *
9066
- * @param options - Raw error options conforming to AlienErrorOptions schema
9067
- * @returns New AlienError instance
9219
+ * Allows public read access to objects without authentication.
9220
+ * Default: `false`.
9221
+ * @param value Whether to allow public read access.
9222
+ * @returns The Storage builder instance.
9068
9223
  */
9069
- static fromOptions(options) {
9070
- return new AlienError(AlienErrorSchema.parse(options));
9224
+ publicRead(value) {
9225
+ this._config.publicRead = value;
9226
+ return this;
9071
9227
  }
9072
9228
  /**
9073
- * Helper function to get a user-friendly type name for error context.
9074
- *
9075
- * @param error - Any value to get the type name for
9076
- * @returns User-friendly type name
9229
+ * Enables object versioning.
9230
+ * Default: `false`.
9231
+ * @param value Whether to enable versioning.
9232
+ * @returns The Storage builder instance.
9077
9233
  */
9078
- static getErrorTypeName(error) {
9079
- if (error === null) return "null";
9080
- if (error === void 0) return "undefined";
9081
- if (error?.constructor?.name) return error.constructor.name;
9082
- const typeofResult = typeof error;
9083
- return typeofResult === "object" ? "Object" : typeofResult.charAt(0).toUpperCase() + typeofResult.slice(1);
9234
+ versioning(value) {
9235
+ this._config.versioning = value;
9236
+ return this;
9084
9237
  }
9085
9238
  /**
9086
- * Convert a JavaScript Error or any object to a generic AlienError.
9087
- *
9088
- * This is equivalent to Rust's `.into_alien_error()` pattern and provides
9089
- * a way to convert any JavaScript error into the structured AlienError format.
9090
- *
9091
- * @param error - Any JavaScript error or object to convert
9092
- * @returns AlienError with GENERIC_ERROR code and preserved original error
9093
- *
9094
- * @example
9095
- * ```typescript
9096
- * try {
9097
- * throw new TypeError("Invalid argument")
9098
- * } catch (error) {
9099
- * const alienError = AlienError.from(error)
9100
- * console.log(alienError.code) // "GENERIC_ERROR"
9101
- * console.log(alienError.context?.originalError) // Serialized TypeError
9102
- * }
9103
- * ```
9104
- *
9105
- * @example Chaining with context
9106
- * ```typescript
9107
- * try {
9108
- * JSON.parse("invalid")
9109
- * } catch (error) {
9110
- * throw AlienError.from(error).withContext(
9111
- * ValidationError.create({
9112
- * input: "invalid",
9113
- * expectedFormat: "JSON"
9114
- * })
9115
- * )
9116
- * }
9117
- * ```
9118
- *
9119
- * @example AxiosError conversion
9120
- * ```typescript
9121
- * try {
9122
- * await axios.get('/api/resource')
9123
- * } catch (error) {
9124
- * // If error.response.data contains a valid AlienError structure, it will be parsed
9125
- * const alienError = AlienError.from(error)
9126
- * console.log(alienError.code) // Could be "REMOTE_RESOURCE_NOT_FOUND" if parsed from response
9127
- * }
9128
- * ```
9239
+ * Defines lifecycle rules for automatic object management (e.g., expiration).
9240
+ * @param rules An array of lifecycle rules.
9241
+ * @returns The Storage builder instance.
9129
9242
  */
9130
- static async from(error) {
9131
- if (error instanceof AlienError) return error;
9132
- if (error instanceof Response) {
9133
- let errorBody;
9134
- try {
9135
- errorBody = await error.json();
9136
- } catch {
9137
- return new AlienError({
9138
- code: "GENERIC_ERROR",
9139
- message: `HTTP request failed with status ${error.status}`,
9140
- retryable: false,
9141
- internal: true,
9142
- httpStatusCode: error.status,
9143
- context: {
9144
- url: error.url,
9145
- status: error.status,
9146
- statusText: error.statusText
9147
- }
9148
- });
9149
- }
9150
- const parseResult = AlienErrorSchema.safeParse(errorBody);
9151
- if (parseResult.success) return new AlienError(parseResult.data);
9152
- return new AlienError({
9153
- code: "GENERIC_ERROR",
9154
- message: errorBody?.message || `HTTP request failed with status ${error.status}`,
9155
- retryable: false,
9156
- internal: true,
9157
- httpStatusCode: error.status,
9158
- context: {
9159
- url: error.url,
9160
- status: error.status,
9161
- statusText: error.statusText,
9162
- responseBody: errorBody
9163
- }
9164
- });
9165
- }
9166
- if (error?.response?.data && typeof error.response.data === "object") {
9167
- const parseResult = AlienErrorSchema.safeParse(error.response.data);
9168
- if (parseResult.success) return new AlienError(parseResult.data);
9169
- }
9170
- const serialized = serializeError(error);
9171
- const message = serialized?.message || String(error);
9172
- return new AlienError({
9173
- code: "GENERIC_ERROR",
9174
- message,
9175
- retryable: false,
9176
- internal: true,
9177
- httpStatusCode: 500,
9178
- context: {
9179
- originalError: serialized,
9180
- errorType: AlienError.getErrorTypeName(error)
9181
- }
9243
+ lifecycleRules(rules) {
9244
+ this._config.lifecycleRules = rules;
9245
+ return this;
9246
+ }
9247
+ /**
9248
+ * Allows browser reads from the listed origins through signed URLs.
9249
+ * Providers enable `GET` and `HEAD`; use `*` only when the signed URL itself
9250
+ * is the credential and browser cookies are not involved.
9251
+ * @param origins Allowed browser origins.
9252
+ * @returns The Storage builder instance.
9253
+ */
9254
+ corsAllowedOrigins(origins) {
9255
+ this._config.corsAllowedOrigins = origins;
9256
+ return this;
9257
+ }
9258
+ /**
9259
+ * Builds and validates the storage configuration.
9260
+ * @returns An immutable Resource representing the configured storage bucket.
9261
+ * @throws Error if the storage configuration is invalid.
9262
+ */
9263
+ build() {
9264
+ const config = StorageSchema.parse(this._config);
9265
+ return this.resource({
9266
+ type: "storage",
9267
+ ...config
9182
9268
  });
9183
9269
  }
9270
+ };
9271
+ //#endregion
9272
+ //#region src/vault.ts
9273
+ /**
9274
+ * Represents a secure vault for storing secrets.
9275
+ * This resource provides a platform-agnostic interface over cloud-native secret management services:
9276
+ * - AWS: AWS Secrets Manager with prefixed secret names
9277
+ * - GCP: Secret Manager with prefixed secret names
9278
+ * - Azure: Key Vault resource
9279
+ *
9280
+ * The vault acts as a namespace for secrets and controls access permissions for workers and services.
9281
+ */
9282
+ var Vault = class extends ResourceBuilder {
9283
+ _config = {};
9184
9284
  /**
9185
- * Add context to this error, creating a new error that wraps this one.
9186
- *
9187
- * This is equivalent to Rust's `.with_context()` pattern and allows
9188
- * building error chains with increasing levels of context.
9189
- *
9190
- * @template TNewContext - Zod schema type for the new context
9191
- * @param definition - Error definition to wrap this error with
9192
- * @returns New AlienError with this error as the source
9193
- *
9194
- * @example
9195
- * ```typescript
9196
- * // Clean fluent API
9197
- * const authError = (await AlienError.from(new Error("ECONNREFUSED")))
9198
- * .withContext(DatabaseError.create({
9199
- * host: "localhost",
9200
- * port: 5432,
9201
- * reason: "Connection refused"
9202
- * }))
9203
- * .withContext(AuthError.create({
9204
- * username: "john",
9205
- * reason: "Database unavailable"
9206
- * }))
9207
- *
9208
- * // Error chain: AuthError -> DatabaseError -> GENERIC_ERROR
9209
- * console.log(authError.toString())
9210
- * ```
9285
+ * Creates a new Vault builder.
9286
+ * @param id Identifier for the vault. Must contain only alphanumeric characters, hyphens, and underscores ([A-Za-z0-9-_]). Maximum 64 characters.
9211
9287
  */
9212
- withContext(definition) {
9213
- const { metadata, context: contextData } = definition;
9214
- const message = metadata.message(contextData);
9215
- const sourceOptions = {
9216
- code: this.code,
9217
- message: this.message,
9218
- retryable: this.retryable,
9219
- internal: this.internal,
9220
- httpStatusCode: this.httpStatusCode,
9221
- context: this.context,
9222
- hint: this.hint,
9223
- source: this.source?.toOptions()
9224
- };
9225
- return new AlienError({
9226
- code: metadata.code,
9227
- message,
9228
- retryable: metadata.retryable,
9229
- internal: metadata.internal,
9230
- httpStatusCode: metadata.httpStatusCode,
9231
- context: contextData,
9232
- source: sourceOptions
9288
+ constructor(id) {
9289
+ super();
9290
+ this._config.id = id;
9291
+ }
9292
+ /**
9293
+ * Returns a ResourceType representing any vault resource.
9294
+ * Used for creating permission targets that apply to all vault resources.
9295
+ * @returns The "vault" resource type.
9296
+ */
9297
+ static any() {
9298
+ return "vault";
9299
+ }
9300
+ /**
9301
+ * Builds and validates the vault configuration.
9302
+ * @returns An immutable Resource representing the configured vault.
9303
+ * @throws Error if the vault configuration is invalid.
9304
+ */
9305
+ build() {
9306
+ const config = VaultSchema.parse(this._config);
9307
+ return this.resource({
9308
+ type: "vault",
9309
+ ...config
9233
9310
  });
9234
9311
  }
9312
+ };
9313
+ //#endregion
9314
+ //#region src/worker.ts
9315
+ /**
9316
+ * Represents a serverless worker that executes code in response to triggers or direct invocations.
9317
+ * Workers are the primary compute resource in serverless applications, designed to be stateless and ephemeral.
9318
+ */
9319
+ var Worker = class extends ResourceBuilder {
9320
+ _config = {
9321
+ links: [],
9322
+ triggers: [],
9323
+ publicEndpoints: [],
9324
+ environment: {}
9325
+ };
9235
9326
  /**
9236
- * Convert this AlienError to the wire format (AlienErrorOptions).
9237
- *
9238
- * This method serializes the error into the standard format used
9239
- * for transmitting errors over the network or storing them.
9240
- *
9241
- * @returns AlienErrorOptions object representing this error
9327
+ * Creates a new Worker builder.
9328
+ * @param id Identifier for the worker. Must contain only alphanumeric characters, hyphens, and underscores ([A-Za-z0-9-_]). Maximum 64 characters.
9242
9329
  */
9243
- toOptions() {
9244
- return {
9245
- code: this.code,
9246
- message: this.message,
9247
- retryable: this.retryable,
9248
- internal: this.internal,
9249
- httpStatusCode: this.httpStatusCode,
9250
- context: this.context,
9251
- hint: this.hint,
9252
- source: this.source?.toOptions()
9253
- };
9330
+ constructor(id) {
9331
+ super();
9332
+ this._config.id = id;
9254
9333
  }
9255
9334
  /**
9256
- * Get a sanitized version for external APIs (hides internal errors).
9257
- *
9258
- * This method is crucial for security - it prevents sensitive internal
9259
- * error details from being exposed to external users while preserving
9260
- * the error chain structure for non-sensitive errors.
9261
- *
9262
- * @returns Sanitized AlienErrorOptions safe for external consumption
9263
- *
9264
- * @example
9265
- * ```typescript
9266
- * const internalError = new AlienError(InternalApiError.create({
9267
- * service: "payment-processor",
9268
- * details: "Database password expired for user admin",
9269
- * traceId: "trace-12345"
9270
- * }))
9271
- *
9272
- * console.log(internalError.toOptions())
9273
- * // Shows full details including sensitive information
9274
- *
9275
- * console.log(internalError.toExternal())
9276
- * // { code: "GENERIC_ERROR", message: "Internal server error", ... }
9277
- * ```
9335
+ * Returns a ResourceType representing any worker resource.
9336
+ * Used for creating permission targets that apply to all worker resources.
9337
+ * @returns The "worker" resource type.
9278
9338
  */
9279
- toExternal() {
9280
- if (this.internal) return {
9281
- code: "GENERIC_ERROR",
9282
- message: "Internal server error",
9283
- retryable: false,
9284
- internal: false,
9285
- httpStatusCode: 500
9286
- };
9287
- return {
9288
- code: this.code,
9289
- message: this.message,
9290
- retryable: this.retryable,
9291
- internal: this.internal,
9292
- httpStatusCode: this.httpStatusCode,
9293
- context: this.context,
9294
- hint: this.hint,
9295
- source: this.source?.toExternal()
9296
- };
9339
+ static any() {
9340
+ return "worker";
9297
9341
  }
9298
9342
  /**
9299
- * Check if this error chain contains an error with a specific code.
9300
- *
9301
- * This method traverses the entire error chain (this error and all
9302
- * source errors) to find if any error has the specified code.
9303
- *
9304
- * @param code - Error code to search for
9305
- * @returns True if the code is found anywhere in the error chain
9306
- *
9307
- * @example
9308
- * ```typescript
9309
- * const chainedError = authError.withContext(dbError.withContext(networkError))
9343
+ * Sets the code for the worker, either a pre-built image or source code to be built.
9344
+ * @param code The worker code configuration.
9345
+ * @returns The Worker builder instance.
9346
+ */
9347
+ code(code) {
9348
+ this._config.code = code;
9349
+ return this;
9350
+ }
9351
+ /**
9352
+ * Sets the memory allocated to the worker in megabytes (MB).
9353
+ * Constraints: 128‑32768 MB (platform-specific limits may apply).
9354
+ * Default: 512 MB.
9355
+ * @param mb The memory in MB.
9356
+ * @returns The Worker builder instance.
9357
+ */
9358
+ memoryMb(mb) {
9359
+ this._config.memoryMb = mb;
9360
+ return this;
9361
+ }
9362
+ /**
9363
+ * Sets the maximum execution time for the worker in seconds.
9364
+ * Constraints: 1‑3600 seconds (platform-specific limits may apply).
9365
+ * Default: 30 seconds.
9366
+ * @param sec The timeout in seconds.
9367
+ * @returns The Worker builder instance.
9368
+ */
9369
+ timeoutSeconds(sec) {
9370
+ this._config.timeoutSeconds = sec;
9371
+ return this;
9372
+ }
9373
+ /**
9374
+ * Sets the maximum number of concurrent executions allowed for the worker.
9375
+ * `null` means platform default applies.
9376
+ * @param limit The concurrency limit, or `null` for platform default.
9377
+ * @returns The Worker builder instance.
9378
+ */
9379
+ concurrencyLimit(limit) {
9380
+ this._config.concurrencyLimit = limit;
9381
+ return this;
9382
+ }
9383
+ /**
9384
+ * Exposes a named public HTTP endpoint for the worker.
9310
9385
  *
9311
- * console.log(chainedError.hasErrorCode("AUTH_FAILED")) // true
9312
- * console.log(chainedError.hasErrorCode("DATABASE_CONNECTION_FAILED")) // true
9313
- * console.log(chainedError.hasErrorCode("NETWORK_TIMEOUT")) // true
9314
- * console.log(chainedError.hasErrorCode("NONEXISTENT_ERROR")) // false
9315
- * ```
9386
+ * If no public endpoint is declared, the worker is private and only reachable
9387
+ * through triggers, commands, or provider invocation APIs.
9388
+ */
9389
+ publicEndpoint(name, options = {}) {
9390
+ if (!this._config.publicEndpoints) this._config.publicEndpoints = [];
9391
+ this._config.publicEndpoints.push({
9392
+ name,
9393
+ hostLabel: options.hostLabel,
9394
+ wildcardSubdomains: options.wildcardSubdomains ?? false
9395
+ });
9396
+ return this;
9397
+ }
9398
+ /**
9399
+ * Sets key-value pairs as environment variables for the worker.
9400
+ * @param env A map of environment variable names to their values.
9401
+ * @returns The Worker builder instance.
9402
+ */
9403
+ environment(env) {
9404
+ this._config.environment = env;
9405
+ return this;
9406
+ }
9407
+ /**
9408
+ * Links another resource (e.g., Storage, KV, Queue) to this worker.
9409
+ * This makes the linked resource accessible to the worker, often by injecting
9410
+ * environment variables or granting permissions.
9411
+ * @param resource The resource to link.
9412
+ * @returns The Worker builder instance.
9413
+ */
9414
+ link(resource) {
9415
+ if (!this._config.links) this._config.links = [];
9416
+ this._config.links.push(resource.ref());
9417
+ return this;
9418
+ }
9419
+ /**
9420
+ * Assigns a permission profile to this worker.
9421
+ * The profile defines the permissions granted to this worker when interacting
9422
+ * with other cloud resources.
9423
+ * @param permissions The permission profile name.
9424
+ * @returns The Worker builder instance.
9316
9425
  */
9317
- hasErrorCode(code) {
9318
- if (this.code === code) return true;
9319
- return this.source?.hasErrorCode(code) ?? false;
9426
+ permissions(permissions) {
9427
+ this._config.permissions = permissions;
9428
+ return this;
9320
9429
  }
9321
9430
  /**
9322
- * Find the first error in the chain with a specific code.
9323
- *
9324
- * This method traverses the error chain and returns the first error
9325
- * instance that matches the specified code, allowing access to its
9326
- * specific context and details.
9327
- *
9328
- * @param code - Error code to search for
9329
- * @returns AlienError instance with the specified code, or undefined if not found
9431
+ * Configures a readiness probe for the worker.
9432
+ * The probe will be executed after provisioning/update to verify the worker is ready.
9433
+ * Only works with workers that declare a public endpoint.
9330
9434
  *
9331
9435
  * @example
9332
9436
  * ```typescript
9333
- * const chainedError = authError.withContext(dbError)
9437
+ * const probe: ReadinessProbe = {
9438
+ * method: "GET",
9439
+ * path: "/health"
9440
+ * };
9334
9441
  *
9335
- * const dbError = chainedError.findErrorByCode("DATABASE_CONNECTION_FAILED")
9336
- * if (dbError) {
9337
- * console.log("Database error context:", dbError.context)
9338
- * console.log("Host:", dbError.context?.host)
9339
- * }
9442
+ * const func = new Worker("my-api")
9443
+ * .code({ type: "image", image: "my-api:latest" })
9444
+ * .publicEndpoint("api")
9445
+ * .readinessProbe(probe)
9446
+ * .build();
9340
9447
  * ```
9448
+ *
9449
+ * @param probe The readiness probe configuration.
9450
+ * @returns The Worker builder instance.
9341
9451
  */
9342
- findErrorByCode(code) {
9343
- if (this.code === code) return this;
9344
- return this.source?.findErrorByCode(code);
9452
+ readinessProbe(probe) {
9453
+ this._config.readinessProbe = probe;
9454
+ return this;
9345
9455
  }
9346
9456
  /**
9347
- * Get a formatted string representation of the error chain.
9348
- *
9349
- * This method provides a human-readable representation of the entire
9350
- * error chain, showing how errors are nested and providing context
9351
- * for debugging and logging.
9352
- *
9353
- * @returns Formatted string showing the complete error chain
9457
+ * Enables or disables the Commands protocol for the worker.
9458
+ * When enabled, the platform pushes commands into the Worker runtime, which executes registered handlers.
9459
+ * Default: false.
9460
+ * @param enabled Whether to enable commands for this worker.
9461
+ * @returns The Worker builder instance.
9462
+ */
9463
+ commandsEnabled(enabled) {
9464
+ this._config.commandsEnabled = enabled;
9465
+ return this;
9466
+ }
9467
+ /**
9468
+ * Adds a trigger to the worker. Workers can have multiple triggers.
9469
+ * Each trigger will independently invoke the worker when its conditions are met.
9354
9470
  *
9355
9471
  * @example
9356
9472
  * ```typescript
9357
- * const chainedError = authError.withContext(dbError.withContext(networkError))
9358
- * console.log(chainedError.toString())
9359
- * // Output:
9360
- * // AUTH_FAILED: User authentication failed for 'john'
9361
- * // ├─▶ DATABASE_CONNECTION_FAILED: Failed to connect to database 'localhost:5432'
9362
- * // ├─▶ GENERIC_ERROR: Connection timeout
9473
+ * // Queue trigger
9474
+ * const queueTrigger: WorkerTrigger = {
9475
+ * type: "queue",
9476
+ * queue: myQueue.ref()
9477
+ * };
9478
+ *
9479
+ * // Schedule trigger
9480
+ * const scheduleTrigg: WorkerTrigger = {
9481
+ * type: "schedule",
9482
+ * cron: "0 * * * *"
9483
+ * };
9484
+ *
9485
+ * const func = new Worker("my-func")
9486
+ * .code({ type: "image", image: "my-image:latest" })
9487
+ * .trigger(queueTrigger)
9488
+ * .trigger(scheduleTrigger)
9489
+ * .build();
9363
9490
  * ```
9491
+ *
9492
+ * @param trigger The trigger configuration.
9493
+ * @returns The Worker builder instance.
9364
9494
  */
9365
- toString() {
9366
- let result = `${this.code}: ${this.message}`;
9367
- let current = this.source;
9368
- let indent = "";
9369
- while (current) {
9370
- indent += " ";
9371
- result += `\n${indent}├─▶ ${current.code}: ${current.message}`;
9372
- current = current.source;
9373
- }
9374
- return result;
9495
+ trigger(trigger) {
9496
+ if (!this._config.triggers) this._config.triggers = [];
9497
+ this._config.triggers.push(trigger);
9498
+ return this;
9375
9499
  }
9376
- };
9377
- //#endregion
9378
- //#region src/common-errors.ts
9379
- /**
9380
- * Error thrown when a requested resource cannot be found in the stack state.
9381
- * This matches the Rust alien-core error: RESOURCE_NOT_FOUND
9382
- */
9383
- const ResourceNotFoundError = defineError({
9384
- code: "RESOURCE_NOT_FOUND",
9385
- context: z$1.object({
9386
- resourceId: z$1.string(),
9387
- availableResources: z$1.array(z$1.string())
9388
- }),
9389
- message: ({ resourceId, availableResources }) => `Resource '${resourceId}' not found in stack state. Available resources: ${JSON.stringify(availableResources)}`,
9390
- retryable: false,
9391
- internal: false,
9392
- httpStatusCode: 404
9393
- });
9394
- /**
9395
- * Error thrown when resource outputs cannot be parsed according to their expected schema.
9396
- * This indicates an internal system error or data corruption.
9397
- */
9398
- const ResourceOutputsParseError = defineError({
9399
- code: "RESOURCE_OUTPUTS_PARSE_ERROR",
9400
- context: z$1.object({
9401
- resourceName: z$1.string(),
9402
- resourceType: z$1.string(),
9403
- validationErrors: z$1.string()
9404
- }),
9405
- message: ({ resourceName, resourceType, validationErrors }) => `Failed to parse outputs for resource '${resourceName}' of type '${resourceType}':\n${validationErrors}`,
9406
- retryable: false,
9407
- internal: true,
9408
- httpStatusCode: 500
9409
- });
9410
- /**
9411
- * Error thrown when there's a resource type mismatch during stack operations.
9412
- * This matches the Rust alien-core error: UNEXPECTED_RESOURCE_TYPE
9413
- */
9414
- const UnexpectedResourceTypeError = defineError({
9415
- code: "UNEXPECTED_RESOURCE_TYPE",
9416
- context: z$1.object({
9417
- resourceId: z$1.string(),
9418
- expected: z$1.string(),
9419
- actual: z$1.string()
9420
- }),
9421
- message: ({ resourceId, expected, actual }) => `Unexpected resource type for resource '${resourceId}': expected ${expected}, but got ${actual}`,
9422
- retryable: false,
9423
- internal: false,
9424
- httpStatusCode: 400
9425
- });
9426
- /**
9427
- * Error thrown when a binding's projected configuration is invalid.
9428
- */
9429
- const InvalidBindingConfigError = defineError({
9430
- code: "INVALID_BINDING_CONFIG",
9431
- context: z$1.object({
9432
- message: z$1.string(),
9433
- suggestion: z$1.string().optional()
9434
- }),
9435
- message: ({ message, suggestion }) => suggestion ? `${message}. ${suggestion}` : message,
9436
- retryable: false,
9437
- internal: false,
9438
- httpStatusCode: 400
9439
- });
9440
- /**
9441
- * Error thrown when a binding is not found.
9442
- */
9443
- const BindingNotFoundError = defineError({
9444
- code: "BINDING_NOT_FOUND",
9445
- context: z$1.object({
9446
- bindingName: z$1.string(),
9447
- bindingType: z$1.string()
9448
- }),
9449
- message: ({ bindingName, bindingType }) => `${bindingType} binding '${bindingName}' not found`,
9450
- retryable: false,
9451
- internal: false,
9452
- httpStatusCode: 404
9453
- });
9454
- //#endregion
9455
- //#region src/get-resource-outputs.ts
9456
- const ResourceSchemaMapping = {
9457
- function: {
9458
- input: WorkerSchema,
9459
- output: WorkerOutputsSchema
9460
- },
9461
- container: {
9462
- input: ContainerSchema,
9463
- output: ContainerOutputsSchema
9464
- },
9465
- storage: {
9466
- input: StorageSchema,
9467
- output: StorageOutputsSchema
9468
- },
9469
- kv: {
9470
- input: KvSchema,
9471
- output: KvOutputsSchema
9472
- },
9473
- queue: {
9474
- input: QueueSchema,
9475
- output: QueueOutputsSchema
9476
- },
9477
- vault: {
9478
- input: VaultSchema,
9479
- output: VaultOutputsSchema
9480
- },
9481
- build: {
9482
- input: BuildSchema,
9483
- output: BuildOutputsSchema
9484
- },
9485
- "artifact-registry": {
9486
- input: ArtifactRegistrySchema,
9487
- output: ArtifactRegistryOutputsSchema
9488
- },
9489
- "service-account": {
9490
- input: ServiceAccountSchema,
9491
- output: ServiceAccountOutputsSchema
9492
- },
9493
- "remote-stack-management": {
9494
- input: RemoteStackManagementSchema,
9495
- output: RemoteStackManagementOutputsSchema
9500
+ /**
9501
+ * Builds and validates the worker configuration.
9502
+ * @returns An immutable Resource representing the configured worker.
9503
+ * @throws Error if the worker configuration is invalid (e.g., missing code).
9504
+ */
9505
+ build() {
9506
+ const config = WorkerSchema.parse(this._config);
9507
+ return this.resource({
9508
+ type: "worker",
9509
+ ...config
9510
+ });
9496
9511
  }
9497
9512
  };
9498
- function getResourceOutputs(params) {
9499
- const { state, resource } = params;
9500
- const resourceState = state.resources[resource.name];
9501
- if (!resourceState) throw new AlienError(ResourceNotFoundError.create({
9502
- resourceId: resource.name,
9503
- availableResources: Object.keys(state.resources)
9504
- }));
9505
- const outputs = ResourceSchemaMapping[resource.type].output.safeParse(resourceState.outputs);
9506
- if (!outputs.success) throw new AlienError(ResourceOutputsParseError.create({
9507
- resourceName: resource.name,
9508
- resourceType: resource.type,
9509
- validationErrors: z$1.prettifyError(outputs.error)
9510
- }));
9511
- return outputs.data;
9512
- }
9513
9513
  //#endregion
9514
9514
  //#region src/experimental/aws-opensearch.ts
9515
9515
  /**