@stacksjs/ts-cloud 0.7.6 → 0.7.9

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.
@@ -26,7 +26,7 @@ import {
26
26
  resolveSiteFramework,
27
27
  resolveSiteKind,
28
28
  resolveUiSource
29
- } from "./chunk-dpkk640m.js";
29
+ } from "./chunk-xzn0ntr0.js";
30
30
  import {
31
31
  artifactKey,
32
32
  composeServerlessAppTemplate,
@@ -3204,6 +3204,230 @@ async function waitForCloudInit(host, options = {}) {
3204
3204
  }
3205
3205
  throw new Error(`cloud-init did not finish on ${host} after ${timeoutMs}ms`);
3206
3206
  }
3207
+ // src/drivers/shared/box-provision.ts
3208
+ var UBUNTU_2404_AMI_PARAM = "/aws/service/canonical/ubuntu/server/24.04/stable/current/amd64/hvm/ebs-gp3/ami-id";
3209
+ function buildBoxUserData(spec) {
3210
+ const key = spec.sshPublicKey.trim();
3211
+ const lines = [
3212
+ "#cloud-config",
3213
+ "disable_root: false",
3214
+ "ssh_authorized_keys:",
3215
+ ` - ${key}`
3216
+ ];
3217
+ if (spec.bootstrapScript) {
3218
+ const path = "/var/lib/cloud/box-bootstrap.sh";
3219
+ const indented = spec.bootstrapScript.split(`
3220
+ `).map((l) => ` ${l}`).join(`
3221
+ `);
3222
+ lines.push("write_files:", ` - path: ${path}`, ` permissions: '0755'`, " owner: root:root", " content: |", indented);
3223
+ }
3224
+ lines.push("runcmd:", ` - mkdir -p /root/.ssh && grep -qF "${key}" /root/.ssh/authorized_keys 2>/dev/null || echo "${key}" >> /root/.ssh/authorized_keys`);
3225
+ if (spec.bootstrapScript)
3226
+ lines.push(" - [ bash, /var/lib/cloud/box-bootstrap.sh ]");
3227
+ return `${lines.join(`
3228
+ `)}
3229
+ `;
3230
+ }
3231
+ function toHetznerRules(ports = []) {
3232
+ const rules = [
3233
+ { direction: "in", protocol: "tcp", port: "22", source_ips: ["0.0.0.0/0", "::/0"], description: "SSH" }
3234
+ ];
3235
+ for (const p of ports) {
3236
+ rules.push({
3237
+ direction: "in",
3238
+ protocol: p.protocol,
3239
+ ...p.protocol === "icmp" ? {} : { port: String(p.port) },
3240
+ source_ips: ["0.0.0.0/0", "::/0"]
3241
+ });
3242
+ }
3243
+ return rules;
3244
+ }
3245
+
3246
+ class HetznerBoxProvisioner {
3247
+ client;
3248
+ provider = "hetzner";
3249
+ constructor(client) {
3250
+ this.client = client;
3251
+ }
3252
+ async ensureBox(spec) {
3253
+ const key = await ensureSshKey(this.client, { name: `${spec.name}-key`, publicKey: spec.sshPublicKey });
3254
+ const firewall = await ensureFirewall(this.client, { name: `${spec.name}-fw`, rules: toHetznerRules(spec.ports) });
3255
+ const { server, created } = await ensureServer(this.client, {
3256
+ name: spec.name,
3257
+ serverType: spec.size,
3258
+ image: spec.image ?? "ubuntu-24.04",
3259
+ location: spec.location,
3260
+ sshKeys: [key.id],
3261
+ firewalls: [{ firewall: firewall.id }],
3262
+ userData: buildBoxUserData(spec),
3263
+ labels: spec.labels
3264
+ });
3265
+ return { provider: "hetzner", id: String(server.id), name: server.name, publicIp: serverPublicIpv4(server), created };
3266
+ }
3267
+ async destroyBox(name) {
3268
+ const destroyed = [];
3269
+ const server = (await this.client.listServers()).find((s) => s.name === name);
3270
+ if (server) {
3271
+ const action = await this.client.deleteServer(server.id);
3272
+ await this.client.waitForAction(action.id).catch(() => {});
3273
+ destroyed.push(`server ${name} (#${server.id})`);
3274
+ }
3275
+ const firewall = (await this.client.listFirewalls()).find((f) => f.name === `${name}-fw`);
3276
+ if (firewall) {
3277
+ for (let i = 0;i < 10; i++) {
3278
+ try {
3279
+ await this.client.deleteFirewall(firewall.id);
3280
+ destroyed.push(`firewall ${name}-fw (#${firewall.id})`);
3281
+ break;
3282
+ } catch {
3283
+ if (i === 9)
3284
+ break;
3285
+ await new Promise((resolve) => setTimeout(resolve, 3000));
3286
+ }
3287
+ }
3288
+ }
3289
+ return { destroyed };
3290
+ }
3291
+ }
3292
+ function toIpPermissions(ports = []) {
3293
+ const permissions = [
3294
+ { IpProtocol: "tcp", FromPort: 22, ToPort: 22, IpRanges: [{ CidrIp: "0.0.0.0/0", Description: "SSH" }] }
3295
+ ];
3296
+ for (const p of ports) {
3297
+ permissions.push(p.protocol === "icmp" ? { IpProtocol: "icmp", FromPort: -1, ToPort: -1, IpRanges: [{ CidrIp: "0.0.0.0/0" }] } : { IpProtocol: p.protocol, FromPort: p.port, ToPort: p.port, IpRanges: [{ CidrIp: "0.0.0.0/0" }] });
3298
+ }
3299
+ return permissions;
3300
+ }
3301
+
3302
+ class AwsBoxProvisioner {
3303
+ provider = "aws";
3304
+ ec2;
3305
+ ssm;
3306
+ constructor(options) {
3307
+ this.ec2 = options.ec2;
3308
+ this.ssm = options.ssm;
3309
+ }
3310
+ async findInstance(name, states) {
3311
+ const result = await this.ec2.describeInstances({
3312
+ Filters: [
3313
+ { Name: "tag:Name", Values: [name] },
3314
+ { Name: "instance-state-name", Values: states }
3315
+ ]
3316
+ });
3317
+ return result.Reservations?.flatMap((r) => r.Instances ?? [])[0];
3318
+ }
3319
+ async waitForPublicIp(instanceId, timeoutMs = 300000) {
3320
+ const start = Date.now();
3321
+ while (Date.now() - start < timeoutMs) {
3322
+ const instance = await this.ec2.getInstance(instanceId);
3323
+ if (instance?.State?.Name === "running" && instance.PublicIpAddress)
3324
+ return instance;
3325
+ await new Promise((resolve) => setTimeout(resolve, 5000));
3326
+ }
3327
+ throw new Error(`EC2 instance ${instanceId} did not reach running with a public IP within ${timeoutMs}ms`);
3328
+ }
3329
+ async ensureSecurityGroup(spec) {
3330
+ const groupName = `${spec.name}-sg`;
3331
+ const existing = await this.ec2.describeSecurityGroups({
3332
+ Filters: [{ Name: "group-name", Values: [groupName] }]
3333
+ });
3334
+ const found = existing.SecurityGroups?.[0]?.GroupId;
3335
+ if (found)
3336
+ return found;
3337
+ const created = await this.ec2.createSecurityGroup({
3338
+ GroupName: groupName,
3339
+ Description: `box ${spec.name} (managed by ts-cloud box-provision)`
3340
+ });
3341
+ if (!created.GroupId)
3342
+ throw new Error(`could not create security group ${groupName}`);
3343
+ await this.ec2.authorizeSecurityGroupIngress({
3344
+ GroupId: created.GroupId,
3345
+ IpPermissions: toIpPermissions(spec.ports)
3346
+ });
3347
+ return created.GroupId;
3348
+ }
3349
+ async resolveImage(spec) {
3350
+ if (spec.image?.startsWith("ami-"))
3351
+ return spec.image;
3352
+ const result = await this.ssm.getParameter({ Name: UBUNTU_2404_AMI_PARAM });
3353
+ const ami = result.Parameter?.Value;
3354
+ if (!ami)
3355
+ throw new Error(`could not resolve the Ubuntu 24.04 AMI via SSM (${UBUNTU_2404_AMI_PARAM})`);
3356
+ return ami;
3357
+ }
3358
+ async ensureBox(spec) {
3359
+ const existing = await this.findInstance(spec.name, ["pending", "running"]);
3360
+ if (existing?.InstanceId) {
3361
+ const instance2 = await this.waitForPublicIp(existing.InstanceId);
3362
+ return { provider: "aws", id: instance2.InstanceId, name: spec.name, publicIp: instance2.PublicIpAddress, created: false };
3363
+ }
3364
+ const [groupId, imageId] = await Promise.all([
3365
+ this.ensureSecurityGroup(spec),
3366
+ this.resolveImage(spec)
3367
+ ]);
3368
+ const tags = [
3369
+ { Key: "Name", Value: spec.name },
3370
+ ...Object.entries(spec.labels ?? {}).map(([Key, Value]) => ({ Key, Value }))
3371
+ ];
3372
+ const result = await this.ec2.runInstances({
3373
+ ImageId: imageId,
3374
+ InstanceType: spec.size,
3375
+ MinCount: 1,
3376
+ MaxCount: 1,
3377
+ SecurityGroupIds: [groupId],
3378
+ UserData: btoa(buildBoxUserData(spec)),
3379
+ TagSpecifications: [{ ResourceType: "instance", Tags: tags }]
3380
+ });
3381
+ const instanceId = result.Instances?.[0]?.InstanceId;
3382
+ if (!instanceId)
3383
+ throw new Error(`RunInstances returned no instance for box ${spec.name}`);
3384
+ const instance = await this.waitForPublicIp(instanceId);
3385
+ return { provider: "aws", id: instanceId, name: spec.name, publicIp: instance.PublicIpAddress, created: true };
3386
+ }
3387
+ async destroyBox(name) {
3388
+ const destroyed = [];
3389
+ const instance = await this.findInstance(name, ["pending", "running", "stopping", "stopped"]);
3390
+ if (instance?.InstanceId) {
3391
+ await this.ec2.terminateInstances([instance.InstanceId]);
3392
+ destroyed.push(`instance ${name} (${instance.InstanceId})`);
3393
+ const start = Date.now();
3394
+ while (Date.now() - start < 300000) {
3395
+ const current = await this.ec2.getInstance(instance.InstanceId);
3396
+ if (!current || current.State?.Name === "terminated")
3397
+ break;
3398
+ await new Promise((resolve) => setTimeout(resolve, 5000));
3399
+ }
3400
+ }
3401
+ const groups = await this.ec2.describeSecurityGroups({
3402
+ Filters: [{ Name: "group-name", Values: [`${name}-sg`] }]
3403
+ });
3404
+ const groupId = groups.SecurityGroups?.[0]?.GroupId;
3405
+ if (groupId) {
3406
+ for (let i = 0;i < 10; i++) {
3407
+ try {
3408
+ await this.ec2.deleteSecurityGroup(groupId);
3409
+ destroyed.push(`security group ${name}-sg (${groupId})`);
3410
+ break;
3411
+ } catch {
3412
+ if (i === 9)
3413
+ break;
3414
+ await new Promise((resolve) => setTimeout(resolve, 3000));
3415
+ }
3416
+ }
3417
+ }
3418
+ return { destroyed };
3419
+ }
3420
+ }
3421
+ function createBoxProvisioner(options) {
3422
+ if (options.provider === "hetzner") {
3423
+ if (!options.hetzner)
3424
+ throw new Error('createBoxProvisioner: options.hetzner (a HetznerClient) is required for provider "hetzner"');
3425
+ return new HetznerBoxProvisioner(options.hetzner);
3426
+ }
3427
+ if (!options.aws)
3428
+ throw new Error('createBoxProvisioner: options.aws ({ ec2, ssm }) is required for provider "aws"');
3429
+ return new AwsBoxProvisioner(options.aws);
3430
+ }
3207
3431
  // src/drivers/shared/env-file.ts
3208
3432
  function formatEnvFile(env) {
3209
3433
  return Object.entries(env).map(([k, v]) => `${k}=${quoteEnvValue(String(v))}`).join(`
@@ -4389,4 +4613,4 @@ function buildCloudFrontOriginConfig(options) {
4389
4613
  CustomErrorResponses: { Quantity: 0 }
4390
4614
  };
4391
4615
  }
4392
- export { isPhpSite, resolveSiteDeployTarget, resolveSiteKind, validateDeploymentConfig, PANTRY_PROJECT_DIR, BACKUP_RUNNER_PATH, buildBackupRestoreScript, buildUbuntuBootstrapScript, AwsDriver, HetznerClient, resolveHetznerApiToken, normalizeSshPublicKey, wrapCloudInitUserData, DEFAULT_RPX_CERTS_DIR, normalizeRoutePath, deriveRouteId, buildRpxConfig, buildRpxLbConfig, renderRpxLauncher, RPX_DIR, RPX_LAUNCHER_PATH, RPX_SERVICE_NAME, buildRpxProvisionScript, HetznerDriver, LocalBoxDriver, isBoxMode, createCloudDriver, CloudDriverFactory, cloudDrivers, ensureSshKey, ensureFirewall, ensureServer, serverPublicIpv4, buildSshArgs, sshExec, sshExecOrThrow, scpUpload, waitForSsh, waitForCloudInit, releasePaths, buildRollbackScript, resolveExecStart, buildSiteDeployScript, buildStaticSiteDeployScript, buildAwsArtifactFetch, buildLocalArtifactFetch, MANAGEMENT_DASHBOARD_SITE, DASHBOARD_CREDENTIALS_FILE, resolveDashboardAuth, resolveUiSource, ensureManagementDashboard, buildManagementDashboardArtifact, resolveSiteFramework, deploySiteRelease, deployAllComputeSites, reloadRpxGateway, MANAGED_CACHE_POLICY_OPTIMIZED, MANAGED_CACHE_POLICY_DISABLED, MANAGED_ORIGIN_REQUEST_POLICY_ALL_VIEWER, buildCloudFrontOriginConfig };
4616
+ export { isPhpSite, resolveSiteDeployTarget, resolveSiteKind, validateDeploymentConfig, PANTRY_PROJECT_DIR, BACKUP_RUNNER_PATH, buildBackupRestoreScript, buildUbuntuBootstrapScript, AwsDriver, HetznerClient, resolveHetznerApiToken, normalizeSshPublicKey, wrapCloudInitUserData, DEFAULT_RPX_CERTS_DIR, normalizeRoutePath, deriveRouteId, buildRpxConfig, buildRpxLbConfig, renderRpxLauncher, RPX_DIR, RPX_LAUNCHER_PATH, RPX_SERVICE_NAME, buildRpxProvisionScript, HetznerDriver, LocalBoxDriver, isBoxMode, createCloudDriver, CloudDriverFactory, cloudDrivers, ensureSshKey, ensureFirewall, ensureServer, serverPublicIpv4, buildSshArgs, sshExec, sshExecOrThrow, scpUpload, waitForSsh, waitForCloudInit, UBUNTU_2404_AMI_PARAM, buildBoxUserData, HetznerBoxProvisioner, AwsBoxProvisioner, createBoxProvisioner, releasePaths, buildRollbackScript, resolveExecStart, buildSiteDeployScript, buildStaticSiteDeployScript, buildAwsArtifactFetch, buildLocalArtifactFetch, MANAGEMENT_DASHBOARD_SITE, DASHBOARD_CREDENTIALS_FILE, resolveDashboardAuth, resolveUiSource, ensureManagementDashboard, buildManagementDashboardArtifact, resolveSiteFramework, deploySiteRelease, deployAllComputeSites, reloadRpxGateway, MANAGED_CACHE_POLICY_OPTIMIZED, MANAGED_CACHE_POLICY_DISABLED, MANAGED_ORIGIN_REQUEST_POLICY_ALL_VIEWER, buildCloudFrontOriginConfig };
@@ -12,7 +12,7 @@ import {
12
12
  sanitizeCloudConfig,
13
13
  setMaintenance,
14
14
  startLocalDashboardServer
15
- } from "../chunk-p6309384.js";
15
+ } from "../chunk-x07dz3sd.js";
16
16
  import {
17
17
  buildAndPushServerlessImage
18
18
  } from "../chunk-0wxyppza.js";
@@ -29,7 +29,7 @@ import {
29
29
  resolveSiteKind,
30
30
  resolveUiSource,
31
31
  validateDeploymentConfig
32
- } from "../chunk-dpkk640m.js";
32
+ } from "../chunk-xzn0ntr0.js";
33
33
  import"../chunk-c6rgvg1j.js";
34
34
  import"../chunk-93hjhs78.js";
35
35
  import {
@@ -8,6 +8,8 @@ export { ensureFirewall, ensureServer, ensureSshKey, serverPublicIpv4 } from './
8
8
  export type { EnsuredResource, EnsuredServer, EnsureFirewallOptions, EnsureServerOptions, EnsureSshKeyOptions, } from './hetzner/provision';
9
9
  export { buildSshArgs, scpUpload, sshExec, sshExecOrThrow, waitForCloudInit, waitForSsh } from './shared/remote-exec';
10
10
  export type { RemoteExecOptions, RemoteExecResult, WaitOptions } from './shared/remote-exec';
11
+ export { AwsBoxProvisioner, buildBoxUserData, createBoxProvisioner, HetznerBoxProvisioner, UBUNTU_2404_AMI_PARAM, } from './shared/box-provision';
12
+ export type { AwsBoxProvisionerOptions, BoxPort, BoxProviderName, BoxProvisioner, BoxSpec, CreateBoxProvisionerOptions, ProvisionedBox, } from './shared/box-provision';
11
13
  export { buildAwsArtifactFetch, buildLocalArtifactFetch, buildSiteDeployScript, buildStaticSiteDeployScript, resolveExecStart, } from './shared/deploy-script';
12
14
  export { deployAllComputeSites, deploySiteRelease, reloadRpxGateway } from './shared/compute-deploy';
13
15
  export { buildRpxConfig, buildRpxLbConfig, buildRpxProvisionScript, deriveRouteId, normalizeRoutePath, renderRpxLauncher, DEFAULT_RPX_CERTS_DIR, RPX_DIR, RPX_LAUNCHER_PATH, RPX_SERVICE_NAME, } from './shared/rpx-gateway';
@@ -1,7 +1,9 @@
1
1
  import {
2
+ AwsBoxProvisioner,
2
3
  AwsDriver,
3
4
  CloudDriverFactory,
4
5
  DEFAULT_RPX_CERTS_DIR,
6
+ HetznerBoxProvisioner,
5
7
  HetznerClient,
6
8
  HetznerDriver,
7
9
  LocalBoxDriver,
@@ -11,7 +13,9 @@ import {
11
13
  RPX_DIR,
12
14
  RPX_LAUNCHER_PATH,
13
15
  RPX_SERVICE_NAME,
16
+ UBUNTU_2404_AMI_PARAM,
14
17
  buildAwsArtifactFetch,
18
+ buildBoxUserData,
15
19
  buildCloudFrontOriginConfig,
16
20
  buildLocalArtifactFetch,
17
21
  buildRpxConfig,
@@ -22,6 +26,7 @@ import {
22
26
  buildStaticSiteDeployScript,
23
27
  buildUbuntuBootstrapScript,
24
28
  cloudDrivers,
29
+ createBoxProvisioner,
25
30
  createCloudDriver,
26
31
  deployAllComputeSites,
27
32
  deploySiteRelease,
@@ -43,7 +48,7 @@ import {
43
48
  waitForCloudInit,
44
49
  waitForSsh,
45
50
  wrapCloudInitUserData
46
- } from "../chunk-dpkk640m.js";
51
+ } from "../chunk-xzn0ntr0.js";
47
52
  import"../chunk-c6rgvg1j.js";
48
53
  import"../chunk-93hjhs78.js";
49
54
  import"../chunk-qpj3edwz.js";
@@ -73,6 +78,7 @@ export {
73
78
  deploySiteRelease,
74
79
  deployAllComputeSites,
75
80
  createCloudDriver,
81
+ createBoxProvisioner,
76
82
  cloudDrivers,
77
83
  buildStaticSiteDeployScript,
78
84
  buildSshArgs,
@@ -82,7 +88,9 @@ export {
82
88
  buildRpxConfig,
83
89
  buildLocalArtifactFetch,
84
90
  buildCloudFrontOriginConfig,
91
+ buildBoxUserData,
85
92
  buildAwsArtifactFetch,
93
+ UBUNTU_2404_AMI_PARAM,
86
94
  RPX_SERVICE_NAME,
87
95
  RPX_LAUNCHER_PATH,
88
96
  RPX_DIR,
@@ -92,7 +100,9 @@ export {
92
100
  LocalBoxDriver,
93
101
  HetznerDriver,
94
102
  HetznerClient,
103
+ HetznerBoxProvisioner,
95
104
  DEFAULT_RPX_CERTS_DIR,
96
105
  CloudDriverFactory,
97
- AwsDriver
106
+ AwsDriver,
107
+ AwsBoxProvisioner
98
108
  };
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Provider-agnostic single-box provisioning.
3
+ *
4
+ * `createBoxProvisioner` gives deploy scripts one interface — ensure a named
5
+ * box exists (running, reachable, firewall open, SSH key authorized, bootstrap
6
+ * script run) and tear it down again — regardless of whether the box lives on
7
+ * Hetzner Cloud or AWS EC2. Idempotent like the underlying `ensure*` helpers:
8
+ * re-running converges instead of duplicating resources.
9
+ *
10
+ * SSH access is normalized to `root@<publicIp>`: the public key is injected
11
+ * via cloud-init (`disable_root: false` plus an authorized_keys append) so the
12
+ * same `sshExec(host, cmd)` calls work on both providers, even though AWS
13
+ * Ubuntu images default to the `ubuntu` user.
14
+ */
15
+ import type { EC2Client } from '../../aws/ec2';
16
+ import type { SSMClient } from '../../aws/ssm';
17
+ import type { HetznerClient } from '../hetzner/client';
18
+ export type BoxProviderName = 'hetzner' | 'aws';
19
+ export interface BoxPort {
20
+ protocol: 'tcp' | 'udp' | 'icmp';
21
+ /** Port number; omit for icmp. */
22
+ port?: number;
23
+ }
24
+ export interface BoxSpec {
25
+ /** Resource name; also names the firewall/security group (`<name>-fw`/`<name>-sg`). */
26
+ name: string;
27
+ /** Provider-native size (Hetzner server type like `cx23`, EC2 instance type like `t3.micro`). */
28
+ size: string;
29
+ /** Hetzner image name or an `ami-...` id. Defaults to Ubuntu 24.04 on both providers. */
30
+ image?: string;
31
+ /** Hetzner location (e.g. `fsn1`). AWS placement follows the provisioner's region. */
32
+ location?: string;
33
+ /** Ingress to open in addition to tcp/22. */
34
+ ports?: BoxPort[];
35
+ /** OpenSSH public key authorized for root. */
36
+ sshPublicKey: string;
37
+ /** Plain bash bootstrap script, run once at first boot via cloud-init. */
38
+ bootstrapScript?: string;
39
+ labels?: Record<string, string>;
40
+ }
41
+ export interface ProvisionedBox {
42
+ provider: BoxProviderName;
43
+ id: string;
44
+ name: string;
45
+ publicIp: string;
46
+ created: boolean;
47
+ }
48
+ export interface BoxProvisioner {
49
+ readonly provider: BoxProviderName;
50
+ ensureBox(spec: BoxSpec): Promise<ProvisionedBox>;
51
+ /** Tear down the box and its firewall/security group. */
52
+ destroyBox(name: string): Promise<{
53
+ destroyed: string[];
54
+ }>;
55
+ }
56
+ /** SSM parameter for the current Ubuntu 24.04 amd64 gp3 AMI (Canonical-published). */
57
+ export declare const UBUNTU_2404_AMI_PARAM = "/aws/service/canonical/ubuntu/server/24.04/stable/current/amd64/hvm/ebs-gp3/ami-id";
58
+ /**
59
+ * Cloud-config shared by both providers: root SSH access with the given key
60
+ * (AWS Ubuntu images otherwise lock root and point at the `ubuntu` user) and
61
+ * the optional bootstrap script.
62
+ */
63
+ export declare function buildBoxUserData(spec: Pick<BoxSpec, 'sshPublicKey' | 'bootstrapScript'>): string;
64
+ export declare class HetznerBoxProvisioner implements BoxProvisioner {
65
+ private client;
66
+ readonly provider: "hetzner";
67
+ constructor(client: HetznerClient);
68
+ ensureBox(spec: BoxSpec): Promise<ProvisionedBox>;
69
+ destroyBox(name: string): Promise<{
70
+ destroyed: string[];
71
+ }>;
72
+ }
73
+ /** The EC2 surface the AWS provisioner uses (injectable for tests). */
74
+ export type BoxEc2Client = Pick<EC2Client, 'describeInstances' | 'describeSecurityGroups' | 'createSecurityGroup' | 'authorizeSecurityGroupIngress' | 'runInstances' | 'terminateInstances' | 'deleteSecurityGroup' | 'getInstance'>;
75
+ /** The SSM surface the AWS provisioner uses (injectable for tests). */
76
+ export type BoxSsmClient = Pick<SSMClient, 'getParameter'>;
77
+ export interface AwsBoxProvisionerOptions {
78
+ ec2: BoxEc2Client;
79
+ ssm: BoxSsmClient;
80
+ }
81
+ export declare class AwsBoxProvisioner implements BoxProvisioner {
82
+ readonly provider: "aws";
83
+ private ec2;
84
+ private ssm;
85
+ constructor(options: AwsBoxProvisionerOptions);
86
+ private findInstance;
87
+ private waitForPublicIp;
88
+ private ensureSecurityGroup;
89
+ private resolveImage;
90
+ ensureBox(spec: BoxSpec): Promise<ProvisionedBox>;
91
+ destroyBox(name: string): Promise<{
92
+ destroyed: string[];
93
+ }>;
94
+ }
95
+ export interface CreateBoxProvisionerOptions {
96
+ provider: BoxProviderName;
97
+ /** Required for provider 'hetzner'. */
98
+ hetzner?: HetznerClient;
99
+ /** Required for provider 'aws'. */
100
+ aws?: AwsBoxProvisionerOptions;
101
+ }
102
+ export declare function createBoxProvisioner(options: CreateBoxProvisionerOptions): BoxProvisioner;
package/dist/index.js CHANGED
@@ -55,7 +55,7 @@ import {
55
55
  sanitizeCloudConfig,
56
56
  setMaintenance,
57
57
  startLocalDashboardServer
58
- } from "./chunk-p6309384.js";
58
+ } from "./chunk-x07dz3sd.js";
59
59
  import {
60
60
  buildAndPushServerlessImage
61
61
  } from "./chunk-0wxyppza.js";
@@ -105,7 +105,7 @@ import {
105
105
  waitForCloudInit,
106
106
  waitForSsh,
107
107
  wrapCloudInitUserData
108
- } from "./chunk-dpkk640m.js";
108
+ } from "./chunk-xzn0ntr0.js";
109
109
  import {
110
110
  ABTestManager,
111
111
  AI,