@stacksjs/ts-cloud 0.2.15 → 0.2.17

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.
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Ensure CloudFront distributions serving app domains allow POST/PUT/PATCH/DELETE
3
+ * on cache behaviors that target compute (default behavior and API path patterns).
4
+ */
5
+ export declare function ensureDynamicMethodsForDomains(domains: string[]): Promise<void>;
@@ -0,0 +1,31 @@
1
+ import type { CloudConfig, EnvironmentType } from '@ts-cloud/core';
2
+ export interface SiteStackMigrationPlan {
3
+ oldStackName: string;
4
+ newStackName: string;
5
+ oldBucket: string;
6
+ newBucket: string;
7
+ distributionId: string;
8
+ oacId: string;
9
+ certificateArn: string;
10
+ templatePath: string;
11
+ importPath: string;
12
+ }
13
+ export interface SiteStackMigrationOptions {
14
+ config: CloudConfig;
15
+ environment: EnvironmentType;
16
+ siteKey: string;
17
+ oldStackName: string;
18
+ oldBucket: string;
19
+ distributionId: string;
20
+ oacId: string;
21
+ outputDir: string;
22
+ }
23
+ export declare function buildSiteStackMigrationPlan(options: SiteStackMigrationOptions & {
24
+ certificateArn?: string;
25
+ }): SiteStackMigrationPlan;
26
+ export declare function resolveSiteCertificateArn(domain: string, region?: string): Promise<string>;
27
+ export declare function deployRetainPoliciesToStack(stackName: string, templatePath: string, region: string): Promise<void>;
28
+ export declare function deleteStackRetainResources(stackName: string, region: string): Promise<void>;
29
+ export declare function importSiteStack(plan: SiteStackMigrationPlan, region: string): Promise<void>;
30
+ export declare function syncSiteBucket(oldBucket: string, newBucket: string, region: string): Promise<void>;
31
+ export declare function uploadSiteAssets(plan: SiteStackMigrationPlan, sourceDir: string, region: string): Promise<void>;
@@ -30,6 +30,17 @@ export interface ExternalDnsStaticSiteConfig {
30
30
  skipDnsVerification?: boolean;
31
31
  /** When true, serves raw files without URL rewriting (for curl | bash install scripts) */
32
32
  passthroughUrls?: boolean;
33
+ /**
34
+ * When true, allow POST/PUT/PATCH/DELETE on the default cache behavior.
35
+ * Use when CloudFront fronts a dynamic app (EC2) rather than static S3 only.
36
+ */
37
+ dynamicApp?: boolean;
38
+ /** EC2 public DNS hostname for CloudFront (required when dynamicApp is true). */
39
+ computeOriginDomain?: string;
40
+ /** HTTP port on the compute origin. @default 3008 */
41
+ computeOriginPort?: number;
42
+ /** CloudFront origin Id for the compute origin. */
43
+ computeOriginId?: string;
33
44
  /**
34
45
  * When true, missing files (S3 403/404) fall through to the index document
35
46
  * with a 200 status — required for client-side-routed SPAs.
@@ -65,6 +76,12 @@ export declare function generateExternalDnsStaticSiteTemplate(config: {
65
76
  errorDocument?: string;
66
77
  passthroughUrls?: boolean;
67
78
  singlePageApp?: boolean;
79
+ dynamicApp?: boolean;
80
+ computeOriginDomain?: string;
81
+ computeOriginPort?: number;
82
+ computeOriginId?: string;
83
+ /** When true, retain S3/CloudFront resources if the stack is deleted (stack migration). */
84
+ retainOnStackDelete?: boolean;
68
85
  }): object;
69
86
  /**
70
87
  * Deploy a static site to AWS with external DNS provider
@@ -0,0 +1,16 @@
1
+ import type { CloudDriver, ComputeStackOutputs, ComputeTarget, FindComputeTargetsOptions, ProvisionComputeOptions, RemoteDeployResult, RunRemoteDeployOptions, UploadReleaseOptions, UploadReleaseResult } from '@ts-cloud/core';
2
+ export interface AwsDriverOptions {
3
+ region?: string;
4
+ }
5
+ export declare class AwsDriver implements CloudDriver {
6
+ readonly name: "aws";
7
+ readonly usesCloudFormation = true;
8
+ private region;
9
+ constructor(options?: AwsDriverOptions);
10
+ private resolveRegion;
11
+ getComputeOutputs(options: ProvisionComputeOptions): Promise<ComputeStackOutputs>;
12
+ uploadRelease(options: UploadReleaseOptions): Promise<UploadReleaseResult>;
13
+ findComputeTargets(options: FindComputeTargetsOptions): Promise<ComputeTarget[]>;
14
+ runRemoteDeploy(options: RunRemoteDeployOptions): Promise<RemoteDeployResult>;
15
+ private pollSsmCommand;
16
+ }
@@ -0,0 +1,17 @@
1
+ import type { CloudConfig, CloudDriver, CloudProviderName } from '@ts-cloud/core';
2
+ export interface CreateCloudDriverOptions {
3
+ config: CloudConfig;
4
+ provider?: CloudProviderName;
5
+ }
6
+ /**
7
+ * Create a cloud infrastructure driver from configuration.
8
+ */
9
+ export declare function createCloudDriver(options: CreateCloudDriverOptions): CloudDriver;
10
+ /**
11
+ * Factory with caching — mirrors DnsProviderFactory.
12
+ */
13
+ export declare class CloudDriverFactory {
14
+ private drivers;
15
+ getDriver(config: CloudConfig, provider?: CloudProviderName): CloudDriver;
16
+ }
17
+ export declare const cloudDrivers: CloudDriverFactory;
@@ -0,0 +1,127 @@
1
+ /**
2
+ * Hetzner Cloud API client
3
+ * @see https://docs.hetzner.cloud/
4
+ */
5
+ export interface HetznerApiErrorBody {
6
+ error?: {
7
+ code?: string;
8
+ message?: string;
9
+ details?: unknown;
10
+ };
11
+ }
12
+ export interface HetznerServer {
13
+ id: number;
14
+ name: string;
15
+ status: string;
16
+ public_net: {
17
+ ipv4?: {
18
+ ip: string;
19
+ };
20
+ ipv6?: {
21
+ ip: string;
22
+ };
23
+ };
24
+ private_net?: Array<{
25
+ ip: string;
26
+ }>;
27
+ labels?: Record<string, string>;
28
+ server_type: {
29
+ name: string;
30
+ };
31
+ datacenter: {
32
+ name: string;
33
+ location: {
34
+ name: string;
35
+ };
36
+ };
37
+ }
38
+ export interface HetznerFirewall {
39
+ id: number;
40
+ name: string;
41
+ labels?: Record<string, string>;
42
+ rules?: HetznerFirewallRule[];
43
+ }
44
+ export interface HetznerFirewallRule {
45
+ direction: 'in' | 'out';
46
+ protocol: 'tcp' | 'udp' | 'icmp' | 'esp' | 'gre';
47
+ port?: string;
48
+ source_ips: string[];
49
+ description?: string;
50
+ }
51
+ export interface HetznerSshKey {
52
+ id: number;
53
+ name: string;
54
+ fingerprint: string;
55
+ public_key: string;
56
+ labels?: Record<string, string>;
57
+ }
58
+ export interface HetznerAction {
59
+ id: number;
60
+ status: 'running' | 'success' | 'error';
61
+ progress?: number;
62
+ error?: {
63
+ code: string;
64
+ message: string;
65
+ };
66
+ }
67
+ export interface CreateServerOptions {
68
+ name: string;
69
+ serverType: string;
70
+ image: string;
71
+ location?: string;
72
+ datacenter?: string;
73
+ sshKeys?: number[];
74
+ userData?: string;
75
+ labels?: Record<string, string>;
76
+ firewalls?: Array<{
77
+ firewall: number;
78
+ }>;
79
+ }
80
+ export interface CreateFirewallOptions {
81
+ name: string;
82
+ rules: HetznerFirewallRule[];
83
+ labels?: Record<string, string>;
84
+ applyTo?: Array<{
85
+ type: 'server';
86
+ server: number;
87
+ }>;
88
+ }
89
+ export interface HetznerClientOptions {
90
+ apiToken: string;
91
+ baseUrl?: string;
92
+ fetchImpl?: typeof fetch;
93
+ }
94
+ export declare class HetznerClient {
95
+ readonly name = "hetzner";
96
+ private apiToken;
97
+ private baseUrl;
98
+ private fetchImpl;
99
+ constructor(options: HetznerClientOptions);
100
+ private request;
101
+ listServers(): Promise<HetznerServer[]>;
102
+ getServer(id: number): Promise<HetznerServer>;
103
+ createServer(options: CreateServerOptions): Promise<{
104
+ server: HetznerServer;
105
+ action: HetznerAction;
106
+ }>;
107
+ deleteServer(id: number): Promise<HetznerAction>;
108
+ listFirewalls(): Promise<HetznerFirewall[]>;
109
+ createFirewall(options: CreateFirewallOptions): Promise<{
110
+ firewall: HetznerFirewall;
111
+ actions: HetznerAction[];
112
+ }>;
113
+ applyFirewallToResources(firewallId: number, applyTo: Array<{
114
+ type: 'server';
115
+ server: number;
116
+ }>): Promise<HetznerAction[]>;
117
+ listSshKeys(): Promise<HetznerSshKey[]>;
118
+ waitForAction(actionId: number, options?: {
119
+ pollIntervalMs?: number;
120
+ maxWaitMs?: number;
121
+ }): Promise<HetznerAction>;
122
+ waitForServerRunning(serverId: number, options?: {
123
+ pollIntervalMs?: number;
124
+ maxWaitMs?: number;
125
+ }): Promise<HetznerServer>;
126
+ }
127
+ export declare function resolveHetznerApiToken(configToken?: string): string;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Ubuntu cloud-init bootstrap for Hetzner compute targets.
3
+ * Mirrors Compute.UserData.generateBunAppScript but uses apt instead of dnf
4
+ * and omits AWS CLI (deploys use SCP + SSH).
5
+ */
6
+ export interface UbuntuBootstrapOptions {
7
+ runtime?: 'bun' | 'node' | 'deno';
8
+ runtimeVersion?: string;
9
+ systemPackages?: string[];
10
+ database?: 'sqlite' | 'mysql' | 'postgres';
11
+ caddyfile?: string;
12
+ }
13
+ export declare function generateUbuntuAppCloudInit(options?: UbuntuBootstrapOptions): string;
14
+ /**
15
+ * Wrap a bash bootstrap script as Hetzner cloud-init user_data (#cloud-config).
16
+ */
17
+ export declare function wrapCloudInitUserData(bootstrapScript: string): string;
@@ -0,0 +1,28 @@
1
+ import type { CloudDriver, ComputeStackOutputs, ComputeTarget, FindComputeTargetsOptions, ProvisionComputeOptions, RemoteDeployResult, RunRemoteDeployOptions, UploadReleaseOptions, UploadReleaseResult } from '@ts-cloud/core';
2
+ import { HetznerClient } from './client';
3
+ export interface HetznerDriverOptions {
4
+ apiToken?: string;
5
+ sshPrivateKeyPath?: string;
6
+ sshUser?: string;
7
+ location?: string;
8
+ client?: HetznerClient;
9
+ }
10
+ export declare class HetznerDriver implements CloudDriver {
11
+ readonly name: "hetzner";
12
+ readonly usesCloudFormation = false;
13
+ private client;
14
+ private sshPrivateKeyPath;
15
+ private sshUser;
16
+ private location;
17
+ constructor(options?: HetznerDriverOptions);
18
+ provisionComputeInfrastructure(options: ProvisionComputeOptions): Promise<ComputeStackOutputs>;
19
+ getComputeOutputs(options: ProvisionComputeOptions): Promise<ComputeStackOutputs>;
20
+ uploadRelease(options: UploadReleaseOptions): Promise<UploadReleaseResult>;
21
+ findComputeTargets(options: FindComputeTargetsOptions): Promise<ComputeTarget[]>;
22
+ runRemoteDeploy(options: RunRemoteDeployOptions): Promise<RemoteDeployResult>;
23
+ private outputsFromState;
24
+ private sshBaseArgs;
25
+ private scpToHost;
26
+ private sshExec;
27
+ }
28
+ export declare function resolveHetznerDeployBucketName(slug: string, environment: string): string;
@@ -0,0 +1,12 @@
1
+ export interface HetznerFirewallRuleInput {
2
+ allowSsh?: boolean;
3
+ sitePorts: number[];
4
+ }
5
+ export type HetznerInboundFirewallRule = {
6
+ direction: 'in';
7
+ protocol: 'tcp';
8
+ port: string;
9
+ source_ips: string[];
10
+ description?: string;
11
+ };
12
+ export declare function buildHetznerFirewallRules(config: HetznerFirewallRuleInput): HetznerInboundFirewallRule[];
@@ -0,0 +1,10 @@
1
+ import type { InstanceSize } from '@ts-cloud/core';
2
+ /**
3
+ * Map ts-cloud instance size shorthands to Hetzner Cloud server types.
4
+ * @see https://www.hetzner.com/cloud
5
+ */
6
+ export declare const HETZNER_INSTANCE_TYPES: Record<Exclude<InstanceSize, string & {}> | 'micro' | 'small' | 'medium' | 'large' | 'xlarge' | '2xlarge', string>;
7
+ export declare function resolveHetznerServerType(size?: string): string;
8
+ export declare const TS_CLOUD_LABEL_PREFIX = "ts-cloud";
9
+ export declare function tsCloudLabels(slug: string, environment: string, role?: string): Record<string, string>;
10
+ export declare function matchesTsCloudLabels(labels: Record<string, string> | undefined, slug: string, environment: string, role?: string): boolean;
@@ -0,0 +1,13 @@
1
+ export interface HetznerDriverState {
2
+ provider: 'hetzner';
3
+ stackName: string;
4
+ serverId: number;
5
+ serverName: string;
6
+ firewallId?: number;
7
+ publicIp?: string;
8
+ deployStoragePath?: string;
9
+ sshUser?: string;
10
+ }
11
+ export declare function driverStatePath(stackName: string): string;
12
+ export declare function readDriverState(stackName: string): Promise<HetznerDriverState | null>;
13
+ export declare function writeDriverState(stackName: string, state: HetznerDriverState): Promise<void>;
@@ -0,0 +1,8 @@
1
+ export * from './factory';
2
+ export { AwsDriver } from './aws/driver';
3
+ export { HetznerDriver } from './hetzner/driver';
4
+ export { HetznerClient, resolveHetznerApiToken } from './hetzner/client';
5
+ export { generateUbuntuAppCloudInit, wrapCloudInitUserData } from './hetzner/cloud-init';
6
+ export { buildCaddyfile } from './shared/caddyfile';
7
+ export { buildAwsArtifactFetch, buildLocalArtifactFetch, buildSiteDeployScript, resolveExecStart, } from './shared/deploy-script';
8
+ export { deployAllComputeSites, deploySiteRelease } from './shared/compute-deploy';
@@ -0,0 +1,6 @@
1
+ import type { SiteConfig } from '@ts-cloud/core';
2
+ /**
3
+ * Build a Caddyfile from site configs. Sites sharing a domain are grouped;
4
+ * explicit paths are ordered before catch-all routes.
5
+ */
6
+ export declare function buildCaddyfile(sites: Record<string, SiteConfig>): string | undefined;
@@ -0,0 +1,25 @@
1
+ import type { CloudConfig, CloudDriver, DeploySiteReleaseOptions, DeploySiteReleaseResult, EnvironmentType } from '@ts-cloud/core';
2
+ export interface ComputeDeployLogger {
3
+ info(message: string): void;
4
+ warn(message: string): void;
5
+ error(message: string): void;
6
+ step(message: string): void;
7
+ success(message: string): void;
8
+ }
9
+ /**
10
+ * Deploy a single site release tarball to compute targets via the active driver.
11
+ */
12
+ export declare function deploySiteRelease(driver: CloudDriver, options: DeploySiteReleaseOptions, logger?: ComputeDeployLogger): Promise<DeploySiteReleaseResult>;
13
+ export interface DeployAllSitesOptions {
14
+ config: CloudConfig;
15
+ environment: EnvironmentType;
16
+ driver: CloudDriver;
17
+ sha: string;
18
+ runtime: 'bun' | 'node' | 'deno';
19
+ tarballForSite: (siteName: string) => string;
20
+ logger?: ComputeDeployLogger;
21
+ }
22
+ /**
23
+ * Deploy every site that declares a `start` command.
24
+ */
25
+ export declare function deployAllComputeSites(options: DeployAllSitesOptions): Promise<boolean>;
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Shared deploy script helpers for Forge-style compute deploys.
3
+ */
4
+ /**
5
+ * Translate a `start` command (e.g. "bun run server.ts") into an absolute
6
+ * systemd ExecStart by swapping the leading runtime word for its absolute path.
7
+ */
8
+ export declare function resolveExecStart(start: string, runtime: 'bun' | 'node' | 'deno'): string;
9
+ export interface BuildSiteDeployScriptOptions {
10
+ siteName: string;
11
+ slug: string;
12
+ /** How the remote host obtains the release tarball */
13
+ artifactFetch: string[];
14
+ appDir?: string;
15
+ execStart: string;
16
+ envEntries: Record<string, string>;
17
+ port?: number;
18
+ }
19
+ /**
20
+ * Build the remote shell commands that install/refresh a site on a compute target.
21
+ */
22
+ export declare function buildSiteDeployScript(options: BuildSiteDeployScriptOptions): string[];
23
+ export declare function buildAwsArtifactFetch(bucket: string, key: string, region: string, siteName: string): string[];
24
+ export declare function buildLocalArtifactFetch(localPath: string, siteName: string): string[];
@@ -25,6 +25,23 @@ export declare class InfrastructureGenerator {
25
25
  */
26
26
  private shouldDeploy;
27
27
  private resolveApiOriginPort;
28
+ private defaultComputeCachePathPatterns;
29
+ private shouldRouteStorageBucketToCompute;
30
+ private resolveComputeCachePathPatterns;
31
+ private createComputeCacheBehavior;
32
+ private appendComputeAppOrigin;
33
+ /**
34
+ * Build a Caddyfile from the sites config. Returns undefined when no
35
+ * site has a `domain` (Caddy install is then skipped — useful for
36
+ * staging EC2 boxes accessed by raw IP).
37
+ *
38
+ * Sites sharing a `domain` collapse into a single block. Within that
39
+ * block, sites with an explicit `path` get `handle <path>` blocks
40
+ * (ordered most-specific first so prefix matches take priority); a
41
+ * site with no `path` (or `path: '/'`) becomes the bare catch-all
42
+ * `handle` at the end.
43
+ */
44
+ private buildCaddyfile;
28
45
  private normalizeMountPath;
29
46
  private storageBucketLogicalId;
30
47
  private pathMountRewriteFunctionCode;
package/dist/index.d.ts CHANGED
@@ -4,9 +4,13 @@ export { validateTemplate, validateTemplateSize, validateResourceLimits, } from
4
4
  export type { ValidationError as TemplateValidationError, ValidationResult as TemplateValidationResult, } from './validation';
5
5
  export { AWSClient, CloudFormationClient, CloudFormationClient as AWSCloudFormationClient, CloudFrontClient, CloudFrontClient as AWSCloudFrontClient, EC2Client, S3Client, Route53Client, Route53DomainsClient, ACMClient, ACMDnsValidator, ECRClient, ECSClient, STSClient, SSMClient, SecretsManagerClient, SESClient, EmailClient, SNSClient, SQSClient, LambdaClient, CloudWatchLogsClient, ConnectClient, ELBv2Client, RDSClient, DynamoDBClient, OpenSearchClient, TranscribeClient, BedrockClient, BedrockRuntimeClient, ComprehendClient, RekognitionClient, TextractClient, PollyClient, TranslateClient, PersonalizeClient, KendraClient, EventBridgeClient, ElastiCacheClient, SchedulerClient, IAMClient, ApplicationAutoScalingClient, SmsClient, VoiceClient, SupportClient, EFSClient, } from './aws';
6
6
  export type { AWSRequestOptions, AWSClientConfig, AWSError, AWSCredentials as AWSClientCredentials, StackParameter, StackTag, CreateStackOptions, UpdateStackOptions, DescribeStacksOptions, StackEvent, Stack, InvalidationOptions, Distribution, S3SyncOptions, S3CopyOptions, S3ListOptions, S3Object, CertificateDetail, Certificate as ELBv2Certificate, RekognitionS3Object, RekognitionBoundingBox, TextractS3Object, TextractBoundingBox, CountryCode, ContactType, ContactDetail, KendraCreateDataSourceCommandInput, KendraCreateDataSourceCommandOutput, KendraListDataSourcesCommandInput, KendraListDataSourcesCommandOutput, InvokeModelCommandInput, InvokeModelCommandOutput, InvokeModelWithResponseStreamCommandInput, InvokeModelWithResponseStreamCommandOutput, CreateModelCustomizationJobCommandInput, CreateModelCustomizationJobCommandOutput, GetModelCustomizationJobCommandInput, GetModelCustomizationJobCommandOutput, ListFoundationModelsCommandInput, ListFoundationModelsCommandOutput, AttributeValue as DynamoDBAttributeValue, KeySchemaElement, AttributeDefinition as DynamoDBAttributeDefinition, } from './aws';
7
+ export { createObjectStorageClient, providerEndpoint, resolveObjectStorage, } from './object-storage';
8
+ export type { ObjectStorageConfig, ObjectStorageCredentials, ObjectStorageProvider, ResolvedObjectStorage, } from './object-storage';
7
9
  export * from './ssl';
8
10
  export { deployStaticSite, deployStaticSiteFull, uploadStaticFiles, invalidateCache, deleteStaticSite, generateStaticSiteTemplate, deployStaticSiteWithExternalDns, deployStaticSiteWithExternalDnsFull, generateExternalDnsStaticSiteTemplate, deploySite, } from './deploy';
9
11
  export type { StaticSiteConfig, DeployResult, UploadOptions, ExternalDnsStaticSiteConfig, ExternalDnsDeployResult, DeploySiteConfig, DeploySiteResult, StaticSiteDnsProvider, } from './deploy';
12
+ export { createCloudDriver, CloudDriverFactory, cloudDrivers, AwsDriver, HetznerDriver, HetznerClient, resolveHetznerApiToken, generateUbuntuAppCloudInit, wrapCloudInitUserData, buildCaddyfile, buildSiteDeployScript, resolveExecStart, deployAllComputeSites, deploySiteRelease, } from './drivers';
13
+ export type { CreateCloudDriverOptions } from './drivers/factory';
10
14
  export { createDnsProvider, detectDnsProvider, DnsProviderFactory, dnsProviders, PorkbunProvider, GoDaddyProvider, Route53Provider, UnifiedDnsValidator, createPorkbunValidator, createGoDaddyValidator, createRoute53Validator, } from './dns';
11
15
  export type { DnsProvider, DnsProviderConfig, DnsRecord, DnsRecordType, DnsRecordResult, CreateRecordResult, DeleteRecordResult, ListRecordsResult, } from './dns';
12
16
  export * from '@ts-cloud/core';