@savestate/cli 0.2.0 → 0.2.1

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.
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,UAAU,aAAa;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,wBAAsB,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAgEzE"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,UAAU,aAAa;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AA8BD,wBAAsB,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAwEzE"}
@@ -2,7 +2,33 @@
2
2
  * savestate config — View/edit configuration
3
3
  */
4
4
  import chalk from 'chalk';
5
- import { isInitialized, loadConfig, localConfigPath } from '../config.js';
5
+ import { isInitialized, loadConfig, saveConfig, localConfigPath } from '../config.js';
6
+ /**
7
+ * Set a deeply nested property on an object using dot-notation path.
8
+ * Auto-creates intermediate objects as needed.
9
+ * Coerces 'true'/'false' to boolean and numeric strings to numbers.
10
+ */
11
+ function setNestedValue(obj, path, rawValue) {
12
+ const keys = path.split('.');
13
+ let current = obj;
14
+ for (let i = 0; i < keys.length - 1; i++) {
15
+ const key = keys[i];
16
+ if (typeof current[key] !== 'object' || current[key] === null) {
17
+ current[key] = {};
18
+ }
19
+ current = current[key];
20
+ }
21
+ const finalKey = keys[keys.length - 1];
22
+ // Coerce value types
23
+ let value = rawValue;
24
+ if (rawValue === 'true')
25
+ value = true;
26
+ else if (rawValue === 'false')
27
+ value = false;
28
+ else if (/^\d+$/.test(rawValue))
29
+ value = parseInt(rawValue, 10);
30
+ current[finalKey] = value;
31
+ }
6
32
  export async function configCommand(options) {
7
33
  console.log();
8
34
  if (!isInitialized()) {
@@ -12,14 +38,19 @@ export async function configCommand(options) {
12
38
  const config = await loadConfig();
13
39
  const configPath = localConfigPath();
14
40
  if (options.set) {
15
- // TODO: Parse key=value and update config
16
- console.log(chalk.yellow(` Setting config values is coming soon.`));
17
- console.log(chalk.dim(` For now, edit directly: ${configPath}`));
18
- console.log();
19
- console.log(chalk.dim(' Usage examples:'));
20
- console.log(chalk.dim(' savestate config --set storage.type=s3'));
21
- console.log(chalk.dim(' savestate config --set defaultAdapter=chatgpt'));
22
- console.log(chalk.dim(' savestate config --set retention.maxSnapshots=50'));
41
+ const eqIndex = options.set.indexOf('=');
42
+ if (eqIndex === -1) {
43
+ console.log(chalk.red(' Invalid format. Use: --set key=value'));
44
+ console.log(chalk.dim(' Example: savestate config --set storage.type=s3'));
45
+ console.log();
46
+ process.exit(1);
47
+ }
48
+ const key = options.set.slice(0, eqIndex);
49
+ const value = options.set.slice(eqIndex + 1);
50
+ setNestedValue(config, key, value);
51
+ await saveConfig(config);
52
+ console.log(chalk.green(` ✓ Set ${chalk.bold(key)} = ${chalk.bold(value)}`));
53
+ console.log(chalk.dim(` ${configPath}`));
23
54
  console.log();
24
55
  return;
25
56
  }
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"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"}
@@ -2,6 +2,8 @@
2
2
  * Storage module re-exports
3
3
  */
4
4
  export { LocalStorageBackend } from './local.js';
5
+ export { S3Storage, S3Error } from './s3.js';
6
+ export type { S3StorageOptions } from './s3.js';
5
7
  export { resolveStorage } from './resolve.js';
6
8
  export type { StorageBackend } from './interface.js';
7
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAC7C,YAAY,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC"}
@@ -2,5 +2,6 @@
2
2
  * Storage module re-exports
3
3
  */
4
4
  export { LocalStorageBackend } from './local.js';
5
+ export { S3Storage, S3Error } from './s3.js';
5
6
  export { resolveStorage } from './resolve.js';
6
7
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAE7C,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../src/storage/resolve.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAGnE;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,eAAe,GAAG,cAAc,CAatE"}
1
+ {"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../src/storage/resolve.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAKnE;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,eAAe,GAAG,cAAc,CA6BtE"}
@@ -4,18 +4,33 @@
4
4
  * Creates a storage backend instance from config.
5
5
  */
6
6
  import { LocalStorageBackend } from './local.js';
7
+ import { S3Storage } from './s3.js';
7
8
  /**
8
9
  * Create a storage backend from the config's storage section.
9
10
  */
10
11
  export function resolveStorage(config) {
11
- switch (config.storage.type) {
12
+ const { type, options } = config.storage;
13
+ switch (type) {
12
14
  case 'local':
13
15
  return new LocalStorageBackend({
14
- path: config.storage.options.path,
16
+ path: options.path,
17
+ });
18
+ case 's3':
19
+ case 'r2':
20
+ case 'b2':
21
+ return new S3Storage({
22
+ bucket: options.bucket,
23
+ endpoint: options.endpoint,
24
+ region: options.region,
25
+ accessKeyId: options.accessKeyId,
26
+ secretAccessKey: options.secretAccessKey,
27
+ prefix: options.prefix,
28
+ timeoutMs: options.timeoutMs,
29
+ maxRetries: options.maxRetries,
15
30
  });
16
31
  default:
17
- throw new Error(`Unknown storage backend: ${config.storage.type}. ` +
18
- `Supported: local. S3/R2/B2 coming soon.`);
32
+ throw new Error(`Unknown storage backend: ${type}. ` +
33
+ `Supported: local, s3, r2, b2.`);
19
34
  }
20
35
  }
21
36
  //# sourceMappingURL=resolve.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../src/storage/resolve.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEjD;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,MAAuB;IACpD,QAAQ,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;QAC5B,KAAK,OAAO;YACV,OAAO,IAAI,mBAAmB,CAAC;gBAC7B,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,IAA0B;aACxD,CAAC,CAAC;QAEL;YACE,MAAM,IAAI,KAAK,CACb,4BAA4B,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI;gBACnD,yCAAyC,CAC1C,CAAC;IACN,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../src/storage/resolve.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAGpC;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,MAAuB;IACpD,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC;IAEzC,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,OAAO;YACV,OAAO,IAAI,mBAAmB,CAAC;gBAC7B,IAAI,EAAE,OAAO,CAAC,IAA0B;aACzC,CAAC,CAAC;QAEL,KAAK,IAAI,CAAC;QACV,KAAK,IAAI,CAAC;QACV,KAAK,IAAI;YACP,OAAO,IAAI,SAAS,CAAC;gBACnB,MAAM,EAAE,OAAO,CAAC,MAAgB;gBAChC,QAAQ,EAAE,OAAO,CAAC,QAAkB;gBACpC,MAAM,EAAE,OAAO,CAAC,MAA4B;gBAC5C,WAAW,EAAE,OAAO,CAAC,WAAiC;gBACtD,eAAe,EAAE,OAAO,CAAC,eAAqC;gBAC9D,MAAM,EAAE,OAAO,CAAC,MAA4B;gBAC5C,SAAS,EAAE,OAAO,CAAC,SAA+B;gBAClD,UAAU,EAAE,OAAO,CAAC,UAAgC;aAC1B,CAAC,CAAC;QAEhC;YACE,MAAM,IAAI,KAAK,CACb,4BAA4B,IAAI,IAAI;gBACpC,+BAA+B,CAChC,CAAC;IACN,CAAC;AACH,CAAC"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * S3-Compatible Storage Backend
3
+ *
4
+ * Works with AWS S3, Cloudflare R2, Backblaze B2, and any S3-compatible service.
5
+ * Uses native fetch() and implements AWS Signature V4 from scratch — zero dependencies.
6
+ *
7
+ * Path-style access only (most compatible across providers).
8
+ */
9
+ import type { StorageBackend } from '../types.js';
10
+ export interface S3StorageOptions {
11
+ /** S3 bucket name */
12
+ bucket: string;
13
+ /** Endpoint URL (e.g., https://<account>.r2.cloudflarestorage.com) */
14
+ endpoint: string;
15
+ /** AWS region (e.g., 'us-east-1', 'auto' for R2) */
16
+ region?: string;
17
+ /** AWS access key ID */
18
+ accessKeyId?: string;
19
+ /** AWS secret access key */
20
+ secretAccessKey?: string;
21
+ /** Optional key prefix (e.g., 'snapshots/') */
22
+ prefix?: string;
23
+ /** Request timeout in milliseconds (default: 30000) */
24
+ timeoutMs?: number;
25
+ /** Max retries on 5xx errors (default: 3) */
26
+ maxRetries?: number;
27
+ }
28
+ export declare class S3Error extends Error {
29
+ readonly statusCode: number;
30
+ readonly code?: string | undefined;
31
+ readonly requestId?: string | undefined;
32
+ constructor(message: string, statusCode: number, code?: string | undefined, requestId?: string | undefined);
33
+ }
34
+ export declare class S3Storage implements StorageBackend {
35
+ readonly id: string;
36
+ private readonly bucket;
37
+ private readonly endpoint;
38
+ private readonly region;
39
+ private readonly accessKeyId;
40
+ private readonly secretAccessKey;
41
+ private readonly prefix;
42
+ private readonly timeoutMs;
43
+ private readonly maxRetries;
44
+ private readonly host;
45
+ constructor(options: S3StorageOptions);
46
+ /**
47
+ * Read from env vars, trying multiple names in order.
48
+ */
49
+ private env;
50
+ /**
51
+ * Build the full object key with prefix.
52
+ */
53
+ private fullKey;
54
+ /**
55
+ * Execute a signed S3 request with retries.
56
+ */
57
+ private request;
58
+ put(key: string, data: Buffer): Promise<void>;
59
+ get(key: string): Promise<Buffer>;
60
+ list(prefix?: string): Promise<string[]>;
61
+ delete(key: string): Promise<void>;
62
+ exists(key: string): Promise<boolean>;
63
+ }
64
+ //# sourceMappingURL=s3.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"s3.d.ts","sourceRoot":"","sources":["../../src/storage/s3.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAIlD,MAAM,WAAW,gBAAgB;IAC/B,qBAAqB;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,sEAAsE;IACtE,QAAQ,EAAE,MAAM,CAAC;IACjB,oDAAoD;IACpD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wBAAwB;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4BAA4B;IAC5B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,+CAA+C;IAC/C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uDAAuD;IACvD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6CAA6C;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAID,qBAAa,OAAQ,SAAQ,KAAK;aAGd,UAAU,EAAE,MAAM;aAClB,IAAI,CAAC,EAAE,MAAM;aACb,SAAS,CAAC,EAAE,MAAM;gBAHlC,OAAO,EAAE,MAAM,EACC,UAAU,EAAE,MAAM,EAClB,IAAI,CAAC,EAAE,MAAM,YAAA,EACb,SAAS,CAAC,EAAE,MAAM,YAAA;CAKrC;AA6JD,qBAAa,SAAU,YAAW,cAAc;IAC9C,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;gBAElB,OAAO,EAAE,gBAAgB;IAkDrC;;OAEG;IACH,OAAO,CAAC,GAAG;IAQX;;OAEG;IACH,OAAO,CAAC,OAAO;IAIf;;OAEG;YACW,OAAO;IAiIf,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI7C,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAMjC,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IA+CxC,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIlC,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAM5C"}
@@ -0,0 +1,360 @@
1
+ /**
2
+ * S3-Compatible Storage Backend
3
+ *
4
+ * Works with AWS S3, Cloudflare R2, Backblaze B2, and any S3-compatible service.
5
+ * Uses native fetch() and implements AWS Signature V4 from scratch — zero dependencies.
6
+ *
7
+ * Path-style access only (most compatible across providers).
8
+ */
9
+ import { createHmac, createHash } from 'node:crypto';
10
+ // ─── Errors ──────────────────────────────────────────────────
11
+ export class S3Error extends Error {
12
+ statusCode;
13
+ code;
14
+ requestId;
15
+ constructor(message, statusCode, code, requestId) {
16
+ super(message);
17
+ this.statusCode = statusCode;
18
+ this.code = code;
19
+ this.requestId = requestId;
20
+ this.name = 'S3Error';
21
+ }
22
+ }
23
+ // ─── AWS Signature V4 ───────────────────────────────────────
24
+ const ALGORITHM = 'AWS4-HMAC-SHA256';
25
+ const SERVICE = 's3';
26
+ const UNSIGNED_PAYLOAD = 'UNSIGNED-PAYLOAD';
27
+ function sha256(data) {
28
+ return createHash('sha256').update(data).digest('hex');
29
+ }
30
+ function hmacSha256(key, data) {
31
+ return createHmac('sha256', key).update(data).digest();
32
+ }
33
+ /**
34
+ * Format a Date as YYYYMMDD'T'HHMMSS'Z' (ISO 8601 basic)
35
+ */
36
+ function toAmzDate(date) {
37
+ return date.toISOString().replace(/[-:]/g, '').replace(/\.\d{3}/, '');
38
+ }
39
+ /**
40
+ * Format a Date as YYYYMMDD
41
+ */
42
+ function toDateStamp(date) {
43
+ return toAmzDate(date).slice(0, 8);
44
+ }
45
+ /**
46
+ * URI-encode per AWS spec (RFC 3986 with some extras).
47
+ * Encodes everything except unreserved characters: A-Za-z0-9 _.-~
48
+ */
49
+ function uriEncode(str, encodeSlash = true) {
50
+ return str
51
+ .split('')
52
+ .map((ch) => {
53
+ if ((ch >= 'A' && ch <= 'Z') ||
54
+ (ch >= 'a' && ch <= 'z') ||
55
+ (ch >= '0' && ch <= '9') ||
56
+ ch === '_' ||
57
+ ch === '-' ||
58
+ ch === '~' ||
59
+ ch === '.') {
60
+ return ch;
61
+ }
62
+ if (ch === '/' && !encodeSlash) {
63
+ return '/';
64
+ }
65
+ return '%' + ch.charCodeAt(0).toString(16).toUpperCase().padStart(2, '0');
66
+ })
67
+ .join('');
68
+ }
69
+ /**
70
+ * AWS Signature V4 signing implementation.
71
+ *
72
+ * Steps:
73
+ * 1. Create canonical request
74
+ * 2. Create string to sign
75
+ * 3. Derive signing key (HMAC chain)
76
+ * 4. Calculate signature
77
+ * 5. Build Authorization header
78
+ */
79
+ function signRequest(params) {
80
+ const { method, path, query, headers, payloadHash, date, region, accessKeyId, secretAccessKey } = params;
81
+ const dateStamp = toDateStamp(date);
82
+ const amzDate = toAmzDate(date);
83
+ const scope = `${dateStamp}/${region}/${SERVICE}/aws4_request`;
84
+ // Step 1: Canonical request
85
+ // Sort query string parameters
86
+ const canonicalQueryString = query
87
+ ? Object.keys(query)
88
+ .sort()
89
+ .map((k) => `${uriEncode(k)}=${uriEncode(query[k])}`)
90
+ .join('&')
91
+ : '';
92
+ // Canonical headers: lowercase, sorted, trimmed
93
+ const signedHeaderNames = Object.keys(headers)
94
+ .map((h) => h.toLowerCase())
95
+ .sort();
96
+ const canonicalHeaders = signedHeaderNames.map((h) => `${h}:${headers[h.toLowerCase()] ?? headers[h]}\n`).join('');
97
+ const signedHeaders = signedHeaderNames.join(';');
98
+ const canonicalRequest = [
99
+ method,
100
+ uriEncode(path, false),
101
+ canonicalQueryString,
102
+ canonicalHeaders,
103
+ signedHeaders,
104
+ payloadHash,
105
+ ].join('\n');
106
+ // Step 2: String to sign
107
+ const stringToSign = [ALGORITHM, amzDate, scope, sha256(canonicalRequest)].join('\n');
108
+ // Step 3: Signing key (HMAC chain)
109
+ const kDate = hmacSha256(`AWS4${secretAccessKey}`, dateStamp);
110
+ const kRegion = hmacSha256(kDate, region);
111
+ const kService = hmacSha256(kRegion, SERVICE);
112
+ const kSigning = hmacSha256(kService, 'aws4_request');
113
+ // Step 4: Signature
114
+ const signature = hmacSha256(kSigning, stringToSign).toString('hex');
115
+ // Step 5: Authorization header
116
+ return `${ALGORITHM} Credential=${accessKeyId}/${scope}, SignedHeaders=${signedHeaders}, Signature=${signature}`;
117
+ }
118
+ // ─── XML Parsing Helpers ─────────────────────────────────────
119
+ function extractXmlTag(xml, tag) {
120
+ const match = xml.match(new RegExp(`<${tag}>([\\s\\S]*?)</${tag}>`));
121
+ return match?.[1];
122
+ }
123
+ function extractAllXmlTags(xml, tag) {
124
+ return [...xml.matchAll(new RegExp(`<${tag}>([\\s\\S]*?)</${tag}>`, 'g'))].map((m) => m[1]);
125
+ }
126
+ /**
127
+ * Parse S3 error XML response.
128
+ */
129
+ function parseS3ErrorXml(xml) {
130
+ return {
131
+ code: extractXmlTag(xml, 'Code'),
132
+ message: extractXmlTag(xml, 'Message'),
133
+ requestId: extractXmlTag(xml, 'RequestId'),
134
+ };
135
+ }
136
+ // ─── S3 Storage Backend ──────────────────────────────────────
137
+ export class S3Storage {
138
+ id;
139
+ bucket;
140
+ endpoint;
141
+ region;
142
+ accessKeyId;
143
+ secretAccessKey;
144
+ prefix;
145
+ timeoutMs;
146
+ maxRetries;
147
+ host;
148
+ constructor(options) {
149
+ this.bucket = options.bucket || this.env('SAVESTATE_S3_BUCKET', '') || '';
150
+ this.endpoint = (options.endpoint || this.env('SAVESTATE_S3_ENDPOINT', 'AWS_ENDPOINT_URL') || '').replace(/\/+$/, '');
151
+ this.region = options.region || this.env('SAVESTATE_S3_REGION', 'AWS_REGION', 'AWS_DEFAULT_REGION') || 'auto';
152
+ this.accessKeyId = options.accessKeyId || this.env('SAVESTATE_S3_ACCESS_KEY_ID', 'AWS_ACCESS_KEY_ID') || '';
153
+ this.secretAccessKey = options.secretAccessKey || this.env('SAVESTATE_S3_SECRET_ACCESS_KEY', 'AWS_SECRET_ACCESS_KEY') || '';
154
+ this.prefix = options.prefix ?? '';
155
+ this.timeoutMs = options.timeoutMs ?? 30_000;
156
+ this.maxRetries = options.maxRetries ?? 3;
157
+ // Validate required fields
158
+ if (!this.bucket) {
159
+ throw new Error('S3 storage: bucket is required. Set storage.options.bucket in config or SAVESTATE_S3_BUCKET env var.');
160
+ }
161
+ if (!this.endpoint) {
162
+ throw new Error('S3 storage: endpoint is required. Set storage.options.endpoint in config or SAVESTATE_S3_ENDPOINT env var.\n' +
163
+ ' Examples:\n' +
164
+ ' Cloudflare R2: https://<account_id>.r2.cloudflarestorage.com\n' +
165
+ ' AWS S3: https://s3.<region>.amazonaws.com\n' +
166
+ ' Backblaze B2: https://s3.<region>.backblazeb2.com');
167
+ }
168
+ if (!this.accessKeyId || !this.secretAccessKey) {
169
+ throw new Error('S3 storage: credentials are required.\n' +
170
+ ' Set storage.options.accessKeyId/secretAccessKey in config, or env vars:\n' +
171
+ ' SAVESTATE_S3_ACCESS_KEY_ID / AWS_ACCESS_KEY_ID\n' +
172
+ ' SAVESTATE_S3_SECRET_ACCESS_KEY / AWS_SECRET_ACCESS_KEY');
173
+ }
174
+ // Extract host from endpoint
175
+ const url = new URL(this.endpoint);
176
+ this.host = url.host;
177
+ // Determine backend id
178
+ if (this.endpoint.includes('.r2.cloudflarestorage.com')) {
179
+ this.id = 'r2';
180
+ }
181
+ else if (this.endpoint.includes('.backblazeb2.com')) {
182
+ this.id = 'b2';
183
+ }
184
+ else if (this.endpoint.includes('.amazonaws.com')) {
185
+ this.id = 's3';
186
+ }
187
+ else {
188
+ this.id = 's3';
189
+ }
190
+ }
191
+ /**
192
+ * Read from env vars, trying multiple names in order.
193
+ */
194
+ env(...names) {
195
+ for (const name of names) {
196
+ const val = process.env[name];
197
+ if (val)
198
+ return val;
199
+ }
200
+ return '';
201
+ }
202
+ /**
203
+ * Build the full object key with prefix.
204
+ */
205
+ fullKey(key) {
206
+ return this.prefix + key;
207
+ }
208
+ /**
209
+ * Execute a signed S3 request with retries.
210
+ */
211
+ async request(method, objectKey, options) {
212
+ const { body, query, allow404 } = options ?? {};
213
+ const path = `/${this.bucket}/${objectKey}`.replace(/\/+/g, '/').replace(/\/$/, '') || '/';
214
+ const payloadHash = body ? sha256(body) : sha256('');
215
+ let lastError;
216
+ for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
217
+ if (attempt > 0) {
218
+ // Exponential backoff: 200ms, 400ms, 800ms...
219
+ const delay = Math.min(200 * Math.pow(2, attempt - 1), 5000);
220
+ await new Promise((r) => setTimeout(r, delay));
221
+ }
222
+ const now = new Date();
223
+ const amzDate = toAmzDate(now);
224
+ // Build headers (lowercase keys for canonical request)
225
+ const headers = {
226
+ host: this.host,
227
+ 'x-amz-date': amzDate,
228
+ 'x-amz-content-sha256': payloadHash,
229
+ };
230
+ if (body) {
231
+ headers['content-length'] = String(body.length);
232
+ }
233
+ // Sign the request
234
+ const authorization = signRequest({
235
+ method,
236
+ path,
237
+ query,
238
+ headers,
239
+ payloadHash,
240
+ date: now,
241
+ region: this.region,
242
+ accessKeyId: this.accessKeyId,
243
+ secretAccessKey: this.secretAccessKey,
244
+ });
245
+ headers['authorization'] = authorization;
246
+ // Build URL with query string
247
+ let url = `${this.endpoint}${path}`;
248
+ if (query && Object.keys(query).length > 0) {
249
+ const qs = Object.entries(query)
250
+ .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)
251
+ .join('&');
252
+ url += `?${qs}`;
253
+ }
254
+ try {
255
+ const response = await fetch(url, {
256
+ method,
257
+ headers,
258
+ body: body ?? undefined,
259
+ signal: AbortSignal.timeout(this.timeoutMs),
260
+ });
261
+ // Retry on 5xx server errors
262
+ if (response.status >= 500 && attempt < this.maxRetries) {
263
+ lastError = new S3Error(`S3 server error (${response.status})`, response.status);
264
+ continue;
265
+ }
266
+ // Handle 404 — return response if allowed, otherwise throw
267
+ if (response.status === 404) {
268
+ if (allow404)
269
+ return response;
270
+ const text = await response.text();
271
+ const err = parseS3ErrorXml(text);
272
+ throw new S3Error(`Object not found: ${objectKey}` + (err.code ? ` (${err.code})` : ''), 404, err.code ?? 'NoSuchKey', err.requestId);
273
+ }
274
+ // Handle other errors
275
+ if (!response.ok) {
276
+ const text = await response.text();
277
+ const err = parseS3ErrorXml(text);
278
+ const msg = err.message ?? `S3 request failed: ${method} ${path} → ${response.status}`;
279
+ throw new S3Error(msg, response.status, err.code, err.requestId);
280
+ }
281
+ return response;
282
+ }
283
+ catch (error) {
284
+ if (error instanceof S3Error)
285
+ throw error;
286
+ // Network/timeout errors — retry if possible
287
+ if (attempt < this.maxRetries) {
288
+ lastError =
289
+ error instanceof Error ? error : new Error(String(error));
290
+ continue;
291
+ }
292
+ if (error instanceof Error && error.name === 'TimeoutError') {
293
+ throw new S3Error(`S3 request timed out after ${this.timeoutMs}ms: ${method} ${path}`, 0, 'TimeoutError');
294
+ }
295
+ throw error;
296
+ }
297
+ }
298
+ // Should not reach here, but just in case
299
+ throw lastError ?? new Error('S3 request failed after retries');
300
+ }
301
+ // ─── StorageBackend Interface ────────────────────────────
302
+ async put(key, data) {
303
+ await this.request('PUT', this.fullKey(key), { body: data });
304
+ }
305
+ async get(key) {
306
+ const response = await this.request('GET', this.fullKey(key));
307
+ const arrayBuffer = await response.arrayBuffer();
308
+ return Buffer.from(arrayBuffer);
309
+ }
310
+ async list(prefix) {
311
+ const keys = [];
312
+ let continuationToken;
313
+ do {
314
+ const query = {
315
+ 'list-type': '2',
316
+ };
317
+ // Combine storage prefix with caller's prefix
318
+ const fullPrefix = this.prefix + (prefix ?? '');
319
+ if (fullPrefix) {
320
+ query['prefix'] = fullPrefix;
321
+ }
322
+ if (continuationToken) {
323
+ query['continuation-token'] = continuationToken;
324
+ }
325
+ // List is on the bucket root path
326
+ const response = await this.request('GET', '', { query });
327
+ const xml = await response.text();
328
+ // Extract keys from XML
329
+ const rawKeys = extractAllXmlTags(xml, 'Key');
330
+ // Strip the storage prefix from keys so callers see relative paths
331
+ for (const rawKey of rawKeys) {
332
+ if (this.prefix && rawKey.startsWith(this.prefix)) {
333
+ keys.push(rawKey.slice(this.prefix.length));
334
+ }
335
+ else {
336
+ keys.push(rawKey);
337
+ }
338
+ }
339
+ // Check for pagination
340
+ const isTruncated = xml.includes('<IsTruncated>true</IsTruncated>');
341
+ if (isTruncated) {
342
+ continuationToken = extractXmlTag(xml, 'NextContinuationToken');
343
+ }
344
+ else {
345
+ continuationToken = undefined;
346
+ }
347
+ } while (continuationToken);
348
+ return keys;
349
+ }
350
+ async delete(key) {
351
+ await this.request('DELETE', this.fullKey(key));
352
+ }
353
+ async exists(key) {
354
+ const response = await this.request('HEAD', this.fullKey(key), {
355
+ allow404: true,
356
+ });
357
+ return response.status !== 404;
358
+ }
359
+ }
360
+ //# sourceMappingURL=s3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"s3.js","sourceRoot":"","sources":["../../src/storage/s3.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@savestate/cli",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Time Machine for AI. Backup, restore, and migrate your AI identity.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",