blogwright-core 0.1.0

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.
Files changed (84) hide show
  1. package/LICENSE +24 -0
  2. package/README.md +7 -0
  3. package/dist/adapters/memory-fs.d.ts +9 -0
  4. package/dist/adapters/memory-fs.js +54 -0
  5. package/dist/adapters/memory-fs.js.map +1 -0
  6. package/dist/adapters/node-fs.d.ts +4 -0
  7. package/dist/adapters/node-fs.js +65 -0
  8. package/dist/adapters/node-fs.js.map +1 -0
  9. package/dist/adapters/node-terminal.d.ts +29 -0
  10. package/dist/adapters/node-terminal.js +58 -0
  11. package/dist/adapters/node-terminal.js.map +1 -0
  12. package/dist/adapters/script-terminal.d.ts +22 -0
  13. package/dist/adapters/script-terminal.js +38 -0
  14. package/dist/adapters/script-terminal.js.map +1 -0
  15. package/dist/aws/acm.d.ts +20 -0
  16. package/dist/aws/acm.js +55 -0
  17. package/dist/aws/acm.js.map +1 -0
  18. package/dist/aws/cloudfront.d.ts +72 -0
  19. package/dist/aws/cloudfront.js +341 -0
  20. package/dist/aws/cloudfront.js.map +1 -0
  21. package/dist/aws/credentials.d.ts +19 -0
  22. package/dist/aws/credentials.js +36 -0
  23. package/dist/aws/credentials.js.map +1 -0
  24. package/dist/aws/endpoint.d.ts +29 -0
  25. package/dist/aws/endpoint.js +58 -0
  26. package/dist/aws/endpoint.js.map +1 -0
  27. package/dist/aws/errors.d.ts +20 -0
  28. package/dist/aws/errors.js +35 -0
  29. package/dist/aws/errors.js.map +1 -0
  30. package/dist/aws/form.d.ts +2 -0
  31. package/dist/aws/form.js +11 -0
  32. package/dist/aws/form.js.map +1 -0
  33. package/dist/aws/iam.d.ts +18 -0
  34. package/dist/aws/iam.js +122 -0
  35. package/dist/aws/iam.js.map +1 -0
  36. package/dist/aws/logs.d.ts +32 -0
  37. package/dist/aws/logs.js +148 -0
  38. package/dist/aws/logs.js.map +1 -0
  39. package/dist/aws/microvms.d.ts +85 -0
  40. package/dist/aws/microvms.js +182 -0
  41. package/dist/aws/microvms.js.map +1 -0
  42. package/dist/aws/route53.d.ts +19 -0
  43. package/dist/aws/route53.js +71 -0
  44. package/dist/aws/route53.js.map +1 -0
  45. package/dist/aws/s3.d.ts +31 -0
  46. package/dist/aws/s3.js +178 -0
  47. package/dist/aws/s3.js.map +1 -0
  48. package/dist/aws/secretsmanager.d.ts +21 -0
  49. package/dist/aws/secretsmanager.js +84 -0
  50. package/dist/aws/secretsmanager.js.map +1 -0
  51. package/dist/aws/signer.d.ts +44 -0
  52. package/dist/aws/signer.js +144 -0
  53. package/dist/aws/signer.js.map +1 -0
  54. package/dist/aws/sts.d.ts +7 -0
  55. package/dist/aws/sts.js +22 -0
  56. package/dist/aws/sts.js.map +1 -0
  57. package/dist/aws/xml.d.ts +18 -0
  58. package/dist/aws/xml.js +65 -0
  59. package/dist/aws/xml.js.map +1 -0
  60. package/dist/clients.d.ts +33 -0
  61. package/dist/clients.js +38 -0
  62. package/dist/clients.js.map +1 -0
  63. package/dist/colors.d.ts +11 -0
  64. package/dist/colors.js +24 -0
  65. package/dist/colors.js.map +1 -0
  66. package/dist/config.d.ts +136 -0
  67. package/dist/config.js +236 -0
  68. package/dist/config.js.map +1 -0
  69. package/dist/index.d.ts +26 -0
  70. package/dist/index.js +27 -0
  71. package/dist/index.js.map +1 -0
  72. package/dist/ports.d.ts +53 -0
  73. package/dist/ports.js +15 -0
  74. package/dist/ports.js.map +1 -0
  75. package/dist/repo-root.d.ts +8 -0
  76. package/dist/repo-root.js +20 -0
  77. package/dist/repo-root.js.map +1 -0
  78. package/dist/state.d.ts +23 -0
  79. package/dist/state.js +44 -0
  80. package/dist/state.js.map +1 -0
  81. package/dist/util.d.ts +15 -0
  82. package/dist/util.js +38 -0
  83. package/dist/util.js.map +1 -0
  84. package/package.json +42 -0
@@ -0,0 +1,71 @@
1
+ import { AwsError } from './errors.js';
2
+ import { encodeEntities, textTag } from './xml.js';
3
+ const API = '/2013-04-01';
4
+ /** Route53 client (REST-XML). Global service, signed in us-east-1. */
5
+ export class Route53Client {
6
+ client;
7
+ constructor(client) {
8
+ this.client = client;
9
+ }
10
+ /** Find the hosted zone id for a domain (e.g. "preview.example.com"). */
11
+ async hostedZoneId(dnsName) {
12
+ const res = await this.client.send({
13
+ service: 'route53',
14
+ method: 'GET',
15
+ path: `${API}/hostedzonesbyname`,
16
+ query: { dnsname: dnsName },
17
+ });
18
+ const xml = res.text();
19
+ const want = dnsName.endsWith('.') ? dnsName : `${dnsName}.`;
20
+ // Match the HostedZone block whose <Name> equals the requested domain.
21
+ for (const block of xml.split('<HostedZone>').slice(1)) {
22
+ if (textTag(block, 'Name') === want) {
23
+ const id = textTag(block, 'Id');
24
+ return id?.replace(/^\/hostedzone\//, '');
25
+ }
26
+ }
27
+ return undefined;
28
+ }
29
+ async change(zoneId, action, r) {
30
+ const body = `<?xml version="1.0" encoding="UTF-8"?>` +
31
+ `<ChangeResourceRecordSetsRequest xmlns="https://route53.amazonaws.com/doc/2013-04-01/">` +
32
+ `<ChangeBatch><Changes><Change>` +
33
+ `<Action>${action}</Action>` +
34
+ `<ResourceRecordSet>` +
35
+ `<Name>${encodeEntities(r.name)}</Name>` +
36
+ `<Type>${r.type}</Type>` +
37
+ `<TTL>${r.ttl ?? 300}</TTL>` +
38
+ `<ResourceRecords><ResourceRecord><Value>${encodeEntities(r.value)}</Value></ResourceRecord></ResourceRecords>` +
39
+ `</ResourceRecordSet>` +
40
+ `</Change></Changes></ChangeBatch>` +
41
+ `</ChangeResourceRecordSetsRequest>`;
42
+ await this.client.send({
43
+ service: 'route53',
44
+ method: 'POST',
45
+ path: `${API}/hostedzone/${zoneId}/rrset`,
46
+ headers: { 'content-type': 'application/xml' },
47
+ body,
48
+ });
49
+ }
50
+ /** Create or update a record (idempotent). */
51
+ async upsertRecord(zoneId, record) {
52
+ await this.change(zoneId, 'UPSERT', record);
53
+ }
54
+ /** Delete a record; ignores an already-absent record. */
55
+ async deleteRecord(zoneId, record) {
56
+ try {
57
+ await this.change(zoneId, 'DELETE', record);
58
+ }
59
+ catch (err) {
60
+ // Route53 rejects a DELETE whose record doesn't exactly match/exist —
61
+ // that (and only that) means "already gone". Throttling, auth, and other
62
+ // failures must surface, or a teardown leaves the record dangling while
63
+ // reporting success.
64
+ const gone = err instanceof AwsError &&
65
+ (err.isNotFound || (err.code === 'InvalidChangeBatch' && /not found/i.test(err.message)));
66
+ if (!gone)
67
+ throw err;
68
+ }
69
+ }
70
+ }
71
+ //# sourceMappingURL=route53.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route53.js","sourceRoot":"","sources":["../../src/aws/route53.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import type { SigningClient } from './signer.js';
2
+ export interface S3Object {
3
+ key: string;
4
+ size: number;
5
+ lastModified: string | undefined;
6
+ /** S3 ETag with surrounding quotes stripped (MD5 hex for single-part objects). */
7
+ etag: string | undefined;
8
+ }
9
+ /** Thin S3 client (path-style addressing) built on the shared signing transport. */
10
+ export declare class S3Client {
11
+ private readonly client;
12
+ constructor(client: SigningClient);
13
+ private objectPath;
14
+ bucketExists(bucket: string): Promise<boolean>;
15
+ /** Create a bucket. Regions other than us-east-1 require a LocationConstraint body. */
16
+ createBucket(bucket: string): Promise<void>;
17
+ deleteBucket(bucket: string): Promise<void>;
18
+ putPublicAccessBlock(bucket: string): Promise<void>;
19
+ putObject(bucket: string, key: string, body: string | Uint8Array, contentType?: string): Promise<void>;
20
+ getObject(bucket: string, key: string): Promise<Uint8Array>;
21
+ getObjectText(bucket: string, key: string): Promise<string | undefined>;
22
+ objectExists(bucket: string, key: string): Promise<boolean>;
23
+ deleteObject(bucket: string, key: string): Promise<void>;
24
+ /** List all objects under a prefix, following continuation tokens. */
25
+ listObjects(bucket: string, prefix: string): Promise<S3Object[]>;
26
+ /** Delete every object under a prefix. Returns the number deleted. */
27
+ deletePrefix(bucket: string, prefix: string): Promise<number>;
28
+ putBucketPolicy(bucket: string, policy: string): Promise<void>;
29
+ /** Build an S3 REST-XML error-free marker; exported for callers needing entity-safe values. */
30
+ static xmlValue(value: string): string;
31
+ }
package/dist/aws/s3.js ADDED
@@ -0,0 +1,178 @@
1
+ import { allTags, encodeEntities, rawTextTag, textTag } from './xml.js';
2
+ import { AwsError } from './errors.js';
3
+ /** Percent-encode an object key for a path-style URL, preserving '/' separators. */
4
+ function encodeKey(key) {
5
+ return key
6
+ .split('/')
7
+ .map((seg) => encodeURIComponent(seg).replace(/[!'()*]/g, (c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`))
8
+ .join('/');
9
+ }
10
+ /** Thin S3 client (path-style addressing) built on the shared signing transport. */
11
+ export class S3Client {
12
+ client;
13
+ constructor(client) {
14
+ this.client = client;
15
+ }
16
+ objectPath(bucket, key) {
17
+ return `/${bucket}/${encodeKey(key)}`;
18
+ }
19
+ async bucketExists(bucket) {
20
+ try {
21
+ await this.client.send({ service: 's3', method: 'HEAD', path: `/${bucket}` });
22
+ return true;
23
+ }
24
+ catch (err) {
25
+ if (err instanceof AwsError && err.isNotFound)
26
+ return false;
27
+ throw err;
28
+ }
29
+ }
30
+ /** Create a bucket. Regions other than us-east-1 require a LocationConstraint body. */
31
+ async createBucket(bucket) {
32
+ const region = this.client.region;
33
+ const body = region && region !== 'us-east-1'
34
+ ? `<?xml version="1.0" encoding="UTF-8"?><CreateBucketConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"><LocationConstraint>${region}</LocationConstraint></CreateBucketConfiguration>`
35
+ : undefined;
36
+ try {
37
+ await this.client.send({
38
+ service: 's3',
39
+ method: 'PUT',
40
+ path: `/${bucket}`,
41
+ ...(body ? { headers: { 'content-type': 'application/xml' }, body } : {}),
42
+ });
43
+ }
44
+ catch (err) {
45
+ if (err instanceof AwsError && err.isAlreadyExists)
46
+ return;
47
+ throw err;
48
+ }
49
+ }
50
+ async deleteBucket(bucket) {
51
+ try {
52
+ await this.client.send({ service: 's3', method: 'DELETE', path: `/${bucket}` });
53
+ }
54
+ catch (err) {
55
+ if (err instanceof AwsError && err.isNotFound)
56
+ return;
57
+ throw err;
58
+ }
59
+ }
60
+ async putPublicAccessBlock(bucket) {
61
+ const body = '<?xml version="1.0" encoding="UTF-8"?>' +
62
+ '<PublicAccessBlockConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">' +
63
+ '<BlockPublicAcls>true</BlockPublicAcls>' +
64
+ '<IgnorePublicAcls>true</IgnorePublicAcls>' +
65
+ '<BlockPublicPolicy>true</BlockPublicPolicy>' +
66
+ '<RestrictPublicBuckets>true</RestrictPublicBuckets>' +
67
+ '</PublicAccessBlockConfiguration>';
68
+ await this.client.send({
69
+ service: 's3',
70
+ method: 'PUT',
71
+ path: `/${bucket}`,
72
+ query: { publicAccessBlock: '' },
73
+ headers: { 'content-type': 'application/xml' },
74
+ body,
75
+ });
76
+ }
77
+ async putObject(bucket, key, body, contentType = 'application/octet-stream') {
78
+ await this.client.send({
79
+ service: 's3',
80
+ method: 'PUT',
81
+ path: this.objectPath(bucket, key),
82
+ headers: { 'content-type': contentType },
83
+ body,
84
+ });
85
+ }
86
+ async getObject(bucket, key) {
87
+ const res = await this.client.send({
88
+ service: 's3',
89
+ method: 'GET',
90
+ path: this.objectPath(bucket, key),
91
+ });
92
+ return res.body;
93
+ }
94
+ async getObjectText(bucket, key) {
95
+ try {
96
+ const bytes = await this.getObject(bucket, key);
97
+ return new TextDecoder().decode(bytes);
98
+ }
99
+ catch (err) {
100
+ if (err instanceof AwsError && err.isNotFound)
101
+ return undefined;
102
+ throw err;
103
+ }
104
+ }
105
+ async objectExists(bucket, key) {
106
+ try {
107
+ await this.client.send({ service: 's3', method: 'HEAD', path: this.objectPath(bucket, key) });
108
+ return true;
109
+ }
110
+ catch (err) {
111
+ if (err instanceof AwsError && err.isNotFound)
112
+ return false;
113
+ throw err;
114
+ }
115
+ }
116
+ async deleteObject(bucket, key) {
117
+ await this.client.send({
118
+ service: 's3',
119
+ method: 'DELETE',
120
+ path: this.objectPath(bucket, key),
121
+ });
122
+ }
123
+ /** List all objects under a prefix, following continuation tokens. */
124
+ async listObjects(bucket, prefix) {
125
+ const out = [];
126
+ let token;
127
+ do {
128
+ const res = await this.client.send({
129
+ service: 's3',
130
+ method: 'GET',
131
+ path: `/${bucket}`,
132
+ query: {
133
+ 'list-type': '2',
134
+ prefix,
135
+ ...(token ? { 'continuation-token': token } : {}),
136
+ },
137
+ });
138
+ const xml = res.text();
139
+ for (const block of allTags(xml, 'Contents')) {
140
+ const key = rawTextTag(block, 'Key');
141
+ if (key === undefined)
142
+ continue;
143
+ out.push({
144
+ key,
145
+ size: Number(textTag(block, 'Size') ?? '0'),
146
+ lastModified: textTag(block, 'LastModified'),
147
+ etag: textTag(block, 'ETag')?.replace(/"/g, ''),
148
+ });
149
+ }
150
+ token =
151
+ textTag(xml, 'IsTruncated') === 'true' ? textTag(xml, 'NextContinuationToken') : undefined;
152
+ } while (token);
153
+ return out;
154
+ }
155
+ /** Delete every object under a prefix. Returns the number deleted. */
156
+ async deletePrefix(bucket, prefix) {
157
+ const objects = await this.listObjects(bucket, prefix);
158
+ for (const obj of objects) {
159
+ await this.deleteObject(bucket, obj.key);
160
+ }
161
+ return objects.length;
162
+ }
163
+ async putBucketPolicy(bucket, policy) {
164
+ await this.client.send({
165
+ service: 's3',
166
+ method: 'PUT',
167
+ path: `/${bucket}`,
168
+ query: { policy: '' },
169
+ headers: { 'content-type': 'application/json' },
170
+ body: policy,
171
+ });
172
+ }
173
+ /** Build an S3 REST-XML error-free marker; exported for callers needing entity-safe values. */
174
+ static xmlValue(value) {
175
+ return encodeEntities(value);
176
+ }
177
+ }
178
+ //# sourceMappingURL=s3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"s3.js","sourceRoot":"","sources":["../../src/aws/s3.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import type { SigningClient } from './signer.js';
2
+ export interface SecretMetadata {
3
+ arn: string;
4
+ name: string;
5
+ /** Epoch seconds (fractional) of the last value change, when reported. */
6
+ lastChangedDate?: number | undefined;
7
+ }
8
+ /** AWS Secrets Manager client (AWS JSON 1.1). */
9
+ export declare class SecretsManagerClient {
10
+ private readonly client;
11
+ constructor(client: SigningClient);
12
+ private call;
13
+ /** Create the secret, or update its value if it already exists. */
14
+ upsertSecret(name: string, value: string, description?: string): Promise<void>;
15
+ /** Fetch the secret's string value; undefined when the secret does not exist. */
16
+ getSecretValue(name: string): Promise<string | undefined>;
17
+ /** Fetch metadata (never the value); undefined when the secret does not exist. */
18
+ describeSecret(name: string): Promise<SecretMetadata | undefined>;
19
+ /** Delete immediately (no recovery window). No-op when the secret does not exist. */
20
+ deleteSecret(name: string): Promise<void>;
21
+ }
@@ -0,0 +1,84 @@
1
+ import { AwsError } from './errors.js';
2
+ const TARGET = 'secretsmanager';
3
+ /** AWS Secrets Manager client (AWS JSON 1.1). */
4
+ export class SecretsManagerClient {
5
+ client;
6
+ constructor(client) {
7
+ this.client = client;
8
+ }
9
+ async call(op, payload) {
10
+ const res = await this.client.send({
11
+ service: 'secretsmanager',
12
+ method: 'POST',
13
+ path: '/',
14
+ headers: {
15
+ 'content-type': 'application/x-amz-json-1.1',
16
+ 'x-amz-target': `${TARGET}.${op}`,
17
+ },
18
+ body: JSON.stringify(payload),
19
+ });
20
+ const text = res.text();
21
+ return (text ? JSON.parse(text) : {});
22
+ }
23
+ /** Create the secret, or update its value if it already exists. */
24
+ async upsertSecret(name, value, description) {
25
+ // The raw API requires the idempotency token SDKs normally generate.
26
+ try {
27
+ await this.call('CreateSecret', {
28
+ Name: name,
29
+ SecretString: value,
30
+ ClientRequestToken: crypto.randomUUID(),
31
+ ...(description ? { Description: description } : {}),
32
+ });
33
+ }
34
+ catch (err) {
35
+ // Secrets Manager reports an existing secret as ResourceExistsException.
36
+ const exists = err instanceof AwsError && (err.isAlreadyExists || err.code === 'ResourceExistsException');
37
+ if (!exists)
38
+ throw err;
39
+ await this.call('PutSecretValue', {
40
+ SecretId: name,
41
+ SecretString: value,
42
+ ClientRequestToken: crypto.randomUUID(),
43
+ });
44
+ }
45
+ }
46
+ /** Fetch the secret's string value; undefined when the secret does not exist. */
47
+ async getSecretValue(name) {
48
+ try {
49
+ const out = await this.call('GetSecretValue', {
50
+ SecretId: name,
51
+ });
52
+ return out.SecretString;
53
+ }
54
+ catch (err) {
55
+ if (err instanceof AwsError && err.isNotFound)
56
+ return undefined;
57
+ throw err;
58
+ }
59
+ }
60
+ /** Fetch metadata (never the value); undefined when the secret does not exist. */
61
+ async describeSecret(name) {
62
+ try {
63
+ const out = await this.call('DescribeSecret', { SecretId: name });
64
+ return { arn: out.ARN, name: out.Name, lastChangedDate: out.LastChangedDate };
65
+ }
66
+ catch (err) {
67
+ if (err instanceof AwsError && err.isNotFound)
68
+ return undefined;
69
+ throw err;
70
+ }
71
+ }
72
+ /** Delete immediately (no recovery window). No-op when the secret does not exist. */
73
+ async deleteSecret(name) {
74
+ try {
75
+ await this.call('DeleteSecret', { SecretId: name, ForceDeleteWithoutRecovery: true });
76
+ }
77
+ catch (err) {
78
+ if (err instanceof AwsError && err.isNotFound)
79
+ return;
80
+ throw err;
81
+ }
82
+ }
83
+ }
84
+ //# sourceMappingURL=secretsmanager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secretsmanager.js","sourceRoot":"","sources":["../../src/aws/secretsmanager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ import type { CredentialProvider } from './credentials.js';
2
+ import { type ServiceKey } from './endpoint.js';
3
+ export interface RawResponse {
4
+ statusCode: number;
5
+ headers: Record<string, string>;
6
+ body: Uint8Array;
7
+ text(): string;
8
+ }
9
+ /** Low-level transport. Injectable so tests can intercept without real network I/O. */
10
+ export type Transport = (req: {
11
+ url: string;
12
+ method: string;
13
+ headers: Record<string, string>;
14
+ body: string | Uint8Array | undefined;
15
+ }) => Promise<RawResponse>;
16
+ export interface SendOptions {
17
+ service: ServiceKey;
18
+ method: string;
19
+ /** Path starting with '/'. For S3 pass an already-percent-encoded path. */
20
+ path: string;
21
+ query?: Record<string, string | number | undefined> | undefined;
22
+ headers?: Record<string, string> | undefined;
23
+ body?: string | Uint8Array | undefined;
24
+ }
25
+ export interface SigningClientOptions {
26
+ region: string;
27
+ endpointOverride?: string | undefined;
28
+ credentials: CredentialProvider;
29
+ transport?: Transport | undefined;
30
+ }
31
+ /** Default transport backed by the global fetch. */
32
+ export declare const fetchTransport: Transport;
33
+ /**
34
+ * Signs and sends raw HTTP requests to AWS services using SigV4. This is the single
35
+ * seam through which every service client talks to AWS (or the floci emulator).
36
+ */
37
+ export declare class SigningClient {
38
+ readonly region: string;
39
+ readonly endpointOverride: string | undefined;
40
+ private readonly credentials;
41
+ private readonly transport;
42
+ constructor(opts: SigningClientOptions);
43
+ send(opts: SendOptions): Promise<RawResponse>;
44
+ }
@@ -0,0 +1,144 @@
1
+ import { Sha256 } from '@aws-crypto/sha256-js';
2
+ import { HttpRequest } from '@smithy/protocol-http';
3
+ import { SignatureV4 } from '@smithy/signature-v4';
4
+ import { resolveEndpoint, SIGNING_NAMES } from './endpoint.js';
5
+ import { AwsError, isRetryable } from './errors.js';
6
+ import { withRetry } from '../util.js';
7
+ import { textTag } from './xml.js';
8
+ /** Default transport backed by the global fetch. */
9
+ export const fetchTransport = async (req) => {
10
+ const init = { method: req.method, headers: req.headers };
11
+ if (req.body !== undefined)
12
+ init.body = req.body;
13
+ const res = await fetch(req.url, init);
14
+ const buf = new Uint8Array(await res.arrayBuffer());
15
+ const headers = {};
16
+ res.headers.forEach((value, key) => {
17
+ headers[key] = value;
18
+ });
19
+ return {
20
+ statusCode: res.status,
21
+ headers,
22
+ body: buf,
23
+ text: () => new TextDecoder().decode(buf),
24
+ };
25
+ };
26
+ /** Strict RFC-3986 percent encoder (matches SigV4 canonicalisation). */
27
+ function escape(component) {
28
+ return encodeURIComponent(component).replace(/[!'()*]/g, (c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`);
29
+ }
30
+ async function sha256Hex(body) {
31
+ const hash = new Sha256();
32
+ hash.update(body ?? '');
33
+ const digest = await hash.digest();
34
+ return Array.from(digest)
35
+ .map((b) => b.toString(16).padStart(2, '0'))
36
+ .join('');
37
+ }
38
+ /**
39
+ * Signs and sends raw HTTP requests to AWS services using SigV4. This is the single
40
+ * seam through which every service client talks to AWS (or the floci emulator).
41
+ */
42
+ export class SigningClient {
43
+ region;
44
+ endpointOverride;
45
+ credentials;
46
+ transport;
47
+ constructor(opts) {
48
+ this.region = opts.region;
49
+ this.endpointOverride = opts.endpointOverride;
50
+ this.credentials = opts.credentials;
51
+ this.transport = opts.transport ?? fetchTransport;
52
+ }
53
+ async send(opts) {
54
+ const ep = resolveEndpoint(opts.service, this.region, this.endpointOverride);
55
+ const [hostname, portStr] = ep.host.split(':');
56
+ const port = portStr ? Number(portStr) : undefined;
57
+ const query = {};
58
+ for (const [key, value] of Object.entries(opts.query ?? {})) {
59
+ if (value !== undefined)
60
+ query[key] = String(value);
61
+ }
62
+ const contentHash = await sha256Hex(opts.body);
63
+ const headers = {
64
+ host: ep.host,
65
+ 'x-amz-content-sha256': contentHash,
66
+ ...opts.headers,
67
+ };
68
+ const request = new HttpRequest({
69
+ protocol: ep.protocol,
70
+ hostname: hostname ?? ep.host,
71
+ ...(port !== undefined ? { port } : {}),
72
+ method: opts.method,
73
+ path: opts.path,
74
+ query,
75
+ headers,
76
+ ...(opts.body !== undefined ? { body: opts.body } : {}),
77
+ });
78
+ const signer = new SignatureV4({
79
+ service: SIGNING_NAMES[opts.service],
80
+ region: ep.signingRegion,
81
+ credentials: async () => {
82
+ const c = await this.credentials();
83
+ return {
84
+ accessKeyId: c.accessKeyId,
85
+ secretAccessKey: c.secretAccessKey,
86
+ ...(c.sessionToken ? { sessionToken: c.sessionToken } : {}),
87
+ };
88
+ },
89
+ sha256: Sha256,
90
+ uriEscapePath: opts.service !== 's3',
91
+ });
92
+ const signed = await signer.sign(request);
93
+ const qs = Object.keys(query)
94
+ .map((k) => `${escape(k)}=${escape(query[k])}`)
95
+ .join('&');
96
+ const url = `${ep.protocol}//${ep.host}${opts.path}${qs ? `?${qs}` : ''}`;
97
+ // Retry transient failures with backoff. For idempotent methods, retry on network
98
+ // errors and 5xx/429. For non-idempotent POSTs, retry ONLY on network errors (the
99
+ // request never reached the server) — never on a 5xx, which may mean the mutation
100
+ // was applied and a retry would double-execute (e.g. launch a second MicroVM).
101
+ const idempotent = ['GET', 'HEAD', 'PUT', 'DELETE'].includes(opts.method);
102
+ const retryable = idempotent ? isRetryable : (err) => err instanceof TypeError;
103
+ return withRetry(async () => {
104
+ const response = await this.transport({
105
+ url,
106
+ method: opts.method,
107
+ headers: signed.headers,
108
+ body: opts.body,
109
+ });
110
+ // Anything outside 2xx is a failure. 3xx matters: S3's region-mismatch
111
+ // PermanentRedirect is a 301 with no Location header, which fetch
112
+ // returns as final — treating it as success would report writes as
113
+ // stored and listings as empty against the wrong endpoint.
114
+ if (response.statusCode >= 300)
115
+ throw parseError(opts.service, response);
116
+ return response;
117
+ }, { retryable });
118
+ }
119
+ }
120
+ function parseError(service, response) {
121
+ const text = response.text();
122
+ let code = `Http${response.statusCode}`;
123
+ let message = text.slice(0, 500) || 'request failed';
124
+ let requestId;
125
+ const trimmed = text.trimStart();
126
+ if (trimmed.startsWith('{')) {
127
+ try {
128
+ const json = JSON.parse(text);
129
+ const rawCode = (json.__type ?? json.code ?? json.Code);
130
+ code = rawCode ? (rawCode.split('#').pop() ?? code) : code;
131
+ message = (json.message ?? json.Message ?? message);
132
+ }
133
+ catch {
134
+ /* fall through */
135
+ }
136
+ }
137
+ else if (trimmed.startsWith('<')) {
138
+ code = textTag(text, 'Code') ?? code;
139
+ message = textTag(text, 'Message') ?? message;
140
+ requestId = textTag(text, 'RequestId') ?? textTag(text, 'RequestID');
141
+ }
142
+ return new AwsError({ service, code, message, statusCode: response.statusCode, requestId });
143
+ }
144
+ //# sourceMappingURL=signer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signer.js","sourceRoot":"","sources":["../../src/aws/signer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { SigningClient } from './signer.js';
2
+ /** STS client — only GetCallerIdentity, used to derive the account id. */
3
+ export declare class StsClient {
4
+ private readonly client;
5
+ constructor(client: SigningClient);
6
+ getAccountId(): Promise<string>;
7
+ }
@@ -0,0 +1,22 @@
1
+ import { textTag } from './xml.js';
2
+ /** STS client — only GetCallerIdentity, used to derive the account id. */
3
+ export class StsClient {
4
+ client;
5
+ constructor(client) {
6
+ this.client = client;
7
+ }
8
+ async getAccountId() {
9
+ const res = await this.client.send({
10
+ service: 'sts',
11
+ method: 'POST',
12
+ path: '/',
13
+ headers: { 'content-type': 'application/x-www-form-urlencoded; charset=utf-8' },
14
+ body: 'Action=GetCallerIdentity&Version=2011-06-15',
15
+ });
16
+ const account = textTag(res.text(), 'Account');
17
+ if (!account)
18
+ throw new Error('STS GetCallerIdentity returned no Account');
19
+ return account;
20
+ }
21
+ }
22
+ //# sourceMappingURL=sts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sts.js","sourceRoot":"","sources":["../../src/aws/sts.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAEnC,0EAA0E;AAC1E,MAAM,OAAO,SAAS;IACS;IAA7B,YAA6B,MAAqB;QAArB,WAAM,GAAN,MAAM,CAAe;IAAG,CAAC;IAEtD,KAAK,CAAC,YAAY;QAChB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;YACjC,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,GAAG;YACT,OAAO,EAAE,EAAE,cAAc,EAAE,kDAAkD,EAAE;YAC/E,IAAI,EAAE,6CAA6C;SACpD,CAAC,CAAC;QACH,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,SAAS,CAAC,CAAC;QAC/C,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;QAC3E,OAAO,OAAO,CAAC;IACjB,CAAC;CACF"}