@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 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;