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,341 @@
1
+ import { AwsError } from './errors.js';
2
+ import { encodeEntities, textTag } from './xml.js';
3
+ const API = '/2020-05-31';
4
+ const XMLNS = 'http://cloudfront.amazonaws.com/doc/2020-05-31/';
5
+ /** AWS managed "CachingOptimized" cache policy. */
6
+ export const CACHING_OPTIMIZED = '658327ea-f89d-4fab-a63d-7e88639e58f6';
7
+ /** AWS managed "CachingDisabled" cache policy (used for previews — no CDN caching). */
8
+ export const CACHING_DISABLED = '4135ea2d-6df8-44a3-9df3-4b5a84be39ad';
9
+ /** CloudFront client (REST-XML). Global service, signed in us-east-1. */
10
+ export class CloudFrontClient {
11
+ client;
12
+ constructor(client) {
13
+ this.client = client;
14
+ }
15
+ async createOriginAccessControl(name) {
16
+ const body = `<?xml version="1.0" encoding="UTF-8"?>` +
17
+ `<OriginAccessControlConfig xmlns="${XMLNS}">` +
18
+ `<Name>${encodeEntities(name)}</Name>` +
19
+ `<Description>OAC for ${encodeEntities(name)}</Description>` +
20
+ `<SigningProtocol>sigv4</SigningProtocol>` +
21
+ `<SigningBehavior>always</SigningBehavior>` +
22
+ `<OriginAccessControlOriginType>s3</OriginAccessControlOriginType>` +
23
+ `</OriginAccessControlConfig>`;
24
+ const res = await this.client.send({
25
+ service: 'cloudfront',
26
+ method: 'POST',
27
+ path: `${API}/origin-access-control`,
28
+ headers: { 'content-type': 'application/xml' },
29
+ body,
30
+ });
31
+ const id = textTag(res.text(), 'Id');
32
+ if (!id)
33
+ throw new Error('CreateOriginAccessControl returned no Id');
34
+ return id;
35
+ }
36
+ async deleteOriginAccessControl(id) {
37
+ try {
38
+ const get = await this.client.send({
39
+ service: 'cloudfront',
40
+ method: 'GET',
41
+ path: `${API}/origin-access-control/${id}`,
42
+ });
43
+ const etag = get.headers['etag'];
44
+ await this.client.send({
45
+ service: 'cloudfront',
46
+ method: 'DELETE',
47
+ path: `${API}/origin-access-control/${id}`,
48
+ ...(etag ? { headers: { 'if-match': etag } } : {}),
49
+ });
50
+ }
51
+ catch (err) {
52
+ if (err instanceof AwsError && err.isNotFound)
53
+ return;
54
+ throw err;
55
+ }
56
+ }
57
+ async createDistribution(input) {
58
+ const body = buildDistributionConfig(input);
59
+ const res = await this.client.send({
60
+ service: 'cloudfront',
61
+ method: 'POST',
62
+ path: `${API}/distribution`,
63
+ headers: { 'content-type': 'application/xml' },
64
+ body,
65
+ });
66
+ return parseDistribution(res.text(), res.headers['etag']);
67
+ }
68
+ async getDistribution(id) {
69
+ try {
70
+ const res = await this.client.send({
71
+ service: 'cloudfront',
72
+ method: 'GET',
73
+ path: `${API}/distribution/${id}`,
74
+ });
75
+ return parseDistribution(res.text(), res.headers['etag']);
76
+ }
77
+ catch (err) {
78
+ if (err instanceof AwsError && err.isNotFound)
79
+ return undefined;
80
+ throw err;
81
+ }
82
+ }
83
+ /** Fetch the raw DistributionConfig XML plus its ETag (needed to update/disable). */
84
+ async getDistributionConfig(id) {
85
+ try {
86
+ const res = await this.client.send({
87
+ service: 'cloudfront',
88
+ method: 'GET',
89
+ path: `${API}/distribution/${id}/config`,
90
+ });
91
+ return { config: res.text(), etag: res.headers['etag'] ?? '' };
92
+ }
93
+ catch (err) {
94
+ if (err instanceof AwsError && err.isNotFound)
95
+ return undefined;
96
+ throw err;
97
+ }
98
+ }
99
+ /**
100
+ * Reconcile the distribution's aliases and viewer certificate in place — the
101
+ * path taken when a domain is added (or changed) after the distribution was
102
+ * first created. Compares semantically (CNAME set + certificate ARN), since
103
+ * the returned config carries legacy elements our builder never emits.
104
+ * Returns true when a change was pushed.
105
+ */
106
+ async setDistributionAliases(id, aliases, acmCertificateArn) {
107
+ const current = await this.getDistributionConfig(id);
108
+ if (!current)
109
+ throw new Error(`distribution ${id} not found while reconciling aliases`);
110
+ const currentAliases = [...current.config.matchAll(/<CNAME>(.*?)<\/CNAME>/g)]
111
+ .map((m) => m[1] ?? '')
112
+ .sort();
113
+ const currentCert = textTag(current.config, 'ACMCertificateArn');
114
+ const sameAliases = currentAliases.length === aliases.length &&
115
+ [...aliases].sort().every((a, i) => a === currentAliases[i]);
116
+ if (sameAliases && currentCert === acmCertificateArn)
117
+ return false;
118
+ const next = current.config
119
+ .replace(/<Aliases>.*?<\/Aliases>/s, aliasesBlock(aliases))
120
+ .replace(/<ViewerCertificate>.*?<\/ViewerCertificate>/s, viewerCertificateBlock(acmCertificateArn));
121
+ await this.client.send({
122
+ service: 'cloudfront',
123
+ method: 'PUT',
124
+ path: `${API}/distribution/${id}/config`,
125
+ headers: { 'content-type': 'application/xml', 'if-match': current.etag },
126
+ body: next,
127
+ });
128
+ return true;
129
+ }
130
+ /**
131
+ * Disable a distribution by flipping its top-level `<Enabled>` to false. The config
132
+ * also contains `<Enabled>false</Enabled>` inside TrustedSigners/Logging, so the
133
+ * distribution-level flag must be matched specifically — it is the one immediately
134
+ * followed by `<ViewerCertificate>` in the schema.
135
+ */
136
+ async disableDistribution(id) {
137
+ const current = await this.getDistributionConfig(id);
138
+ if (!current)
139
+ return;
140
+ if (/<Enabled>false<\/Enabled><ViewerCertificate>/.test(current.config))
141
+ return; // already disabled
142
+ const disabled = current.config.replace(/<Enabled>true<\/Enabled><ViewerCertificate>/, '<Enabled>false</Enabled><ViewerCertificate>');
143
+ await this.client.send({
144
+ service: 'cloudfront',
145
+ method: 'PUT',
146
+ path: `${API}/distribution/${id}/config`,
147
+ headers: { 'content-type': 'application/xml', 'if-match': current.etag },
148
+ body: disabled,
149
+ });
150
+ }
151
+ async deleteDistribution(id) {
152
+ try {
153
+ const res = await this.client.send({
154
+ service: 'cloudfront',
155
+ method: 'GET',
156
+ path: `${API}/distribution/${id}`,
157
+ });
158
+ const etag = res.headers['etag'];
159
+ await this.client.send({
160
+ service: 'cloudfront',
161
+ method: 'DELETE',
162
+ path: `${API}/distribution/${id}`,
163
+ ...(etag ? { headers: { 'if-match': etag } } : {}),
164
+ });
165
+ }
166
+ catch (err) {
167
+ if (err instanceof AwsError && err.isNotFound)
168
+ return;
169
+ throw err;
170
+ }
171
+ }
172
+ /** Invalidate paths (defaults to everything). Returns the invalidation id. */
173
+ async createInvalidation(id, paths, reference) {
174
+ const items = paths.map((p) => `<Path>${encodeEntities(p)}</Path>`).join('');
175
+ const body = `<?xml version="1.0" encoding="UTF-8"?>` +
176
+ `<InvalidationBatch xmlns="${XMLNS}">` +
177
+ `<Paths><Quantity>${paths.length}</Quantity><Items>${items}</Items></Paths>` +
178
+ `<CallerReference>${encodeEntities(reference)}</CallerReference>` +
179
+ `</InvalidationBatch>`;
180
+ const res = await this.client.send({
181
+ service: 'cloudfront',
182
+ method: 'POST',
183
+ path: `${API}/distribution/${id}/invalidation`,
184
+ headers: { 'content-type': 'application/xml' },
185
+ body,
186
+ });
187
+ return textTag(res.text(), 'Id') ?? '';
188
+ }
189
+ // --- CloudFront Functions (viewer-request routing for previews) ---
190
+ functionBody(root, name, code, comment) {
191
+ const b64 = Buffer.from(code, 'utf8').toString('base64');
192
+ return (`<?xml version="1.0" encoding="UTF-8"?>` +
193
+ `<${root} xmlns="${XMLNS}">` +
194
+ `<FunctionCode>${b64}</FunctionCode>` +
195
+ `<FunctionConfig><Comment>${encodeEntities(comment)}</Comment><Runtime>cloudfront-js-2.0</Runtime></FunctionConfig>` +
196
+ `<Name>${encodeEntities(name)}</Name>` +
197
+ `</${root}>`);
198
+ }
199
+ async describeFunction(name) {
200
+ // DescribeFunction is GET …/function/{name}/describe (XML summary). The
201
+ // bare GET …/function/{name} is GetFunction, whose body is the raw code
202
+ // bytes — no FunctionARN to parse.
203
+ try {
204
+ const res = await this.client.send({
205
+ service: 'cloudfront',
206
+ method: 'GET',
207
+ path: `${API}/function/${name}/describe`,
208
+ });
209
+ return { arn: textTag(res.text(), 'FunctionARN') ?? '', etag: res.headers['etag'] ?? '' };
210
+ }
211
+ catch (err) {
212
+ if (err instanceof AwsError && err.isNotFound)
213
+ return undefined;
214
+ throw err;
215
+ }
216
+ }
217
+ /** Create-or-update the function code and publish it. Returns the published ARN. */
218
+ async ensureFunction(name, code, comment) {
219
+ const existing = await this.describeFunction(name);
220
+ if (existing) {
221
+ await this.client.send({
222
+ service: 'cloudfront',
223
+ method: 'PUT',
224
+ path: `${API}/function/${name}`,
225
+ headers: { 'content-type': 'application/xml', 'if-match': existing.etag },
226
+ body: this.functionBody('UpdateFunctionRequest', name, code, comment),
227
+ });
228
+ }
229
+ else {
230
+ await this.client.send({
231
+ service: 'cloudfront',
232
+ method: 'POST',
233
+ path: `${API}/function`,
234
+ headers: { 'content-type': 'application/xml' },
235
+ body: this.functionBody('CreateFunctionRequest', name, code, comment),
236
+ });
237
+ }
238
+ // Re-read the current ETag before publishing. Create/update return a fresh ETag, but
239
+ // it isn't reliably surfaced from the response headers — publishing the DEVELOPMENT
240
+ // stage with a stale ETag fails the precondition (HTTP 412), which is what broke
241
+ // reconciling an already-existing function.
242
+ const current = await this.describeFunction(name);
243
+ const pub = await this.client.send({
244
+ service: 'cloudfront',
245
+ method: 'POST',
246
+ path: `${API}/function/${name}/publish`,
247
+ headers: { 'if-match': current?.etag ?? '' },
248
+ });
249
+ return textTag(pub.text(), 'FunctionARN') ?? current?.arn ?? existing?.arn ?? '';
250
+ }
251
+ async deleteFunction(name) {
252
+ const existing = await this.describeFunction(name);
253
+ if (!existing)
254
+ return;
255
+ await this.client.send({
256
+ service: 'cloudfront',
257
+ method: 'DELETE',
258
+ path: `${API}/function/${name}`,
259
+ headers: { 'if-match': existing.etag },
260
+ });
261
+ }
262
+ }
263
+ /** Build the <CustomErrorResponses> block, ordered by error code for a stable payload. */
264
+ function buildCustomErrorResponses(responses) {
265
+ if (!responses || responses.length === 0) {
266
+ return `<CustomErrorResponses><Quantity>0</Quantity></CustomErrorResponses>`;
267
+ }
268
+ const items = [...responses]
269
+ .sort((a, b) => a.errorCode - b.errorCode)
270
+ .map((r) => `<CustomErrorResponse>` +
271
+ `<ErrorCode>${r.errorCode}</ErrorCode>` +
272
+ `<ResponsePagePath>${encodeEntities(r.responsePagePath)}</ResponsePagePath>` +
273
+ `<ResponseCode>${r.responseCode}</ResponseCode>` +
274
+ `<ErrorCachingMinTTL>${r.errorCachingMinTtl ?? 10}</ErrorCachingMinTTL>` +
275
+ `</CustomErrorResponse>`)
276
+ .join('');
277
+ return `<CustomErrorResponses><Quantity>${responses.length}</Quantity><Items>${items}</Items></CustomErrorResponses>`;
278
+ }
279
+ function parseDistribution(xml, etag) {
280
+ return {
281
+ id: textTag(xml, 'Id') ?? '',
282
+ arn: textTag(xml, 'ARN') ?? '',
283
+ domainName: textTag(xml, 'DomainName') ?? '',
284
+ status: textTag(xml, 'Status') ?? 'InProgress',
285
+ etag,
286
+ };
287
+ }
288
+ function aliasesBlock(aliases) {
289
+ return aliases.length > 0
290
+ ? `<Aliases><Quantity>${aliases.length}</Quantity><Items>${aliases
291
+ .map((a) => `<CNAME>${encodeEntities(a)}</CNAME>`)
292
+ .join('')}</Items></Aliases>`
293
+ : `<Aliases><Quantity>0</Quantity></Aliases>`;
294
+ }
295
+ function viewerCertificateBlock(acmCertificateArn) {
296
+ return acmCertificateArn
297
+ ? `<ViewerCertificate><ACMCertificateArn>${encodeEntities(acmCertificateArn)}</ACMCertificateArn><SSLSupportMethod>sni-only</SSLSupportMethod><MinimumProtocolVersion>TLSv1.2_2021</MinimumProtocolVersion></ViewerCertificate>`
298
+ : `<ViewerCertificate><CloudFrontDefaultCertificate>true</CloudFrontDefaultCertificate></ViewerCertificate>`;
299
+ }
300
+ /** Build a DistributionConfig document. Element order follows the CloudFront schema. */
301
+ function buildDistributionConfig(input) {
302
+ const aliases = aliasesBlock(input.aliases);
303
+ const viewerCertificate = viewerCertificateBlock(input.acmCertificateArn);
304
+ return (`<?xml version="1.0" encoding="UTF-8"?>` +
305
+ `<DistributionConfig xmlns="${XMLNS}">` +
306
+ `<CallerReference>${encodeEntities(input.callerReference)}</CallerReference>` +
307
+ aliases +
308
+ `<DefaultRootObject>${encodeEntities(input.defaultRootObject)}</DefaultRootObject>` +
309
+ `<Origins><Quantity>1</Quantity><Items><Origin>` +
310
+ `<Id>s3-site</Id>` +
311
+ `<DomainName>${encodeEntities(input.bucketDomainName)}</DomainName>` +
312
+ `<OriginPath>${encodeEntities(input.originPath)}</OriginPath>` +
313
+ `<CustomHeaders><Quantity>0</Quantity></CustomHeaders>` +
314
+ `<S3OriginConfig><OriginAccessIdentity></OriginAccessIdentity></S3OriginConfig>` +
315
+ `<OriginAccessControlId>${encodeEntities(input.originAccessControlId)}</OriginAccessControlId>` +
316
+ `<ConnectionAttempts>3</ConnectionAttempts><ConnectionTimeout>10</ConnectionTimeout>` +
317
+ `</Origin></Items></Origins>` +
318
+ `<DefaultCacheBehavior>` +
319
+ `<TargetOriginId>s3-site</TargetOriginId>` +
320
+ `<TrustedSigners><Enabled>false</Enabled><Quantity>0</Quantity></TrustedSigners>` +
321
+ `<ViewerProtocolPolicy>redirect-to-https</ViewerProtocolPolicy>` +
322
+ `<Compress>true</Compress>` +
323
+ (input.functionArn
324
+ ? `<FunctionAssociations><Quantity>1</Quantity><Items><FunctionAssociation><EventType>viewer-request</EventType><FunctionARN>${encodeEntities(input.functionArn)}</FunctionARN></FunctionAssociation></Items></FunctionAssociations>`
325
+ : `<FunctionAssociations><Quantity>0</Quantity></FunctionAssociations>`) +
326
+ `<CachePolicyId>${input.cachePolicyId ?? CACHING_OPTIMIZED}</CachePolicyId>` +
327
+ `</DefaultCacheBehavior>` +
328
+ `<CacheBehaviors><Quantity>0</Quantity></CacheBehaviors>` +
329
+ buildCustomErrorResponses(input.customErrorResponses) +
330
+ `<Comment>${encodeEntities(input.comment)}</Comment>` +
331
+ `<Logging><Enabled>false</Enabled><IncludeCookies>false</IncludeCookies><Bucket></Bucket><Prefix></Prefix></Logging>` +
332
+ `<PriceClass>PriceClass_100</PriceClass>` +
333
+ `<Enabled>true</Enabled>` +
334
+ viewerCertificate +
335
+ `<Restrictions><GeoRestriction><RestrictionType>none</RestrictionType><Quantity>0</Quantity></GeoRestriction></Restrictions>` +
336
+ `<WebACLId></WebACLId>` +
337
+ `<HttpVersion>http2and3</HttpVersion>` +
338
+ `<IsIPV6Enabled>true</IsIPV6Enabled>` +
339
+ `</DistributionConfig>`);
340
+ }
341
+ //# sourceMappingURL=cloudfront.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloudfront.js","sourceRoot":"","sources":["../../src/aws/cloudfront.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ export interface AwsCredentials {
2
+ accessKeyId: string;
3
+ secretAccessKey: string;
4
+ sessionToken?: string | undefined;
5
+ }
6
+ export type CredentialProvider = () => Promise<AwsCredentials>;
7
+ /**
8
+ * Resolve ambient AWS credentials (env vars, shared config/credentials files, SSO,
9
+ * container/instance metadata) via the standard Node provider chain.
10
+ *
11
+ * When an endpoint override is in play (floci/localstack) and no real credentials
12
+ * are configured, fall back to the emulator's dummy `test/test` pair so signing
13
+ * still succeeds — floci does not validate signatures.
14
+ */
15
+ export declare function createCredentialProvider(opts: {
16
+ override?: boolean | undefined;
17
+ }): CredentialProvider;
18
+ /** A fixed-credentials provider, useful for tests. */
19
+ export declare function staticCredentials(creds: AwsCredentials): CredentialProvider;
@@ -0,0 +1,36 @@
1
+ import { fromNodeProviderChain } from '@aws-sdk/credential-providers';
2
+ /**
3
+ * Resolve ambient AWS credentials (env vars, shared config/credentials files, SSO,
4
+ * container/instance metadata) via the standard Node provider chain.
5
+ *
6
+ * When an endpoint override is in play (floci/localstack) and no real credentials
7
+ * are configured, fall back to the emulator's dummy `test/test` pair so signing
8
+ * still succeeds — floci does not validate signatures.
9
+ */
10
+ export function createCredentialProvider(opts) {
11
+ const chain = fromNodeProviderChain();
12
+ return async () => {
13
+ try {
14
+ const creds = await chain();
15
+ return {
16
+ accessKeyId: creds.accessKeyId,
17
+ secretAccessKey: creds.secretAccessKey,
18
+ sessionToken: creds.sessionToken,
19
+ };
20
+ }
21
+ catch (err) {
22
+ if (opts.override) {
23
+ return {
24
+ accessKeyId: process.env.AWS_ACCESS_KEY_ID ?? 'test',
25
+ secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY ?? 'test',
26
+ };
27
+ }
28
+ throw err;
29
+ }
30
+ };
31
+ }
32
+ /** A fixed-credentials provider, useful for tests. */
33
+ export function staticCredentials(creds) {
34
+ return () => Promise.resolve(creds);
35
+ }
36
+ //# sourceMappingURL=credentials.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credentials.js","sourceRoot":"","sources":["../../src/aws/credentials.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AAUtE;;;;;;;GAOG;AACH,MAAM,UAAU,wBAAwB,CAAC,IAExC;IACC,MAAM,KAAK,GAAG,qBAAqB,EAAE,CAAC;IACtC,OAAO,KAAK,IAAI,EAAE;QAChB,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,KAAK,EAAE,CAAC;YAC5B,OAAO;gBACL,WAAW,EAAE,KAAK,CAAC,WAAW;gBAC9B,eAAe,EAAE,KAAK,CAAC,eAAe;gBACtC,YAAY,EAAE,KAAK,CAAC,YAAY;aACjC,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAClB,OAAO;oBACL,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,MAAM;oBACpD,eAAe,EAAE,OAAO,CAAC,GAAG,CAAC,qBAAqB,IAAI,MAAM;iBAC7D,CAAC;YACJ,CAAC;YACD,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED,sDAAsD;AACtD,MAAM,UAAU,iBAAiB,CAAC,KAAqB;IACrD,OAAO,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AACtC,CAAC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Endpoint resolution for AWS services.
3
+ *
4
+ * When an endpoint override is present (config or `AWS_ENDPOINT_URL`, e.g. the
5
+ * floci emulator on http://localhost:4566) every service is routed to that single
6
+ * origin. Otherwise the canonical per-service AWS hostname is used.
7
+ */
8
+ export interface ResolvedEndpoint {
9
+ protocol: 'http:' | 'https:';
10
+ host: string;
11
+ /** Signing region — some services (iam, cloudfront) are global and sign as us-east-1. */
12
+ signingRegion: string;
13
+ /** True when talking to an override origin (floci/localstack); forces S3 path-style. */
14
+ override: boolean;
15
+ }
16
+ /** Service keys understood by the resolver. The value is the SigV4 signing name. */
17
+ export declare const SIGNING_NAMES: {
18
+ readonly s3: "s3";
19
+ readonly sts: "sts";
20
+ readonly iam: "iam";
21
+ readonly logs: "logs";
22
+ readonly acm: "acm";
23
+ readonly cloudfront: "cloudfront";
24
+ readonly route53: "route53";
25
+ readonly microvms: "lambda";
26
+ readonly secretsmanager: "secretsmanager";
27
+ };
28
+ export type ServiceKey = keyof typeof SIGNING_NAMES;
29
+ export declare function resolveEndpoint(service: ServiceKey, region: string, override: string | undefined): ResolvedEndpoint;
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Endpoint resolution for AWS services.
3
+ *
4
+ * When an endpoint override is present (config or `AWS_ENDPOINT_URL`, e.g. the
5
+ * floci emulator on http://localhost:4566) every service is routed to that single
6
+ * origin. Otherwise the canonical per-service AWS hostname is used.
7
+ */
8
+ /** Service keys understood by the resolver. The value is the SigV4 signing name. */
9
+ export const SIGNING_NAMES = {
10
+ s3: 's3',
11
+ sts: 'sts',
12
+ iam: 'iam',
13
+ logs: 'logs',
14
+ acm: 'acm',
15
+ cloudfront: 'cloudfront',
16
+ route53: 'route53',
17
+ // Lambda MicroVMs is served off the standard Lambda endpoint (host + signing name
18
+ // "lambda"); operations are distinguished by the /2025-09-09/ path prefix.
19
+ microvms: 'lambda',
20
+ secretsmanager: 'secretsmanager',
21
+ };
22
+ /** Services that are global; they always sign in us-east-1. */
23
+ const GLOBAL_SERVICES = new Set(['iam', 'cloudfront', 'route53']);
24
+ export function resolveEndpoint(service, region, override) {
25
+ const signingRegion = GLOBAL_SERVICES.has(service) ? 'us-east-1' : region;
26
+ if (override) {
27
+ const url = new URL(override);
28
+ return {
29
+ protocol: url.protocol === 'http:' ? 'http:' : 'https:',
30
+ host: url.host,
31
+ signingRegion,
32
+ override: true,
33
+ };
34
+ }
35
+ return {
36
+ protocol: 'https:',
37
+ host: canonicalHost(service, region),
38
+ signingRegion,
39
+ override: false,
40
+ };
41
+ }
42
+ function canonicalHost(service, region) {
43
+ switch (service) {
44
+ case 'iam':
45
+ return 'iam.amazonaws.com';
46
+ case 'cloudfront':
47
+ return 'cloudfront.amazonaws.com';
48
+ case 'route53':
49
+ return 'route53.amazonaws.com';
50
+ case 's3':
51
+ return `s3.${region}.amazonaws.com`;
52
+ case 'microvms':
53
+ return `lambda.${region}.amazonaws.com`;
54
+ default:
55
+ return `${service}.${region}.amazonaws.com`;
56
+ }
57
+ }
58
+ //# sourceMappingURL=endpoint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"endpoint.js","sourceRoot":"","sources":["../../src/aws/endpoint.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAWH,oFAAoF;AACpF,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,EAAE,EAAE,IAAI;IACR,GAAG,EAAE,KAAK;IACV,GAAG,EAAE,KAAK;IACV,IAAI,EAAE,MAAM;IACZ,GAAG,EAAE,KAAK;IACV,UAAU,EAAE,YAAY;IACxB,OAAO,EAAE,SAAS;IAClB,kFAAkF;IAClF,2EAA2E;IAC3E,QAAQ,EAAE,QAAQ;IAClB,cAAc,EAAE,gBAAgB;CACxB,CAAC;AAIX,+DAA+D;AAC/D,MAAM,eAAe,GAAG,IAAI,GAAG,CAAa,CAAC,KAAK,EAAE,YAAY,EAAE,SAAS,CAAC,CAAC,CAAC;AAE9E,MAAM,UAAU,eAAe,CAC7B,OAAmB,EACnB,MAAc,EACd,QAA4B;IAE5B,MAAM,aAAa,GAAG,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC;IAE1E,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC9B,OAAO;YACL,QAAQ,EAAE,GAAG,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ;YACvD,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,aAAa;YACb,QAAQ,EAAE,IAAI;SACf,CAAC;IACJ,CAAC;IAED,OAAO;QACL,QAAQ,EAAE,QAAQ;QAClB,IAAI,EAAE,aAAa,CAAC,OAAO,EAAE,MAAM,CAAC;QACpC,aAAa;QACb,QAAQ,EAAE,KAAK;KAChB,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,OAAmB,EAAE,MAAc;IACxD,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,KAAK;YACR,OAAO,mBAAmB,CAAC;QAC7B,KAAK,YAAY;YACf,OAAO,0BAA0B,CAAC;QACpC,KAAK,SAAS;YACZ,OAAO,uBAAuB,CAAC;QACjC,KAAK,IAAI;YACP,OAAO,MAAM,MAAM,gBAAgB,CAAC;QACtC,KAAK,UAAU;YACb,OAAO,UAAU,MAAM,gBAAgB,CAAC;QAC1C;YACE,OAAO,GAAG,OAAO,IAAI,MAAM,gBAAgB,CAAC;IAChD,CAAC;AACH,CAAC"}
@@ -0,0 +1,20 @@
1
+ /** A structured error raised when an AWS API returns a non-2xx response. */
2
+ export declare class AwsError extends Error {
3
+ readonly code: string;
4
+ readonly statusCode: number;
5
+ readonly requestId: string | undefined;
6
+ readonly service: string;
7
+ constructor(opts: {
8
+ service: string;
9
+ code: string;
10
+ message: string;
11
+ statusCode: number;
12
+ requestId?: string | undefined;
13
+ });
14
+ /** True for error codes that indicate the resource simply does not exist. */
15
+ get isNotFound(): boolean;
16
+ /** True for "already exists" style conflicts that bootstrap can treat as success. */
17
+ get isAlreadyExists(): boolean;
18
+ }
19
+ /** True for transient errors worth retrying with backoff. */
20
+ export declare function isRetryable(err: unknown): boolean;
@@ -0,0 +1,35 @@
1
+ /** A structured error raised when an AWS API returns a non-2xx response. */
2
+ export class AwsError extends Error {
3
+ code;
4
+ statusCode;
5
+ requestId;
6
+ service;
7
+ constructor(opts) {
8
+ super(`${opts.service}: ${opts.code} — ${opts.message} (HTTP ${opts.statusCode})`);
9
+ this.name = 'AwsError';
10
+ this.service = opts.service;
11
+ this.code = opts.code;
12
+ this.statusCode = opts.statusCode;
13
+ this.requestId = opts.requestId;
14
+ }
15
+ /** True for error codes that indicate the resource simply does not exist. */
16
+ get isNotFound() {
17
+ return (this.statusCode === 404 ||
18
+ /NotFound|NoSuchEntity|NoSuchBucket|NoSuchKey|ResourceNotFoundException/i.test(this.code));
19
+ }
20
+ /** True for "already exists" style conflicts that bootstrap can treat as success. */
21
+ get isAlreadyExists() {
22
+ return /AlreadyExists|BucketAlreadyOwnedByYou|EntityAlreadyExists|Conflict/i.test(this.code);
23
+ }
24
+ }
25
+ /** True for transient errors worth retrying with backoff. */
26
+ export function isRetryable(err) {
27
+ if (err instanceof AwsError) {
28
+ return (err.statusCode >= 500 ||
29
+ err.statusCode === 429 ||
30
+ /Throttling|TooManyRequests|InternalError|ServiceUnavailable/i.test(err.code));
31
+ }
32
+ // Network-level failures (fetch throws TypeError) are retryable.
33
+ return err instanceof TypeError;
34
+ }
35
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/aws/errors.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,MAAM,OAAO,QAAS,SAAQ,KAAK;IACxB,IAAI,CAAS;IACb,UAAU,CAAS;IACnB,SAAS,CAAqB;IAC9B,OAAO,CAAS;IAEzB,YAAY,IAMX;QACC,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,KAAK,IAAI,CAAC,IAAI,MAAM,IAAI,CAAC,OAAO,UAAU,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC;QACnF,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;QACvB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;QAC5B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACtB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;QAClC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;IAClC,CAAC;IAED,6EAA6E;IAC7E,IAAI,UAAU;QACZ,OAAO,CACL,IAAI,CAAC,UAAU,KAAK,GAAG;YACvB,yEAAyE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAC1F,CAAC;IACJ,CAAC;IAED,qFAAqF;IACrF,IAAI,eAAe;QACjB,OAAO,qEAAqE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/F,CAAC;CACF;AAED,6DAA6D;AAC7D,MAAM,UAAU,WAAW,CAAC,GAAY;IACtC,IAAI,GAAG,YAAY,QAAQ,EAAE,CAAC;QAC5B,OAAO,CACL,GAAG,CAAC,UAAU,IAAI,GAAG;YACrB,GAAG,CAAC,UAAU,KAAK,GAAG;YACtB,8DAA8D,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAC9E,CAAC;IACJ,CAAC;IACD,iEAAiE;IACjE,OAAO,GAAG,YAAY,SAAS,CAAC;AAClC,CAAC"}
@@ -0,0 +1,2 @@
1
+ /** Encode a map as an application/x-www-form-urlencoded body (query protocol). */
2
+ export declare function formEncode(params: Record<string, string | undefined>): string;
@@ -0,0 +1,11 @@
1
+ /** Encode a map as an application/x-www-form-urlencoded body (query protocol). */
2
+ export function formEncode(params) {
3
+ return Object.entries(params)
4
+ .filter((entry) => entry[1] !== undefined)
5
+ .map(([k, v]) => `${encode(k)}=${encode(v)}`)
6
+ .join('&');
7
+ }
8
+ function encode(value) {
9
+ return encodeURIComponent(value).replace(/[!'()*]/g, (c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`);
10
+ }
11
+ //# sourceMappingURL=form.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form.js","sourceRoot":"","sources":["../../src/aws/form.ts"],"names":[],"mappings":"AAAA,kFAAkF;AAClF,MAAM,UAAU,UAAU,CAAC,MAA0C;IACnE,OAAO,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;SAC1B,MAAM,CAAC,CAAC,KAAK,EAA6B,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC;SACpE,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;SAC5C,IAAI,CAAC,GAAG,CAAC,CAAC;AACf,CAAC;AAED,SAAS,MAAM,CAAC,KAAa;IAC3B,OAAO,kBAAkB,CAAC,KAAK,CAAC,CAAC,OAAO,CACtC,UAAU,EACV,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,WAAW,EAAE,EAAE,CACxD,CAAC;AACJ,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { SigningClient } from './signer.js';
2
+ /** IAM client (query protocol) — roles with inline policies. */
3
+ export declare class IamClient {
4
+ private readonly client;
5
+ constructor(client: SigningClient);
6
+ private call;
7
+ /** Return the role ARN, or undefined if the role does not exist. */
8
+ getRoleArn(roleName: string): Promise<string | undefined>;
9
+ /** Create a role (idempotent) and return its ARN. */
10
+ ensureRole(roleName: string, assumeRolePolicy: object, description?: string): Promise<string>;
11
+ putRolePolicy(roleName: string, policyName: string, policy: object): Promise<void>;
12
+ listRolePolicies(roleName: string): Promise<string[]>;
13
+ deleteRolePolicy(roleName: string, policyName: string): Promise<void>;
14
+ /** Create an OIDC identity provider (idempotent). Account-global; never deleted here. */
15
+ ensureOidcProvider(url: string, clientId: string, thumbprint: string): Promise<void>;
16
+ /** Delete a role, first removing any inline policies. Idempotent. */
17
+ deleteRole(roleName: string): Promise<void>;
18
+ }