@stacksjs/ts-cloud 0.2.22 → 0.2.24
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/aws/s3.d.ts +17 -0
- package/dist/bin/cli.js +583 -567
- package/dist/deploy/site-target.d.ts +3 -3
- package/dist/drivers/hetzner/driver.d.ts +5 -4
- package/dist/drivers/index.d.ts +0 -1
- package/dist/drivers/shared/compute-deploy.d.ts +1 -1
- package/dist/drivers/shared/deploy-script.d.ts +3 -3
- package/dist/index.d.ts +3 -1
- package/dist/index.js +226 -213
- package/dist/object-storage/index.d.ts +1 -0
- package/dist/object-storage/migrate.d.ts +125 -0
- package/package.json +3 -3
- package/dist/drivers/shared/caddyfile.d.ts +0 -46
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-provider object-storage migration.
|
|
3
|
+
*
|
|
4
|
+
* Copies objects from one S3-compatible bucket to another — AWS S3, Backblaze
|
|
5
|
+
* B2, Hetzner Object Storage, in any direction. Both sides are driven by the
|
|
6
|
+
* same {@link createObjectStorageClient}, so the only thing that changes per
|
|
7
|
+
* side is the provider/region/endpoint/credentials.
|
|
8
|
+
*
|
|
9
|
+
* Bytes are copied (not strings) via {@link S3Client.getObjectBytes}, so binary
|
|
10
|
+
* payloads (images, archives, mail attachments) survive intact. Content-Type is
|
|
11
|
+
* preserved when the source reports it.
|
|
12
|
+
*
|
|
13
|
+
* The copy is idempotent: an object already present at the destination with the
|
|
14
|
+
* same size is skipped unless `force` is set. Keys may be remapped by stripping
|
|
15
|
+
* `fromPrefix` and prepending `toPrefix`, and filtered with include/exclude
|
|
16
|
+
* prefix lists so an operator can clearly see what was migrated vs. deliberately
|
|
17
|
+
* left behind.
|
|
18
|
+
*/
|
|
19
|
+
import type { S3Client } from '../aws/s3';
|
|
20
|
+
import type { ObjectStorageProvider } from './index';
|
|
21
|
+
/** One side (source or destination) of a migration. */
|
|
22
|
+
export interface MigrateEndpoint {
|
|
23
|
+
provider: ObjectStorageProvider;
|
|
24
|
+
bucket: string;
|
|
25
|
+
region?: string;
|
|
26
|
+
/** Endpoint host override (no scheme). Defaults to the provider's standard endpoint. */
|
|
27
|
+
endpoint?: string;
|
|
28
|
+
forcePathStyle?: boolean;
|
|
29
|
+
/** Key prefix. On the source it scopes/strips; on the dest it is prepended. */
|
|
30
|
+
prefix?: string;
|
|
31
|
+
/** Explicit credentials. When omitted, resolved from the provider's env vars. */
|
|
32
|
+
credentials?: {
|
|
33
|
+
accessKeyId: string;
|
|
34
|
+
secretAccessKey: string;
|
|
35
|
+
sessionToken?: string;
|
|
36
|
+
};
|
|
37
|
+
/** Pre-built client (used by tests to inject an in-memory mock). */
|
|
38
|
+
client?: S3Client;
|
|
39
|
+
}
|
|
40
|
+
export interface MigrateOptions {
|
|
41
|
+
from: MigrateEndpoint;
|
|
42
|
+
to: MigrateEndpoint;
|
|
43
|
+
/** Only copy keys whose (source) key starts with one of these prefixes. */
|
|
44
|
+
include?: string[];
|
|
45
|
+
/** Skip keys whose (source) key starts with one of these prefixes. */
|
|
46
|
+
exclude?: string[];
|
|
47
|
+
/** Plan only — do not write to the destination. */
|
|
48
|
+
dryRun?: boolean;
|
|
49
|
+
/** Re-copy even if the destination already has an object of the same size. */
|
|
50
|
+
force?: boolean;
|
|
51
|
+
/** Delete destination keys (within the dest prefix) that are not in the copied set. Default OFF. */
|
|
52
|
+
deleteExtraneous?: boolean;
|
|
53
|
+
/** Max in-flight copies. Default 8. */
|
|
54
|
+
concurrency?: number;
|
|
55
|
+
/** After copying, re-list the destination and assert counts + sizes match the copied set. */
|
|
56
|
+
verify?: boolean;
|
|
57
|
+
/** Optional progress callback, invoked per object after it is copied/skipped. */
|
|
58
|
+
onProgress?: (event: MigrateProgress) => void;
|
|
59
|
+
}
|
|
60
|
+
export interface MigrateProgress {
|
|
61
|
+
/** Source key. */
|
|
62
|
+
key: string;
|
|
63
|
+
/** Destination key the object maps to. */
|
|
64
|
+
destKey: string;
|
|
65
|
+
size: number;
|
|
66
|
+
action: 'copied' | 'skipped' | 'excluded' | 'error' | 'planned';
|
|
67
|
+
/** 1-based index of this object within the full source listing. */
|
|
68
|
+
index: number;
|
|
69
|
+
total: number;
|
|
70
|
+
}
|
|
71
|
+
export interface MigrateError {
|
|
72
|
+
key: string;
|
|
73
|
+
message: string;
|
|
74
|
+
}
|
|
75
|
+
export interface MigratePlanItem {
|
|
76
|
+
key: string;
|
|
77
|
+
destKey: string;
|
|
78
|
+
size: number;
|
|
79
|
+
}
|
|
80
|
+
export interface MigrateResult {
|
|
81
|
+
copied: number;
|
|
82
|
+
skipped: number;
|
|
83
|
+
excluded: number;
|
|
84
|
+
bytesCopied: number;
|
|
85
|
+
errors: MigrateError[];
|
|
86
|
+
/** Keys that were excluded by include/exclude filters (source keys). */
|
|
87
|
+
excludedKeys: string[];
|
|
88
|
+
/** Keys deleted from the destination via `deleteExtraneous`. */
|
|
89
|
+
deleted: string[];
|
|
90
|
+
/** When `dryRun` is set, the objects that would be copied. */
|
|
91
|
+
plan?: MigratePlanItem[];
|
|
92
|
+
/** Verification outcome when `verify` is set. */
|
|
93
|
+
verification?: MigrateVerification;
|
|
94
|
+
}
|
|
95
|
+
export interface MigrateVerification {
|
|
96
|
+
ok: boolean;
|
|
97
|
+
/** Number of (key,size) pairs that matched at the destination. */
|
|
98
|
+
matched: number;
|
|
99
|
+
/** Copied keys missing at the destination. */
|
|
100
|
+
missing: string[];
|
|
101
|
+
/** Copied keys present at the destination but with a different size. */
|
|
102
|
+
sizeMismatches: Array<{
|
|
103
|
+
key: string;
|
|
104
|
+
expected: number;
|
|
105
|
+
actual: number;
|
|
106
|
+
}>;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Compute the destination key for a source key: strip the source prefix, then
|
|
110
|
+
* prepend the destination prefix. Exported for unit testing.
|
|
111
|
+
*/
|
|
112
|
+
export declare function remapKey(sourceKey: string, fromPrefix?: string, toPrefix?: string): string;
|
|
113
|
+
/**
|
|
114
|
+
* Decide whether a source key passes the include/exclude prefix filters.
|
|
115
|
+
* `include` (when non-empty) is a whitelist; `exclude` always wins. Exported for
|
|
116
|
+
* unit testing.
|
|
117
|
+
*/
|
|
118
|
+
export declare function keyMatchesFilters(key: string, include?: string[], exclude?: string[]): boolean;
|
|
119
|
+
/**
|
|
120
|
+
* Migrate objects from one S3-compatible bucket to another.
|
|
121
|
+
*
|
|
122
|
+
* @returns a structured {@link MigrateResult} so callers (CLI, buddy, scripts)
|
|
123
|
+
* can report exactly what was copied, skipped, excluded, deleted and verified.
|
|
124
|
+
*/
|
|
125
|
+
export declare function migrateObjectStorage(options: MigrateOptions): Promise<MigrateResult>;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stacksjs/ts-cloud",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.24",
|
|
5
5
|
"description": "A lightweight, performant infrastructure-as-code library and CLI for deploying both server-based (EC2) and serverless applications.",
|
|
6
6
|
"author": "Chris Breuer <chris@stacksjs.com>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -89,8 +89,8 @@
|
|
|
89
89
|
"test": "bun test"
|
|
90
90
|
},
|
|
91
91
|
"dependencies": {
|
|
92
|
-
"@ts-cloud/aws-types": "0.2.
|
|
93
|
-
"@ts-cloud/core": "0.2.
|
|
92
|
+
"@ts-cloud/aws-types": "0.2.24",
|
|
93
|
+
"@ts-cloud/core": "0.2.24",
|
|
94
94
|
"@stacksjs/ts-xml": "^0.1.0"
|
|
95
95
|
},
|
|
96
96
|
"devDependencies": {
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import type { CaddyAppConfig, CaddyProxyConfig, SiteConfig } from '@ts-cloud/core';
|
|
2
|
-
/** A domain is "on-demand" (needs lazy TLS) if it's a wildcard or bare catch-all. */
|
|
3
|
-
export declare function isOnDemandDomain(domain: string): boolean;
|
|
4
|
-
/**
|
|
5
|
-
* The on-server install path a static site's `root` is shipped to. Mirrors the
|
|
6
|
-
* release layout used by the systemd app deploy (`/var/www/<name>`), so a box
|
|
7
|
-
* can host both proxied apps and file-served static sites side by side.
|
|
8
|
-
*/
|
|
9
|
-
export declare function staticSiteServerRoot(name: string): string;
|
|
10
|
-
/**
|
|
11
|
-
* Build a complete Caddyfile from a typed {@link CaddyProxyConfig}.
|
|
12
|
-
*
|
|
13
|
-
* Produces:
|
|
14
|
-
* - a global options block (ACME email, on-demand TLS `ask`, staging CA, extras);
|
|
15
|
-
* - one site block per unique domain set, each performing host-based routing to
|
|
16
|
-
* its upstream app(s);
|
|
17
|
-
* - `tls { on_demand }` inside any block whose domains are wildcards/catch-all.
|
|
18
|
-
*
|
|
19
|
-
* Returns `undefined` when there's nothing to route (no apps, no raw).
|
|
20
|
-
*/
|
|
21
|
-
export declare function buildCaddyfileFromProxy(proxy: CaddyProxyConfig): string | undefined;
|
|
22
|
-
/**
|
|
23
|
-
* Derive a {@link CaddyProxyConfig} from the legacy `sites` map: every site
|
|
24
|
-
* that declares a `domain` + `port` becomes a Caddy app. Keeps single-app /
|
|
25
|
-
* sites-driven deploys working without an explicit `compute.proxy` block.
|
|
26
|
-
*/
|
|
27
|
-
export declare function proxyConfigFromSites(sites: Record<string, SiteConfig>): CaddyProxyConfig & {
|
|
28
|
-
apps: CaddyAppConfig[];
|
|
29
|
-
};
|
|
30
|
-
/**
|
|
31
|
-
* Resolve the final Caddyfile for a deploy. Prefers the typed `compute.proxy`
|
|
32
|
-
* config (merging in `sites`-derived apps when `proxy.apps` is omitted), and
|
|
33
|
-
* falls back to deriving everything from `sites`.
|
|
34
|
-
*
|
|
35
|
-
* Returns `undefined` when there's nothing to route.
|
|
36
|
-
*/
|
|
37
|
-
export declare function resolveCaddyfile(sites: Record<string, SiteConfig>, proxy?: CaddyProxyConfig): string | undefined;
|
|
38
|
-
/**
|
|
39
|
-
* Build a Caddyfile from site configs. Sites sharing a domain are grouped;
|
|
40
|
-
* explicit paths are ordered before catch-all routes.
|
|
41
|
-
*
|
|
42
|
-
* @deprecated Prefer {@link resolveCaddyfile} / {@link buildCaddyfileFromProxy},
|
|
43
|
-
* which support multi-app host routing and on-demand TLS. Retained for
|
|
44
|
-
* backward compatibility.
|
|
45
|
-
*/
|
|
46
|
-
export declare function buildCaddyfile(sites: Record<string, SiteConfig>): string | undefined;
|