cdk-nextjs 0.5.15 → 0.6.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.
- package/.jsii +821 -253
- package/.jsii.tabl.json +1 -1
- package/API.md +787 -18
- package/README.md +3 -3
- package/docs/breaking-changes.md +86 -0
- package/docs/caching-guide.md +6 -0
- package/docs/plans/adapter-runtime-release.md +362 -0
- package/docs/plans/phase-0-image-function-opt-in.md +295 -0
- package/lib/generated-structs/OptionalNextjsDistributionProps.d.ts +13 -0
- package/lib/generated-structs/OptionalNextjsDistributionProps.js +1 -1
- package/lib/image-optimization/handler-utils.d.ts +34 -0
- package/lib/image-optimization/handler-utils.js +83 -0
- package/lib/image-optimization/handler-utils.test.d.ts +1 -0
- package/lib/image-optimization/handler-utils.test.js +178 -0
- package/lib/image-optimization/handler.mjs +56126 -0
- package/lib/index.d.ts +2 -1
- package/lib/index.js +4 -2
- package/lib/nextjs-api.d.ts +44 -0
- package/lib/nextjs-api.js +64 -20
- package/lib/nextjs-api.test.d.ts +1 -0
- package/lib/nextjs-api.test.js +144 -0
- package/lib/nextjs-build/nextjs-build.d.ts +60 -0
- package/lib/nextjs-build/nextjs-build.js +184 -27
- package/lib/nextjs-cache.js +1 -1
- package/lib/nextjs-compute/nextjs-containers.js +1 -1
- package/lib/nextjs-compute/nextjs-functions.js +1 -1
- package/lib/nextjs-compute/nextjs-image-function.d.ts +53 -0
- package/lib/nextjs-compute/nextjs-image-function.js +59 -0
- package/lib/nextjs-distribution.d.ts +33 -0
- package/lib/nextjs-distribution.js +39 -11
- package/lib/nextjs-post-deploy.js +1 -1
- package/lib/nextjs-static-assets.d.ts +18 -0
- package/lib/nextjs-static-assets.js +33 -6
- package/lib/nextjs-static-assets.test.d.ts +1 -0
- package/lib/nextjs-static-assets.test.js +58 -0
- package/lib/root-constructs/nextjs-base-construct.d.ts +62 -2
- package/lib/root-constructs/nextjs-base-construct.js +81 -3
- package/lib/root-constructs/nextjs-global-containers.d.ts +6 -1
- package/lib/root-constructs/nextjs-global-containers.js +11 -5
- package/lib/root-constructs/nextjs-global-functions.d.ts +16 -5
- package/lib/root-constructs/nextjs-global-functions.js +23 -21
- package/lib/root-constructs/nextjs-regional-containers.js +1 -1
- package/lib/root-constructs/nextjs-regional-functions.d.ts +11 -5
- package/lib/root-constructs/nextjs-regional-functions.js +17 -21
- package/lib/utils/base-path.d.ts +40 -0
- package/lib/utils/base-path.js +123 -0
- package/lib/utils/base-path.test.d.ts +1 -0
- package/lib/utils/base-path.test.js +163 -0
- package/lib/utils/experimental-flags.d.ts +24 -0
- package/lib/utils/experimental-flags.js +30 -0
- package/lib/utils/get-architecture.d.ts +10 -0
- package/lib/utils/get-architecture.js +17 -2
- package/package.json +3 -1
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
# Phase 0 — Make the dedicated image optimization Lambda opt-in
|
|
2
|
+
|
|
3
|
+
Handoff plan. Self-contained; assumes no context from the session that wrote it.
|
|
4
|
+
|
|
5
|
+
## Goal
|
|
6
|
+
|
|
7
|
+
Land the `feat-nextjs-img-opt` branch **with zero breaking changes** by making the
|
|
8
|
+
dedicated image optimization Lambda opt-in (`dedicatedImageFunction`, default
|
|
9
|
+
`false`). The default stays what `main` does today: `_next/image` is served by the
|
|
10
|
+
Next.js server function.
|
|
11
|
+
|
|
12
|
+
## Why
|
|
13
|
+
|
|
14
|
+
The branch currently routes `_next/image` to a dedicated Lambda unconditionally.
|
|
15
|
+
That Lambda is not the Next.js server, so **Next.js middleware no longer runs for
|
|
16
|
+
image requests** — a real breaking change for anyone whose middleware matcher
|
|
17
|
+
covers `/_next/image` (the default matcher `/:path*` does; the matcher
|
|
18
|
+
`create-next-app` scaffolds does not).
|
|
19
|
+
|
|
20
|
+
Making it opt-in means:
|
|
21
|
+
|
|
22
|
+
- No breaking change, no migration doc.
|
|
23
|
+
- The sharp fix in `40b7837` ships now. Without it the dedicated Lambda serves
|
|
24
|
+
every image as unoptimized original bytes with an HTTP 200 and nothing in the
|
|
25
|
+
logs — see "Background" below.
|
|
26
|
+
- The flag is not throwaway. A later phase adds a middleware runner to the image
|
|
27
|
+
Lambda (using `outputs.middleware` from the Next.js adapters API), and *that*
|
|
28
|
+
release flips the default and deprecates the flag.
|
|
29
|
+
|
|
30
|
+
## Starting state
|
|
31
|
+
|
|
32
|
+
Branch `feat-nextjs-img-opt`. `HEAD` = `40b7837 fix: ship a loadable sharp to the
|
|
33
|
+
image optimization Lambda`.
|
|
34
|
+
|
|
35
|
+
Ten files are **uncommitted** and complete — a second batch of code-review fixes.
|
|
36
|
+
All checks were green when they were written (`tsc`, `jest src/` 51 passing,
|
|
37
|
+
`eslint`, `jsii`):
|
|
38
|
+
|
|
39
|
+
| File | What changed |
|
|
40
|
+
| --- | --- |
|
|
41
|
+
| `src/image-optimization/handler-utils.ts` + `.test.ts` | S3 key derivation now *ensures* the `basePath` prefix instead of stripping it (`NextjsStaticAssets` uploads under `basePath`), and matches `basePath` only on a path boundary so `/basement/logo.png` isn't read as `/base` + `ment/...` |
|
|
42
|
+
| `src/image-optimization/handler.mts` | 304 responses only write the API-Gateway-appeasing space byte on the API Gateway path (RFC 9110 forbids a body on 304); adds `isApiGatewayEvent` type guard |
|
|
43
|
+
| `src/utils/get-architecture.ts` | `getNodeArchitecture()` as the single source of truth, replacing two inline `process.arch.startsWith("arm")` copies |
|
|
44
|
+
| `src/nextjs-build/nextjs-build.ts` | Uses `getNodeArchitecture()` |
|
|
45
|
+
| `src/root-constructs/nextjs-base-construct.ts`, `nextjs-global-functions.ts`, `nextjs-regional-functions.ts`, `src/index.ts` | New `NextjsFunctionsConstructOverrides` holds `nextjsFunctionsProps` / `nextjsImageFunctionProps`, which the Containers constructs previously accepted and silently ignored |
|
|
46
|
+
| `docs/breaking-changes.md` | Two new `## 0.6.0` sections |
|
|
47
|
+
|
|
48
|
+
### Step 0 — commit them first
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
git add -A && git commit
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Suggested message: `fix: correct image optimization basePath keys, 304 bodies, and Functions-only overrides`
|
|
55
|
+
|
|
56
|
+
Commit as-is even though Step 5 deletes one of the breaking-changes sections it
|
|
57
|
+
adds — each commit stays internally consistent, and the sections are removed in
|
|
58
|
+
the same PR.
|
|
59
|
+
|
|
60
|
+
## Design decisions (already made — don't relitigate)
|
|
61
|
+
|
|
62
|
+
**Flag name:** `dedicatedImageFunction?: boolean`, `@default false`.
|
|
63
|
+
|
|
64
|
+
**Where it goes:** three sibling interfaces.
|
|
65
|
+
|
|
66
|
+
- `NextjsBaseConstructProps` (`src/root-constructs/nextjs-base-construct.ts:124`)
|
|
67
|
+
— so `NextjsBaseConstruct` can read `this.baseProps.dedicatedImageFunction`
|
|
68
|
+
when it builds `NextjsBuild`.
|
|
69
|
+
- `NextjsGlobalFunctionsProps` (`src/root-constructs/nextjs-global-functions.ts:47`)
|
|
70
|
+
- `NextjsRegionalFunctionsProps` (`src/root-constructs/nextjs-regional-functions.ts:43`)
|
|
71
|
+
|
|
72
|
+
**Not** on `NextjsBaseProps` — the Containers constructs would accept it and
|
|
73
|
+
silently ignore it, which is the exact anti-pattern the uncommitted
|
|
74
|
+
`NextjsFunctionsConstructOverrides` change fixes.
|
|
75
|
+
|
|
76
|
+
> JSII note: all three interfaces extend `NextjsBaseProps` but none extends
|
|
77
|
+
> another, so declaring the same member on all three is legal. Declaring it on
|
|
78
|
+
> both a parent and a child interface is **not** — that produces
|
|
79
|
+
> `Interface ... re-declares member`, the error documented at
|
|
80
|
+
> `nextjs-base-construct.ts:120-123`.
|
|
81
|
+
|
|
82
|
+
**Why a boolean and not an enum:** JSII rejects string-literal union types, so a
|
|
83
|
+
`"server" | "dedicated"` choice would need a real exported enum. Not worth it for
|
|
84
|
+
a flag that gets deprecated in two releases.
|
|
85
|
+
|
|
86
|
+
## Tasks
|
|
87
|
+
|
|
88
|
+
### 1. `src/nextjs-build/nextjs-build.ts` — the part that will bite
|
|
89
|
+
|
|
90
|
+
Add `dedicatedImageFunction?: boolean` to `NextjsBuildProps`, then rework the
|
|
91
|
+
constructor block at **lines 132-152**.
|
|
92
|
+
|
|
93
|
+
Current logic strips whatever platform sharp binaries output file tracing
|
|
94
|
+
bundled, then installs musl replacements **only for Containers**, on the
|
|
95
|
+
assumption that Functions deployments never invoke sharp from the standalone
|
|
96
|
+
server. That assumption is exactly what this flag breaks.
|
|
97
|
+
|
|
98
|
+
```ts
|
|
99
|
+
const useDedicatedImageFunction =
|
|
100
|
+
isFunctions && props.dedicatedImageFunction === true;
|
|
101
|
+
|
|
102
|
+
this.removeExistingSharpBinaries(standalonePath);
|
|
103
|
+
// The standalone server serves `_next/image` itself unless a dedicated image
|
|
104
|
+
// Lambda takes that route, and it runs on node:24-alpine (see
|
|
105
|
+
// functions.Dockerfile), so it needs musl binaries.
|
|
106
|
+
if (!useDedicatedImageFunction) {
|
|
107
|
+
this.downloadAndInstallSharpBinaries();
|
|
108
|
+
}
|
|
109
|
+
if (useDedicatedImageFunction) {
|
|
110
|
+
this.imageOptimizationAssetPath =
|
|
111
|
+
this.prepareImageOptimizationAssets(standalonePath);
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
**Get this right or Phase 0 ships broken image optimization on the default
|
|
116
|
+
path.** `removeExistingSharpBinaries()` runs unconditionally and deletes the
|
|
117
|
+
host's (macOS/glibc) binaries. If the musl install doesn't run for Functions
|
|
118
|
+
deployments that no longer have a dedicated image Lambda, `require('sharp')`
|
|
119
|
+
throws inside the server, Next.js's `imageOptimizer` catches it internally and
|
|
120
|
+
returns the *original* buffer, and you get an HTTP 200 with plausible headers
|
|
121
|
+
serving unoptimized images. Silent. This is the same failure the branch already
|
|
122
|
+
fixed once for the dedicated Lambda; don't reintroduce it on the default path.
|
|
123
|
+
|
|
124
|
+
Also update the comment at lines 137-143, which currently states the now-
|
|
125
|
+
conditional claim as fact.
|
|
126
|
+
|
|
127
|
+
Adding a prop to `NextjsBuildProps` means `OptionalNextjsBuildProps` must be
|
|
128
|
+
regenerated — see Verification.
|
|
129
|
+
|
|
130
|
+
### 2. `src/root-constructs/nextjs-base-construct.ts`
|
|
131
|
+
|
|
132
|
+
- Add the prop to `NextjsBaseConstructProps`.
|
|
133
|
+
- Pass it into `NextjsBuild` in `createNextjsBuild()` (line 195).
|
|
134
|
+
- `createNextjsImageFunction()` (line 251) keeps throwing when
|
|
135
|
+
`imageOptimizationAssetPath` is missing — that's still a genuine invariant
|
|
136
|
+
violation, since callers only reach it when the flag is on.
|
|
137
|
+
|
|
138
|
+
### 3. The two Functions root constructs
|
|
139
|
+
|
|
140
|
+
Make the field optional and conditional:
|
|
141
|
+
|
|
142
|
+
```ts
|
|
143
|
+
nextjsImageFunction?: NextjsImageFunction;
|
|
144
|
+
// ...
|
|
145
|
+
if (props.dedicatedImageFunction) {
|
|
146
|
+
this.nextjsImageFunction = this.createNextjsImageFunction(
|
|
147
|
+
this.props.overrides?.nextjsImageFunction,
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
- `nextjs-global-functions.ts:67` (field), `:83` (creation), `:95` — pass
|
|
153
|
+
`imageFunctionUrl: this.nextjsImageFunction?.functionUrl`.
|
|
154
|
+
- `nextjs-regional-functions.ts:56` (field), `:76` (creation), `:87` — pass
|
|
155
|
+
`imageFunction: this.nextjsImageFunction?.function`.
|
|
156
|
+
|
|
157
|
+
An optional class property is fine for JSII (`NextjsBuild.imageOptimizationAssetPath`
|
|
158
|
+
already is one).
|
|
159
|
+
|
|
160
|
+
### 4. Make the two consumers tolerate a missing image function
|
|
161
|
+
|
|
162
|
+
**`src/nextjs-api.ts`** — revert this branch's tightening:
|
|
163
|
+
|
|
164
|
+
- `validateProps` (line 110-114): drop the "imageFunction must be set when
|
|
165
|
+
serverFunction is set" throw.
|
|
166
|
+
- Constructor (line 97-100): call `createImageIntegration` only when
|
|
167
|
+
`props.imageFunction` is set. With no image integration, `_next/image` falls
|
|
168
|
+
through to the `{proxy+}` catch-all on the server function — which is what
|
|
169
|
+
`main` does.
|
|
170
|
+
- Update the `imageFunction` doc comment (line 53-62): no longer "Required if
|
|
171
|
+
`serverFunction` is set".
|
|
172
|
+
|
|
173
|
+
**`src/nextjs-distribution.ts`** — `createImageOrigin()` (line 201-215) already
|
|
174
|
+
falls back to `this.dynamicOrigin` for non-Functions compute. Extend that
|
|
175
|
+
fallback instead of throwing:
|
|
176
|
+
|
|
177
|
+
```ts
|
|
178
|
+
if (!this.isFunctionCompute || !this.props.imageFunctionUrl) {
|
|
179
|
+
return this.dynamicOrigin;
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Keep the dedicated `_next/image*` behavior and its image-specific cache policy
|
|
184
|
+
in both cases — pointing that behavior at the dynamic origin is strictly better
|
|
185
|
+
than dropping it, because the image cache policy (`queryStringBehavior: all()`,
|
|
186
|
+
`accept` in the cache key) is the right one for image requests either way. Update
|
|
187
|
+
the doc comment on `imageFunctionUrl` (line 79-83) and on `createImageOrigin`.
|
|
188
|
+
|
|
189
|
+
### 5. `docs/breaking-changes.md`
|
|
190
|
+
|
|
191
|
+
From the `## 0.6.0` section added in Step 0:
|
|
192
|
+
|
|
193
|
+
- **Delete** "`_next/image` no longer runs Next.js middleware (Functions only)".
|
|
194
|
+
It isn't true once the flag defaults off.
|
|
195
|
+
- **Rewrite** "NextjsApi: `imageFunction` now required alongside
|
|
196
|
+
`serverFunction`" — it's optional again. Either delete it or restate it as a
|
|
197
|
+
non-breaking addition.
|
|
198
|
+
- **Keep** "Functions-only overrides moved off the Containers constructs". That
|
|
199
|
+
one is a real (tiny) breaking change and it ships.
|
|
200
|
+
|
|
201
|
+
Document the trade-off on the new prop's JSDoc, since that's what users will
|
|
202
|
+
read:
|
|
203
|
+
|
|
204
|
+
- **off (default)** — middleware runs for image requests; on Regional Functions
|
|
205
|
+
the response goes through API Gateway buffered (6 MB cap); images share the
|
|
206
|
+
server function's memory and concurrency; optimized images are cached via the
|
|
207
|
+
configured `cacheHandler`.
|
|
208
|
+
- **on** — dedicated Lambda with response streaming and independent sizing; no
|
|
209
|
+
middleware for `_next/image`; caching relies on CloudFront.
|
|
210
|
+
- Note that a future release will default this on once middleware support lands.
|
|
211
|
+
|
|
212
|
+
### 6. Examples and e2e
|
|
213
|
+
|
|
214
|
+
Set `dedicatedImageFunction: true` in **`examples/global-functions/app.ts`** only.
|
|
215
|
+
Leave `examples/regional-functions/app.ts` on the default. That way CI covers
|
|
216
|
+
both paths: `glbl-fns` exercises the dedicated Lambda, `rgnl-fns` exercises the
|
|
217
|
+
server-function path.
|
|
218
|
+
|
|
219
|
+
`examples/e2e-tests/src/image-optimization.test.ts` should pass unchanged on both
|
|
220
|
+
— including the `content-type: image/webp` assertion added in `40b7837`, since
|
|
221
|
+
the server function re-encodes with sharp too (that's what Task 1 guarantees).
|
|
222
|
+
If it fails on `rgnl-fns`, suspect the musl install, not the test.
|
|
223
|
+
|
|
224
|
+
### 7. Stretch — first construct test
|
|
225
|
+
|
|
226
|
+
`test/` currently holds only a `tsconfig.json`; there are no CDK assertion tests.
|
|
227
|
+
A worthwhile addition: with the flag off, assert the synthesized template has one
|
|
228
|
+
Lambda and the `_next/image*` cache behavior targets the server origin; with it
|
|
229
|
+
on, two Lambdas. The obstacle is that `NextjsBuild` runs `next build` in its
|
|
230
|
+
constructor, so a test needs `skipBuild: true` plus a committed fixture `.next`
|
|
231
|
+
directory. Skip if it balloons; it's not a Phase 0 blocker.
|
|
232
|
+
|
|
233
|
+
## Verification
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
npx tsc --noEmit -p tsconfig.json
|
|
237
|
+
npx jest src/ # 51 tests before this change
|
|
238
|
+
ESLINT_USE_FLAT_CONFIG=false npx eslint --fix --ext .ts src/
|
|
239
|
+
npx jsii --silence-warnings=reserved-word
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
Then, because `NextjsBuildProps` changed, in this order (the build-order quirk in
|
|
243
|
+
`CLAUDE.md`):
|
|
244
|
+
|
|
245
|
+
```bash
|
|
246
|
+
pnpm compile # writes .jsii
|
|
247
|
+
pnpm projen # regenerates src/generated-structs/OptionalNextjsBuildProps.ts from .jsii
|
|
248
|
+
pnpm build
|
|
249
|
+
npx jsii-docgen -o API.md # API.md is committed and generated from .jsii
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
Notes:
|
|
253
|
+
|
|
254
|
+
- `pnpm eslint` and `pnpm projen` shell out to `pnpm dlx projen`, which needs
|
|
255
|
+
network access to `registry.npmjs.org`. In a sandboxed session that fails with
|
|
256
|
+
`ERR_PNPM_FETCH_403`; the `npx` forms above work around it.
|
|
257
|
+
- `src/image-optimization/handler.mts` cannot be linted — pre-existing, the
|
|
258
|
+
ESLint project service only covers `.ts`/`.tsx`.
|
|
259
|
+
- `API.md` is 11,973 lines and committed. Forgetting to regenerate it will show
|
|
260
|
+
up as a CI self-mutation diff.
|
|
261
|
+
|
|
262
|
+
## Out of scope
|
|
263
|
+
|
|
264
|
+
- Any middleware execution. That's the next phase: copy
|
|
265
|
+
`ctx.outputs.middleware.filePath` + `assets` in `onBuildComplete`, match on
|
|
266
|
+
`config.matchers[].sourceRegex` with `has`/`missing`, invoke the entrypoint's
|
|
267
|
+
exported `handler(req, res, ctx)`. Node runtime only — edge is deprecated in
|
|
268
|
+
Next.js 16.
|
|
269
|
+
- Replacing the server function with adapter entrypoints.
|
|
270
|
+
- Widening the image cache policy's `cookieBehavior` (currently `none()` at
|
|
271
|
+
`nextjs-distribution.ts:338`). Only matters once middleware makes
|
|
272
|
+
cookie-dependent decisions for image requests.
|
|
273
|
+
|
|
274
|
+
## Background: the bug that started this
|
|
275
|
+
|
|
276
|
+
`next/dist/server/image-optimizer.js` reports a failed optimization by
|
|
277
|
+
**returning** `{ buffer: upstreamBuffer, ..., error }` rather than throwing. The
|
|
278
|
+
handler dropped `error`, so a broken sharp produced a valid HTTP 200 serving
|
|
279
|
+
full-size originals forever, with clean logs. It got through four green e2e jobs
|
|
280
|
+
and a live CloudFront endpoint that rendered all three test images correctly.
|
|
281
|
+
|
|
282
|
+
It was caught by comparing bytes: the `_next/image` response was byte-identical
|
|
283
|
+
to the raw S3 asset (31,283 bytes, md5 `ac38a73ecb20a904d52ebc9b28aa171f`),
|
|
284
|
+
returned `content-type: image/png` despite `Accept: image/webp`, and carried
|
|
285
|
+
S3's MD5 ETag rather than Next.js's sha256/base64url one.
|
|
286
|
+
|
|
287
|
+
Root cause: `next build`'s output file tracing preserves the installer's layout,
|
|
288
|
+
and under pnpm there is never a hoisted `node_modules/sharp` — only
|
|
289
|
+
`node_modules/.pnpm/sharp@<version>/node_modules/sharp`. The old flat
|
|
290
|
+
`existsSync` check never matched, so sharp was never bundled. Fixed in `40b7837`
|
|
291
|
+
along with logging the swallowed `error`.
|
|
292
|
+
|
|
293
|
+
The lesson for every later phase: the e2e suite asserts status codes, so it
|
|
294
|
+
cannot see semantically wrong but syntactically fine responses. Assertions on
|
|
295
|
+
bytes and headers are what caught this.
|
|
@@ -9,6 +9,16 @@ export interface OptionalNextjsDistributionProps {
|
|
|
9
9
|
* @stability stable
|
|
10
10
|
*/
|
|
11
11
|
readonly loadBalancer?: aws_elasticloadbalancingv2.IApplicationLoadBalancer;
|
|
12
|
+
/**
|
|
13
|
+
* Function URL of the dedicated image optimization Lambda.
|
|
14
|
+
* Only applicable
|
|
15
|
+
* to `NextjsType.GLOBAL_FUNCTIONS`, and only when the dedicated image
|
|
16
|
+
* function is enabled. When omitted, the `_next/image*` behavior points at
|
|
17
|
+
* the dynamic origin, which serves image optimization from the Next.js
|
|
18
|
+
* server itself.
|
|
19
|
+
* @stability stable
|
|
20
|
+
*/
|
|
21
|
+
readonly imageFunctionUrl?: aws_lambda.IFunctionUrl;
|
|
12
22
|
/**
|
|
13
23
|
* Required if `NextjsType.GLOBAL_FUNCTIONS`.
|
|
14
24
|
* @stability stable
|
|
@@ -24,6 +34,9 @@ export interface OptionalNextjsDistributionProps {
|
|
|
24
34
|
*/
|
|
25
35
|
readonly certificate?: aws_certificatemanager.ICertificate;
|
|
26
36
|
/**
|
|
37
|
+
* URI path prefix the app is served at.
|
|
38
|
+
* Surrounding slashes are normalized
|
|
39
|
+
* away, so "/base", "base" and "/base/" all produce the same cache behaviors.
|
|
27
40
|
* @stability stable
|
|
28
41
|
*/
|
|
29
42
|
readonly basePath?: string;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiT3B0aW9uYWxOZXh0anNEaXN0cmlidXRpb25Qcm9wcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9nZW5lcmF0ZWQtc3RydWN0cy9PcHRpb25hbE5leHRqc0Rpc3RyaWJ1dGlvblByb3BzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiIiLCJzb3VyY2VzQ29udGVudCI6WyIvLyB+fiBHZW5lcmF0ZWQgYnkgcHJvamVuLiBUbyBtb2RpZnksIGVkaXQgLnByb2plbnJjLnRzIGFuZCBydW4gXCJwbnBtIGRseCBwcm9qZW5cIi5cbmltcG9ydCB0eXBlIHsgYXdzX2NlcnRpZmljYXRlbWFuYWdlciwgYXdzX2Nsb3VkZnJvbnQsIGF3c19lbGFzdGljbG9hZGJhbGFuY2luZ3YyLCBhd3NfbGFtYmRhLCBhd3NfczMgfSBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgdHlwZSB7IE5leHRqc1R5cGUsIFB1YmxpY0RpckVudHJ5IH0gZnJvbSAnLi4vJztcblxuLyoqXG4gKiBPcHRpb25hbE5leHRqc0Rpc3RyaWJ1dGlvblByb3BzXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgT3B0aW9uYWxOZXh0anNEaXN0cmlidXRpb25Qcm9wcyB7XG4gIC8qKlxuICAgKiBSZXF1aXJlZCBpZiBgTmV4dGpzVHlwZS5HTE9CQUxfQ09OVEFJTkVSU2Agb3IgYE5leHRqc1R5cGUuUkVHSU9OQUxfQ09OVEFJTkVSU2AuXG4gICAqIEBzdGFiaWxpdHkgc3RhYmxlXG4gICAqL1xuICByZWFkb25seSBsb2FkQmFsYW5jZXI/
|
|
3
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiT3B0aW9uYWxOZXh0anNEaXN0cmlidXRpb25Qcm9wcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9nZW5lcmF0ZWQtc3RydWN0cy9PcHRpb25hbE5leHRqc0Rpc3RyaWJ1dGlvblByb3BzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiIiLCJzb3VyY2VzQ29udGVudCI6WyIvLyB+fiBHZW5lcmF0ZWQgYnkgcHJvamVuLiBUbyBtb2RpZnksIGVkaXQgLnByb2plbnJjLnRzIGFuZCBydW4gXCJwbnBtIGRseCBwcm9qZW5cIi5cbmltcG9ydCB0eXBlIHsgYXdzX2NlcnRpZmljYXRlbWFuYWdlciwgYXdzX2Nsb3VkZnJvbnQsIGF3c19lbGFzdGljbG9hZGJhbGFuY2luZ3YyLCBhd3NfbGFtYmRhLCBhd3NfczMgfSBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgdHlwZSB7IE5leHRqc1R5cGUsIFB1YmxpY0RpckVudHJ5IH0gZnJvbSAnLi4vJztcblxuLyoqXG4gKiBPcHRpb25hbE5leHRqc0Rpc3RyaWJ1dGlvblByb3BzXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgT3B0aW9uYWxOZXh0anNEaXN0cmlidXRpb25Qcm9wcyB7XG4gIC8qKlxuICAgKiBSZXF1aXJlZCBpZiBgTmV4dGpzVHlwZS5HTE9CQUxfQ09OVEFJTkVSU2Agb3IgYE5leHRqc1R5cGUuUkVHSU9OQUxfQ09OVEFJTkVSU2AuXG4gICAqIEBzdGFiaWxpdHkgc3RhYmxlXG4gICAqL1xuICByZWFkb25seSBsb2FkQmFsYW5jZXI/OiBhd3NfZWxhc3RpY2xvYWRiYWxhbmNpbmd2Mi5JQXBwbGljYXRpb25Mb2FkQmFsYW5jZXI7XG4gIC8qKlxuICAgKiBGdW5jdGlvbiBVUkwgb2YgdGhlIGRlZGljYXRlZCBpbWFnZSBvcHRpbWl6YXRpb24gTGFtYmRhLlxuICAgKiBPbmx5IGFwcGxpY2FibGVcbiAgICogdG8gYE5leHRqc1R5cGUuR0xPQkFMX0ZVTkNUSU9OU2AsIGFuZCBvbmx5IHdoZW4gdGhlIGRlZGljYXRlZCBpbWFnZVxuICAgKiBmdW5jdGlvbiBpcyBlbmFibGVkLiBXaGVuIG9taXR0ZWQsIHRoZSBgX25leHQvaW1hZ2UqYCBiZWhhdmlvciBwb2ludHMgYXRcbiAgICogdGhlIGR5bmFtaWMgb3JpZ2luLCB3aGljaCBzZXJ2ZXMgaW1hZ2Ugb3B0aW1pemF0aW9uIGZyb20gdGhlIE5leHQuanNcbiAgICogc2VydmVyIGl0c2VsZi5cbiAgICogQHN0YWJpbGl0eSBzdGFibGVcbiAgICovXG4gIHJlYWRvbmx5IGltYWdlRnVuY3Rpb25Vcmw/OiBhd3NfbGFtYmRhLklGdW5jdGlvblVybDtcbiAgLyoqXG4gICAqIFJlcXVpcmVkIGlmIGBOZXh0anNUeXBlLkdMT0JBTF9GVU5DVElPTlNgLlxuICAgKiBAc3RhYmlsaXR5IHN0YWJsZVxuICAgKi9cbiAgcmVhZG9ubHkgZnVuY3Rpb25Vcmw/OiBhd3NfbGFtYmRhLklGdW5jdGlvblVybDtcbiAgLyoqXG4gICAqIEBzdGFiaWxpdHkgc3RhYmxlXG4gICAqL1xuICByZWFkb25seSBkaXN0cmlidXRpb24/OiBhd3NfY2xvdWRmcm9udC5EaXN0cmlidXRpb247XG4gIC8qKlxuICAgKiBPcHRpb25hbCBidXQgb25seSBhcHBsaWNhYmxlIGZvciBgTmV4dGpzVHlwZS5HTE9CQUxfQ09OVEFJTkVSU2AuXG4gICAqIEBzdGFiaWxpdHkgc3RhYmxlXG4gICAqL1xuICByZWFkb25seSBjZXJ0aWZpY2F0ZT86IGF3c19jZXJ0aWZpY2F0ZW1hbmFnZXIuSUNlcnRpZmljYXRlO1xuICAvKipcbiAgICogVVJJIHBhdGggcHJlZml4IHRoZSBhcHAgaXMgc2VydmVkIGF0LlxuICAgKiBTdXJyb3VuZGluZyBzbGFzaGVzIGFyZSBub3JtYWxpemVkXG4gICAqIGF3YXksIHNvIFwiL2Jhc2VcIiwgXCJiYXNlXCIgYW5kIFwiL2Jhc2UvXCIgYWxsIHByb2R1Y2UgdGhlIHNhbWUgY2FjaGUgYmVoYXZpb3JzLlxuICAgKiBAc3RhYmlsaXR5IHN0YWJsZVxuICAgKi9cbiAgcmVhZG9ubHkgYmFzZVBhdGg/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBFbnRyaWVzIChmaWxlcy9kaXJlY3Rvcmllcykgd2l0aGluIE5leHQuanMgYXBwJ3MgcHVibGljIGRpcmVjdG9yeS4gVXNlZCB0byBhZGQgc3RhdGljIGJlaGF2aW9ycyB0byBkaXN0cmlidXRpb24uXG4gICAqIEBzdGFiaWxpdHkgc3RhYmxlXG4gICAqL1xuICByZWFkb25seSBwdWJsaWNEaXJFbnRyaWVzPzogQXJyYXk8UHVibGljRGlyRW50cnk+O1xuICAvKipcbiAgICogQHN0YWJpbGl0eSBzdGFibGVcbiAgICovXG4gIHJlYWRvbmx5IG5leHRqc1R5cGU/OiBOZXh0anNUeXBlO1xuICAvKipcbiAgICogQnVja2V0IGNvbnRhaW5pbmcgc3RhdGljIGFzc2V0cy5cbiAgICogTXVzdCBiZSBwcm92aWRlZCBpZiB5b3Ugd2FudCB0byBzZXJ2ZSBzdGF0aWMgZmlsZXMuXG4gICAqIEBzdGFiaWxpdHkgc3RhYmxlXG4gICAqL1xuICByZWFkb25seSBhc3NldHNCdWNrZXQ/OiBhd3NfczMuSUJ1Y2tldDtcbn1cbiJdfQ==
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { S3Client } from "@aws-sdk/client-s3";
|
|
2
|
+
/**
|
|
3
|
+
* Fetches a non-absolute (local) image referenced by an `<Image>` from S3.
|
|
4
|
+
*
|
|
5
|
+
* `url` is inconsistent: next-image-loader bakes the app's own `basePath` into
|
|
6
|
+
* the href for statically imported images, while plain string paths are passed
|
|
7
|
+
* through as literally written. So `nextBasePath` (the app's config) is stripped
|
|
8
|
+
* off, then `staticAssetsKeyPrefix` (`NextjsStaticAssets.keyPrefix`) applied.
|
|
9
|
+
* The two are separate arguments because nothing requires them to be the same
|
|
10
|
+
* value — e.g. an app whose `basePath` is an API Gateway stage, deployed without
|
|
11
|
+
* the CDK `basePath` prop.
|
|
12
|
+
*/
|
|
13
|
+
export declare function fetchFromS3(s3: S3Client, bucket: string, url: string, nextBasePath: string, staticAssetsKeyPrefix?: string): Promise<{
|
|
14
|
+
buffer: Buffer;
|
|
15
|
+
contentType: string | null;
|
|
16
|
+
etag: string;
|
|
17
|
+
}>;
|
|
18
|
+
/** Mirrors Next.js's own `getFileNameWithExtension` in image-optimizer.js. */
|
|
19
|
+
export declare function getFileNameWithExtension(url: string, contentType: string | null): string;
|
|
20
|
+
/**
|
|
21
|
+
* Maps an error thrown while processing an image request to the HTTP
|
|
22
|
+
* status/message it should produce, preserving the status Next.js's own
|
|
23
|
+
* `ImageError`/`fetchExternalImage` attach. A missing S3 object is mapped to
|
|
24
|
+
* the same 400 Next.js's own local-image fetch path (`fetchInternalImage` in
|
|
25
|
+
* image-optimizer.js) produces for a missing file: it never inspects the
|
|
26
|
+
* internal request's status code, so a 404 there just flows into the normal
|
|
27
|
+
* "not a valid image" content-type check as if it were malformed image
|
|
28
|
+
* bytes. This mirrors that behavior instead of surfacing a 404, so Functions
|
|
29
|
+
* and Containers deployments respond identically for this case.
|
|
30
|
+
*/
|
|
31
|
+
export declare function resolveErrorResponse(error: unknown): {
|
|
32
|
+
statusCode: number;
|
|
33
|
+
message: string;
|
|
34
|
+
};
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.fetchFromS3 = fetchFromS3;
|
|
4
|
+
exports.getFileNameWithExtension = getFileNameWithExtension;
|
|
5
|
+
exports.resolveErrorResponse = resolveErrorResponse;
|
|
6
|
+
/* eslint-disable import/no-extraneous-dependencies */
|
|
7
|
+
const client_s3_1 = require("@aws-sdk/client-s3");
|
|
8
|
+
const image_optimizer_js_1 = require("next/dist/server/image-optimizer.js");
|
|
9
|
+
const serve_static_js_1 = require("next/dist/server/serve-static.js");
|
|
10
|
+
const base_path_1 = require("../utils/base-path");
|
|
11
|
+
/**
|
|
12
|
+
* Fetches a non-absolute (local) image referenced by an `<Image>` from S3.
|
|
13
|
+
*
|
|
14
|
+
* `url` is inconsistent: next-image-loader bakes the app's own `basePath` into
|
|
15
|
+
* the href for statically imported images, while plain string paths are passed
|
|
16
|
+
* through as literally written. So `nextBasePath` (the app's config) is stripped
|
|
17
|
+
* off, then `staticAssetsKeyPrefix` (`NextjsStaticAssets.keyPrefix`) applied.
|
|
18
|
+
* The two are separate arguments because nothing requires them to be the same
|
|
19
|
+
* value — e.g. an app whose `basePath` is an API Gateway stage, deployed without
|
|
20
|
+
* the CDK `basePath` prop.
|
|
21
|
+
*/
|
|
22
|
+
async function fetchFromS3(s3, bucket, url, nextBasePath, staticAssetsKeyPrefix = "") {
|
|
23
|
+
// Matching on a path boundary keeps a sibling like "/basement/logo.png" from
|
|
24
|
+
// being treated as nextBasePath "/base" plus "ment/logo.png". It's still
|
|
25
|
+
// indistinguishable from a real `public/base/` directory, which loses; that's
|
|
26
|
+
// the right trade, since every statically imported image carries the prefix
|
|
27
|
+
// and the alternative costs an S3 round trip per request to detect it.
|
|
28
|
+
const hasNextBasePath = !!nextBasePath &&
|
|
29
|
+
(url === nextBasePath || url.startsWith(`${nextBasePath}/`));
|
|
30
|
+
const key = (0, base_path_1.joinPath)(staticAssetsKeyPrefix, hasNextBasePath ? url.slice(nextBasePath.length) : url);
|
|
31
|
+
const response = await s3.send(new client_s3_1.GetObjectCommand({
|
|
32
|
+
Bucket: bucket,
|
|
33
|
+
Key: key,
|
|
34
|
+
}));
|
|
35
|
+
const body = response.Body;
|
|
36
|
+
if (!body) {
|
|
37
|
+
throw new Error(`Empty response from S3 for key: ${key}`);
|
|
38
|
+
}
|
|
39
|
+
const chunks = [];
|
|
40
|
+
for await (const chunk of body) {
|
|
41
|
+
chunks.push(Buffer.from(chunk));
|
|
42
|
+
}
|
|
43
|
+
return {
|
|
44
|
+
buffer: Buffer.concat(chunks),
|
|
45
|
+
contentType: response.ContentType || null,
|
|
46
|
+
etag: response.ETag || "",
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/** Mirrors Next.js's own `getFileNameWithExtension` in image-optimizer.js. */
|
|
50
|
+
function getFileNameWithExtension(url, contentType) {
|
|
51
|
+
const [urlWithoutQueryParams] = url.split("?", 1);
|
|
52
|
+
const fileNameWithExtension = urlWithoutQueryParams.split("/").pop();
|
|
53
|
+
if (!contentType || !fileNameWithExtension) {
|
|
54
|
+
return "image.bin";
|
|
55
|
+
}
|
|
56
|
+
const [fileName] = fileNameWithExtension.split(".", 1);
|
|
57
|
+
const extension = (0, serve_static_js_1.getExtension)(contentType);
|
|
58
|
+
return `${fileName}.${extension}`;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Maps an error thrown while processing an image request to the HTTP
|
|
62
|
+
* status/message it should produce, preserving the status Next.js's own
|
|
63
|
+
* `ImageError`/`fetchExternalImage` attach. A missing S3 object is mapped to
|
|
64
|
+
* the same 400 Next.js's own local-image fetch path (`fetchInternalImage` in
|
|
65
|
+
* image-optimizer.js) produces for a missing file: it never inspects the
|
|
66
|
+
* internal request's status code, so a 404 there just flows into the normal
|
|
67
|
+
* "not a valid image" content-type check as if it were malformed image
|
|
68
|
+
* bytes. This mirrors that behavior instead of surfacing a 404, so Functions
|
|
69
|
+
* and Containers deployments respond identically for this case.
|
|
70
|
+
*/
|
|
71
|
+
function resolveErrorResponse(error) {
|
|
72
|
+
if (error instanceof image_optimizer_js_1.ImageError) {
|
|
73
|
+
return { statusCode: error.statusCode, message: error.message };
|
|
74
|
+
}
|
|
75
|
+
if (error instanceof Error && error.name === "NoSuchKey") {
|
|
76
|
+
return {
|
|
77
|
+
statusCode: 400,
|
|
78
|
+
message: "The requested resource isn't a valid image.",
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
return { statusCode: 500, message: "Internal Server Error" };
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGFuZGxlci11dGlscy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9pbWFnZS1vcHRpbWl6YXRpb24vaGFuZGxlci11dGlscy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQWlCQSxrQ0EwQ0M7QUFHRCw0REFZQztBQWFELG9EQWNDO0FBckdELHNEQUFzRDtBQUN0RCxrREFBZ0U7QUFDaEUsNEVBQWlFO0FBQ2pFLHNFQUFnRTtBQUNoRSxrREFBOEM7QUFFOUM7Ozs7Ozs7Ozs7R0FVRztBQUNJLEtBQUssVUFBVSxXQUFXLENBQy9CLEVBQVksRUFDWixNQUFjLEVBQ2QsR0FBVyxFQUNYLFlBQW9CLEVBQ3BCLHdCQUFnQyxFQUFFO0lBRWxDLDZFQUE2RTtJQUM3RSx5RUFBeUU7SUFDekUsOEVBQThFO0lBQzlFLDRFQUE0RTtJQUM1RSx1RUFBdUU7SUFDdkUsTUFBTSxlQUFlLEdBQ25CLENBQUMsQ0FBQyxZQUFZO1FBQ2QsQ0FBQyxHQUFHLEtBQUssWUFBWSxJQUFJLEdBQUcsQ0FBQyxVQUFVLENBQUMsR0FBRyxZQUFZLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDL0QsTUFBTSxHQUFHLEdBQUcsSUFBQSxvQkFBUSxFQUNsQixxQkFBcUIsRUFDckIsZUFBZSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUN2RCxDQUFDO0lBRUYsTUFBTSxRQUFRLEdBQUcsTUFBTSxFQUFFLENBQUMsSUFBSSxDQUM1QixJQUFJLDRCQUFnQixDQUFDO1FBQ25CLE1BQU0sRUFBRSxNQUFNO1FBQ2QsR0FBRyxFQUFFLEdBQUc7S0FDVCxDQUFDLENBQ0gsQ0FBQztJQUVGLE1BQU0sSUFBSSxHQUFHLFFBQVEsQ0FBQyxJQUFJLENBQUM7SUFDM0IsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ1YsTUFBTSxJQUFJLEtBQUssQ0FBQyxtQ0FBbUMsR0FBRyxFQUFFLENBQUMsQ0FBQztJQUM1RCxDQUFDO0lBRUQsTUFBTSxNQUFNLEdBQWEsRUFBRSxDQUFDO0lBQzVCLElBQUksS0FBSyxFQUFFLE1BQU0sS0FBSyxJQUFJLElBQWlDLEVBQUUsQ0FBQztRQUM1RCxNQUFNLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztJQUNsQyxDQUFDO0lBRUQsT0FBTztRQUNMLE1BQU0sRUFBRSxNQUFNLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQztRQUM3QixXQUFXLEVBQUUsUUFBUSxDQUFDLFdBQVcsSUFBSSxJQUFJO1FBQ3pDLElBQUksRUFBRSxRQUFRLENBQUMsSUFBSSxJQUFJLEVBQUU7S0FDMUIsQ0FBQztBQUNKLENBQUM7QUFFRCw4RUFBOEU7QUFDOUUsU0FBZ0Isd0JBQXdCLENBQ3RDLEdBQVcsRUFDWCxXQUEwQjtJQUUxQixNQUFNLENBQUMscUJBQXFCLENBQUMsR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNsRCxNQUFNLHFCQUFxQixHQUFHLHFCQUFxQixDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQztJQUNyRSxJQUFJLENBQUMsV0FBVyxJQUFJLENBQUMscUJBQXFCLEVBQUUsQ0FBQztRQUMzQyxPQUFPLFdBQVcsQ0FBQztJQUNyQixDQUFDO0lBQ0QsTUFBTSxDQUFDLFFBQVEsQ0FBQyxHQUFHLHFCQUFxQixDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDdkQsTUFBTSxTQUFTLEdBQUcsSUFBQSw4QkFBWSxFQUFDLFdBQVcsQ0FBQyxDQUFDO0lBQzVDLE9BQU8sR0FBRyxRQUFRLElBQUksU0FBUyxFQUFFLENBQUM7QUFDcEMsQ0FBQztBQUVEOzs7Ozs7Ozs7O0dBVUc7QUFDSCxTQUFnQixvQkFBb0IsQ0FBQyxLQUFjO0lBSWpELElBQUksS0FBSyxZQUFZLCtCQUFVLEVBQUUsQ0FBQztRQUNoQyxPQUFPLEVBQUUsVUFBVSxFQUFFLEtBQUssQ0FBQyxVQUFVLEVBQUUsT0FBTyxFQUFFLEtBQUssQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUNsRSxDQUFDO0lBQ0QsSUFBSSxLQUFLLFlBQVksS0FBSyxJQUFJLEtBQUssQ0FBQyxJQUFJLEtBQUssV0FBVyxFQUFFLENBQUM7UUFDekQsT0FBTztZQUNMLFVBQVUsRUFBRSxHQUFHO1lBQ2YsT0FBTyxFQUFFLDZDQUE2QztTQUN2RCxDQUFDO0lBQ0osQ0FBQztJQUNELE9BQU8sRUFBRSxVQUFVLEVBQUUsR0FBRyxFQUFFLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxDQUFDO0FBQy9ELENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKiBlc2xpbnQtZGlzYWJsZSBpbXBvcnQvbm8tZXh0cmFuZW91cy1kZXBlbmRlbmNpZXMgKi9cbmltcG9ydCB7IEdldE9iamVjdENvbW1hbmQsIFMzQ2xpZW50IH0gZnJvbSBcIkBhd3Mtc2RrL2NsaWVudC1zM1wiO1xuaW1wb3J0IHsgSW1hZ2VFcnJvciB9IGZyb20gXCJuZXh0L2Rpc3Qvc2VydmVyL2ltYWdlLW9wdGltaXplci5qc1wiO1xuaW1wb3J0IHsgZ2V0RXh0ZW5zaW9uIH0gZnJvbSBcIm5leHQvZGlzdC9zZXJ2ZXIvc2VydmUtc3RhdGljLmpzXCI7XG5pbXBvcnQgeyBqb2luUGF0aCB9IGZyb20gXCIuLi91dGlscy9iYXNlLXBhdGhcIjtcblxuLyoqXG4gKiBGZXRjaGVzIGEgbm9uLWFic29sdXRlIChsb2NhbCkgaW1hZ2UgcmVmZXJlbmNlZCBieSBhbiBgPEltYWdlPmAgZnJvbSBTMy5cbiAqXG4gKiBgdXJsYCBpcyBpbmNvbnNpc3RlbnQ6IG5leHQtaW1hZ2UtbG9hZGVyIGJha2VzIHRoZSBhcHAncyBvd24gYGJhc2VQYXRoYCBpbnRvXG4gKiB0aGUgaHJlZiBmb3Igc3RhdGljYWxseSBpbXBvcnRlZCBpbWFnZXMsIHdoaWxlIHBsYWluIHN0cmluZyBwYXRocyBhcmUgcGFzc2VkXG4gKiB0aHJvdWdoIGFzIGxpdGVyYWxseSB3cml0dGVuLiBTbyBgbmV4dEJhc2VQYXRoYCAodGhlIGFwcCdzIGNvbmZpZykgaXMgc3RyaXBwZWRcbiAqIG9mZiwgdGhlbiBgc3RhdGljQXNzZXRzS2V5UHJlZml4YCAoYE5leHRqc1N0YXRpY0Fzc2V0cy5rZXlQcmVmaXhgKSBhcHBsaWVkLlxuICogVGhlIHR3byBhcmUgc2VwYXJhdGUgYXJndW1lbnRzIGJlY2F1c2Ugbm90aGluZyByZXF1aXJlcyB0aGVtIHRvIGJlIHRoZSBzYW1lXG4gKiB2YWx1ZSDigJQgZS5nLiBhbiBhcHAgd2hvc2UgYGJhc2VQYXRoYCBpcyBhbiBBUEkgR2F0ZXdheSBzdGFnZSwgZGVwbG95ZWQgd2l0aG91dFxuICogdGhlIENESyBgYmFzZVBhdGhgIHByb3AuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBmZXRjaEZyb21TMyhcbiAgczM6IFMzQ2xpZW50LFxuICBidWNrZXQ6IHN0cmluZyxcbiAgdXJsOiBzdHJpbmcsXG4gIG5leHRCYXNlUGF0aDogc3RyaW5nLFxuICBzdGF0aWNBc3NldHNLZXlQcmVmaXg6IHN0cmluZyA9IFwiXCIsXG4pOiBQcm9taXNlPHsgYnVmZmVyOiBCdWZmZXI7IGNvbnRlbnRUeXBlOiBzdHJpbmcgfCBudWxsOyBldGFnOiBzdHJpbmcgfT4ge1xuICAvLyBNYXRjaGluZyBvbiBhIHBhdGggYm91bmRhcnkga2VlcHMgYSBzaWJsaW5nIGxpa2UgXCIvYmFzZW1lbnQvbG9nby5wbmdcIiBmcm9tXG4gIC8vIGJlaW5nIHRyZWF0ZWQgYXMgbmV4dEJhc2VQYXRoIFwiL2Jhc2VcIiBwbHVzIFwibWVudC9sb2dvLnBuZ1wiLiBJdCdzIHN0aWxsXG4gIC8vIGluZGlzdGluZ3Vpc2hhYmxlIGZyb20gYSByZWFsIGBwdWJsaWMvYmFzZS9gIGRpcmVjdG9yeSwgd2hpY2ggbG9zZXM7IHRoYXQnc1xuICAvLyB0aGUgcmlnaHQgdHJhZGUsIHNpbmNlIGV2ZXJ5IHN0YXRpY2FsbHkgaW1wb3J0ZWQgaW1hZ2UgY2FycmllcyB0aGUgcHJlZml4XG4gIC8vIGFuZCB0aGUgYWx0ZXJuYXRpdmUgY29zdHMgYW4gUzMgcm91bmQgdHJpcCBwZXIgcmVxdWVzdCB0byBkZXRlY3QgaXQuXG4gIGNvbnN0IGhhc05leHRCYXNlUGF0aCA9XG4gICAgISFuZXh0QmFzZVBhdGggJiZcbiAgICAodXJsID09PSBuZXh0QmFzZVBhdGggfHwgdXJsLnN0YXJ0c1dpdGgoYCR7bmV4dEJhc2VQYXRofS9gKSk7XG4gIGNvbnN0IGtleSA9IGpvaW5QYXRoKFxuICAgIHN0YXRpY0Fzc2V0c0tleVByZWZpeCxcbiAgICBoYXNOZXh0QmFzZVBhdGggPyB1cmwuc2xpY2UobmV4dEJhc2VQYXRoLmxlbmd0aCkgOiB1cmwsXG4gICk7XG5cbiAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBzMy5zZW5kKFxuICAgIG5ldyBHZXRPYmplY3RDb21tYW5kKHtcbiAgICAgIEJ1Y2tldDogYnVja2V0LFxuICAgICAgS2V5OiBrZXksXG4gICAgfSksXG4gICk7XG5cbiAgY29uc3QgYm9keSA9IHJlc3BvbnNlLkJvZHk7XG4gIGlmICghYm9keSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgRW1wdHkgcmVzcG9uc2UgZnJvbSBTMyBmb3Iga2V5OiAke2tleX1gKTtcbiAgfVxuXG4gIGNvbnN0IGNodW5rczogQnVmZmVyW10gPSBbXTtcbiAgZm9yIGF3YWl0IChjb25zdCBjaHVuayBvZiBib2R5IGFzIEFzeW5jSXRlcmFibGU8VWludDhBcnJheT4pIHtcbiAgICBjaHVua3MucHVzaChCdWZmZXIuZnJvbShjaHVuaykpO1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBidWZmZXI6IEJ1ZmZlci5jb25jYXQoY2h1bmtzKSxcbiAgICBjb250ZW50VHlwZTogcmVzcG9uc2UuQ29udGVudFR5cGUgfHwgbnVsbCxcbiAgICBldGFnOiByZXNwb25zZS5FVGFnIHx8IFwiXCIsXG4gIH07XG59XG5cbi8qKiBNaXJyb3JzIE5leHQuanMncyBvd24gYGdldEZpbGVOYW1lV2l0aEV4dGVuc2lvbmAgaW4gaW1hZ2Utb3B0aW1pemVyLmpzLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldEZpbGVOYW1lV2l0aEV4dGVuc2lvbihcbiAgdXJsOiBzdHJpbmcsXG4gIGNvbnRlbnRUeXBlOiBzdHJpbmcgfCBudWxsLFxuKTogc3RyaW5nIHtcbiAgY29uc3QgW3VybFdpdGhvdXRRdWVyeVBhcmFtc10gPSB1cmwuc3BsaXQoXCI/XCIsIDEpO1xuICBjb25zdCBmaWxlTmFtZVdpdGhFeHRlbnNpb24gPSB1cmxXaXRob3V0UXVlcnlQYXJhbXMuc3BsaXQoXCIvXCIpLnBvcCgpO1xuICBpZiAoIWNvbnRlbnRUeXBlIHx8ICFmaWxlTmFtZVdpdGhFeHRlbnNpb24pIHtcbiAgICByZXR1cm4gXCJpbWFnZS5iaW5cIjtcbiAgfVxuICBjb25zdCBbZmlsZU5hbWVdID0gZmlsZU5hbWVXaXRoRXh0ZW5zaW9uLnNwbGl0KFwiLlwiLCAxKTtcbiAgY29uc3QgZXh0ZW5zaW9uID0gZ2V0RXh0ZW5zaW9uKGNvbnRlbnRUeXBlKTtcbiAgcmV0dXJuIGAke2ZpbGVOYW1lfS4ke2V4dGVuc2lvbn1gO1xufVxuXG4vKipcbiAqIE1hcHMgYW4gZXJyb3IgdGhyb3duIHdoaWxlIHByb2Nlc3NpbmcgYW4gaW1hZ2UgcmVxdWVzdCB0byB0aGUgSFRUUFxuICogc3RhdHVzL21lc3NhZ2UgaXQgc2hvdWxkIHByb2R1Y2UsIHByZXNlcnZpbmcgdGhlIHN0YXR1cyBOZXh0LmpzJ3Mgb3duXG4gKiBgSW1hZ2VFcnJvcmAvYGZldGNoRXh0ZXJuYWxJbWFnZWAgYXR0YWNoLiBBIG1pc3NpbmcgUzMgb2JqZWN0IGlzIG1hcHBlZCB0b1xuICogdGhlIHNhbWUgNDAwIE5leHQuanMncyBvd24gbG9jYWwtaW1hZ2UgZmV0Y2ggcGF0aCAoYGZldGNoSW50ZXJuYWxJbWFnZWAgaW5cbiAqIGltYWdlLW9wdGltaXplci5qcykgcHJvZHVjZXMgZm9yIGEgbWlzc2luZyBmaWxlOiBpdCBuZXZlciBpbnNwZWN0cyB0aGVcbiAqIGludGVybmFsIHJlcXVlc3QncyBzdGF0dXMgY29kZSwgc28gYSA0MDQgdGhlcmUganVzdCBmbG93cyBpbnRvIHRoZSBub3JtYWxcbiAqIFwibm90IGEgdmFsaWQgaW1hZ2VcIiBjb250ZW50LXR5cGUgY2hlY2sgYXMgaWYgaXQgd2VyZSBtYWxmb3JtZWQgaW1hZ2VcbiAqIGJ5dGVzLiBUaGlzIG1pcnJvcnMgdGhhdCBiZWhhdmlvciBpbnN0ZWFkIG9mIHN1cmZhY2luZyBhIDQwNCwgc28gRnVuY3Rpb25zXG4gKiBhbmQgQ29udGFpbmVycyBkZXBsb3ltZW50cyByZXNwb25kIGlkZW50aWNhbGx5IGZvciB0aGlzIGNhc2UuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXNvbHZlRXJyb3JSZXNwb25zZShlcnJvcjogdW5rbm93bik6IHtcbiAgc3RhdHVzQ29kZTogbnVtYmVyO1xuICBtZXNzYWdlOiBzdHJpbmc7XG59IHtcbiAgaWYgKGVycm9yIGluc3RhbmNlb2YgSW1hZ2VFcnJvcikge1xuICAgIHJldHVybiB7IHN0YXR1c0NvZGU6IGVycm9yLnN0YXR1c0NvZGUsIG1lc3NhZ2U6IGVycm9yLm1lc3NhZ2UgfTtcbiAgfVxuICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBFcnJvciAmJiBlcnJvci5uYW1lID09PSBcIk5vU3VjaEtleVwiKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHN0YXR1c0NvZGU6IDQwMCxcbiAgICAgIG1lc3NhZ2U6IFwiVGhlIHJlcXVlc3RlZCByZXNvdXJjZSBpc24ndCBhIHZhbGlkIGltYWdlLlwiLFxuICAgIH07XG4gIH1cbiAgcmV0dXJuIHsgc3RhdHVzQ29kZTogNTAwLCBtZXNzYWdlOiBcIkludGVybmFsIFNlcnZlciBFcnJvclwiIH07XG59XG4iXX0=
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|