@alienplatform/core 3.3.10 → 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.d.ts +1260 -1260
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1427 -1427
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
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
|
|
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
|
|
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/
|
|
7085
|
+
//#region src/ai.ts
|
|
7086
7086
|
/**
|
|
7087
|
-
* Represents an
|
|
7087
|
+
* Represents an AI Gateway resource that provides a unified interface to
|
|
7088
|
+
* managed AI inference services across cloud providers.
|
|
7088
7089
|
*/
|
|
7089
|
-
var
|
|
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
|
|
7098
|
-
* @param id
|
|
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
|
|
7106
|
-
* Used for creating permission targets that apply to all
|
|
7107
|
-
* @returns The "
|
|
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 "
|
|
7106
|
+
return "ai";
|
|
7111
7107
|
}
|
|
7112
7108
|
/**
|
|
7113
|
-
*
|
|
7114
|
-
*
|
|
7115
|
-
* @
|
|
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
|
-
|
|
7119
|
-
this._config
|
|
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
|
-
*
|
|
7124
|
-
*
|
|
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
|
-
|
|
7129
|
-
this._config.
|
|
7130
|
-
return this;
|
|
7134
|
+
constructor(id) {
|
|
7135
|
+
this._config.id = id;
|
|
7131
7136
|
}
|
|
7132
7137
|
/**
|
|
7133
|
-
*
|
|
7134
|
-
*
|
|
7135
|
-
* @returns The
|
|
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
|
-
|
|
7138
|
-
|
|
7139
|
-
return this;
|
|
7142
|
+
static any() {
|
|
7143
|
+
return "artifact-registry";
|
|
7140
7144
|
}
|
|
7141
7145
|
/**
|
|
7142
|
-
*
|
|
7143
|
-
*
|
|
7144
|
-
*
|
|
7145
|
-
*
|
|
7146
|
-
* @
|
|
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
|
-
|
|
7149
|
-
this._config.
|
|
7152
|
+
replicationRegions(regions) {
|
|
7153
|
+
this._config.replicationRegions = regions;
|
|
7150
7154
|
return this;
|
|
7151
7155
|
}
|
|
7152
7156
|
/**
|
|
7153
|
-
* Builds and validates the
|
|
7154
|
-
* @returns An immutable Resource representing the configured
|
|
7155
|
-
* @throws Error if the
|
|
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
|
-
|
|
7159
|
-
|
|
7160
|
-
|
|
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/
|
|
7169
|
+
//#region src/build.ts
|
|
7167
7170
|
/**
|
|
7168
|
-
* Represents a
|
|
7169
|
-
*
|
|
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
|
|
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
|
|
7180
|
-
* @param id Identifier for the
|
|
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
|
|
7188
|
-
* Used for creating permission targets that apply to all
|
|
7189
|
-
* @returns The "
|
|
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 "
|
|
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
|
-
*
|
|
7237
|
-
*
|
|
7238
|
-
*
|
|
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
|
-
|
|
7242
|
-
|
|
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
|
|
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
|
|
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,
|
|
7261
|
-
* This makes the linked resource accessible to the
|
|
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
|
|
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
|
|
7273
|
-
* The profile defines the permissions granted to this
|
|
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
|
|
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
|
-
*
|
|
7284
|
-
*
|
|
7285
|
-
*
|
|
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
|
-
|
|
7316
|
-
|
|
7317
|
-
|
|
7241
|
+
build() {
|
|
7242
|
+
return new Resource({
|
|
7243
|
+
type: "build",
|
|
7244
|
+
...BuildSchema.parse(this._config)
|
|
7245
|
+
});
|
|
7318
7246
|
}
|
|
7319
|
-
|
|
7320
|
-
|
|
7321
|
-
|
|
7322
|
-
|
|
7323
|
-
|
|
7324
|
-
|
|
7325
|
-
|
|
7326
|
-
|
|
7327
|
-
|
|
7328
|
-
|
|
7329
|
-
|
|
7330
|
-
|
|
7331
|
-
|
|
7332
|
-
|
|
7333
|
-
|
|
7334
|
-
|
|
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
|
-
*
|
|
7338
|
-
*
|
|
7339
|
-
*
|
|
7340
|
-
*
|
|
7341
|
-
*
|
|
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
|
-
*
|
|
7345
|
-
*
|
|
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
|
-
|
|
7348
|
-
|
|
7349
|
-
|
|
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
|
-
*
|
|
7354
|
-
*
|
|
7355
|
-
*
|
|
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
|
-
|
|
7359
|
-
|
|
7360
|
-
|
|
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/
|
|
8506
|
+
//#region src/email.ts
|
|
8023
8507
|
/**
|
|
8024
|
-
*
|
|
8025
|
-
*
|
|
8026
|
-
*
|
|
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
|
|
8029
|
-
_config = {
|
|
8030
|
-
links: [],
|
|
8031
|
-
environment: {}
|
|
8032
|
-
};
|
|
8529
|
+
var Email = class extends ResourceBuilder {
|
|
8530
|
+
_config = { domains: [] };
|
|
8033
8531
|
/**
|
|
8034
|
-
* Creates a new
|
|
8035
|
-
* @param id Identifier for the
|
|
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
|
|
8042
|
-
* Used for creating permission targets that apply to all
|
|
8043
|
-
* @returns The "
|
|
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 "
|
|
8545
|
+
return "email";
|
|
8047
8546
|
}
|
|
8048
8547
|
/**
|
|
8049
|
-
* Sets the
|
|
8050
|
-
*
|
|
8051
|
-
* @
|
|
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
|
-
|
|
8054
|
-
this._config.
|
|
8553
|
+
domains(domains) {
|
|
8554
|
+
this._config.domains = domains;
|
|
8055
8555
|
return this;
|
|
8056
8556
|
}
|
|
8057
8557
|
/**
|
|
8058
|
-
*
|
|
8059
|
-
* @param
|
|
8060
|
-
* @returns The
|
|
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
|
-
|
|
8063
|
-
this._config.
|
|
8562
|
+
domain(domain) {
|
|
8563
|
+
this._config.domains = [...this._config.domains ?? [], domain];
|
|
8064
8564
|
return this;
|
|
8065
8565
|
}
|
|
8066
8566
|
/**
|
|
8067
|
-
*
|
|
8068
|
-
*
|
|
8069
|
-
*
|
|
8070
|
-
* @param
|
|
8071
|
-
* @returns The
|
|
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
|
-
|
|
8074
|
-
|
|
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
|
-
*
|
|
8080
|
-
*
|
|
8081
|
-
*
|
|
8082
|
-
* @
|
|
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
|
-
|
|
8086
|
-
this._config.
|
|
8583
|
+
events(queue) {
|
|
8584
|
+
this._config.events = { queue: queue.ref() };
|
|
8087
8585
|
return this;
|
|
8088
8586
|
}
|
|
8089
8587
|
/**
|
|
8090
|
-
* Builds and validates the
|
|
8091
|
-
* @returns An immutable Resource representing the configured
|
|
8092
|
-
* @throws Error if the
|
|
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
|
-
|
|
8096
|
-
|
|
8097
|
-
|
|
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/
|
|
8103
|
-
|
|
8104
|
-
|
|
8105
|
-
|
|
8106
|
-
|
|
8107
|
-
|
|
8108
|
-
|
|
8109
|
-
|
|
8110
|
-
|
|
8111
|
-
|
|
8112
|
-
|
|
8113
|
-
|
|
8114
|
-
|
|
8115
|
-
|
|
8116
|
-
|
|
8117
|
-
|
|
8118
|
-
|
|
8119
|
-
|
|
8120
|
-
|
|
8121
|
-
|
|
8122
|
-
|
|
8123
|
-
|
|
8124
|
-
|
|
8125
|
-
|
|
8126
|
-
|
|
8127
|
-
|
|
8128
|
-
|
|
8129
|
-
|
|
8130
|
-
|
|
8131
|
-
|
|
8132
|
-
|
|
8133
|
-
|
|
8134
|
-
|
|
8135
|
-
}
|
|
8136
|
-
|
|
8137
|
-
|
|
8138
|
-
|
|
8139
|
-
|
|
8140
|
-
|
|
8141
|
-
|
|
8142
|
-
|
|
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/
|
|
8150
|
-
|
|
8151
|
-
|
|
8152
|
-
|
|
8153
|
-
|
|
8154
|
-
|
|
8155
|
-
|
|
8156
|
-
|
|
8157
|
-
|
|
8158
|
-
|
|
8159
|
-
|
|
8160
|
-
|
|
8161
|
-
|
|
8162
|
-
|
|
8163
|
-
|
|
8164
|
-
|
|
8165
|
-
|
|
8166
|
-
|
|
8167
|
-
|
|
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
|
-
|
|
8171
|
-
|
|
8172
|
-
|
|
8173
|
-
|
|
8174
|
-
|
|
8175
|
-
|
|
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
|
-
|
|
8179
|
-
|
|
8180
|
-
|
|
8181
|
-
|
|
8182
|
-
|
|
8183
|
-
|
|
8184
|
-
|
|
8185
|
-
|
|
8186
|
-
|
|
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 =
|
|
8978
|
+
const config = PostgresSchema.parse(this._config);
|
|
8377
8979
|
return this.resource({
|
|
8378
|
-
type: "
|
|
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
|
-
|
|
8733
|
-
|
|
8734
|
-
|
|
8735
|
-
|
|
8736
|
-
|
|
8737
|
-
|
|
8738
|
-
|
|
8739
|
-
|
|
8740
|
-
|
|
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/
|
|
8855
|
-
/**
|
|
8856
|
-
*
|
|
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
|
|
9011
|
-
|
|
9012
|
-
|
|
9013
|
-
|
|
9014
|
-
|
|
9015
|
-
|
|
9016
|
-
|
|
9017
|
-
/**
|
|
9018
|
-
|
|
9019
|
-
|
|
9020
|
-
|
|
9021
|
-
|
|
9022
|
-
|
|
9023
|
-
|
|
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
|
-
*
|
|
9055
|
-
*
|
|
9056
|
-
* @
|
|
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
|
|
9061
|
-
return
|
|
9215
|
+
static any() {
|
|
9216
|
+
return "storage";
|
|
9062
9217
|
}
|
|
9063
9218
|
/**
|
|
9064
|
-
*
|
|
9065
|
-
*
|
|
9066
|
-
* @param
|
|
9067
|
-
* @returns
|
|
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
|
-
|
|
9070
|
-
|
|
9224
|
+
publicRead(value) {
|
|
9225
|
+
this._config.publicRead = value;
|
|
9226
|
+
return this;
|
|
9071
9227
|
}
|
|
9072
9228
|
/**
|
|
9073
|
-
*
|
|
9074
|
-
*
|
|
9075
|
-
* @param
|
|
9076
|
-
* @returns
|
|
9229
|
+
* Enables object versioning.
|
|
9230
|
+
* Default: `false`.
|
|
9231
|
+
* @param value Whether to enable versioning.
|
|
9232
|
+
* @returns The Storage builder instance.
|
|
9077
9233
|
*/
|
|
9078
|
-
|
|
9079
|
-
|
|
9080
|
-
|
|
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
|
-
*
|
|
9087
|
-
*
|
|
9088
|
-
*
|
|
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
|
-
|
|
9131
|
-
|
|
9132
|
-
|
|
9133
|
-
|
|
9134
|
-
|
|
9135
|
-
|
|
9136
|
-
|
|
9137
|
-
|
|
9138
|
-
|
|
9139
|
-
|
|
9140
|
-
|
|
9141
|
-
|
|
9142
|
-
|
|
9143
|
-
|
|
9144
|
-
|
|
9145
|
-
|
|
9146
|
-
|
|
9147
|
-
|
|
9148
|
-
|
|
9149
|
-
|
|
9150
|
-
|
|
9151
|
-
|
|
9152
|
-
|
|
9153
|
-
|
|
9154
|
-
|
|
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
|
-
*
|
|
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
|
-
|
|
9213
|
-
|
|
9214
|
-
|
|
9215
|
-
|
|
9216
|
-
|
|
9217
|
-
|
|
9218
|
-
|
|
9219
|
-
|
|
9220
|
-
|
|
9221
|
-
|
|
9222
|
-
|
|
9223
|
-
|
|
9224
|
-
|
|
9225
|
-
|
|
9226
|
-
|
|
9227
|
-
|
|
9228
|
-
|
|
9229
|
-
|
|
9230
|
-
|
|
9231
|
-
|
|
9232
|
-
|
|
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
|
-
*
|
|
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
|
-
|
|
9244
|
-
|
|
9245
|
-
|
|
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
|
-
*
|
|
9257
|
-
*
|
|
9258
|
-
*
|
|
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
|
-
|
|
9280
|
-
|
|
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
|
-
*
|
|
9300
|
-
*
|
|
9301
|
-
*
|
|
9302
|
-
|
|
9303
|
-
|
|
9304
|
-
|
|
9305
|
-
|
|
9306
|
-
|
|
9307
|
-
|
|
9308
|
-
*
|
|
9309
|
-
*
|
|
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
|
-
*
|
|
9312
|
-
*
|
|
9313
|
-
|
|
9314
|
-
|
|
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
|
-
|
|
9318
|
-
|
|
9319
|
-
return this
|
|
9426
|
+
permissions(permissions) {
|
|
9427
|
+
this._config.permissions = permissions;
|
|
9428
|
+
return this;
|
|
9320
9429
|
}
|
|
9321
9430
|
/**
|
|
9322
|
-
*
|
|
9323
|
-
*
|
|
9324
|
-
*
|
|
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
|
|
9437
|
+
* const probe: ReadinessProbe = {
|
|
9438
|
+
* method: "GET",
|
|
9439
|
+
* path: "/health"
|
|
9440
|
+
* };
|
|
9334
9441
|
*
|
|
9335
|
-
* const
|
|
9336
|
-
*
|
|
9337
|
-
*
|
|
9338
|
-
*
|
|
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
|
-
|
|
9343
|
-
|
|
9344
|
-
return this
|
|
9452
|
+
readinessProbe(probe) {
|
|
9453
|
+
this._config.readinessProbe = probe;
|
|
9454
|
+
return this;
|
|
9345
9455
|
}
|
|
9346
9456
|
/**
|
|
9347
|
-
*
|
|
9348
|
-
*
|
|
9349
|
-
*
|
|
9350
|
-
*
|
|
9351
|
-
*
|
|
9352
|
-
|
|
9353
|
-
|
|
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
|
-
*
|
|
9358
|
-
*
|
|
9359
|
-
*
|
|
9360
|
-
*
|
|
9361
|
-
*
|
|
9362
|
-
*
|
|
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
|
-
|
|
9366
|
-
|
|
9367
|
-
|
|
9368
|
-
|
|
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
|
-
|
|
9378
|
-
|
|
9379
|
-
|
|
9380
|
-
|
|
9381
|
-
|
|
9382
|
-
|
|
9383
|
-
|
|
9384
|
-
|
|
9385
|
-
|
|
9386
|
-
|
|
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
|
/**
|