@openelement/adapter-vite 0.41.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +87 -0
- package/package.json +87 -0
- package/src/alias-utils.js +39 -0
- package/src/build-context.d.ts +111 -0
- package/src/build-context.js +184 -0
- package/src/build-manifest.d.ts +38 -0
- package/src/build-manifest.js +198 -0
- package/src/build.js +97 -0
- package/src/cli/build-client.d.ts +3 -0
- package/src/cli/build-client.js +292 -0
- package/src/cli/build-ssg.d.ts +40 -0
- package/src/cli/build-ssg.js +377 -0
- package/src/cli/build.d.ts +0 -0
- package/src/cli/build.js +27 -0
- package/src/cli/ssg-render.js +32 -0
- package/src/generated-data-resolver.d.ts +12 -0
- package/src/generated-data-resolver.js +52 -0
- package/src/head-injection.d.ts +31 -0
- package/src/head-injection.js +248 -0
- package/src/index.d.ts +58 -0
- package/src/index.js +52 -0
- package/src/island-transform.js +27 -0
- package/src/nitro-mount.d.ts +24 -0
- package/src/nitro-mount.js +27 -0
- package/src/plugin-mdx.d.ts +7 -0
- package/src/plugin-mdx.js +15 -0
- package/src/plugin.d.ts +22 -0
- package/src/plugin.js +264 -0
- package/src/ssg-package-resolver.js +256 -0
- package/src/subpath-resolver.d.ts +26 -0
- package/src/subpath-resolver.js +153 -0
- package/src/workspace-alias.js +113 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Zhi
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# @openelement/adapter-vite
|
|
2
|
+
|
|
3
|
+
openElement build orchestration for Vite.
|
|
4
|
+
|
|
5
|
+
> v0.39 surface: advanced Framework infrastructure. First-run apps should use
|
|
6
|
+
> `@openelement/app/vite` or generated `@openelement/create` tasks instead of
|
|
7
|
+
> importing this package directly.
|
|
8
|
+
|
|
9
|
+
This package scans routes and islands, generates virtual entries, builds client
|
|
10
|
+
island chunks, runs SSG, and writes post-processed HTML. It is build-time
|
|
11
|
+
infrastructure; runtime primitives live in `@openelement/core`.
|
|
12
|
+
|
|
13
|
+
## Install
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install @openelement/adapter-vite
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
import { createOpenPlugin } from '@openelement/adapter-vite/plugin';
|
|
23
|
+
import { defineConfig } from 'vite';
|
|
24
|
+
|
|
25
|
+
export default defineConfig({
|
|
26
|
+
plugins: [
|
|
27
|
+
createOpenPlugin({
|
|
28
|
+
routesDir: 'app/routes',
|
|
29
|
+
islandsDir: 'app/islands',
|
|
30
|
+
componentsDir: 'app/components',
|
|
31
|
+
packageIslands: ['@openelement/ui'],
|
|
32
|
+
}),
|
|
33
|
+
],
|
|
34
|
+
});
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Most applications should use `openElement()` from `@openelement/app/vite`
|
|
38
|
+
instead; it combines the core adapter, content pipeline, and i18n with one
|
|
39
|
+
shared build context.
|
|
40
|
+
|
|
41
|
+
## Main Options
|
|
42
|
+
|
|
43
|
+
| Option | Default | Purpose |
|
|
44
|
+
| ---------------- | ------------------ | ----------------------------------------------- |
|
|
45
|
+
| `routesDir` | `'app/routes'` | Page routes, API routes, renderers, middleware. |
|
|
46
|
+
| `islandsDir` | `'app/islands'` | Local Custom Elements for client upgrade. |
|
|
47
|
+
| `componentsDir` | `'app/components'` | Shared server-rendered components. |
|
|
48
|
+
| `packageIslands` | `[]` | Packages exporting an `islands` metadata array. |
|
|
49
|
+
| `html` | `{}` | Document metadata. |
|
|
50
|
+
| `inject` | none | Structured stylesheet/script/head injection. |
|
|
51
|
+
| `middleware` | none | Hono middleware configuration. |
|
|
52
|
+
| `pwa` | none | PWA metadata and assets. |
|
|
53
|
+
|
|
54
|
+
## SSG Pipeline
|
|
55
|
+
|
|
56
|
+
```text
|
|
57
|
+
Phase 1: route, API, middleware, and island scan
|
|
58
|
+
Phase 2: client island entry and browser chunks
|
|
59
|
+
Phase 3: SSR bundle, Hono toSSG(), HTML post-processing
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Build Utilities
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
import {
|
|
66
|
+
buildIslandChunkMap,
|
|
67
|
+
extractCustomElementTags,
|
|
68
|
+
generateIslandManifests,
|
|
69
|
+
injectClientScript,
|
|
70
|
+
injectCspMeta,
|
|
71
|
+
injectDsdPolyfill,
|
|
72
|
+
scanClientBuild,
|
|
73
|
+
scanSSGOutput,
|
|
74
|
+
writeIslandManifests,
|
|
75
|
+
} from '@openelement/adapter-vite';
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Registry Boundary
|
|
79
|
+
|
|
80
|
+
`packageIslands` currently scans packages that export `islands`. It should not be
|
|
81
|
+
treated as a complete marketplace or registry protocol. Future `open add`
|
|
82
|
+
behavior must first validate a CEM-compatible manifest, generate a dry-run diff,
|
|
83
|
+
and only then update config and generated registration.
|
|
84
|
+
|
|
85
|
+
## License
|
|
86
|
+
|
|
87
|
+
MIT
|
package/package.json
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@openelement/adapter-vite",
|
|
3
|
+
"version": "0.41.0-alpha.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./src/index.js",
|
|
6
|
+
"types": "./src/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./src/index.d.ts",
|
|
10
|
+
"import": "./src/index.js",
|
|
11
|
+
"default": "./src/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./build-context": {
|
|
14
|
+
"types": "./src/build-context.d.ts",
|
|
15
|
+
"import": "./src/build-context.js",
|
|
16
|
+
"default": "./src/build-context.js"
|
|
17
|
+
},
|
|
18
|
+
"./head-injection": {
|
|
19
|
+
"types": "./src/head-injection.d.ts",
|
|
20
|
+
"import": "./src/head-injection.js",
|
|
21
|
+
"default": "./src/head-injection.js"
|
|
22
|
+
},
|
|
23
|
+
"./nitro-mount": {
|
|
24
|
+
"types": "./src/nitro-mount.d.ts",
|
|
25
|
+
"import": "./src/nitro-mount.js",
|
|
26
|
+
"default": "./src/nitro-mount.js"
|
|
27
|
+
},
|
|
28
|
+
"./plugin": {
|
|
29
|
+
"types": "./src/plugin.d.ts",
|
|
30
|
+
"import": "./src/plugin.js",
|
|
31
|
+
"default": "./src/plugin.js"
|
|
32
|
+
},
|
|
33
|
+
"./generated-data-resolver": {
|
|
34
|
+
"types": "./src/generated-data-resolver.d.ts",
|
|
35
|
+
"import": "./src/generated-data-resolver.js",
|
|
36
|
+
"default": "./src/generated-data-resolver.js"
|
|
37
|
+
},
|
|
38
|
+
"./subpath-resolver": {
|
|
39
|
+
"types": "./src/subpath-resolver.d.ts",
|
|
40
|
+
"import": "./src/subpath-resolver.js",
|
|
41
|
+
"default": "./src/subpath-resolver.js"
|
|
42
|
+
},
|
|
43
|
+
"./plugin-mdx": {
|
|
44
|
+
"types": "./src/plugin-mdx.d.ts",
|
|
45
|
+
"import": "./src/plugin-mdx.js",
|
|
46
|
+
"default": "./src/plugin-mdx.js"
|
|
47
|
+
},
|
|
48
|
+
"./cli/build": {
|
|
49
|
+
"types": "./src/cli/build.d.ts",
|
|
50
|
+
"import": "./src/cli/build.js",
|
|
51
|
+
"default": "./src/cli/build.js"
|
|
52
|
+
},
|
|
53
|
+
"./cli/build-client": {
|
|
54
|
+
"types": "./src/cli/build-client.d.ts",
|
|
55
|
+
"import": "./src/cli/build-client.js",
|
|
56
|
+
"default": "./src/cli/build-client.js"
|
|
57
|
+
},
|
|
58
|
+
"./cli/build-ssg": {
|
|
59
|
+
"types": "./src/cli/build-ssg.d.ts",
|
|
60
|
+
"import": "./src/cli/build-ssg.js",
|
|
61
|
+
"default": "./src/cli/build-ssg.js"
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
"dependencies": {
|
|
65
|
+
"@mdx-js/rollup": "^3.1.1",
|
|
66
|
+
"@hono/vite-dev-server": "^0.25.3",
|
|
67
|
+
"sanitize-html": "^2.17.4",
|
|
68
|
+
"@types/sanitize-html": "^2",
|
|
69
|
+
"vite": "^8.0.10",
|
|
70
|
+
"@openelement/protocol": "^0.41.0-alpha.1",
|
|
71
|
+
"@openelement/core": "^0.41.0-alpha.1",
|
|
72
|
+
"@openelement/ssg": "^0.41.0-alpha.1",
|
|
73
|
+
"@openelement/content": "^0.41.0-alpha.1",
|
|
74
|
+
"@deno/shim-deno": "~0.19.0"
|
|
75
|
+
},
|
|
76
|
+
"repository": {
|
|
77
|
+
"type": "git",
|
|
78
|
+
"url": "git+https://github.com/open-element/openelement.git"
|
|
79
|
+
},
|
|
80
|
+
"keywords": [
|
|
81
|
+
"openelement",
|
|
82
|
+
"web-components",
|
|
83
|
+
"ssg",
|
|
84
|
+
"framework",
|
|
85
|
+
"deno"
|
|
86
|
+
]
|
|
87
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @openelement/adapter-vite - Alias normalization helpers.
|
|
3
|
+
*
|
|
4
|
+
* Utilities for converting user-provided alias mappings into Vite's Alias[]
|
|
5
|
+
* shape with absolute, root-relative replacements.
|
|
6
|
+
*/ import { resolve } from 'node:path';
|
|
7
|
+
function normalizeAliasReplacement(root, replacement) {
|
|
8
|
+
return replacement.startsWith('/') || /^[A-Za-z]:/.test(replacement) || replacement.startsWith('file:') || replacement.startsWith('\0') ? replacement : resolve(root, replacement);
|
|
9
|
+
}
|
|
10
|
+
function aliasSpecificity(find) {
|
|
11
|
+
return typeof find === 'string' ? find.length : 0;
|
|
12
|
+
}
|
|
13
|
+
function sortAliasEntries(aliases) {
|
|
14
|
+
return [
|
|
15
|
+
...aliases
|
|
16
|
+
].sort((a, b)=>{
|
|
17
|
+
return aliasSpecificity(b.find) - aliasSpecificity(a.find);
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Normalize a user-provided alias map into Vite Alias entries.
|
|
22
|
+
*
|
|
23
|
+
* Accepts either a record of find -> replacement strings or an existing Alias
|
|
24
|
+
* array. Relative replacements are resolved against `root`. Entries are sorted
|
|
25
|
+
* by specificity so longer/more specific aliases match first.
|
|
26
|
+
*/ export function normalizeViteAliases(aliases, root) {
|
|
27
|
+
if (!aliases) return undefined;
|
|
28
|
+
if (Array.isArray(aliases)) {
|
|
29
|
+
return sortAliasEntries(aliases.map((alias)=>typeof alias.replacement === 'string' ? {
|
|
30
|
+
...alias,
|
|
31
|
+
replacement: normalizeAliasReplacement(root, alias.replacement)
|
|
32
|
+
} : alias));
|
|
33
|
+
}
|
|
34
|
+
return sortAliasEntries(Object.entries(aliases).map(([find, replacement])=>({
|
|
35
|
+
find,
|
|
36
|
+
replacement: normalizeAliasReplacement(root, replacement)
|
|
37
|
+
})));
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImZpbGU6Ly8vaG9tZS9ydW5uZXIvd29yay9vcGVuZWxlbWVudC9vcGVuZWxlbWVudC9wYWNrYWdlcy9hZGFwdGVyLXZpdGUvc3JjL2FsaWFzLXV0aWxzLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQG9wZW5lbGVtZW50L2FkYXB0ZXItdml0ZSAtIEFsaWFzIG5vcm1hbGl6YXRpb24gaGVscGVycy5cbiAqXG4gKiBVdGlsaXRpZXMgZm9yIGNvbnZlcnRpbmcgdXNlci1wcm92aWRlZCBhbGlhcyBtYXBwaW5ncyBpbnRvIFZpdGUncyBBbGlhc1tdXG4gKiBzaGFwZSB3aXRoIGFic29sdXRlLCByb290LXJlbGF0aXZlIHJlcGxhY2VtZW50cy5cbiAqL1xuXG5pbXBvcnQgeyByZXNvbHZlIH0gZnJvbSAnbm9kZTpwYXRoJztcbmltcG9ydCB7IHR5cGUgQWxpYXMgfSBmcm9tICd2aXRlJztcblxuZnVuY3Rpb24gbm9ybWFsaXplQWxpYXNSZXBsYWNlbWVudChyb290OiBzdHJpbmcsIHJlcGxhY2VtZW50OiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gcmVwbGFjZW1lbnQuc3RhcnRzV2l0aCgnLycpIHx8IC9eW0EtWmEtel06Ly50ZXN0KHJlcGxhY2VtZW50KSB8fFxuICAgICAgcmVwbGFjZW1lbnQuc3RhcnRzV2l0aCgnZmlsZTonKSB8fCByZXBsYWNlbWVudC5zdGFydHNXaXRoKCdcXDAnKVxuICAgID8gcmVwbGFjZW1lbnRcbiAgICA6IHJlc29sdmUocm9vdCwgcmVwbGFjZW1lbnQpO1xufVxuXG5mdW5jdGlvbiBhbGlhc1NwZWNpZmljaXR5KGZpbmQ6IHVua25vd24pOiBudW1iZXIge1xuICByZXR1cm4gdHlwZW9mIGZpbmQgPT09ICdzdHJpbmcnID8gZmluZC5sZW5ndGggOiAwO1xufVxuXG5mdW5jdGlvbiBzb3J0QWxpYXNFbnRyaWVzPFQgZXh0ZW5kcyBBbGlhcz4oYWxpYXNlczogVFtdKTogVFtdIHtcbiAgcmV0dXJuIFsuLi5hbGlhc2VzXS5zb3J0KChhLCBiKSA9PiB7XG4gICAgcmV0dXJuIGFsaWFzU3BlY2lmaWNpdHkoYi5maW5kKSAtIGFsaWFzU3BlY2lmaWNpdHkoYS5maW5kKTtcbiAgfSk7XG59XG5cbi8qKlxuICogTm9ybWFsaXplIGEgdXNlci1wcm92aWRlZCBhbGlhcyBtYXAgaW50byBWaXRlIEFsaWFzIGVudHJpZXMuXG4gKlxuICogQWNjZXB0cyBlaXRoZXIgYSByZWNvcmQgb2YgZmluZCAtPiByZXBsYWNlbWVudCBzdHJpbmdzIG9yIGFuIGV4aXN0aW5nIEFsaWFzXG4gKiBhcnJheS4gUmVsYXRpdmUgcmVwbGFjZW1lbnRzIGFyZSByZXNvbHZlZCBhZ2FpbnN0IGByb290YC4gRW50cmllcyBhcmUgc29ydGVkXG4gKiBieSBzcGVjaWZpY2l0eSBzbyBsb25nZXIvbW9yZSBzcGVjaWZpYyBhbGlhc2VzIG1hdGNoIGZpcnN0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gbm9ybWFsaXplVml0ZUFsaWFzZXMoXG4gIGFsaWFzZXM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gfCBBbGlhc1tdIHwgbnVsbCB8IHVuZGVmaW5lZCxcbiAgcm9vdDogc3RyaW5nLFxuKTogQWxpYXNbXSB8IHVuZGVmaW5lZCB7XG4gIGlmICghYWxpYXNlcykgcmV0dXJuIHVuZGVmaW5lZDtcbiAgaWYgKEFycmF5LmlzQXJyYXkoYWxpYXNlcykpIHtcbiAgICByZXR1cm4gc29ydEFsaWFzRW50cmllcyhcbiAgICAgIGFsaWFzZXMubWFwKChhbGlhcykgPT5cbiAgICAgICAgdHlwZW9mIGFsaWFzLnJlcGxhY2VtZW50ID09PSAnc3RyaW5nJ1xuICAgICAgICAgID8geyAuLi5hbGlhcywgcmVwbGFjZW1lbnQ6IG5vcm1hbGl6ZUFsaWFzUmVwbGFjZW1lbnQocm9vdCwgYWxpYXMucmVwbGFjZW1lbnQpIH1cbiAgICAgICAgICA6IGFsaWFzXG4gICAgICApLFxuICAgICk7XG4gIH1cbiAgcmV0dXJuIHNvcnRBbGlhc0VudHJpZXMoXG4gICAgT2JqZWN0LmVudHJpZXMoYWxpYXNlcykubWFwKChbZmluZCwgcmVwbGFjZW1lbnRdKSA9PiAoe1xuICAgICAgZmluZCxcbiAgICAgIHJlcGxhY2VtZW50OiBub3JtYWxpemVBbGlhc1JlcGxhY2VtZW50KHJvb3QsIHJlcGxhY2VtZW50KSxcbiAgICB9KSksXG4gICk7XG59XG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7O0NBS0MsR0FFRCxTQUFTLE9BQU8sUUFBUSxZQUFZO0FBR3BDLFNBQVMsMEJBQTBCLElBQVksRUFBRSxXQUFtQjtFQUNsRSxPQUFPLFlBQVksVUFBVSxDQUFDLFFBQVEsYUFBYSxJQUFJLENBQUMsZ0JBQ3BELFlBQVksVUFBVSxDQUFDLFlBQVksWUFBWSxVQUFVLENBQUMsUUFDMUQsY0FDQSxRQUFRLE1BQU07QUFDcEI7QUFFQSxTQUFTLGlCQUFpQixJQUFhO0VBQ3JDLE9BQU8sT0FBTyxTQUFTLFdBQVcsS0FBSyxNQUFNLEdBQUc7QUFDbEQ7QUFFQSxTQUFTLGlCQUFrQyxPQUFZO0VBQ3JELE9BQU87T0FBSTtHQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRztJQUMzQixPQUFPLGlCQUFpQixFQUFFLElBQUksSUFBSSxpQkFBaUIsRUFBRSxJQUFJO0VBQzNEO0FBQ0Y7QUFFQTs7Ozs7O0NBTUMsR0FDRCxPQUFPLFNBQVMscUJBQ2QsT0FBNEQsRUFDNUQsSUFBWTtFQUVaLElBQUksQ0FBQyxTQUFTLE9BQU87RUFDckIsSUFBSSxNQUFNLE9BQU8sQ0FBQyxVQUFVO0lBQzFCLE9BQU8saUJBQ0wsUUFBUSxHQUFHLENBQUMsQ0FBQyxRQUNYLE9BQU8sTUFBTSxXQUFXLEtBQUssV0FDekI7UUFBRSxHQUFHLEtBQUs7UUFBRSxhQUFhLDBCQUEwQixNQUFNLE1BQU0sV0FBVztNQUFFLElBQzVFO0VBR1Y7RUFDQSxPQUFPLGlCQUNMLE9BQU8sT0FBTyxDQUFDLFNBQVMsR0FBRyxDQUFDLENBQUMsQ0FBQyxNQUFNLFlBQVksR0FBSyxDQUFDO01BQ3BEO01BQ0EsYUFBYSwwQkFBMEIsTUFBTTtJQUMvQyxDQUFDO0FBRUwifQ==
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @openelement/adapter-vite - openElement Build Context
|
|
3
|
+
*
|
|
4
|
+
* Shared mutable state for all openElement Vite plugins.
|
|
5
|
+
* Replaces the closure-captured variables (honoEntryCode, scannedIslandTagNames, etc.)
|
|
6
|
+
* with a single object that's explicitly passed around.
|
|
7
|
+
*
|
|
8
|
+
* Also replaces the .openElement/ temp directory as IPC between build phases:
|
|
9
|
+
* - Phase 1 (open:build) writes metadata -> ctx fields
|
|
10
|
+
* - Phase 2 (build-client) reads metadata -> ctx fields
|
|
11
|
+
* - Phase 3 (build-ssg) reads metadata -> ctx fields
|
|
12
|
+
* - Sub-plugins (openContent, openI18n) write their data -> ctx fields
|
|
13
|
+
*
|
|
14
|
+
* ctx is passed via explicit parameter - no globalThis or module-level discovery.
|
|
15
|
+
* use openElement() from @openelement/app/vite for the recommended unified entry.
|
|
16
|
+
*
|
|
17
|
+
* Fields are grouped by Phase to improve type safety and maintainability.
|
|
18
|
+
*/ import type { Alias, ResolvedConfig } from 'vite';
|
|
19
|
+
import type { CompatibilityClassification, FrameworkOptions, HydrationStrategy, OpenElementBlogOptions, OpenElementHeaderNavLink, OpenElementI18nContextOptions, OpenElementNavSection, RouteEntry } from '@openelement/protocol/framework';
|
|
20
|
+
import type { OpenElementPackageManifest } from '@openelement/protocol/manifest';
|
|
21
|
+
import type { IslandDecl, SsrAdmissionPlan } from '@openelement/protocol/ssg';
|
|
22
|
+
export type Phase1Token = {
|
|
23
|
+
readonly __phase1: unique symbol;
|
|
24
|
+
};
|
|
25
|
+
export type Phase2Token = {
|
|
26
|
+
readonly __phase2: unique symbol;
|
|
27
|
+
};
|
|
28
|
+
export type Phase3Token = {
|
|
29
|
+
readonly __phase3: unique symbol;
|
|
30
|
+
};
|
|
31
|
+
export declare class Phase1Meta {
|
|
32
|
+
/** The generated Hono entry module code (virtual module content) */ honoEntryCode: string;
|
|
33
|
+
/** Cached routes from buildStart() for virtual entry regeneration */ cachedRoutes: RouteEntry[];
|
|
34
|
+
/** Island tag names discovered during route scanning (local islands) */ islandTagNames: string[];
|
|
35
|
+
/** Relative file paths for local islands */ islandFiles: string[];
|
|
36
|
+
/** Local island metadata indexed by tag name. */ islandMeta: Record<string, Partial<IslandDecl>>;
|
|
37
|
+
/** Package manifests discovered from npm/JSR packages */ packageManifests: OpenElementPackageManifest[];
|
|
38
|
+
/** Package island declarations extracted from manifests */ packageIslandDecls: IslandDecl[];
|
|
39
|
+
/** SSR admission plan produced before SSR entry generation. */ ssrAdmissionPlan: SsrAdmissionPlan | null;
|
|
40
|
+
/** v0.18.0: CEM-derived compatibility classifications from the classifier. */ cemClassifications: CompatibilityClassification[];
|
|
41
|
+
/** Whether the SSR+client build has completed */ buildCompleted: boolean;
|
|
42
|
+
/** Vite resolved config (set in configResolved hook) */ resolvedConfig: ResolvedConfig | null;
|
|
43
|
+
/** User-provided resolve.alias in its original format */ userResolveAlias: Record<string, string> | Alias[] | null;
|
|
44
|
+
}
|
|
45
|
+
export declare class Phase2Meta {
|
|
46
|
+
/** Generated client island entry code */ clientEntryCode: string;
|
|
47
|
+
}
|
|
48
|
+
export declare class Phase3Meta {
|
|
49
|
+
/** Generated SSG entry code (for viteBuild SSR input) */ ssgEntryCode: string;
|
|
50
|
+
/** Project root directory */ root: string;
|
|
51
|
+
/** Output directory (default: 'dist') */ outDir: string;
|
|
52
|
+
/** Base URL path (default: '/') */ base: string;
|
|
53
|
+
/** Middleware config from createOpenPlugin() options */ middleware: FrameworkOptions['middleware'] | null;
|
|
54
|
+
/** HTML document options from createOpenPlugin() options */ html: {
|
|
55
|
+
lang?: string;
|
|
56
|
+
title?: string;
|
|
57
|
+
} | null;
|
|
58
|
+
/** Island hydration strategy (default: 'idle') */ upgradeStrategy: HydrationStrategy;
|
|
59
|
+
/** View Transitions enabled (default: true) */ viewTransition: boolean;
|
|
60
|
+
/** Speculation Rules config from createOpenPlugin() options */ speculation: FrameworkOptions['speculation'] | null;
|
|
61
|
+
/** Extra HTML to inject into <head> */ headExtras: string;
|
|
62
|
+
/** Whether headExtras scripts were produced by structured injection APIs. */ allowHeadExtrasScripts: boolean;
|
|
63
|
+
/** Application shell rendered around routes. */ appShell: FrameworkOptions['appShell'];
|
|
64
|
+
/** Named route layouts selected by route meta. */ layouts: FrameworkOptions['layouts'];
|
|
65
|
+
/** SSR noExternal patterns (serialized) */ ssrNoExternal: (string | {
|
|
66
|
+
__type: 'RegExp';
|
|
67
|
+
source: string;
|
|
68
|
+
flags: string;
|
|
69
|
+
})[];
|
|
70
|
+
/** SSR deps to keep as external (resolved by Deno import() at runtime per ADR-0043) */ ssrExternal: string[];
|
|
71
|
+
/** Routes directory */ routesDir: string;
|
|
72
|
+
/** Islands directory */ islandsDir: string;
|
|
73
|
+
/** Components directory */ componentsDir: string;
|
|
74
|
+
/** ADR-0047: Pre-resolved external dependency manifest (auto-generated from deno info). */ externalManifest?: import('@openelement/protocol/ssg').ExternalManifest;
|
|
75
|
+
/** Skip Deno pre-resolution, use regex fallback. */ skipPreResolution?: boolean;
|
|
76
|
+
}
|
|
77
|
+
export declare class OpenElementBuildContext {
|
|
78
|
+
/** Phase completion tokens - used for compile-time ordering enforcement */ readonly _phaseTokens: {
|
|
79
|
+
1: Phase1Token | null;
|
|
80
|
+
2: Phase2Token | null;
|
|
81
|
+
3: Phase3Token | null;
|
|
82
|
+
};
|
|
83
|
+
/** Mark Phase 1 as complete and return the token for subsequent phases */ completePhase1(): Phase1Token;
|
|
84
|
+
/** Mark Phase 2 as complete (after Phase 1 or Phase 3) */ completePhase2(token: Phase1Token | Phase3Token): Phase2Token;
|
|
85
|
+
/** Mark Phase 3 as complete (only requires Phase 1, not Phase 2) */ completePhase3(token: Phase1Token): Phase3Token;
|
|
86
|
+
/** Populate Phase 3 invariants from resolved Vite config and framework options. */ populatePhase3(options: FrameworkOptions & {
|
|
87
|
+
allowHeadExtrasScripts?: boolean;
|
|
88
|
+
}, config: ResolvedConfig, ssrNoExternal: (string | {
|
|
89
|
+
__type: 'RegExp';
|
|
90
|
+
source: string;
|
|
91
|
+
flags: string;
|
|
92
|
+
})[]): void;
|
|
93
|
+
/** Return a read-only view of Phase 3 metadata. */ getPhase3Meta(): Readonly<Phase3Meta>;
|
|
94
|
+
/** Check whether a phase has been completed. */ isPhaseComplete(phase: 1 | 2 | 3): boolean;
|
|
95
|
+
/** Run Phase 3 after Phase 1, enforcing ordering and logging. */ runPhase3(runner: (ctx: this) => Promise<void>): Promise<void>;
|
|
96
|
+
/** Run Phase 2 after Phase 3, enforcing ordering and logging. */ runPhase2(runner: (ctx: this) => Promise<void>): Promise<void>;
|
|
97
|
+
/** Phase 1: Route scanning & build metadata */ readonly phase1: Phase1Meta;
|
|
98
|
+
/** Phase 2: Client island build state */ readonly phase2: Phase2Meta;
|
|
99
|
+
/** Phase 3: SSG rendering state */ readonly phase3: Phase3Meta;
|
|
100
|
+
/** Plugin data from content/i18n sub-plugins */ readonly plugins: {
|
|
101
|
+
blogOptions: OpenElementBlogOptions | null;
|
|
102
|
+
navSections: OpenElementNavSection[];
|
|
103
|
+
headerNav: OpenElementHeaderNavLink[];
|
|
104
|
+
sitemapOptions: Record<string, unknown> | null;
|
|
105
|
+
i18nOptions: OpenElementI18nContextOptions | null;
|
|
106
|
+
[key: string]: unknown;
|
|
107
|
+
};
|
|
108
|
+
/** Resolved framework options with defaults applied (read-only after construction) */ readonly options: FrameworkOptions;
|
|
109
|
+
constructor(options: FrameworkOptions);
|
|
110
|
+
/** Reset all mutable state (for watch mode / testing) */ reset(): void;
|
|
111
|
+
}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @openelement/adapter-vite - openElement Build Context
|
|
3
|
+
*
|
|
4
|
+
* Shared mutable state for all openElement Vite plugins.
|
|
5
|
+
* Replaces the closure-captured variables (honoEntryCode, scannedIslandTagNames, etc.)
|
|
6
|
+
* with a single object that's explicitly passed around.
|
|
7
|
+
*
|
|
8
|
+
* Also replaces the .openElement/ temp directory as IPC between build phases:
|
|
9
|
+
* - Phase 1 (open:build) writes metadata -> ctx fields
|
|
10
|
+
* - Phase 2 (build-client) reads metadata -> ctx fields
|
|
11
|
+
* - Phase 3 (build-ssg) reads metadata -> ctx fields
|
|
12
|
+
* - Sub-plugins (openContent, openI18n) write their data -> ctx fields
|
|
13
|
+
*
|
|
14
|
+
* ctx is passed via explicit parameter - no globalThis or module-level discovery.
|
|
15
|
+
* use openElement() from @openelement/app/vite for the recommended unified entry.
|
|
16
|
+
*
|
|
17
|
+
* Fields are grouped by Phase to improve type safety and maintainability.
|
|
18
|
+
*/ import { createLogger } from '@openelement/core/logger';
|
|
19
|
+
const log = createLogger('core');
|
|
20
|
+
export class Phase1Meta {
|
|
21
|
+
/** The generated Hono entry module code (virtual module content) */ honoEntryCode = '';
|
|
22
|
+
/** Cached routes from buildStart() for virtual entry regeneration */ cachedRoutes = [];
|
|
23
|
+
/** Island tag names discovered during route scanning (local islands) */ islandTagNames = [];
|
|
24
|
+
/** Relative file paths for local islands */ islandFiles = [];
|
|
25
|
+
/** Local island metadata indexed by tag name. */ islandMeta = {};
|
|
26
|
+
/** Package manifests discovered from npm/JSR packages */ packageManifests = [];
|
|
27
|
+
/** Package island declarations extracted from manifests */ packageIslandDecls = [];
|
|
28
|
+
/** SSR admission plan produced before SSR entry generation. */ ssrAdmissionPlan = null;
|
|
29
|
+
/** v0.18.0: CEM-derived compatibility classifications from the classifier. */ cemClassifications = [];
|
|
30
|
+
/** Whether the SSR+client build has completed */ buildCompleted = false;
|
|
31
|
+
/** Vite resolved config (set in configResolved hook) */ resolvedConfig = null;
|
|
32
|
+
/** User-provided resolve.alias in its original format */ userResolveAlias = null;
|
|
33
|
+
}
|
|
34
|
+
export class Phase2Meta {
|
|
35
|
+
/** Generated client island entry code */ clientEntryCode = '';
|
|
36
|
+
}
|
|
37
|
+
export class Phase3Meta {
|
|
38
|
+
/** Generated SSG entry code (for viteBuild SSR input) */ ssgEntryCode = '';
|
|
39
|
+
/** Project root directory */ root = '';
|
|
40
|
+
/** Output directory (default: 'dist') */ outDir = 'dist';
|
|
41
|
+
/** Base URL path (default: '/') */ base = '/';
|
|
42
|
+
/** Middleware config from createOpenPlugin() options */ middleware = null;
|
|
43
|
+
/** HTML document options from createOpenPlugin() options */ html = null;
|
|
44
|
+
/** Island hydration strategy (default: 'idle') */ upgradeStrategy = 'idle';
|
|
45
|
+
/** View Transitions enabled (default: true) */ viewTransition = true;
|
|
46
|
+
/** Speculation Rules config from createOpenPlugin() options */ speculation = null;
|
|
47
|
+
/** Extra HTML to inject into <head> */ headExtras = '';
|
|
48
|
+
/** Whether headExtras scripts were produced by structured injection APIs. */ allowHeadExtrasScripts = false;
|
|
49
|
+
/** Application shell rendered around routes. */ appShell = undefined;
|
|
50
|
+
/** Named route layouts selected by route meta. */ layouts = undefined;
|
|
51
|
+
/** SSR noExternal patterns (serialized) */ ssrNoExternal = [];
|
|
52
|
+
/** SSR deps to keep as external (resolved by Deno import() at runtime per ADR-0043) */ ssrExternal = [];
|
|
53
|
+
/** Routes directory */ routesDir = 'app/routes';
|
|
54
|
+
/** Islands directory */ islandsDir = 'app/islands';
|
|
55
|
+
/** Components directory */ componentsDir = 'app/components';
|
|
56
|
+
/** ADR-0047: Pre-resolved external dependency manifest (auto-generated from deno info). */ externalManifest;
|
|
57
|
+
/** Skip Deno pre-resolution, use regex fallback. */ skipPreResolution;
|
|
58
|
+
}
|
|
59
|
+
export class OpenElementBuildContext {
|
|
60
|
+
/** Phase completion tokens - used for compile-time ordering enforcement */ _phaseTokens = {
|
|
61
|
+
1: null,
|
|
62
|
+
2: null,
|
|
63
|
+
3: null
|
|
64
|
+
};
|
|
65
|
+
/** Mark Phase 1 as complete and return the token for subsequent phases */ completePhase1() {
|
|
66
|
+
const token = {
|
|
67
|
+
__phase1: Symbol()
|
|
68
|
+
};
|
|
69
|
+
this._phaseTokens[1] = token;
|
|
70
|
+
return token;
|
|
71
|
+
}
|
|
72
|
+
/** Mark Phase 2 as complete (after Phase 1 or Phase 3) */ completePhase2(token) {
|
|
73
|
+
if (this._phaseTokens[1] !== token && this._phaseTokens[3] !== token) {
|
|
74
|
+
throw new Error('Phase 2 called before Phase 1 completed');
|
|
75
|
+
}
|
|
76
|
+
const t2 = {
|
|
77
|
+
__phase2: Symbol()
|
|
78
|
+
};
|
|
79
|
+
this._phaseTokens[2] = t2;
|
|
80
|
+
return t2;
|
|
81
|
+
}
|
|
82
|
+
/** Mark Phase 3 as complete (only requires Phase 1, not Phase 2) */ completePhase3(token) {
|
|
83
|
+
if (this._phaseTokens[1] !== token) {
|
|
84
|
+
throw new Error('Phase 3 called before Phase 1 completed');
|
|
85
|
+
}
|
|
86
|
+
const t3 = {
|
|
87
|
+
__phase3: Symbol()
|
|
88
|
+
};
|
|
89
|
+
this._phaseTokens[3] = t3;
|
|
90
|
+
return t3;
|
|
91
|
+
}
|
|
92
|
+
/** Populate Phase 3 invariants from resolved Vite config and framework options. */ populatePhase3(options, config, ssrNoExternal) {
|
|
93
|
+
let base = config.base || '/';
|
|
94
|
+
if (!base.endsWith('/')) base += '/';
|
|
95
|
+
this.phase3.root = config.root;
|
|
96
|
+
this.phase3.outDir = options.build?.outDir || 'dist';
|
|
97
|
+
this.phase3.base = base;
|
|
98
|
+
this.phase3.ssrNoExternal = ssrNoExternal;
|
|
99
|
+
this.phase3.routesDir = options.routesDir || 'app/routes';
|
|
100
|
+
this.phase3.islandsDir = options.islandsDir || 'app/islands';
|
|
101
|
+
this.phase3.componentsDir = options.componentsDir || 'app/components';
|
|
102
|
+
this.phase3.middleware = options.middleware || null;
|
|
103
|
+
this.phase3.html = options.html || null;
|
|
104
|
+
this.phase3.upgradeStrategy = options.island?.upgradeStrategy || 'idle';
|
|
105
|
+
this.phase3.viewTransition = options.viewTransition ?? true;
|
|
106
|
+
this.phase3.speculation = options.speculation ?? null;
|
|
107
|
+
this.phase3.headExtras = options.headExtras || '';
|
|
108
|
+
this.phase3.allowHeadExtrasScripts = options.allowHeadExtrasScripts || false;
|
|
109
|
+
this.phase3.appShell = options.appShell;
|
|
110
|
+
this.phase3.layouts = options.layouts;
|
|
111
|
+
}
|
|
112
|
+
/** Return a read-only view of Phase 3 metadata. */ getPhase3Meta() {
|
|
113
|
+
return this.phase3;
|
|
114
|
+
}
|
|
115
|
+
/** Check whether a phase has been completed. */ isPhaseComplete(phase) {
|
|
116
|
+
return this._phaseTokens[phase] !== null;
|
|
117
|
+
}
|
|
118
|
+
/** Run Phase 3 after Phase 1, enforcing ordering and logging. */ async runPhase3(runner) {
|
|
119
|
+
const phase1Token = this._phaseTokens[1];
|
|
120
|
+
if (!phase1Token) {
|
|
121
|
+
throw new Error('Phase 3 called before Phase 1 completed');
|
|
122
|
+
}
|
|
123
|
+
this.completePhase3(phase1Token);
|
|
124
|
+
log.info('[3/3] Static site generation...');
|
|
125
|
+
try {
|
|
126
|
+
await runner(this);
|
|
127
|
+
log.info('[3/3] Static site generation - complete');
|
|
128
|
+
} catch (error) {
|
|
129
|
+
log.error(`[3/3] Static site generation - FAILED: ${error}`);
|
|
130
|
+
throw error;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/** Run Phase 2 after Phase 3, enforcing ordering and logging. */ async runPhase2(runner) {
|
|
134
|
+
const phase3Token = this._phaseTokens[3];
|
|
135
|
+
if (!phase3Token) {
|
|
136
|
+
throw new Error('Phase 2 called before Phase 3 completed');
|
|
137
|
+
}
|
|
138
|
+
this.completePhase2(phase3Token);
|
|
139
|
+
log.info('[2/3] Client island build...');
|
|
140
|
+
try {
|
|
141
|
+
await runner(this);
|
|
142
|
+
log.info('[2/3] Client island build - complete');
|
|
143
|
+
} catch (error) {
|
|
144
|
+
log.error(`[2/3] Client island build - FAILED: ${error}`);
|
|
145
|
+
throw error;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
/** Phase 1: Route scanning & build metadata */ phase1 = new Phase1Meta();
|
|
149
|
+
/** Phase 2: Client island build state */ phase2 = new Phase2Meta();
|
|
150
|
+
/** Phase 3: SSG rendering state */ phase3 = new Phase3Meta();
|
|
151
|
+
/** Plugin data from content/i18n sub-plugins */ plugins = {
|
|
152
|
+
blogOptions: null,
|
|
153
|
+
navSections: [],
|
|
154
|
+
headerNav: [],
|
|
155
|
+
sitemapOptions: null,
|
|
156
|
+
i18nOptions: null
|
|
157
|
+
};
|
|
158
|
+
/** Resolved framework options with defaults applied (read-only after construction) */ options;
|
|
159
|
+
constructor(options){
|
|
160
|
+
this.options = options;
|
|
161
|
+
}
|
|
162
|
+
/** Reset all mutable state (for watch mode / testing) */ reset() {
|
|
163
|
+
this._phaseTokens[1] = null;
|
|
164
|
+
this._phaseTokens[2] = null;
|
|
165
|
+
this._phaseTokens[3] = null;
|
|
166
|
+
const userResolveAlias = this.phase1.userResolveAlias;
|
|
167
|
+
// NOTE: userResolveAlias is NOT reset - it's user configuration, not
|
|
168
|
+
// build state. It's set in config()/configResolved() and must persist
|
|
169
|
+
// through buildStart() for Phase 2 and 3 to use.
|
|
170
|
+
Object.assign(this.phase1, new Phase1Meta(), {
|
|
171
|
+
userResolveAlias
|
|
172
|
+
});
|
|
173
|
+
Object.assign(this.phase2, new Phase2Meta());
|
|
174
|
+
Object.assign(this.phase3, new Phase3Meta());
|
|
175
|
+
Object.assign(this.plugins, {
|
|
176
|
+
blogOptions: null,
|
|
177
|
+
navSections: [],
|
|
178
|
+
headerNav: [],
|
|
179
|
+
sitemapOptions: null,
|
|
180
|
+
i18nOptions: null
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImZpbGU6Ly8vaG9tZS9ydW5uZXIvd29yay9vcGVuZWxlbWVudC9vcGVuZWxlbWVudC9wYWNrYWdlcy9hZGFwdGVyLXZpdGUvc3JjL2J1aWxkLWNvbnRleHQudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAb3BlbmVsZW1lbnQvYWRhcHRlci12aXRlIC0gb3BlbkVsZW1lbnQgQnVpbGQgQ29udGV4dFxuICpcbiAqIFNoYXJlZCBtdXRhYmxlIHN0YXRlIGZvciBhbGwgb3BlbkVsZW1lbnQgVml0ZSBwbHVnaW5zLlxuICogUmVwbGFjZXMgdGhlIGNsb3N1cmUtY2FwdHVyZWQgdmFyaWFibGVzIChob25vRW50cnlDb2RlLCBzY2FubmVkSXNsYW5kVGFnTmFtZXMsIGV0Yy4pXG4gKiB3aXRoIGEgc2luZ2xlIG9iamVjdCB0aGF0J3MgZXhwbGljaXRseSBwYXNzZWQgYXJvdW5kLlxuICpcbiAqIEFsc28gcmVwbGFjZXMgdGhlIC5vcGVuRWxlbWVudC8gdGVtcCBkaXJlY3RvcnkgYXMgSVBDIGJldHdlZW4gYnVpbGQgcGhhc2VzOlxuICogLSBQaGFzZSAxIChvcGVuOmJ1aWxkKSB3cml0ZXMgbWV0YWRhdGEgLT4gY3R4IGZpZWxkc1xuICogLSBQaGFzZSAyIChidWlsZC1jbGllbnQpIHJlYWRzIG1ldGFkYXRhIC0+IGN0eCBmaWVsZHNcbiAqIC0gUGhhc2UgMyAoYnVpbGQtc3NnKSByZWFkcyBtZXRhZGF0YSAtPiBjdHggZmllbGRzXG4gKiAtIFN1Yi1wbHVnaW5zIChvcGVuQ29udGVudCwgb3BlbkkxOG4pIHdyaXRlIHRoZWlyIGRhdGEgLT4gY3R4IGZpZWxkc1xuICpcbiAqIGN0eCBpcyBwYXNzZWQgdmlhIGV4cGxpY2l0IHBhcmFtZXRlciAtIG5vIGdsb2JhbFRoaXMgb3IgbW9kdWxlLWxldmVsIGRpc2NvdmVyeS5cbiAqIHVzZSBvcGVuRWxlbWVudCgpIGZyb20gQG9wZW5lbGVtZW50L2FwcC92aXRlIGZvciB0aGUgcmVjb21tZW5kZWQgdW5pZmllZCBlbnRyeS5cbiAqXG4gKiBGaWVsZHMgYXJlIGdyb3VwZWQgYnkgUGhhc2UgdG8gaW1wcm92ZSB0eXBlIHNhZmV0eSBhbmQgbWFpbnRhaW5hYmlsaXR5LlxuICovXG5cbmltcG9ydCB0eXBlIHsgQWxpYXMsIFJlc29sdmVkQ29uZmlnIH0gZnJvbSAndml0ZSc7XG5pbXBvcnQgdHlwZSB7XG4gIENvbXBhdGliaWxpdHlDbGFzc2lmaWNhdGlvbixcbiAgRnJhbWV3b3JrT3B0aW9ucyxcbiAgSHlkcmF0aW9uU3RyYXRlZ3ksXG4gIE9wZW5FbGVtZW50QmxvZ09wdGlvbnMsXG4gIE9wZW5FbGVtZW50SGVhZGVyTmF2TGluayxcbiAgT3BlbkVsZW1lbnRJMThuQ29udGV4dE9wdGlvbnMsXG4gIE9wZW5FbGVtZW50TmF2U2VjdGlvbixcbiAgUm91dGVFbnRyeSxcbn0gZnJvbSAnQG9wZW5lbGVtZW50L3Byb3RvY29sL2ZyYW1ld29yayc7XG5pbXBvcnQgdHlwZSB7IE9wZW5FbGVtZW50UGFja2FnZU1hbmlmZXN0IH0gZnJvbSAnQG9wZW5lbGVtZW50L3Byb3RvY29sL21hbmlmZXN0JztcbmltcG9ydCB0eXBlIHsgSXNsYW5kRGVjbCwgU3NyQWRtaXNzaW9uUGxhbiB9IGZyb20gJ0BvcGVuZWxlbWVudC9wcm90b2NvbC9zc2cnO1xuaW1wb3J0IHsgY3JlYXRlTG9nZ2VyIH0gZnJvbSAnQG9wZW5lbGVtZW50L2NvcmUvbG9nZ2VyJztcblxuY29uc3QgbG9nID0gY3JlYXRlTG9nZ2VyKCdjb3JlJyk7XG5cbi8vIFRoZXNlIGJyYW5kZWQgdHlwZXMgZW5zdXJlIFBoYXNlIDIgY2FuIG9ubHkgcnVuIGFmdGVyIFBoYXNlIDEsXG4vLyBhbmQgUGhhc2UgMyBjYW4gb25seSBydW4gYWZ0ZXIgUGhhc2UgMi4gVGhlIGNvbXBpbGVyIGNhdGNoZXNcbi8vIG91dC1vZi1vcmRlciBwaGFzZSBjYWxscyBhdCBidWlsZCB0aW1lLlxuZXhwb3J0IHR5cGUgUGhhc2UxVG9rZW4gPSB7IHJlYWRvbmx5IF9fcGhhc2UxOiB1bmlxdWUgc3ltYm9sIH07XG5leHBvcnQgdHlwZSBQaGFzZTJUb2tlbiA9IHsgcmVhZG9ubHkgX19waGFzZTI6IHVuaXF1ZSBzeW1ib2wgfTtcbmV4cG9ydCB0eXBlIFBoYXNlM1Rva2VuID0geyByZWFkb25seSBfX3BoYXNlMzogdW5pcXVlIHN5bWJvbCB9O1xuXG5leHBvcnQgY2xhc3MgUGhhc2UxTWV0YSB7XG4gIC8qKiBUaGUgZ2VuZXJhdGVkIEhvbm8gZW50cnkgbW9kdWxlIGNvZGUgKHZpcnR1YWwgbW9kdWxlIGNvbnRlbnQpICovXG4gIGhvbm9FbnRyeUNvZGU6IHN0cmluZyA9ICcnO1xuXG4gIC8qKiBDYWNoZWQgcm91dGVzIGZyb20gYnVpbGRTdGFydCgpIGZvciB2aXJ0dWFsIGVudHJ5IHJlZ2VuZXJhdGlvbiAqL1xuICBjYWNoZWRSb3V0ZXM6IFJvdXRlRW50cnlbXSA9IFtdO1xuXG4gIC8qKiBJc2xhbmQgdGFnIG5hbWVzIGRpc2NvdmVyZWQgZHVyaW5nIHJvdXRlIHNjYW5uaW5nIChsb2NhbCBpc2xhbmRzKSAqL1xuICBpc2xhbmRUYWdOYW1lczogc3RyaW5nW10gPSBbXTtcblxuICAvKiogUmVsYXRpdmUgZmlsZSBwYXRocyBmb3IgbG9jYWwgaXNsYW5kcyAqL1xuICBpc2xhbmRGaWxlczogc3RyaW5nW10gPSBbXTtcblxuICAvKiogTG9jYWwgaXNsYW5kIG1ldGFkYXRhIGluZGV4ZWQgYnkgdGFnIG5hbWUuICovXG4gIGlzbGFuZE1ldGE6IFJlY29yZDxzdHJpbmcsIFBhcnRpYWw8SXNsYW5kRGVjbD4+ID0ge307XG5cbiAgLyoqIFBhY2thZ2UgbWFuaWZlc3RzIGRpc2NvdmVyZWQgZnJvbSBucG0vSlNSIHBhY2thZ2VzICovXG4gIHBhY2thZ2VNYW5pZmVzdHM6IE9wZW5FbGVtZW50UGFja2FnZU1hbmlmZXN0W10gPSBbXTtcblxuICAvKiogUGFja2FnZSBpc2xhbmQgZGVjbGFyYXRpb25zIGV4dHJhY3RlZCBmcm9tIG1hbmlmZXN0cyAqL1xuICBwYWNrYWdlSXNsYW5kRGVjbHM6IElzbGFuZERlY2xbXSA9IFtdO1xuXG4gIC8qKiBTU1IgYWRtaXNzaW9uIHBsYW4gcHJvZHVjZWQgYmVmb3JlIFNTUiBlbnRyeSBnZW5lcmF0aW9uLiAqL1xuICBzc3JBZG1pc3Npb25QbGFuOiBTc3JBZG1pc3Npb25QbGFuIHwgbnVsbCA9IG51bGw7XG5cbiAgLyoqIHYwLjE4LjA6IENFTS1kZXJpdmVkIGNvbXBhdGliaWxpdHkgY2xhc3NpZmljYXRpb25zIGZyb20gdGhlIGNsYXNzaWZpZXIuICovXG4gIGNlbUNsYXNzaWZpY2F0aW9uczogQ29tcGF0aWJpbGl0eUNsYXNzaWZpY2F0aW9uW10gPSBbXTtcblxuICAvKiogV2hldGhlciB0aGUgU1NSK2NsaWVudCBidWlsZCBoYXMgY29tcGxldGVkICovXG4gIGJ1aWxkQ29tcGxldGVkOiBib29sZWFuID0gZmFsc2U7XG5cbiAgLyoqIFZpdGUgcmVzb2x2ZWQgY29uZmlnIChzZXQgaW4gY29uZmlnUmVzb2x2ZWQgaG9vaykgKi9cbiAgcmVzb2x2ZWRDb25maWc6IFJlc29sdmVkQ29uZmlnIHwgbnVsbCA9IG51bGw7XG5cbiAgLyoqIFVzZXItcHJvdmlkZWQgcmVzb2x2ZS5hbGlhcyBpbiBpdHMgb3JpZ2luYWwgZm9ybWF0ICovXG4gIHVzZXJSZXNvbHZlQWxpYXM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gfCBBbGlhc1tdIHwgbnVsbCA9IG51bGw7XG59XG5cbmV4cG9ydCBjbGFzcyBQaGFzZTJNZXRhIHtcbiAgLyoqIEdlbmVyYXRlZCBjbGllbnQgaXNsYW5kIGVudHJ5IGNvZGUgKi9cbiAgY2xpZW50RW50cnlDb2RlOiBzdHJpbmcgPSAnJztcbn1cblxuZXhwb3J0IGNsYXNzIFBoYXNlM01ldGEge1xuICAvKiogR2VuZXJhdGVkIFNTRyBlbnRyeSBjb2RlIChmb3Igdml0ZUJ1aWxkIFNTUiBpbnB1dCkgKi9cbiAgc3NnRW50cnlDb2RlOiBzdHJpbmcgPSAnJztcblxuICAvKiogUHJvamVjdCByb290IGRpcmVjdG9yeSAqL1xuICByb290OiBzdHJpbmcgPSAnJztcblxuICAvKiogT3V0cHV0IGRpcmVjdG9yeSAoZGVmYXVsdDogJ2Rpc3QnKSAqL1xuICBvdXREaXI6IHN0cmluZyA9ICdkaXN0JztcblxuICAvKiogQmFzZSBVUkwgcGF0aCAoZGVmYXVsdDogJy8nKSAqL1xuICBiYXNlOiBzdHJpbmcgPSAnLyc7XG5cbiAgLyoqIE1pZGRsZXdhcmUgY29uZmlnIGZyb20gY3JlYXRlT3BlblBsdWdpbigpIG9wdGlvbnMgKi9cbiAgbWlkZGxld2FyZTogRnJhbWV3b3JrT3B0aW9uc1snbWlkZGxld2FyZSddIHwgbnVsbCA9IG51bGw7XG5cbiAgLyoqIEhUTUwgZG9jdW1lbnQgb3B0aW9ucyBmcm9tIGNyZWF0ZU9wZW5QbHVnaW4oKSBvcHRpb25zICovXG4gIGh0bWw6IHsgbGFuZz86IHN0cmluZzsgdGl0bGU/OiBzdHJpbmcgfSB8IG51bGwgPSBudWxsO1xuXG4gIC8qKiBJc2xhbmQgaHlkcmF0aW9uIHN0cmF0ZWd5IChkZWZhdWx0OiAnaWRsZScpICovXG4gIHVwZ3JhZGVTdHJhdGVneTogSHlkcmF0aW9uU3RyYXRlZ3kgPSAnaWRsZSc7XG5cbiAgLyoqIFZpZXcgVHJhbnNpdGlvbnMgZW5hYmxlZCAoZGVmYXVsdDogdHJ1ZSkgKi9cbiAgdmlld1RyYW5zaXRpb246IGJvb2xlYW4gPSB0cnVlO1xuXG4gIC8qKiBTcGVjdWxhdGlvbiBSdWxlcyBjb25maWcgZnJvbSBjcmVhdGVPcGVuUGx1Z2luKCkgb3B0aW9ucyAqL1xuICBzcGVjdWxhdGlvbjogRnJhbWV3b3JrT3B0aW9uc1snc3BlY3VsYXRpb24nXSB8IG51bGwgPSBudWxsO1xuXG4gIC8qKiBFeHRyYSBIVE1MIHRvIGluamVjdCBpbnRvIDxoZWFkPiAqL1xuICBoZWFkRXh0cmFzOiBzdHJpbmcgPSAnJztcblxuICAvKiogV2hldGhlciBoZWFkRXh0cmFzIHNjcmlwdHMgd2VyZSBwcm9kdWNlZCBieSBzdHJ1Y3R1cmVkIGluamVjdGlvbiBBUElzLiAqL1xuICBhbGxvd0hlYWRFeHRyYXNTY3JpcHRzOiBib29sZWFuID0gZmFsc2U7XG5cbiAgLyoqIEFwcGxpY2F0aW9uIHNoZWxsIHJlbmRlcmVkIGFyb3VuZCByb3V0ZXMuICovXG4gIGFwcFNoZWxsOiBGcmFtZXdvcmtPcHRpb25zWydhcHBTaGVsbCddID0gdW5kZWZpbmVkO1xuXG4gIC8qKiBOYW1lZCByb3V0ZSBsYXlvdXRzIHNlbGVjdGVkIGJ5IHJvdXRlIG1ldGEuICovXG4gIGxheW91dHM6IEZyYW1ld29ya09wdGlvbnNbJ2xheW91dHMnXSA9IHVuZGVmaW5lZDtcblxuICAvKiogU1NSIG5vRXh0ZXJuYWwgcGF0dGVybnMgKHNlcmlhbGl6ZWQpICovXG4gIHNzck5vRXh0ZXJuYWw6IChzdHJpbmcgfCB7IF9fdHlwZTogJ1JlZ0V4cCc7IHNvdXJjZTogc3RyaW5nOyBmbGFnczogc3RyaW5nIH0pW10gPSBbXTtcblxuICAvKiogU1NSIGRlcHMgdG8ga2VlcCBhcyBleHRlcm5hbCAocmVzb2x2ZWQgYnkgRGVubyBpbXBvcnQoKSBhdCBydW50aW1lIHBlciBBRFItMDA0MykgKi9cbiAgc3NyRXh0ZXJuYWw6IHN0cmluZ1tdID0gW107XG5cbiAgLyoqIFJvdXRlcyBkaXJlY3RvcnkgKi9cbiAgcm91dGVzRGlyOiBzdHJpbmcgPSAnYXBwL3JvdXRlcyc7XG5cbiAgLyoqIElzbGFuZHMgZGlyZWN0b3J5ICovXG4gIGlzbGFuZHNEaXI6IHN0cmluZyA9ICdhcHAvaXNsYW5kcyc7XG5cbiAgLyoqIENvbXBvbmVudHMgZGlyZWN0b3J5ICovXG4gIGNvbXBvbmVudHNEaXI6IHN0cmluZyA9ICdhcHAvY29tcG9uZW50cyc7XG5cbiAgLyoqIEFEUi0wMDQ3OiBQcmUtcmVzb2x2ZWQgZXh0ZXJuYWwgZGVwZW5kZW5jeSBtYW5pZmVzdCAoYXV0by1nZW5lcmF0ZWQgZnJvbSBkZW5vIGluZm8pLiAqL1xuICBleHRlcm5hbE1hbmlmZXN0PzogaW1wb3J0KCdAb3BlbmVsZW1lbnQvcHJvdG9jb2wvc3NnJykuRXh0ZXJuYWxNYW5pZmVzdDtcblxuICAvKiogU2tpcCBEZW5vIHByZS1yZXNvbHV0aW9uLCB1c2UgcmVnZXggZmFsbGJhY2suICovXG4gIHNraXBQcmVSZXNvbHV0aW9uPzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGNsYXNzIE9wZW5FbGVtZW50QnVpbGRDb250ZXh0IHtcbiAgLyoqIFBoYXNlIGNvbXBsZXRpb24gdG9rZW5zIC0gdXNlZCBmb3IgY29tcGlsZS10aW1lIG9yZGVyaW5nIGVuZm9yY2VtZW50ICovXG4gIHJlYWRvbmx5IF9waGFzZVRva2Vuczoge1xuICAgIDE6IFBoYXNlMVRva2VuIHwgbnVsbDtcbiAgICAyOiBQaGFzZTJUb2tlbiB8IG51bGw7XG4gICAgMzogUGhhc2UzVG9rZW4gfCBudWxsO1xuICB9ID0geyAxOiBudWxsLCAyOiBudWxsLCAzOiBudWxsIH07XG5cbiAgLyoqIE1hcmsgUGhhc2UgMSBhcyBjb21wbGV0ZSBhbmQgcmV0dXJuIHRoZSB0b2tlbiBmb3Igc3Vic2VxdWVudCBwaGFzZXMgKi9cbiAgY29tcGxldGVQaGFzZTEoKTogUGhhc2UxVG9rZW4ge1xuICAgIGNvbnN0IHRva2VuOiBQaGFzZTFUb2tlbiA9IHsgX19waGFzZTE6IFN5bWJvbCgpIGFzIG5ldmVyIH07XG4gICAgdGhpcy5fcGhhc2VUb2tlbnNbMV0gPSB0b2tlbjtcbiAgICByZXR1cm4gdG9rZW47XG4gIH1cblxuICAvKiogTWFyayBQaGFzZSAyIGFzIGNvbXBsZXRlIChhZnRlciBQaGFzZSAxIG9yIFBoYXNlIDMpICovXG4gIGNvbXBsZXRlUGhhc2UyKHRva2VuOiBQaGFzZTFUb2tlbiB8IFBoYXNlM1Rva2VuKTogUGhhc2UyVG9rZW4ge1xuICAgIGlmICh0aGlzLl9waGFzZVRva2Vuc1sxXSAhPT0gdG9rZW4gJiYgdGhpcy5fcGhhc2VUb2tlbnNbM10gIT09IHRva2VuKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1BoYXNlIDIgY2FsbGVkIGJlZm9yZSBQaGFzZSAxIGNvbXBsZXRlZCcpO1xuICAgIH1cbiAgICBjb25zdCB0MjogUGhhc2UyVG9rZW4gPSB7IF9fcGhhc2UyOiBTeW1ib2woKSBhcyBuZXZlciB9O1xuICAgIHRoaXMuX3BoYXNlVG9rZW5zWzJdID0gdDI7XG4gICAgcmV0dXJuIHQyO1xuICB9XG5cbiAgLyoqIE1hcmsgUGhhc2UgMyBhcyBjb21wbGV0ZSAob25seSByZXF1aXJlcyBQaGFzZSAxLCBub3QgUGhhc2UgMikgKi9cbiAgY29tcGxldGVQaGFzZTModG9rZW46IFBoYXNlMVRva2VuKTogUGhhc2UzVG9rZW4ge1xuICAgIGlmICh0aGlzLl9waGFzZVRva2Vuc1sxXSAhPT0gdG9rZW4pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignUGhhc2UgMyBjYWxsZWQgYmVmb3JlIFBoYXNlIDEgY29tcGxldGVkJyk7XG4gICAgfVxuICAgIGNvbnN0IHQzOiBQaGFzZTNUb2tlbiA9IHsgX19waGFzZTM6IFN5bWJvbCgpIGFzIG5ldmVyIH07XG4gICAgdGhpcy5fcGhhc2VUb2tlbnNbM10gPSB0MztcbiAgICByZXR1cm4gdDM7XG4gIH1cblxuICAvKiogUG9wdWxhdGUgUGhhc2UgMyBpbnZhcmlhbnRzIGZyb20gcmVzb2x2ZWQgVml0ZSBjb25maWcgYW5kIGZyYW1ld29yayBvcHRpb25zLiAqL1xuICBwb3B1bGF0ZVBoYXNlMyhcbiAgICBvcHRpb25zOiBGcmFtZXdvcmtPcHRpb25zICYgeyBhbGxvd0hlYWRFeHRyYXNTY3JpcHRzPzogYm9vbGVhbiB9LFxuICAgIGNvbmZpZzogUmVzb2x2ZWRDb25maWcsXG4gICAgc3NyTm9FeHRlcm5hbDogKHN0cmluZyB8IHsgX190eXBlOiAnUmVnRXhwJzsgc291cmNlOiBzdHJpbmc7IGZsYWdzOiBzdHJpbmcgfSlbXSxcbiAgKTogdm9pZCB7XG4gICAgbGV0IGJhc2UgPSBjb25maWcuYmFzZSB8fCAnLyc7XG4gICAgaWYgKCFiYXNlLmVuZHNXaXRoKCcvJykpIGJhc2UgKz0gJy8nO1xuXG4gICAgdGhpcy5waGFzZTMucm9vdCA9IGNvbmZpZy5yb290O1xuICAgIHRoaXMucGhhc2UzLm91dERpciA9IG9wdGlvbnMuYnVpbGQ/Lm91dERpciB8fCAnZGlzdCc7XG4gICAgdGhpcy5waGFzZTMuYmFzZSA9IGJhc2U7XG4gICAgdGhpcy5waGFzZTMuc3NyTm9FeHRlcm5hbCA9IHNzck5vRXh0ZXJuYWw7XG4gICAgdGhpcy5waGFzZTMucm91dGVzRGlyID0gb3B0aW9ucy5yb3V0ZXNEaXIgfHwgJ2FwcC9yb3V0ZXMnO1xuICAgIHRoaXMucGhhc2UzLmlzbGFuZHNEaXIgPSBvcHRpb25zLmlzbGFuZHNEaXIgfHwgJ2FwcC9pc2xhbmRzJztcbiAgICB0aGlzLnBoYXNlMy5jb21wb25lbnRzRGlyID0gb3B0aW9ucy5jb21wb25lbnRzRGlyIHx8ICdhcHAvY29tcG9uZW50cyc7XG4gICAgdGhpcy5waGFzZTMubWlkZGxld2FyZSA9IG9wdGlvbnMubWlkZGxld2FyZSB8fCBudWxsO1xuICAgIHRoaXMucGhhc2UzLmh0bWwgPSBvcHRpb25zLmh0bWwgfHwgbnVsbDtcbiAgICB0aGlzLnBoYXNlMy51cGdyYWRlU3RyYXRlZ3kgPSBvcHRpb25zLmlzbGFuZD8udXBncmFkZVN0cmF0ZWd5IHx8ICdpZGxlJztcbiAgICB0aGlzLnBoYXNlMy52aWV3VHJhbnNpdGlvbiA9IG9wdGlvbnMudmlld1RyYW5zaXRpb24gPz8gdHJ1ZTtcbiAgICB0aGlzLnBoYXNlMy5zcGVjdWxhdGlvbiA9IG9wdGlvbnMuc3BlY3VsYXRpb24gPz8gbnVsbDtcbiAgICB0aGlzLnBoYXNlMy5oZWFkRXh0cmFzID0gb3B0aW9ucy5oZWFkRXh0cmFzIHx8ICcnO1xuICAgIHRoaXMucGhhc2UzLmFsbG93SGVhZEV4dHJhc1NjcmlwdHMgPSBvcHRpb25zLmFsbG93SGVhZEV4dHJhc1NjcmlwdHMgfHwgZmFsc2U7XG4gICAgdGhpcy5waGFzZTMuYXBwU2hlbGwgPSBvcHRpb25zLmFwcFNoZWxsO1xuICAgIHRoaXMucGhhc2UzLmxheW91dHMgPSBvcHRpb25zLmxheW91dHM7XG4gIH1cblxuICAvKiogUmV0dXJuIGEgcmVhZC1vbmx5IHZpZXcgb2YgUGhhc2UgMyBtZXRhZGF0YS4gKi9cbiAgZ2V0UGhhc2UzTWV0YSgpOiBSZWFkb25seTxQaGFzZTNNZXRhPiB7XG4gICAgcmV0dXJuIHRoaXMucGhhc2UzO1xuICB9XG5cbiAgLyoqIENoZWNrIHdoZXRoZXIgYSBwaGFzZSBoYXMgYmVlbiBjb21wbGV0ZWQuICovXG4gIGlzUGhhc2VDb21wbGV0ZShwaGFzZTogMSB8IDIgfCAzKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuX3BoYXNlVG9rZW5zW3BoYXNlXSAhPT0gbnVsbDtcbiAgfVxuXG4gIC8qKiBSdW4gUGhhc2UgMyBhZnRlciBQaGFzZSAxLCBlbmZvcmNpbmcgb3JkZXJpbmcgYW5kIGxvZ2dpbmcuICovXG4gIGFzeW5jIHJ1blBoYXNlMyhydW5uZXI6IChjdHg6IHRoaXMpID0+IFByb21pc2U8dm9pZD4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBwaGFzZTFUb2tlbiA9IHRoaXMuX3BoYXNlVG9rZW5zWzFdO1xuICAgIGlmICghcGhhc2UxVG9rZW4pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignUGhhc2UgMyBjYWxsZWQgYmVmb3JlIFBoYXNlIDEgY29tcGxldGVkJyk7XG4gICAgfVxuICAgIHRoaXMuY29tcGxldGVQaGFzZTMocGhhc2UxVG9rZW4pO1xuXG4gICAgbG9nLmluZm8oJ1szLzNdIFN0YXRpYyBzaXRlIGdlbmVyYXRpb24uLi4nKTtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgcnVubmVyKHRoaXMpO1xuICAgICAgbG9nLmluZm8oJ1szLzNdIFN0YXRpYyBzaXRlIGdlbmVyYXRpb24gLSBjb21wbGV0ZScpO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBsb2cuZXJyb3IoYFszLzNdIFN0YXRpYyBzaXRlIGdlbmVyYXRpb24gLSBGQUlMRUQ6ICR7ZXJyb3J9YCk7XG4gICAgICB0aHJvdyBlcnJvcjtcbiAgICB9XG4gIH1cblxuICAvKiogUnVuIFBoYXNlIDIgYWZ0ZXIgUGhhc2UgMywgZW5mb3JjaW5nIG9yZGVyaW5nIGFuZCBsb2dnaW5nLiAqL1xuICBhc3luYyBydW5QaGFzZTIocnVubmVyOiAoY3R4OiB0aGlzKSA9PiBQcm9taXNlPHZvaWQ+KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgcGhhc2UzVG9rZW4gPSB0aGlzLl9waGFzZVRva2Vuc1szXTtcbiAgICBpZiAoIXBoYXNlM1Rva2VuKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1BoYXNlIDIgY2FsbGVkIGJlZm9yZSBQaGFzZSAzIGNvbXBsZXRlZCcpO1xuICAgIH1cbiAgICB0aGlzLmNvbXBsZXRlUGhhc2UyKHBoYXNlM1Rva2VuKTtcblxuICAgIGxvZy5pbmZvKCdbMi8zXSBDbGllbnQgaXNsYW5kIGJ1aWxkLi4uJyk7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHJ1bm5lcih0aGlzKTtcbiAgICAgIGxvZy5pbmZvKCdbMi8zXSBDbGllbnQgaXNsYW5kIGJ1aWxkIC0gY29tcGxldGUnKTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgbG9nLmVycm9yKGBbMi8zXSBDbGllbnQgaXNsYW5kIGJ1aWxkIC0gRkFJTEVEOiAke2Vycm9yfWApO1xuICAgICAgdGhyb3cgZXJyb3I7XG4gICAgfVxuICB9XG5cbiAgLyoqIFBoYXNlIDE6IFJvdXRlIHNjYW5uaW5nICYgYnVpbGQgbWV0YWRhdGEgKi9cbiAgcmVhZG9ubHkgcGhhc2UxOiBQaGFzZTFNZXRhID0gbmV3IFBoYXNlMU1ldGEoKTtcblxuICAvKiogUGhhc2UgMjogQ2xpZW50IGlzbGFuZCBidWlsZCBzdGF0ZSAqL1xuICByZWFkb25seSBwaGFzZTI6IFBoYXNlMk1ldGEgPSBuZXcgUGhhc2UyTWV0YSgpO1xuXG4gIC8qKiBQaGFzZSAzOiBTU0cgcmVuZGVyaW5nIHN0YXRlICovXG4gIHJlYWRvbmx5IHBoYXNlMzogUGhhc2UzTWV0YSA9IG5ldyBQaGFzZTNNZXRhKCk7XG5cbiAgLyoqIFBsdWdpbiBkYXRhIGZyb20gY29udGVudC9pMThuIHN1Yi1wbHVnaW5zICovXG4gIHJlYWRvbmx5IHBsdWdpbnM6IHtcbiAgICBibG9nT3B0aW9uczogT3BlbkVsZW1lbnRCbG9nT3B0aW9ucyB8IG51bGw7XG4gICAgbmF2U2VjdGlvbnM6IE9wZW5FbGVtZW50TmF2U2VjdGlvbltdO1xuICAgIGhlYWRlck5hdjogT3BlbkVsZW1lbnRIZWFkZXJOYXZMaW5rW107XG4gICAgc2l0ZW1hcE9wdGlvbnM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IHwgbnVsbDtcbiAgICBpMThuT3B0aW9uczogT3BlbkVsZW1lbnRJMThuQ29udGV4dE9wdGlvbnMgfCBudWxsO1xuICAgIFtrZXk6IHN0cmluZ106IHVua25vd247XG4gIH0gPSB7XG4gICAgYmxvZ09wdGlvbnM6IG51bGwsXG4gICAgbmF2U2VjdGlvbnM6IFtdLFxuICAgIGhlYWRlck5hdjogW10sXG4gICAgc2l0ZW1hcE9wdGlvbnM6IG51bGwsXG4gICAgaTE4bk9wdGlvbnM6IG51bGwsXG4gIH07XG5cbiAgLyoqIFJlc29sdmVkIGZyYW1ld29yayBvcHRpb25zIHdpdGggZGVmYXVsdHMgYXBwbGllZCAocmVhZC1vbmx5IGFmdGVyIGNvbnN0cnVjdGlvbikgKi9cbiAgcmVhZG9ubHkgb3B0aW9uczogRnJhbWV3b3JrT3B0aW9ucztcblxuICBjb25zdHJ1Y3RvcihvcHRpb25zOiBGcmFtZXdvcmtPcHRpb25zKSB7XG4gICAgdGhpcy5vcHRpb25zID0gb3B0aW9ucztcbiAgfVxuXG4gIC8qKiBSZXNldCBhbGwgbXV0YWJsZSBzdGF0ZSAoZm9yIHdhdGNoIG1vZGUgLyB0ZXN0aW5nKSAqL1xuICByZXNldCgpOiB2b2lkIHtcbiAgICB0aGlzLl9waGFzZVRva2Vuc1sxXSA9IG51bGw7XG4gICAgdGhpcy5fcGhhc2VUb2tlbnNbMl0gPSBudWxsO1xuICAgIHRoaXMuX3BoYXNlVG9rZW5zWzNdID0gbnVsbDtcblxuICAgIGNvbnN0IHVzZXJSZXNvbHZlQWxpYXMgPSB0aGlzLnBoYXNlMS51c2VyUmVzb2x2ZUFsaWFzO1xuICAgIC8vIE5PVEU6IHVzZXJSZXNvbHZlQWxpYXMgaXMgTk9UIHJlc2V0IC0gaXQncyB1c2VyIGNvbmZpZ3VyYXRpb24sIG5vdFxuICAgIC8vIGJ1aWxkIHN0YXRlLiBJdCdzIHNldCBpbiBjb25maWcoKS9jb25maWdSZXNvbHZlZCgpIGFuZCBtdXN0IHBlcnNpc3RcbiAgICAvLyB0aHJvdWdoIGJ1aWxkU3RhcnQoKSBmb3IgUGhhc2UgMiBhbmQgMyB0byB1c2UuXG4gICAgT2JqZWN0LmFzc2lnbih0aGlzLnBoYXNlMSwgbmV3IFBoYXNlMU1ldGEoKSwgeyB1c2VyUmVzb2x2ZUFsaWFzIH0pO1xuICAgIE9iamVjdC5hc3NpZ24odGhpcy5waGFzZTIsIG5ldyBQaGFzZTJNZXRhKCkpO1xuICAgIE9iamVjdC5hc3NpZ24odGhpcy5waGFzZTMsIG5ldyBQaGFzZTNNZXRhKCkpO1xuICAgIE9iamVjdC5hc3NpZ24odGhpcy5wbHVnaW5zLCB7XG4gICAgICBibG9nT3B0aW9uczogbnVsbCxcbiAgICAgIG5hdlNlY3Rpb25zOiBbXSxcbiAgICAgIGhlYWRlck5hdjogW10sXG4gICAgICBzaXRlbWFwT3B0aW9uczogbnVsbCxcbiAgICAgIGkxOG5PcHRpb25zOiBudWxsLFxuICAgIH0pO1xuICB9XG59XG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7O0NBaUJDLEdBZUQsU0FBUyxZQUFZLFFBQVEsMkJBQTJCO0FBRXhELE1BQU0sTUFBTSxhQUFhO0FBU3pCLE9BQU8sTUFBTTtFQUNYLGtFQUFrRSxHQUNsRSxnQkFBd0IsR0FBRztFQUUzQixtRUFBbUUsR0FDbkUsZUFBNkIsRUFBRSxDQUFDO0VBRWhDLHNFQUFzRSxHQUN0RSxpQkFBMkIsRUFBRSxDQUFDO0VBRTlCLDBDQUEwQyxHQUMxQyxjQUF3QixFQUFFLENBQUM7RUFFM0IsK0NBQStDLEdBQy9DLGFBQWtELENBQUMsRUFBRTtFQUVyRCx1REFBdUQsR0FDdkQsbUJBQWlELEVBQUUsQ0FBQztFQUVwRCx5REFBeUQsR0FDekQscUJBQW1DLEVBQUUsQ0FBQztFQUV0Qyw2REFB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
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/** File size info for a single artifact */ export interface ArtifactInfo {
|
|
2
|
+
name: string;
|
|
3
|
+
path: string;
|
|
4
|
+
sizeBytes: number;
|
|
5
|
+
sizeKB: string;
|
|
6
|
+
}
|
|
7
|
+
/** Full build manifest summary */ export interface BuildManifest {
|
|
8
|
+
phase: 1 | 2 | 3;
|
|
9
|
+
timestamp: string;
|
|
10
|
+
islands: ArtifactInfo[];
|
|
11
|
+
clientEntry: ArtifactInfo | null;
|
|
12
|
+
htmlPages: ArtifactInfo[];
|
|
13
|
+
totalJsBytes: number;
|
|
14
|
+
totalHtmlBytes: number;
|
|
15
|
+
headExtrasSize: number;
|
|
16
|
+
/** Budget warnings (files > threshold) */ warnings: string[];
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Scan client build output (dist/client/) for island chunks.
|
|
20
|
+
*/ export declare function scanClientBuild(root: string, outDir?: string): {
|
|
21
|
+
islands: ArtifactInfo[];
|
|
22
|
+
clientEntry: ArtifactInfo | null;
|
|
23
|
+
totalJsBytes: number;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Scan SSG output (dist/*.html) for page information.
|
|
27
|
+
*/ export declare function scanSSGOutput(root: string, outDir?: string): ArtifactInfo[];
|
|
28
|
+
/**
|
|
29
|
+
* Print a formatted build manifest table to console.
|
|
30
|
+
*
|
|
31
|
+
* This is called at the end of each build phase to provide observability
|
|
32
|
+
* into what was produced and how large everything is.
|
|
33
|
+
*/ export declare function printBuildManifest(options: {
|
|
34
|
+
root: string;
|
|
35
|
+
outDir?: string;
|
|
36
|
+
phase: 2 | 3;
|
|
37
|
+
headExtras?: string;
|
|
38
|
+
}): BuildManifest;
|