handoff-app 1.2.2-7 → 2.0.0-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/Changelog.md +37 -15
- package/README.md +372 -118
- package/dist/app-builder/build.d.ts +41 -2
- package/dist/app-builder/build.js +455 -18
- package/dist/app-builder/client-config.d.ts +15 -2
- package/dist/app-builder/client-config.js +43 -4
- package/dist/app-builder/config-diff/snapshot.d.ts +1 -6
- package/dist/app-builder/config-diff/snapshot.js +2 -9
- package/dist/app-builder/index.d.ts +1 -1
- package/dist/app-builder/index.js +3 -1
- package/dist/app-builder/nav-shell.d.ts +23 -0
- package/dist/app-builder/nav-shell.js +80 -0
- package/dist/app-builder/paths.js +25 -1
- package/dist/app-builder/static-export.d.ts +17 -0
- package/dist/app-builder/static-export.js +206 -0
- package/dist/app-builder/vercel-output.d.ts +39 -0
- package/dist/app-builder/vercel-output.js +259 -0
- package/dist/app-builder/watchers/utils.d.ts +2 -0
- package/dist/app-builder/watchers.d.ts +14 -4
- package/dist/app-builder/watchers.js +123 -28
- package/dist/app-builder/websocket.js +1 -1
- package/dist/artifacts/index.d.ts +2 -0
- package/dist/artifacts/index.js +16 -0
- package/dist/artifacts/types.d.ts +136 -0
- package/dist/artifacts/types.js +24 -0
- package/dist/artifacts/url.d.ts +67 -0
- package/dist/artifacts/url.js +116 -0
- package/dist/cache/build-cache.js +48 -4
- package/dist/cli.js +0 -0
- package/dist/commands/build/app.js +1 -2
- package/dist/commands/build/index.d.ts +17 -0
- package/dist/commands/build/index.js +66 -0
- package/dist/commands/checkout/index.d.ts +24 -0
- package/dist/commands/checkout/index.js +71 -0
- package/dist/commands/db/migrate.d.ts +11 -0
- package/dist/commands/db/migrate.js +33 -0
- package/dist/commands/index.js +8 -0
- package/dist/commands/publish/index.d.ts +21 -0
- package/dist/commands/publish/index.js +68 -0
- package/dist/config/defaults.js +15 -1
- package/dist/config/loader.js +6 -1
- package/dist/config/normalizers/declaration.js +4 -1
- package/dist/config/normalizers/page.d.ts +18 -0
- package/dist/config/normalizers/page.js +34 -0
- package/dist/config/normalizers/pattern.js +7 -1
- package/dist/config/runtime.d.ts +4 -0
- package/dist/config/runtime.js +53 -5
- package/dist/index.d.ts +65 -1
- package/dist/index.js +123 -3
- package/dist/nav/index.d.ts +83 -0
- package/dist/nav/index.js +9 -0
- package/dist/nav/registry.d.ts +15 -0
- package/dist/nav/registry.js +42 -0
- package/dist/nav/resolver.d.ts +8 -0
- package/dist/nav/resolver.js +192 -0
- package/dist/nav/workspace.d.ts +18 -0
- package/dist/nav/workspace.js +103 -0
- package/dist/pipeline/styles.js +7 -35
- package/dist/pipeline/token-transformers.d.ts +45 -0
- package/dist/pipeline/token-transformers.js +71 -0
- package/dist/registry/asset-storage/adapters/vercel-blob.d.ts +17 -0
- package/dist/registry/asset-storage/adapters/vercel-blob.js +87 -0
- package/dist/registry/asset-storage/define.d.ts +10 -0
- package/dist/registry/asset-storage/define.js +13 -0
- package/dist/registry/asset-storage/resolve.d.ts +45 -0
- package/dist/registry/asset-storage/resolve.js +36 -0
- package/dist/registry/asset-storage/types.d.ts +51 -0
- package/dist/registry/asset-storage/types.js +9 -0
- package/dist/registry/assets/layout.d.ts +22 -0
- package/dist/registry/assets/layout.js +30 -0
- package/dist/registry/assets/sets.d.ts +18 -0
- package/dist/registry/assets/sets.js +44 -0
- package/dist/registry/assets/transfer.d.ts +45 -0
- package/dist/registry/assets/transfer.js +11 -0
- package/dist/registry/checkout/assets.d.ts +16 -0
- package/dist/registry/checkout/assets.js +150 -0
- package/dist/registry/checkout/index.d.ts +33 -0
- package/dist/registry/checkout/index.js +610 -0
- package/dist/registry/checkout/tokens.d.ts +15 -0
- package/dist/registry/checkout/tokens.js +171 -0
- package/dist/registry/client.d.ts +61 -0
- package/dist/registry/client.js +211 -0
- package/dist/registry/connection.d.ts +30 -0
- package/dist/registry/connection.js +36 -0
- package/dist/registry/db/adapter.d.ts +43 -0
- package/dist/registry/db/adapter.js +59 -0
- package/dist/registry/db/client.d.ts +35 -0
- package/dist/registry/db/client.js +94 -0
- package/dist/registry/db/index.d.ts +5 -0
- package/dist/registry/db/index.js +24 -0
- package/dist/registry/db/migrate.d.ts +23 -0
- package/dist/registry/db/migrate.js +64 -0
- package/dist/registry/db/schema.d.ts +4869 -0
- package/dist/registry/db/schema.js +347 -0
- package/dist/registry/path.d.ts +4 -0
- package/dist/registry/path.js +31 -0
- package/dist/registry/publish/artifacts.d.ts +16 -0
- package/dist/registry/publish/artifacts.js +132 -0
- package/dist/registry/publish/assets.d.ts +16 -0
- package/dist/registry/publish/assets.js +129 -0
- package/dist/registry/publish/errors.d.ts +5 -0
- package/dist/registry/publish/errors.js +26 -0
- package/dist/registry/publish/index.d.ts +27 -0
- package/dist/registry/publish/index.js +126 -0
- package/dist/registry/publish/package.d.ts +27 -0
- package/dist/registry/publish/package.js +257 -0
- package/dist/registry/publish/publish-build.d.ts +12 -0
- package/dist/registry/publish/publish-build.js +43 -0
- package/dist/registry/publish/tokens.d.ts +18 -0
- package/dist/registry/publish/tokens.js +112 -0
- package/dist/registry/tokens/sets.d.ts +59 -0
- package/dist/registry/tokens/sets.js +109 -0
- package/dist/registry/tokens/transfer.d.ts +48 -0
- package/dist/registry/tokens/transfer.js +10 -0
- package/dist/registry/transfer.d.ts +75 -0
- package/dist/registry/transfer.js +11 -0
- package/dist/store/filesystem-assets.d.ts +17 -0
- package/dist/store/filesystem-assets.js +147 -0
- package/dist/store/filesystem.d.ts +76 -0
- package/dist/store/filesystem.js +208 -0
- package/dist/store/index.d.ts +20 -0
- package/dist/store/index.js +38 -0
- package/dist/store/registry.d.ts +77 -0
- package/dist/store/registry.js +350 -0
- package/dist/store/source-files.d.ts +24 -0
- package/dist/store/source-files.js +147 -0
- package/dist/store/types.d.ts +185 -0
- package/dist/store/types.js +12 -0
- package/dist/transformers/plugins/csf-render.js +17 -8
- package/dist/transformers/plugins/handlebars-previews.js +10 -3
- package/dist/transformers/plugins/ssr-render.js +116 -49
- package/dist/transformers/preview/component/api.js +3 -1
- package/dist/transformers/preview/component/artifacts.js +8 -1
- package/dist/transformers/preview/component/builder.js +13 -5
- package/dist/transformers/preview/component/css.js +9 -1
- package/dist/transformers/preview/component/javascript.d.ts +9 -3
- package/dist/transformers/preview/component/javascript.js +45 -17
- package/dist/transformers/preview/component/shared-artifacts.d.ts +83 -0
- package/dist/transformers/preview/component/shared-artifacts.js +92 -0
- package/dist/transformers/preview/component.js +5 -2
- package/dist/transformers/preview/pattern/builder.js +28 -9
- package/dist/transformers/preview/pattern/html.d.ts +13 -10
- package/dist/transformers/preview/pattern/html.js +62 -27
- package/dist/transformers/preview/types.d.ts +38 -0
- package/dist/transformers/utils/handlebars.d.ts +3 -0
- package/dist/transformers/utils/handlebars.js +19 -5
- package/dist/types/config.d.ts +124 -31
- package/dist/utils/menu-shell.d.ts +60 -0
- package/dist/utils/menu-shell.js +221 -0
- package/dist/utils/stable-stringify.d.ts +2 -0
- package/dist/utils/stable-stringify.js +8 -0
- package/docs/cli.md +4 -2
- package/drizzle/0000_init_registry_storage.sql +95 -0
- package/drizzle/0001_add_review_metadata.sql +2 -0
- package/drizzle/0002_add_pages.sql +28 -0
- package/drizzle/0003_add_tokens.sql +29 -0
- package/drizzle/0004_add_assets.sql +37 -0
- package/drizzle/meta/0000_snapshot.json +642 -0
- package/drizzle/meta/0001_snapshot.json +654 -0
- package/drizzle/meta/0002_snapshot.json +835 -0
- package/drizzle/meta/0003_snapshot.json +1023 -0
- package/drizzle/meta/0004_snapshot.json +1252 -0
- package/drizzle/meta/_journal.json +41 -0
- package/drizzle.config.ts +16 -0
- package/package.json +10 -1
- package/src/app/components/Component/Preview.tsx +3 -2
- package/src/app/components/Component/RegistryActions.tsx +150 -0
- package/src/app/components/Foundations/DisplayLogo.tsx +11 -3
- package/src/app/components/Layout/Header.tsx +21 -3
- package/src/app/components/Layout/Main.tsx +11 -3
- package/src/app/components/Navigation/MainNav.tsx +4 -2
- package/src/app/components/Navigation/MobileNav.tsx +4 -2
- package/src/app/components/Navigation/SideNav.tsx +46 -11
- package/src/app/components/NotFound.tsx +24 -0
- package/src/app/components/context/NavProvider.tsx +71 -0
- package/src/app/components/old/Header.tsx +3 -3
- package/src/app/components/util/index.ts +203 -380
- package/src/app/components/util/useCollectionAssets.ts +125 -0
- package/src/app/components/util/useFoundationTokens.ts +67 -0
- package/src/app/generated/default-pages.json +1 -0
- package/src/app/generated/nav-shell.json +1 -0
- package/src/app/lib/api/query.ts +6 -0
- package/src/app/lib/api/redact.ts +46 -0
- package/src/app/lib/asset-storage.ts +81 -0
- package/src/app/lib/docs-api/artifacts.ts +116 -0
- package/src/app/lib/docs-api/backend.ts +151 -0
- package/src/app/lib/docs-api/errors.ts +52 -0
- package/src/app/lib/docs-api/handler.ts +34 -0
- package/src/app/lib/docs-api/index.ts +7 -0
- package/src/app/lib/docs-api/records.ts +189 -0
- package/src/app/lib/docs-api/registry.ts +130 -0
- package/src/app/lib/docs-api/runtime-config.ts +173 -0
- package/src/app/lib/docs-api/serve.ts +37 -0
- package/src/app/lib/docs-api/token-detail.ts +19 -0
- package/src/app/lib/registry-api/allowlist.ts +163 -0
- package/src/app/lib/registry-api/asset-transfer.ts +363 -0
- package/src/app/lib/registry-api/auth.ts +68 -0
- package/src/app/lib/registry-api/entity-routes.ts +197 -0
- package/src/app/lib/registry-api/errors.ts +51 -0
- package/src/app/lib/registry-api/files.ts +135 -0
- package/src/app/lib/registry-api/handler.ts +96 -0
- package/src/app/lib/registry-api/index.ts +4 -0
- package/src/app/lib/registry-api/meta.ts +87 -0
- package/src/app/lib/registry-api/revalidate.ts +36 -0
- package/src/app/lib/registry-api/store.ts +348 -0
- package/src/app/lib/registry-api/token-transfer.ts +231 -0
- package/src/app/lib/registry-api/transfer.ts +513 -0
- package/src/app/lib/registry-api/validation.ts +74 -0
- package/src/app/lib/registry-connection.ts +58 -0
- package/src/app/lib/utils.ts +14 -0
- package/src/app/next.config.mjs +72 -13
- package/src/app/pages/[...slug]/index.tsx +74 -20
- package/src/app/pages/_app.tsx +5 -2
- package/src/app/pages/api/docs/artifacts/[...artifactPath].ts +16 -0
- package/src/app/pages/api/docs/assets/[collection]/[...path].ts +50 -0
- package/src/app/pages/api/docs/assets/[collection]/index.ts +22 -0
- package/src/app/pages/api/docs/components/[id]/assets/[asset].ts +33 -0
- package/src/app/pages/api/docs/components/[id]/inspect/[previewId].ts +20 -0
- package/src/app/pages/api/docs/components/[id]/previews/[previewId].ts +21 -0
- package/src/app/pages/api/docs/components/[id].ts +24 -0
- package/src/app/pages/api/docs/components.json.ts +12 -0
- package/src/app/pages/api/docs/nav.json.ts +48 -0
- package/src/app/pages/api/docs/patterns/[id]/preview.ts +19 -0
- package/src/app/pages/api/docs/patterns/[id].ts +24 -0
- package/src/app/pages/api/docs/patterns.json.ts +12 -0
- package/src/app/pages/api/docs/tokens/components/[id].ts +30 -0
- package/src/app/pages/api/docs/tokens/foundations/[type].ts +32 -0
- package/src/app/pages/api/registry/components/[id]/files/[...filePath].ts +19 -0
- package/src/app/pages/api/registry/components/[id]/files/index.ts +19 -0
- package/src/app/pages/api/registry/components/[id].ts +20 -0
- package/src/app/pages/api/registry/components/index.ts +19 -0
- package/src/app/pages/api/registry/health.ts +20 -0
- package/src/app/pages/api/registry/patterns/[id]/files/[...filePath].ts +19 -0
- package/src/app/pages/api/registry/patterns/[id]/files/index.ts +19 -0
- package/src/app/pages/api/registry/patterns/[id].ts +20 -0
- package/src/app/pages/api/registry/patterns/index.ts +19 -0
- package/src/app/pages/api/registry/transfer/[kind]/[id].ts +39 -0
- package/src/app/pages/api/registry/transfer/assets/[collection].ts +24 -0
- package/src/app/pages/api/registry/transfer/assets/blobs/[hash].ts +23 -0
- package/src/app/pages/api/registry/transfer/assets/blobs/have.ts +11 -0
- package/src/app/pages/api/registry/transfer/assets/index.ts +10 -0
- package/src/app/pages/api/registry/transfer/tokens/[...setId].ts +26 -0
- package/src/app/pages/api/registry/transfer/tokens/index.ts +11 -0
- package/src/app/pages/assets/fonts.tsx +41 -17
- package/src/app/pages/assets/index.tsx +2 -2
- package/src/app/pages/assets/logos.tsx +6 -3
- package/src/app/pages/foundations/colors.tsx +18 -8
- package/src/app/pages/foundations/effects.tsx +18 -8
- package/src/app/pages/foundations/icons/[name]/index.tsx +28 -16
- package/src/app/pages/foundations/icons/index.tsx +18 -12
- package/src/app/pages/foundations/index.tsx +1 -1
- package/src/app/pages/foundations/logo.tsx +12 -8
- package/src/app/pages/foundations/typography.tsx +19 -9
- package/src/app/pages/index.tsx +1 -1
- package/src/app/pages/system/component/[component]/index.tsx +87 -17
- package/src/app/pages/system/index.tsx +13 -4
- package/src/app/pages/system/pattern/[pattern]/index.tsx +70 -14
- package/src/app/pages/system/tokens/components/[component]/index.tsx +42 -14
- package/src/app/pages/system/tokens/foundations/colors.tsx +7 -5
- package/src/app/pages/system/tokens/foundations/effects.tsx +7 -5
- package/src/app/pages/system/tokens/foundations/typography.tsx +8 -4
- package/src/app/tsconfig.json +2 -3
- package/src/app-builder/build.ts +555 -11
- package/src/app-builder/client-config.ts +61 -4
- package/src/app-builder/config-diff/snapshot.ts +1 -11
- package/src/app-builder/index.ts +1 -1
- package/src/app-builder/nav-shell.ts +74 -0
- package/src/app-builder/paths.ts +27 -1
- package/src/app-builder/static-export.ts +242 -0
- package/src/app-builder/vercel-output.ts +297 -0
- package/src/app-builder/watchers/utils.ts +2 -0
- package/src/app-builder/watchers.ts +149 -25
- package/src/app-builder/websocket.ts +2 -2
- package/src/artifacts/README.md +14 -0
- package/src/artifacts/index.ts +24 -0
- package/src/artifacts/types.ts +146 -0
- package/src/artifacts/url.ts +122 -0
- package/src/cache/build-cache.ts +47 -2
- package/src/commands/build/app.ts +1 -2
- package/src/commands/build/index.ts +61 -0
- package/src/commands/checkout/index.ts +66 -0
- package/src/commands/db/migrate.ts +25 -0
- package/src/commands/index.ts +8 -0
- package/src/commands/publish/index.ts +63 -0
- package/src/config/defaults.ts +15 -0
- package/src/config/loader.ts +10 -1
- package/src/config/normalizers/declaration.ts +3 -0
- package/src/config/normalizers/page.ts +45 -0
- package/src/config/normalizers/pattern.ts +4 -1
- package/src/config/runtime.ts +48 -2
- package/src/index.ts +126 -3
- package/src/nav/index.ts +94 -0
- package/src/nav/registry.ts +54 -0
- package/src/nav/resolver.ts +217 -0
- package/src/nav/workspace.ts +87 -0
- package/src/pipeline/styles.ts +4 -35
- package/src/pipeline/token-transformers.ts +97 -0
- package/src/registry/asset-storage/adapters/vercel-blob.ts +51 -0
- package/src/registry/asset-storage/define.ts +15 -0
- package/src/registry/asset-storage/resolve.ts +72 -0
- package/src/registry/asset-storage/types.ts +46 -0
- package/src/registry/assets/layout.ts +38 -0
- package/src/registry/assets/sets.ts +48 -0
- package/src/registry/assets/transfer.ts +50 -0
- package/src/registry/checkout/assets.ts +126 -0
- package/src/registry/checkout/index.ts +596 -0
- package/src/registry/checkout/tokens.ts +152 -0
- package/src/registry/client.ts +234 -0
- package/src/registry/connection.ts +50 -0
- package/src/registry/db/adapter.ts +74 -0
- package/src/registry/db/client.ts +88 -0
- package/src/registry/db/index.ts +35 -0
- package/src/registry/db/migrate.ts +56 -0
- package/src/registry/db/schema.ts +444 -0
- package/src/registry/path.ts +26 -0
- package/src/registry/publish/artifacts.ts +147 -0
- package/src/registry/publish/assets.ts +129 -0
- package/src/registry/publish/errors.ts +34 -0
- package/src/registry/publish/index.ts +128 -0
- package/src/registry/publish/package.ts +272 -0
- package/src/registry/publish/publish-build.ts +51 -0
- package/src/registry/publish/tokens.ts +119 -0
- package/src/registry/tokens/sets.ts +132 -0
- package/src/registry/tokens/transfer.ts +53 -0
- package/src/registry/transfer.ts +82 -0
- package/src/store/filesystem-assets.ts +152 -0
- package/src/store/filesystem.ts +237 -0
- package/src/store/index.ts +62 -0
- package/src/store/registry.ts +334 -0
- package/src/store/source-files.ts +155 -0
- package/src/store/types.ts +210 -0
- package/src/transformers/plugins/csf-render.ts +31 -7
- package/src/transformers/plugins/handlebars-previews.ts +22 -3
- package/src/transformers/plugins/ssr-render.ts +145 -57
- package/src/transformers/preview/component/api.ts +2 -1
- package/src/transformers/preview/component/artifacts.ts +10 -1
- package/src/transformers/preview/component/builder.ts +9 -2
- package/src/transformers/preview/component/css.ts +10 -1
- package/src/transformers/preview/component/javascript.ts +55 -20
- package/src/transformers/preview/component/shared-artifacts.ts +146 -0
- package/src/transformers/preview/component.ts +5 -2
- package/src/transformers/preview/pattern/builder.ts +33 -7
- package/src/transformers/preview/pattern/html.ts +71 -27
- package/src/transformers/preview/types.ts +42 -0
- package/src/transformers/utils/handlebars.ts +31 -5
- package/src/types/config.ts +129 -31
- package/src/utils/menu-shell.ts +241 -0
- package/src/utils/stable-stringify.ts +7 -0
- package/templates/default/package.json.tpl +1 -1
- package/handoff.config.js +0 -90
- package/src/app/components/ComponentSearch.tsx +0 -93
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.writeRegistryVercelOutput = exports.writeStaticVercelOutput = exports.getVercelOutputPath = void 0;
|
|
16
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
17
|
+
const path_1 = __importDefault(require("path"));
|
|
18
|
+
const logger_1 = require("../utils/logger");
|
|
19
|
+
/**
|
|
20
|
+
* Vercel Build Output API layout.
|
|
21
|
+
*
|
|
22
|
+
* `--package vercel` emits the Vercel Build Output API directory (`.vercel/output`) instead of the
|
|
23
|
+
* sites-directory deliverable. This module is the single seam that produces that layout; it is
|
|
24
|
+
* invoked as the final-assembly branch from the build functions and never re-stages or re-runs Next.
|
|
25
|
+
*
|
|
26
|
+
* Hard constraint: `.vercel/output` must live at the **repo root** (`handoff.workingPath`) with that
|
|
27
|
+
* exact name. Vercel ignores any `sitesOutputDirectory`-style override for this packaging.
|
|
28
|
+
*/
|
|
29
|
+
/** Build Output API config version emitted in `.vercel/output/config.json`. */
|
|
30
|
+
const BUILD_OUTPUT_API_VERSION = 3;
|
|
31
|
+
/** Absolute path of the `.vercel/output` directory at the repo root. */
|
|
32
|
+
const getVercelOutputPath = (handoff) => path_1.default.resolve(handoff.workingPath, '.vercel', 'output');
|
|
33
|
+
exports.getVercelOutputPath = getVercelOutputPath;
|
|
34
|
+
/**
|
|
35
|
+
* Resolve the app base path exactly as `next.config.mjs`'s `resolveBasePath` does, so the emitted
|
|
36
|
+
* `config.json` reflects the same `basePath` the static export was built with. Empty string means no
|
|
37
|
+
* base path (the Build Output API omits the field rather than carrying an empty value).
|
|
38
|
+
*/
|
|
39
|
+
const resolveBasePath = (rawBasePath) => {
|
|
40
|
+
if (!rawBasePath) {
|
|
41
|
+
return '';
|
|
42
|
+
}
|
|
43
|
+
const trimmed = rawBasePath.replace(/^\/+|\/+$/g, '');
|
|
44
|
+
return trimmed ? `/${trimmed}` : '';
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Lay a materialized static export under `.vercel/output/static/` and write a minimal Build Output
|
|
48
|
+
* API v3 `config.json` carrying the app's `trailingSlash` and resolved `basePath`. Pure CDN files —
|
|
49
|
+
* no functions, no database.
|
|
50
|
+
*
|
|
51
|
+
* @param exportDir Absolute path of the materialized static export (the same content the static
|
|
52
|
+
* target writes to `out/<projectId>`).
|
|
53
|
+
*/
|
|
54
|
+
const writeStaticVercelOutput = (handoff, exportDir) => __awaiter(void 0, void 0, void 0, function* () {
|
|
55
|
+
var _a, _b;
|
|
56
|
+
const outputPath = (0, exports.getVercelOutputPath)(handoff);
|
|
57
|
+
yield fs_extra_1.default.remove(outputPath);
|
|
58
|
+
yield fs_extra_1.default.ensureDir(outputPath);
|
|
59
|
+
// Lay the export under static/ — pure CDN files, served directly by Vercel.
|
|
60
|
+
const staticDir = path_1.default.join(outputPath, 'static');
|
|
61
|
+
yield fs_extra_1.default.copy(exportDir, staticDir, { overwrite: true });
|
|
62
|
+
// The staged Next app sets `trailingSlash: true` (src/app/next.config.mjs); the registry/static
|
|
63
|
+
// exports inherit it. Carry it and the resolved base path so the static deploy serves correct URLs.
|
|
64
|
+
const basePath = resolveBasePath((_b = (_a = handoff.config) === null || _a === void 0 ? void 0 : _a.app) === null || _b === void 0 ? void 0 : _b.base_path);
|
|
65
|
+
const config = {
|
|
66
|
+
version: BUILD_OUTPUT_API_VERSION,
|
|
67
|
+
trailingSlash: true,
|
|
68
|
+
};
|
|
69
|
+
if (basePath) {
|
|
70
|
+
config.basePath = basePath;
|
|
71
|
+
}
|
|
72
|
+
yield fs_extra_1.default.writeFile(path_1.default.join(outputPath, 'config.json'), `${JSON.stringify(config, null, 2)}\n`);
|
|
73
|
+
logger_1.Logger.success(`Packaged static Vercel Build Output API artifact at ${outputPath} (static/ + config.json).`);
|
|
74
|
+
});
|
|
75
|
+
exports.writeStaticVercelOutput = writeStaticVercelOutput;
|
|
76
|
+
/**
|
|
77
|
+
* Node.js runtime identifier baked into the registry function's `.vc-config.json`. The `pg` adapter
|
|
78
|
+
* (and the Neon serverless driver in its Node fallback) need the Node.js runtime, not the edge
|
|
79
|
+
* runtime — this is the required baseline. Vercel resolves the patch
|
|
80
|
+
* version within this major; pinning the major keeps the artifact stable.
|
|
81
|
+
*/
|
|
82
|
+
const VERCEL_NODE_RUNTIME = 'nodejs20.x';
|
|
83
|
+
/** Name (sans `.func`) of the single registry function. Served at `/` and the catch-all route. */
|
|
84
|
+
const REGISTRY_FUNCTION_NAME = 'index';
|
|
85
|
+
/** Handler file the Node launcher executes; wraps the Next standalone server as a request listener. */
|
|
86
|
+
const REGISTRY_FUNCTION_HANDLER = 'index.js';
|
|
87
|
+
/** Catch-all docs pages may be overridden by registry records and must always reach the function. */
|
|
88
|
+
const MUTABLE_REGISTRY_PAGE_SRC_ROUTE = '/[...slug]';
|
|
89
|
+
/**
|
|
90
|
+
* Node launcher emitted into the registry function directory. The Next `standalone` `server.js`
|
|
91
|
+
* binds a port via `startServer`, which is not the Vercel Node function contract (a module exporting
|
|
92
|
+
* a `(req, res)` request listener). This launcher reuses the exact same request pipeline that
|
|
93
|
+
* `startServer` boots — the router-server handler from `next/dist/server/lib/start-server` — but
|
|
94
|
+
* without the port bind, so it serves requests identically to `node server.js`.
|
|
95
|
+
*
|
|
96
|
+
* Why not the public `next().getRequestHandler()`: that handler resolves page/document and `/api`
|
|
97
|
+
* routes, but does NOT resolve on-demand `/_next/data/<buildId>/…json` requests for
|
|
98
|
+
* `fallback:'blocking'` pages — it 404s them. That broke client-side `<Link>` navigation to the
|
|
99
|
+
* component/pattern detail pages (their data fetch went to the function and came back 404, which the
|
|
100
|
+
* Next router then turns into a hard navigation). `getRequestHandlers` returns the full router-server
|
|
101
|
+
* handler (data-route resolution, dynamic param extraction, `trailingSlash` redirects), so on-demand
|
|
102
|
+
* data routes resolve the same way they do under the standalone server. `minimalMode:false` keeps
|
|
103
|
+
* the function doing full in-process routing (the catch-all route forwards everything here).
|
|
104
|
+
*
|
|
105
|
+
* Runtime mode, adapter, and the DB env-var *name* are already baked into the resolved config the
|
|
106
|
+
* standalone build wrote to `.next/required-server-files.json`; the connection-string value is still
|
|
107
|
+
* read from the named env var at request time, never baked.
|
|
108
|
+
*/
|
|
109
|
+
const REGISTRY_FUNCTION_LAUNCHER = `// Generated by handoff-app (\`build --target registry --package vercel\`). Do not edit.
|
|
110
|
+
// Wraps the Next.js standalone server as a Vercel Build Output API Node function.
|
|
111
|
+
process.env.NODE_ENV = 'production';
|
|
112
|
+
process.chdir(__dirname);
|
|
113
|
+
|
|
114
|
+
const requiredServerFiles = require('./.next/required-server-files.json');
|
|
115
|
+
const nextConfig = requiredServerFiles.config;
|
|
116
|
+
|
|
117
|
+
// The standalone runtime reads its resolved config from this env var (mirrors standalone server.js).
|
|
118
|
+
process.env.__NEXT_PRIVATE_STANDALONE_CONFIG = JSON.stringify(nextConfig);
|
|
119
|
+
|
|
120
|
+
// require('next') first so its module hooks are installed before pulling the internal server lib,
|
|
121
|
+
// matching the require order of the generated standalone server.js.
|
|
122
|
+
require('next');
|
|
123
|
+
const { getRequestHandlers } = require('next/dist/server/lib/start-server');
|
|
124
|
+
|
|
125
|
+
// Initialize the router-server handler once on cold start and reuse it across warm invocations.
|
|
126
|
+
// This is the same handler the standalone server.js uses; it does NOT bind a port (the port bind
|
|
127
|
+
// lives in startServer, which we never call), so it fits the (req, res) Node function contract.
|
|
128
|
+
let handlersPromise;
|
|
129
|
+
const ready = () =>
|
|
130
|
+
(handlersPromise =
|
|
131
|
+
handlersPromise ||
|
|
132
|
+
getRequestHandlers({
|
|
133
|
+
dir: __dirname,
|
|
134
|
+
port: parseInt(process.env.PORT, 10) || 3000,
|
|
135
|
+
hostname: process.env.HOSTNAME || 'localhost',
|
|
136
|
+
isDev: false,
|
|
137
|
+
minimalMode: false,
|
|
138
|
+
}));
|
|
139
|
+
|
|
140
|
+
module.exports = async (req, res) => {
|
|
141
|
+
const { requestHandler } = await ready();
|
|
142
|
+
return requestHandler(req, res);
|
|
143
|
+
};
|
|
144
|
+
`;
|
|
145
|
+
/**
|
|
146
|
+
* Copy the genuinely-static prerendered pages into the Edge CDN layer (`static/`) so their HTML and
|
|
147
|
+
* `_next/data` JSON are served directly by the CDN instead of invoking the single registry function.
|
|
148
|
+
* This is a load/latency optimization, not a correctness requirement: the function (see the launcher)
|
|
149
|
+
* now resolves on-demand data routes itself, so anything not copied here still resolves via the
|
|
150
|
+
* catch-all.
|
|
151
|
+
*
|
|
152
|
+
* Routes materialized from the mutable docs catch-all also appear in `routes` when package defaults
|
|
153
|
+
* are prerendered. They are identified by `srcRoute` and deliberately left behind the function so a
|
|
154
|
+
* published DB record can override the fallback. Other `fallback:'blocking'` dynamic routes are
|
|
155
|
+
* absent and naturally reach the function. Immutable pages — e.g. the header's `<Link href="/">`
|
|
156
|
+
* prefetch of `/_next/data/<buildId>/index.json` — are served straight from the CDN.
|
|
157
|
+
*
|
|
158
|
+
* No-op when nothing is prerendered (empty `routes`). Paths are emitted base-path-less, matching the
|
|
159
|
+
* existing `_next/static` copy and the registry route table.
|
|
160
|
+
*/
|
|
161
|
+
const copyPrerenderedStaticPages = (appPath, staticOutDir) => __awaiter(void 0, void 0, void 0, function* () {
|
|
162
|
+
var _a;
|
|
163
|
+
const nextDir = path_1.default.resolve(appPath, '.next');
|
|
164
|
+
const manifestPath = path_1.default.join(nextDir, 'prerender-manifest.json');
|
|
165
|
+
const buildIdPath = path_1.default.join(nextDir, 'BUILD_ID');
|
|
166
|
+
if (!fs_extra_1.default.existsSync(manifestPath) || !fs_extra_1.default.existsSync(buildIdPath)) {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
const manifest = (yield fs_extra_1.default.readJson(manifestPath));
|
|
170
|
+
const routes = (_a = manifest.routes) !== null && _a !== void 0 ? _a : {};
|
|
171
|
+
const serverPages = path_1.default.join(nextDir, 'server', 'pages');
|
|
172
|
+
let copied = 0;
|
|
173
|
+
for (const [route, routeConfig] of Object.entries(routes)) {
|
|
174
|
+
// A static copy would win at the Build Output API filesystem route and permanently hide a
|
|
175
|
+
// published override (and its on-demand revalidation) from the registry function.
|
|
176
|
+
if (routeConfig.srcRoute === MUTABLE_REGISTRY_PAGE_SRC_ROUTE) {
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
// `.next/server/pages/<rel>.{html,json}` — `/` maps to `index`, nested routes keep their path.
|
|
180
|
+
const rel = route === '/' ? 'index' : route.replace(/^\/+/, '');
|
|
181
|
+
const htmlSrc = path_1.default.join(serverPages, `${rel}.html`);
|
|
182
|
+
const jsonSrc = path_1.default.join(serverPages, `${rel}.json`);
|
|
183
|
+
if (fs_extra_1.default.existsSync(htmlSrc)) {
|
|
184
|
+
// trailingSlash:true → serve as `<route>/index.html`; `/` → `static/index.html`.
|
|
185
|
+
const htmlDestDir = route === '/' ? staticOutDir : path_1.default.join(staticOutDir, rel);
|
|
186
|
+
yield fs_extra_1.default.ensureDir(htmlDestDir);
|
|
187
|
+
yield fs_extra_1.default.copy(htmlSrc, path_1.default.join(htmlDestDir, 'index.html'), { overwrite: true });
|
|
188
|
+
}
|
|
189
|
+
// The data URL (with the build's BUILD_ID baked in) comes from the manifest's `dataRoute`.
|
|
190
|
+
const dataRoute = routeConfig.dataRoute;
|
|
191
|
+
if (dataRoute && fs_extra_1.default.existsSync(jsonSrc)) {
|
|
192
|
+
const jsonDest = path_1.default.join(staticOutDir, dataRoute.replace(/^\/+/, ''));
|
|
193
|
+
yield fs_extra_1.default.ensureDir(path_1.default.dirname(jsonDest));
|
|
194
|
+
yield fs_extra_1.default.copy(jsonSrc, jsonDest, { overwrite: true });
|
|
195
|
+
copied += 1;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
logger_1.Logger.info(`Copied ${copied} prerendered static page data file(s) into the Edge CDN layer.`);
|
|
199
|
+
});
|
|
200
|
+
/**
|
|
201
|
+
* Package the dynamic registry app as the Vercel Build Output API directory. Lays the traced
|
|
202
|
+
* standalone bundle into a single Node function (`functions/index.func/`)
|
|
203
|
+
* wrapping the Next standalone server, copies the immutable static assets + public tree under
|
|
204
|
+
* `static/` for the Edge CDN, and writes a route table that serves static files first and routes
|
|
205
|
+
* everything else (SSR pages, the docs read API, the registry API) to the function.
|
|
206
|
+
*
|
|
207
|
+
* Hard constraint: `.vercel/output` lives at the repo root with that exact name (see module header).
|
|
208
|
+
*/
|
|
209
|
+
const writeRegistryVercelOutput = (handoff, options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
210
|
+
const { appPath, standaloneRoot, assembleStandalone } = options;
|
|
211
|
+
const outputPath = (0, exports.getVercelOutputPath)(handoff);
|
|
212
|
+
yield fs_extra_1.default.remove(outputPath);
|
|
213
|
+
yield fs_extra_1.default.ensureDir(outputPath);
|
|
214
|
+
// The function directory *is* the standalone bundle root: the traced server + node_modules, the
|
|
215
|
+
// server entry flattened to its root, and `.next/static` + public + runtime config beside it. The
|
|
216
|
+
// launcher constructs a NextServer from this directory, so it needs the full standalone layout.
|
|
217
|
+
const functionDir = path_1.default.join(outputPath, 'functions', `${REGISTRY_FUNCTION_NAME}.func`);
|
|
218
|
+
yield fs_extra_1.default.ensureDir(functionDir);
|
|
219
|
+
yield assembleStandalone(handoff, appPath, standaloneRoot, functionDir);
|
|
220
|
+
// The standalone `server.js` binds a port; replace the entry with the Build Output API Node
|
|
221
|
+
// launcher (a `(req, res)` request listener) and declare the Node runtime so the pg/Neon drivers
|
|
222
|
+
// work. `server.js` is left in place (harmless, unused) to keep the bundle a valid standalone too.
|
|
223
|
+
yield fs_extra_1.default.writeFile(path_1.default.join(functionDir, REGISTRY_FUNCTION_HANDLER), REGISTRY_FUNCTION_LAUNCHER);
|
|
224
|
+
const functionConfig = {
|
|
225
|
+
runtime: VERCEL_NODE_RUNTIME,
|
|
226
|
+
handler: REGISTRY_FUNCTION_HANDLER,
|
|
227
|
+
launcherType: 'Nodejs',
|
|
228
|
+
};
|
|
229
|
+
yield fs_extra_1.default.writeFile(path_1.default.join(functionDir, '.vc-config.json'), `${JSON.stringify(functionConfig, null, 2)}\n`);
|
|
230
|
+
// Serve the app's immutable assets straight from the Edge CDN. `_next/static` is content-hashed and
|
|
231
|
+
// public files sit at the URL root; copying them under `static/` lets the route table satisfy them
|
|
232
|
+
// via `handle: filesystem` before the catch-all reaches the function.
|
|
233
|
+
const staticOutDir = path_1.default.join(outputPath, 'static');
|
|
234
|
+
yield fs_extra_1.default.ensureDir(staticOutDir);
|
|
235
|
+
const nextStaticSrc = path_1.default.resolve(appPath, '.next', 'static');
|
|
236
|
+
if (fs_extra_1.default.existsSync(nextStaticSrc)) {
|
|
237
|
+
yield fs_extra_1.default.copy(nextStaticSrc, path_1.default.join(staticOutDir, '_next', 'static'), { overwrite: true });
|
|
238
|
+
}
|
|
239
|
+
const publicSrc = path_1.default.resolve(appPath, 'public');
|
|
240
|
+
if (fs_extra_1.default.existsSync(publicSrc)) {
|
|
241
|
+
yield fs_extra_1.default.copy(publicSrc, staticOutDir, { overwrite: true });
|
|
242
|
+
}
|
|
243
|
+
// Serve genuinely-static prerendered pages (HTML + `_next/data` JSON) from the CDN as an
|
|
244
|
+
// optimization so they skip the function. Dynamic `fallback:'blocking'` pages are not copied (their
|
|
245
|
+
// data is live), and the function now resolves their on-demand `_next/data` routes itself.
|
|
246
|
+
yield copyPrerenderedStaticPages(appPath, staticOutDir);
|
|
247
|
+
// Route table: try static files first (`handle: filesystem` serves anything copied into static/),
|
|
248
|
+
// then route every remaining request — SSR/on-demand pages, their `/_next/data/*` routes,
|
|
249
|
+
// /api/docs/*, /api/registry/* — to the single function. The `.func` suffix is dropped from the
|
|
250
|
+
// URL, so `index.func` is reached via `/index`.
|
|
251
|
+
const config = {
|
|
252
|
+
version: BUILD_OUTPUT_API_VERSION,
|
|
253
|
+
routes: [{ handle: 'filesystem' }, { src: '/(.*)', dest: `/${REGISTRY_FUNCTION_NAME}` }],
|
|
254
|
+
};
|
|
255
|
+
yield fs_extra_1.default.writeFile(path_1.default.join(outputPath, 'config.json'), `${JSON.stringify(config, null, 2)}\n`);
|
|
256
|
+
logger_1.Logger.success(`Packaged registry Vercel Build Output API artifact at ${outputPath} ` +
|
|
257
|
+
`(functions/${REGISTRY_FUNCTION_NAME}.func + static/ + config.json).`);
|
|
258
|
+
});
|
|
259
|
+
exports.writeRegistryVercelOutput = writeRegistryVercelOutput;
|
|
@@ -5,6 +5,8 @@ export interface WatcherState {
|
|
|
5
5
|
runtimeComponentsWatcher: chokidar.FSWatcher | null;
|
|
6
6
|
runtimeConfigurationWatcher: chokidar.FSWatcher | null;
|
|
7
7
|
componentDirectoriesWatcher: chokidar.FSWatcher | null;
|
|
8
|
+
/** Watches entries.patterns parent directories for newly created pattern subdirectories. */
|
|
9
|
+
patternDirectoriesWatcher: chokidar.FSWatcher | null;
|
|
8
10
|
}
|
|
9
11
|
/**
|
|
10
12
|
* Schedules a handler for execution with mutual exclusion and per-source
|
|
@@ -36,9 +36,19 @@ export declare const watchRuntimeComponents: (handoff: Handoff, state: WatcherSt
|
|
|
36
36
|
*/
|
|
37
37
|
export declare const watchRuntimeConfiguration: (handoff: Handoff, state: WatcherState) => void;
|
|
38
38
|
/**
|
|
39
|
-
* Watches the parent component directories from config.entries.components
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
39
|
+
* Watches the parent component directories from config.entries.components for
|
|
40
|
+
* new components being added. When a new config file appears in a new
|
|
41
|
+
* subdirectory, reloads the runtime config, restarts the component and
|
|
42
|
+
* configuration watchers, then builds the new component and any patterns that
|
|
43
|
+
* reference it.
|
|
43
44
|
*/
|
|
44
45
|
export declare const watchComponentDirectories: (handoff: Handoff, state: WatcherState, chokidarConfig: chokidar.WatchOptions) => void;
|
|
46
|
+
/**
|
|
47
|
+
* Watches the parent pattern directories from config.entries.patterns for new
|
|
48
|
+
* patterns being added. The rebuild sequence intentionally differs from
|
|
49
|
+
* watchComponentDirectories because the dependency arrow is reversed: a new
|
|
50
|
+
* pattern references existing components, so we rebuild only the preview
|
|
51
|
+
* segment of those components (to produce the __pattern_* HTML files that
|
|
52
|
+
* injectPatternPreviews registered) before composing the pattern itself.
|
|
53
|
+
*/
|
|
54
|
+
export declare const watchPatternDirectories: (handoff: Handoff, state: WatcherState, chokidarConfig: chokidar.WatchOptions) => void;
|
|
@@ -35,10 +35,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
35
35
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
36
36
|
};
|
|
37
37
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
|
-
exports.watchComponentDirectories = exports.watchRuntimeConfiguration = exports.watchRuntimeComponents = exports.watchGlobalEntries = exports.watchPages = exports.watchAppSource = exports.watchPublicDirectory = exports.mapEntryTypeToSegment = exports.getRuntimeComponentsPathsToWatch = void 0;
|
|
38
|
+
exports.watchPatternDirectories = exports.watchComponentDirectories = exports.watchRuntimeConfiguration = exports.watchRuntimeComponents = exports.watchGlobalEntries = exports.watchPages = exports.watchAppSource = exports.watchPublicDirectory = exports.mapEntryTypeToSegment = exports.getRuntimeComponentsPathsToWatch = void 0;
|
|
39
39
|
const chokidar_1 = __importDefault(require("chokidar"));
|
|
40
40
|
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
41
41
|
const path_1 = __importDefault(require("path"));
|
|
42
|
+
const patterns_1 = require("../pipeline/patterns");
|
|
42
43
|
const builder_1 = __importStar(require("../transformers/preview/component/builder"));
|
|
43
44
|
const css_1 = require("../transformers/preview/component/css");
|
|
44
45
|
const javascript_1 = require("../transformers/preview/component/javascript");
|
|
@@ -226,6 +227,15 @@ const watchRuntimeComponents = (handoff, state, runtimeComponentPathsToWatch) =>
|
|
|
226
227
|
}
|
|
227
228
|
};
|
|
228
229
|
exports.watchRuntimeComponents = watchRuntimeComponents;
|
|
230
|
+
const rebuildPatternComponentPreviews = (handoff, patternId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
231
|
+
var _a, _b, _c, _d;
|
|
232
|
+
const pattern = (_c = (_b = (_a = handoff.runtimeConfig) === null || _a === void 0 ? void 0 : _a.entries) === null || _b === void 0 ? void 0 : _b.patterns) === null || _c === void 0 ? void 0 : _c[patternId];
|
|
233
|
+
if (!((_d = pattern === null || pattern === void 0 ? void 0 : pattern.components) === null || _d === void 0 ? void 0 : _d.length))
|
|
234
|
+
return;
|
|
235
|
+
for (const ref of pattern.components) {
|
|
236
|
+
yield (0, builder_1.default)(handoff, ref.id, builder_1.ComponentSegment.Previews);
|
|
237
|
+
}
|
|
238
|
+
});
|
|
229
239
|
/**
|
|
230
240
|
* Watches the runtime configuration for changes.
|
|
231
241
|
*
|
|
@@ -269,6 +279,9 @@ const watchRuntimeConfiguration = (handoff, state) => {
|
|
|
269
279
|
else if (handle) {
|
|
270
280
|
yield handle.apply(handoff, entryAfter === null || entryAfter === void 0 ? void 0 : entryAfter.entityId);
|
|
271
281
|
}
|
|
282
|
+
else if ((entryAfter === null || entryAfter === void 0 ? void 0 : entryAfter.kind) === 'pattern') {
|
|
283
|
+
yield rebuildPatternComponentPreviews(handoff, entryAfter.entityId);
|
|
284
|
+
}
|
|
272
285
|
else {
|
|
273
286
|
const effectiveId = (_a = entryAfter === null || entryAfter === void 0 ? void 0 : entryAfter.entityId) !== null && _a !== void 0 ? _a : path_1.default.basename(path_1.default.dirname(changedFile));
|
|
274
287
|
yield (0, builder_1.default)(handoff, effectiveId);
|
|
@@ -286,56 +299,138 @@ const watchRuntimeConfiguration = (handoff, state) => {
|
|
|
286
299
|
};
|
|
287
300
|
exports.watchRuntimeConfiguration = watchRuntimeConfiguration;
|
|
288
301
|
/**
|
|
289
|
-
*
|
|
290
|
-
*
|
|
291
|
-
*
|
|
292
|
-
*
|
|
302
|
+
* Shared factory for watching a parent directory for newly created entity
|
|
303
|
+
* subdirectories (components or patterns). Handles the common scaffolding so
|
|
304
|
+
* that callers only describe what differs for their entity kind:
|
|
305
|
+
*
|
|
306
|
+
* - which config-entry paths to watch
|
|
307
|
+
* - how to read the current known ids after a reload
|
|
308
|
+
* - which WatcherState slot to use
|
|
309
|
+
* - a log label for the entity kind
|
|
310
|
+
* - the rebuild work to run once the runtime config is fresh
|
|
293
311
|
*/
|
|
294
|
-
const
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
312
|
+
const watchEntityDirectories = (handoff, state, chokidarConfig, options) => {
|
|
313
|
+
const { getConfigPaths, getKnownIds, getWatcher, setWatcher, scheduleKeyPrefix, entityLabel, onDetected } = options;
|
|
314
|
+
const existingWatcher = getWatcher(state);
|
|
315
|
+
if (existingWatcher) {
|
|
316
|
+
existingWatcher.close();
|
|
298
317
|
}
|
|
299
|
-
const
|
|
300
|
-
if (
|
|
318
|
+
const configPaths = getConfigPaths(handoff);
|
|
319
|
+
if (configPaths.length === 0)
|
|
301
320
|
return;
|
|
302
321
|
const dirsToWatch = [];
|
|
303
|
-
for (const
|
|
304
|
-
const resolved = path_1.default.resolve(handoff.workingPath,
|
|
322
|
+
for (const configPath of configPaths) {
|
|
323
|
+
const resolved = path_1.default.resolve(handoff.workingPath, configPath);
|
|
305
324
|
if (fs_extra_1.default.existsSync(resolved) && fs_extra_1.default.statSync(resolved).isDirectory()) {
|
|
306
325
|
dirsToWatch.push(resolved);
|
|
307
326
|
}
|
|
308
327
|
}
|
|
309
328
|
if (dirsToWatch.length === 0)
|
|
310
329
|
return;
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
330
|
+
// Snapshot known ids at watch startup so we only react to genuinely new
|
|
331
|
+
// entities, not to file changes inside already-known directories.
|
|
332
|
+
const knownIds = new Set(getKnownIds(handoff));
|
|
333
|
+
const watcher = chokidar_1.default.watch(dirsToWatch, Object.assign(Object.assign({}, chokidarConfig), { depth: 1 }));
|
|
334
|
+
setWatcher(state, watcher);
|
|
335
|
+
watcher.on('add', (file) => __awaiter(void 0, void 0, void 0, function* () {
|
|
314
336
|
const basename = path_1.default.basename(file);
|
|
315
337
|
const dirName = path_1.default.basename(path_1.default.dirname(file));
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
338
|
+
// Only react to the primary declaration file for the directory (e.g.
|
|
339
|
+
// button.json, button.js, or button.handoff.ts inside a button/ subdir).
|
|
340
|
+
// The basename.startsWith(dirName) guard below ensures .ts here only
|
|
341
|
+
// ever matches files named after their parent directory, not arbitrary
|
|
342
|
+
// TypeScript source files.
|
|
343
|
+
const isConfigFile = basename.endsWith('.json') || basename.endsWith('.js') || basename.endsWith('.cjs') || basename.endsWith('.ts');
|
|
344
|
+
const isNewEntity = isConfigFile && basename.startsWith(dirName) && !knownIds.has(dirName);
|
|
345
|
+
if (!isNewEntity)
|
|
319
346
|
return;
|
|
320
|
-
yield (0, utils_1.scheduleHandler)(state,
|
|
321
|
-
var _a, _b, _c;
|
|
347
|
+
yield (0, utils_1.scheduleHandler)(state, `${scheduleKeyPrefix}:${dirName}`, () => __awaiter(void 0, void 0, void 0, function* () {
|
|
322
348
|
try {
|
|
323
|
-
logger_1.Logger.warn(`New
|
|
349
|
+
logger_1.Logger.warn(`New ${entityLabel} detected: ${dirName}. Reloading configuration...`);
|
|
350
|
+
// Snapshot ids before reload so we can tell whether the new entity
|
|
351
|
+
// was successfully registered afterwards.
|
|
352
|
+
const idsBefore = new Set(getKnownIds(handoff));
|
|
324
353
|
handoff.reload();
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
354
|
+
// Refresh from the post-reload runtime config so any ids that were
|
|
355
|
+
// discovered alongside the new entity are also marked as known.
|
|
356
|
+
const idsAfter = getKnownIds(handoff);
|
|
357
|
+
const addedIds = idsAfter.filter((id) => !idsBefore.has(id));
|
|
358
|
+
for (const id of idsAfter) {
|
|
359
|
+
knownIds.add(id);
|
|
328
360
|
}
|
|
329
361
|
yield (0, client_config_1.persistClientConfig)(handoff);
|
|
362
|
+
// Re-register file watchers so the new config file and any runtime
|
|
363
|
+
// files it introduces are covered going forward. This must happen even
|
|
364
|
+
// when the file failed to parse so that watchRuntimeConfiguration can
|
|
365
|
+
// trigger a retry the moment the file is saved with valid content.
|
|
330
366
|
(0, exports.watchRuntimeComponents)(handoff, state, (0, component_1.getRuntimeComponentsPathsToWatch)(handoff));
|
|
331
367
|
(0, exports.watchRuntimeConfiguration)(handoff, state);
|
|
332
|
-
|
|
333
|
-
|
|
368
|
+
// If no new ids appeared after reload the file was empty or invalid.
|
|
369
|
+
// Skip the build — watchRuntimeConfiguration will fire when it is saved.
|
|
370
|
+
if (addedIds.length === 0) {
|
|
371
|
+
logger_1.Logger.warn(`${entityLabel} "${dirName}" config is empty or incomplete — build will run automatically once the file is saved.`);
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
yield onDetected(handoff, { dirName, addedIds });
|
|
334
375
|
}
|
|
335
376
|
catch (e) {
|
|
336
|
-
logger_1.Logger.error(
|
|
377
|
+
logger_1.Logger.error(`Error processing new ${entityLabel}:`, e);
|
|
337
378
|
}
|
|
338
379
|
}));
|
|
339
380
|
}));
|
|
340
381
|
};
|
|
382
|
+
/**
|
|
383
|
+
* Watches the parent component directories from config.entries.components for
|
|
384
|
+
* new components being added. When a new config file appears in a new
|
|
385
|
+
* subdirectory, reloads the runtime config, restarts the component and
|
|
386
|
+
* configuration watchers, then builds the new component and any patterns that
|
|
387
|
+
* reference it.
|
|
388
|
+
*/
|
|
389
|
+
const watchComponentDirectories = (handoff, state, chokidarConfig) => {
|
|
390
|
+
watchEntityDirectories(handoff, state, chokidarConfig, {
|
|
391
|
+
getConfigPaths: (h) => { var _a, _b; return (_b = (_a = h.config.entries) === null || _a === void 0 ? void 0 : _a.components) !== null && _b !== void 0 ? _b : []; },
|
|
392
|
+
getKnownIds: (h) => { var _a, _b, _c; return Object.keys((_c = (_b = (_a = h.runtimeConfig) === null || _a === void 0 ? void 0 : _a.entries) === null || _b === void 0 ? void 0 : _b.components) !== null && _c !== void 0 ? _c : {}); },
|
|
393
|
+
getWatcher: (s) => s.componentDirectoriesWatcher,
|
|
394
|
+
setWatcher: (s, w) => { s.componentDirectoriesWatcher = w; },
|
|
395
|
+
scheduleKeyPrefix: 'newComponent',
|
|
396
|
+
entityLabel: 'component',
|
|
397
|
+
onDetected: (handoff_1, _a) => __awaiter(void 0, [handoff_1, _a], void 0, function* (handoff, { addedIds }) {
|
|
398
|
+
for (const componentId of addedIds) {
|
|
399
|
+
yield (0, builder_1.default)(handoff, componentId);
|
|
400
|
+
yield (0, config_diff_1.runAllFinalizers)(handoff, { patternRebuildComponentIds: [componentId] });
|
|
401
|
+
}
|
|
402
|
+
}),
|
|
403
|
+
});
|
|
404
|
+
};
|
|
341
405
|
exports.watchComponentDirectories = watchComponentDirectories;
|
|
406
|
+
/**
|
|
407
|
+
* Watches the parent pattern directories from config.entries.patterns for new
|
|
408
|
+
* patterns being added. The rebuild sequence intentionally differs from
|
|
409
|
+
* watchComponentDirectories because the dependency arrow is reversed: a new
|
|
410
|
+
* pattern references existing components, so we rebuild only the preview
|
|
411
|
+
* segment of those components (to produce the __pattern_* HTML files that
|
|
412
|
+
* injectPatternPreviews registered) before composing the pattern itself.
|
|
413
|
+
*/
|
|
414
|
+
const watchPatternDirectories = (handoff, state, chokidarConfig) => {
|
|
415
|
+
watchEntityDirectories(handoff, state, chokidarConfig, {
|
|
416
|
+
getConfigPaths: (h) => { var _a, _b; return (_b = (_a = h.config.entries) === null || _a === void 0 ? void 0 : _a.patterns) !== null && _b !== void 0 ? _b : []; },
|
|
417
|
+
getKnownIds: (h) => { var _a, _b, _c; return Object.keys((_c = (_b = (_a = h.runtimeConfig) === null || _a === void 0 ? void 0 : _a.entries) === null || _b === void 0 ? void 0 : _b.patterns) !== null && _c !== void 0 ? _c : {}); },
|
|
418
|
+
getWatcher: (s) => s.patternDirectoriesWatcher,
|
|
419
|
+
setWatcher: (s, w) => { s.patternDirectoriesWatcher = w; },
|
|
420
|
+
scheduleKeyPrefix: 'newPattern',
|
|
421
|
+
entityLabel: 'pattern',
|
|
422
|
+
onDetected: (handoff_1, _a) => __awaiter(void 0, [handoff_1, _a], void 0, function* (handoff, { addedIds }) {
|
|
423
|
+
// Rebuild only the previews segment for each component the new pattern
|
|
424
|
+
// references. Their JS/CSS/structure are unchanged — only the new
|
|
425
|
+
// synthetic preview HTML files need to be generated so that buildPatterns
|
|
426
|
+
// can assemble the pattern from them.
|
|
427
|
+
for (const patternId of addedIds) {
|
|
428
|
+
yield rebuildPatternComponentPreviews(handoff, patternId);
|
|
429
|
+
}
|
|
430
|
+
// Build only the new pattern directly rather than going through
|
|
431
|
+
// runAllFinalizers, which would rebuild all patterns unnecessarily.
|
|
432
|
+
yield (0, patterns_1.buildPatterns)(handoff, { onlyPatternIds: new Set(addedIds) });
|
|
433
|
+
}),
|
|
434
|
+
});
|
|
435
|
+
};
|
|
436
|
+
exports.watchPatternDirectories = watchPatternDirectories;
|
|
@@ -21,7 +21,7 @@ const logger_1 = require("../utils/logger");
|
|
|
21
21
|
*/
|
|
22
22
|
const createWebSocketServer = (...args_1) => __awaiter(void 0, [...args_1], void 0, function* (port = 3001) {
|
|
23
23
|
logger_1.Logger.info(`Starting WebSocket server for live reload on port ${port}…`);
|
|
24
|
-
const wss = new ws_1.
|
|
24
|
+
const wss = new ws_1.WebSocketServer({ port });
|
|
25
25
|
wss.on('listening', () => {
|
|
26
26
|
logger_1.Logger.info(`WebSocket server listening on ws://localhost:${port} (live reload)`);
|
|
27
27
|
});
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export { ARTIFACT_METADATA_PATH, REACT_PREVIEW_FORMAT_VERSION, SHARED_MAIN_CSS_ARTIFACT_PATH, SHARED_MAIN_JS_ARTIFACT_PATH, SHARED_STYLES_CSS_ARTIFACT_PATH, type ArtifactBuildMetadata, type ArtifactBuildStatus, type ArtifactDescriptor, type ArtifactKind, type ArtifactOwnerKind, type ArtifactReference, type ArtifactReferenceKind, type ArtifactSizeDiagnostics, } from './types';
|
|
2
|
+
export { ARTIFACTS_ROUTE_SEGMENT, ASSETS_ROUTE_SEGMENT, buildArtifactUrl, buildAssetDownloadUrl, buildAssetUrl, normalizeBasePath, } from './url';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.normalizeBasePath = exports.buildAssetUrl = exports.buildAssetDownloadUrl = exports.buildArtifactUrl = exports.ASSETS_ROUTE_SEGMENT = exports.ARTIFACTS_ROUTE_SEGMENT = exports.SHARED_STYLES_CSS_ARTIFACT_PATH = exports.SHARED_MAIN_JS_ARTIFACT_PATH = exports.SHARED_MAIN_CSS_ARTIFACT_PATH = exports.REACT_PREVIEW_FORMAT_VERSION = exports.ARTIFACT_METADATA_PATH = void 0;
|
|
4
|
+
var types_1 = require("./types");
|
|
5
|
+
Object.defineProperty(exports, "ARTIFACT_METADATA_PATH", { enumerable: true, get: function () { return types_1.ARTIFACT_METADATA_PATH; } });
|
|
6
|
+
Object.defineProperty(exports, "REACT_PREVIEW_FORMAT_VERSION", { enumerable: true, get: function () { return types_1.REACT_PREVIEW_FORMAT_VERSION; } });
|
|
7
|
+
Object.defineProperty(exports, "SHARED_MAIN_CSS_ARTIFACT_PATH", { enumerable: true, get: function () { return types_1.SHARED_MAIN_CSS_ARTIFACT_PATH; } });
|
|
8
|
+
Object.defineProperty(exports, "SHARED_MAIN_JS_ARTIFACT_PATH", { enumerable: true, get: function () { return types_1.SHARED_MAIN_JS_ARTIFACT_PATH; } });
|
|
9
|
+
Object.defineProperty(exports, "SHARED_STYLES_CSS_ARTIFACT_PATH", { enumerable: true, get: function () { return types_1.SHARED_STYLES_CSS_ARTIFACT_PATH; } });
|
|
10
|
+
var url_1 = require("./url");
|
|
11
|
+
Object.defineProperty(exports, "ARTIFACTS_ROUTE_SEGMENT", { enumerable: true, get: function () { return url_1.ARTIFACTS_ROUTE_SEGMENT; } });
|
|
12
|
+
Object.defineProperty(exports, "ASSETS_ROUTE_SEGMENT", { enumerable: true, get: function () { return url_1.ASSETS_ROUTE_SEGMENT; } });
|
|
13
|
+
Object.defineProperty(exports, "buildArtifactUrl", { enumerable: true, get: function () { return url_1.buildArtifactUrl; } });
|
|
14
|
+
Object.defineProperty(exports, "buildAssetDownloadUrl", { enumerable: true, get: function () { return url_1.buildAssetDownloadUrl; } });
|
|
15
|
+
Object.defineProperty(exports, "buildAssetUrl", { enumerable: true, get: function () { return url_1.buildAssetUrl; } });
|
|
16
|
+
Object.defineProperty(exports, "normalizeBasePath", { enumerable: true, get: function () { return url_1.normalizeBasePath; } });
|