handoff-app 2.0.0-0 → 2.0.0-10
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/AGENTS.md +7 -0
- package/CLAUDE.md +7 -0
- package/README.md +732 -304
- package/UPGRADE.md +218 -0
- package/config/config.template.js +1 -4
- package/config/config.template.ts +1 -2
- package/config/docs/foundations/colors/guidelines.md +9 -0
- package/config/docs/foundations/effects/guidelines.md +9 -0
- package/config/docs/foundations/effects/resources.md +9 -0
- package/config/docs/foundations/grid.md +10 -0
- package/config/docs/foundations/icons/guidelines.md +9 -0
- package/config/docs/foundations/images/guidelines.md +9 -0
- package/config/docs/foundations/images/resources.md +9 -0
- package/config/docs/foundations/images.md +10 -0
- package/config/docs/foundations/logo/resources.md +9 -0
- package/config/docs/foundations/typography/guidelines.md +9 -0
- package/config/docs/foundations/typography/resources.md +9 -0
- package/config/docs/foundations.md +5 -3
- package/dist/ai/connections.d.ts +64 -0
- package/dist/ai/connections.js +136 -0
- package/dist/ai/define.d.ts +10 -0
- package/dist/ai/define.js +13 -0
- package/dist/ai/types.d.ts +27 -0
- package/dist/ai/types.js +10 -0
- package/dist/app-builder/build.d.ts +12 -0
- package/dist/app-builder/build.js +227 -69
- package/dist/app-builder/client-config.js +16 -12
- package/dist/app-builder/config-diff/strategies/pattern.js +3 -3
- package/dist/app-builder/nav-shell.js +8 -15
- package/dist/app-builder/paths.js +23 -1
- package/dist/app-builder/static-export.js +25 -0
- package/dist/app-builder/vercel-output.js +6 -6
- package/dist/app-builder/watchers/component.js +5 -5
- package/dist/app-builder/watchers/utils.d.ts +2 -3
- package/dist/app-builder/watchers.d.ts +8 -15
- package/dist/app-builder/watchers.js +70 -61
- package/dist/artifacts/index.d.ts +1 -1
- package/dist/artifacts/index.js +4 -1
- package/dist/artifacts/url.d.ts +18 -0
- package/dist/artifacts/url.js +31 -1
- package/dist/cache/build-cache.js +23 -23
- package/dist/catalog/define.d.ts +6 -0
- package/dist/catalog/define.js +72 -0
- package/dist/catalog/implementation.d.ts +27 -0
- package/dist/catalog/implementation.js +133 -0
- package/dist/catalog/index.d.ts +6 -0
- package/dist/catalog/index.js +22 -0
- package/dist/catalog/normalize.d.ts +16 -0
- package/dist/catalog/normalize.js +118 -0
- package/dist/catalog/previews.d.ts +18 -0
- package/dist/catalog/previews.js +107 -0
- package/dist/catalog/renderers.d.ts +43 -0
- package/dist/catalog/renderers.js +62 -0
- package/dist/catalog/types.d.ts +71 -0
- package/dist/cli/auth/browser.d.ts +2 -0
- package/dist/cli/auth/browser.js +33 -0
- package/dist/cli/auth/device.d.ts +16 -0
- package/dist/cli/auth/device.js +158 -0
- package/dist/cli/auth/store.d.ts +38 -0
- package/dist/cli/auth/store.js +199 -0
- package/dist/cli/create.js +48 -3
- package/dist/cli/make.d.ts +0 -5
- package/dist/cli/make.js +24 -69
- package/dist/cli/scaffold.js +39 -181
- package/dist/cli.js +39 -7
- package/dist/commands/build/app.js +1 -5
- package/dist/commands/build/components.js +1 -5
- package/dist/commands/build/index.js +1 -5
- package/dist/commands/checkout/index.d.ts +18 -12
- package/dist/commands/checkout/index.js +19 -59
- package/dist/commands/compat/deprecations.d.ts +46 -0
- package/dist/commands/compat/deprecations.js +62 -0
- package/dist/commands/compat/push-args.d.ts +48 -0
- package/dist/commands/compat/push-args.js +73 -0
- package/dist/commands/db/migrate.js +1 -5
- package/dist/commands/dev/index.js +1 -5
- package/dist/commands/eject/config.js +1 -5
- package/dist/commands/eject/pages.js +1 -5
- package/dist/commands/eject/theme.js +1 -5
- package/dist/commands/fetch/index.js +1 -5
- package/dist/commands/index.js +8 -2
- package/dist/commands/login/index.d.ts +13 -0
- package/dist/commands/login/index.js +61 -0
- package/dist/commands/logout/index.d.ts +12 -0
- package/dist/commands/logout/index.js +89 -0
- package/dist/commands/make/component.js +1 -5
- package/dist/commands/make/page.js +3 -7
- package/dist/commands/publish/index.d.ts +21 -11
- package/dist/commands/publish/index.js +22 -58
- package/dist/commands/pull/index.d.ts +13 -0
- package/dist/commands/pull/index.js +20 -0
- package/dist/commands/push/index.d.ts +23 -0
- package/dist/commands/push/index.js +58 -0
- package/dist/commands/scaffold/index.js +1 -5
- package/dist/commands/start/index.js +1 -5
- package/dist/commands/types.d.ts +12 -0
- package/dist/commands/utils.d.ts +100 -1
- package/dist/commands/utils.js +103 -2
- package/dist/commands/validate/components.js +1 -5
- package/dist/config/catalog-include.d.ts +43 -0
- package/dist/config/catalog-include.js +203 -0
- package/dist/config/defaults.d.ts +4 -2
- package/dist/config/defaults.js +58 -49
- package/dist/config/env.d.ts +9 -0
- package/dist/config/env.js +43 -0
- package/dist/config/errors.d.ts +4 -0
- package/dist/config/errors.js +11 -0
- package/dist/config/from-env.d.ts +24 -0
- package/dist/config/from-env.js +7 -0
- package/dist/config/helpers.d.ts +2 -0
- package/dist/config/helpers.js +3 -1
- package/dist/config/index.d.ts +6 -2
- package/dist/config/index.js +12 -1
- package/dist/config/loader.d.ts +40 -9
- package/dist/config/loader.js +148 -35
- package/dist/config/normalizers/page.d.ts +4 -4
- package/dist/config/normalizers/page.js +2 -2
- package/dist/config/resolve-env.d.ts +6 -0
- package/dist/config/resolve-env.js +115 -0
- package/dist/config/runtime.d.ts +15 -16
- package/dist/config/runtime.js +178 -196
- package/dist/config/validator.d.ts +2 -2
- package/dist/config/validator.js +2 -4
- package/dist/handlebars.d.ts +17 -0
- package/dist/handlebars.js +16 -0
- package/dist/index.d.ts +120 -27
- package/dist/index.js +242 -53
- package/dist/nav/resolver.js +3 -1
- package/dist/nav/workspace.js +2 -2
- package/dist/pattern.d.ts +7 -0
- package/dist/pattern.js +13 -0
- package/dist/pipeline/index.d.ts +1 -1
- package/dist/pipeline/index.js +1 -1
- package/dist/react.d.ts +43 -0
- package/dist/react.js +11 -0
- package/dist/registry/asset-storage/adapters/vercel-blob.js +1 -1
- package/dist/registry/asset-storage/define.d.ts +1 -1
- package/dist/registry/asset-storage/define.js +1 -1
- package/dist/registry/asset-storage/resolve.d.ts +3 -3
- package/dist/registry/asset-storage/resolve.js +5 -2
- package/dist/registry/auth/access-tokens.d.ts +54 -0
- package/dist/registry/auth/access-tokens.js +191 -0
- package/dist/registry/auth/action-tokens.d.ts +66 -0
- package/dist/registry/auth/action-tokens.js +178 -0
- package/dist/registry/auth/ai-keys.d.ts +32 -0
- package/dist/registry/auth/ai-keys.js +69 -0
- package/dist/registry/auth/crypto.d.ts +21 -0
- package/dist/registry/auth/crypto.js +76 -0
- package/dist/registry/auth/database.d.ts +7 -0
- package/dist/registry/auth/database.js +22 -0
- package/dist/registry/auth/device-authorizations.d.ts +51 -0
- package/dist/registry/auth/device-authorizations.js +170 -0
- package/dist/registry/auth/gravatar.d.ts +1 -0
- package/dist/registry/auth/gravatar.js +8 -0
- package/dist/registry/auth/index.d.ts +13 -0
- package/dist/registry/auth/index.js +89 -0
- package/dist/registry/auth/installation.d.ts +42 -0
- package/dist/registry/auth/installation.js +105 -0
- package/dist/registry/auth/password.d.ts +12 -0
- package/dist/registry/auth/password.js +58 -0
- package/dist/registry/auth/rate-limits.d.ts +22 -0
- package/dist/registry/auth/rate-limits.js +75 -0
- package/dist/registry/auth/sync-secret.d.ts +27 -0
- package/dist/registry/auth/sync-secret.js +65 -0
- package/dist/registry/auth/types.d.ts +45 -0
- package/dist/registry/auth/types.js +11 -0
- package/dist/registry/auth/user-record.d.ts +13 -0
- package/dist/registry/auth/user-record.js +16 -0
- package/dist/registry/auth/users.d.ts +31 -0
- package/dist/registry/auth/users.js +135 -0
- package/dist/registry/auth/validation.d.ts +14 -0
- package/dist/registry/auth/validation.js +45 -0
- package/dist/registry/checkout/assets.d.ts +1 -1
- package/dist/registry/checkout/assets.js +25 -8
- package/dist/registry/checkout/index.d.ts +27 -6
- package/dist/registry/checkout/index.js +479 -131
- package/dist/registry/checkout/tokens.d.ts +1 -1
- package/dist/registry/checkout/tokens.js +16 -7
- package/dist/registry/client.d.ts +2 -1
- package/dist/registry/client.js +8 -0
- package/dist/registry/connection.d.ts +34 -11
- package/dist/registry/connection.js +77 -18
- package/dist/registry/content-kinds.d.ts +27 -0
- package/dist/registry/content-kinds.js +33 -0
- package/dist/registry/db/client.d.ts +14 -9
- package/dist/registry/db/client.js +22 -9
- package/dist/registry/db/driver.d.ts +39 -0
- package/dist/registry/db/driver.js +50 -0
- package/dist/registry/db/index.d.ts +2 -2
- package/dist/registry/db/index.js +14 -9
- package/dist/registry/db/migrate.d.ts +1 -1
- package/dist/registry/db/migrate.js +5 -5
- package/dist/registry/db/schema.d.ts +2992 -963
- package/dist/registry/db/schema.js +158 -8
- package/dist/registry/publish/assets.d.ts +2 -2
- package/dist/registry/publish/assets.js +46 -35
- package/dist/registry/publish/errors.js +3 -3
- package/dist/registry/publish/index.d.ts +45 -3
- package/dist/registry/publish/index.js +247 -24
- package/dist/registry/publish/package.js +14 -1
- package/dist/registry/publish/tokens.d.ts +2 -2
- package/dist/registry/publish/tokens.js +30 -24
- package/dist/registry/selection.d.ts +32 -0
- package/dist/registry/selection.js +58 -0
- package/dist/registry/transfer.d.ts +13 -0
- package/dist/store/filesystem.d.ts +3 -3
- package/dist/store/filesystem.js +7 -7
- package/dist/store/registry.d.ts +48 -0
- package/dist/store/registry.js +99 -15
- package/dist/transformers/plugins/csf-render.js +4 -2
- package/dist/transformers/plugins/ssr-render.js +52 -18
- package/dist/transformers/preview/component/api.d.ts +8 -0
- package/dist/transformers/preview/component/api.js +11 -15
- package/dist/transformers/preview/component/artifacts.d.ts +1 -1
- package/dist/transformers/preview/component/artifacts.js +11 -7
- package/dist/transformers/preview/component/builder.js +15 -18
- package/dist/transformers/preview/component/css.d.ts +3 -0
- package/dist/transformers/preview/component/css.js +93 -58
- package/dist/transformers/preview/component/html.js +18 -16
- package/dist/transformers/preview/component/javascript.js +2 -4
- package/dist/transformers/preview/pattern/builder.js +31 -18
- package/dist/transformers/preview/pattern/html.js +3 -1
- package/dist/transformers/preview/types.d.ts +30 -3
- package/dist/transformers/utils/build.d.ts +19 -0
- package/dist/transformers/utils/build.js +83 -1
- package/dist/transformers/utils/module.js +2 -1
- package/dist/types/config.d.ts +156 -45
- package/dist/utils/markdown.d.ts +10 -0
- package/dist/utils/markdown.js +17 -0
- package/dist/utils/menu-shell.js +14 -7
- package/dist/utils/pages.d.ts +22 -0
- package/dist/utils/pages.js +73 -0
- package/dist/utils/path.d.ts +5 -0
- package/dist/utils/path.js +9 -0
- package/docs/api.md +35 -3
- package/docs/cli.md +6 -2
- package/drizzle/0002_add_pages.sql +5 -3
- package/drizzle/0005_add_registry_auth.sql +95 -0
- package/drizzle/0006_add_component_source_format.sql +3 -0
- package/drizzle/0007_add_ai_keys.sql +11 -0
- package/drizzle/meta/0002_snapshot.json +17 -8
- package/drizzle/meta/0003_snapshot.json +17 -8
- package/drizzle/meta/0004_snapshot.json +17 -8
- package/drizzle/meta/0005_snapshot.json +1935 -0
- package/drizzle/meta/0006_snapshot.json +1941 -0
- package/drizzle/meta/0007_snapshot.json +2013 -0
- package/drizzle/meta/_journal.json +21 -0
- package/drizzle.config.ts +1 -1
- package/package.json +44 -5
- package/src/ai/README.md +42 -0
- package/src/ai/connections.ts +172 -0
- package/src/ai/define.ts +15 -0
- package/src/ai/types.ts +31 -0
- package/src/app/components/AiAssistant/AiAssistantPanel.tsx +144 -0
- package/src/app/components/AiAssistant/AiAssistantProvider.tsx +215 -0
- package/src/app/components/AiAssistant/AiConversation.tsx +674 -0
- package/src/app/components/AiAssistant/AiToolResult.tsx +99 -0
- package/src/app/components/AiAssistant/dockState.ts +86 -0
- package/src/app/components/AiAssistant/toolLabel.ts +22 -0
- package/src/app/components/AiAssistant/useAiChat.ts +147 -0
- package/src/app/components/AiAssistant/useAiConnections.ts +86 -0
- package/src/app/components/AiAssistant/usePageContext.ts +59 -0
- package/src/app/components/Auth/AccountLayout.tsx +124 -0
- package/src/app/components/Auth/AuthControls.tsx +99 -0
- package/src/app/components/Auth/AuthShell.tsx +73 -0
- package/src/app/components/Auth/RegistryInstallGate.tsx +23 -0
- package/src/app/components/Auth/RegistrySessionProvider.tsx +15 -0
- package/src/app/components/Auth/api.ts +20 -0
- package/src/app/components/Component/PageSliceResolver.tsx +1 -0
- package/src/app/components/Component/Preview.tsx +406 -226
- package/src/app/components/Component/slices/ComponentDisplaySlice.tsx +4 -0
- package/src/app/components/CopyToClipboard.tsx +27 -26
- package/src/app/components/Foundations/DisplayLogo.tsx +8 -2
- package/src/app/components/Layout/Header.tsx +10 -14
- package/src/app/components/Layout/RuntimeModeBadge.tsx +18 -0
- package/src/app/components/Markdown/CodeHighlight.tsx +73 -70
- package/src/app/components/Markdown/MarkdownComponents.tsx +30 -32
- package/src/app/components/McpIntegration/McpConfigDialog.tsx +349 -0
- package/src/app/components/McpIntegration/McpIcon.tsx +10 -0
- package/src/app/components/Navigation/MobileNav.tsx +7 -1
- package/src/app/components/Navigation/SideNav.tsx +1 -15
- package/src/app/components/context/PreviewContext.tsx +5 -5
- package/src/app/components/ui/attachment.tsx +50 -0
- package/src/app/components/ui/bubble.tsx +57 -0
- package/src/app/components/ui/button.tsx +3 -1
- package/src/app/components/ui/dialog.tsx +73 -0
- package/src/app/components/ui/marker.tsx +56 -0
- package/src/app/components/ui/sidebar.tsx +3 -1
- package/src/app/components/util/index.ts +14 -38
- package/src/app/css/index.css +64 -0
- package/src/app/lib/ai/auth.ts +33 -0
- package/src/app/lib/ai/context.ts +96 -0
- package/src/app/lib/ai/model.ts +85 -0
- package/src/app/lib/ai/prompt.ts +36 -0
- package/src/app/lib/ai/resolve.ts +97 -0
- package/src/app/lib/ai/tools.ts +120 -0
- package/src/app/lib/api/methods.ts +13 -0
- package/src/app/lib/auth/api.ts +105 -0
- package/src/app/lib/auth/config.ts +175 -0
- package/src/app/lib/auth/email.ts +34 -0
- package/src/app/lib/docs-api/backend.ts +16 -1
- package/src/app/lib/docs-api/errors.ts +8 -7
- package/src/app/lib/docs-api/handler.ts +2 -3
- package/src/app/lib/docs-api/index.ts +2 -0
- package/src/app/lib/docs-api/page-discovery.ts +121 -0
- package/src/app/lib/docs-api/page-rendering.ts +37 -0
- package/src/app/lib/docs-api/page-search.ts +191 -0
- package/src/app/lib/docs-api/records.ts +31 -24
- package/src/app/lib/docs-api/registry.ts +92 -11
- package/src/app/lib/docs-api/runtime-config.ts +42 -35
- package/src/app/lib/docs-api/search.ts +120 -0
- package/src/app/lib/mcp/auth.ts +64 -0
- package/src/app/lib/mcp/index.ts +2 -0
- package/src/app/lib/mcp/server.ts +357 -0
- package/src/app/lib/mcp/shape.ts +628 -0
- package/src/app/lib/registry-api/allowlist.ts +7 -5
- package/src/app/lib/registry-api/asset-transfer.ts +58 -31
- package/src/app/lib/registry-api/auth.ts +108 -45
- package/src/app/lib/registry-api/entity-routes.ts +17 -7
- package/src/app/lib/registry-api/errors.ts +12 -6
- package/src/app/lib/registry-api/handler.ts +22 -19
- package/src/app/lib/registry-api/meta.ts +4 -0
- package/src/app/lib/registry-api/revalidate.ts +31 -12
- package/src/app/lib/registry-api/store.ts +89 -26
- package/src/app/lib/registry-api/sync-compat.ts +166 -0
- package/src/app/lib/registry-api/token-transfer.ts +45 -13
- package/src/app/lib/registry-api/transfer-batch.ts +116 -0
- package/src/app/lib/registry-api/transfer.ts +99 -41
- package/src/app/lib/registry-api/validation.ts +33 -1
- package/src/app/lib/registry-connection.ts +2 -2
- package/src/app/lib/utils.ts +13 -0
- package/src/app/next.config.mjs +62 -16
- package/src/app/pages/[...slug]/index.tsx +52 -51
- package/src/app/pages/_app.tsx +14 -4
- package/src/app/pages/_document.tsx +6 -0
- package/src/app/pages/account/ai.tsx +162 -0
- package/src/app/pages/account/index.tsx +148 -0
- package/src/app/pages/account/tokens.tsx +232 -0
- package/src/app/pages/account/users.tsx +310 -0
- package/src/app/pages/api/account/ai/keys/[connectionId].ts +60 -0
- package/src/app/pages/api/account/ai/keys/index.ts +20 -0
- package/src/app/pages/api/account/index.ts +26 -0
- package/src/app/pages/api/account/tokens/[id].ts +17 -0
- package/src/app/pages/api/account/tokens/index.ts +35 -0
- package/src/app/pages/api/admin/users/[id]/[action].ts +89 -0
- package/src/app/pages/api/admin/users/index.ts +53 -0
- package/src/app/pages/api/ai/chat.ts +115 -0
- package/src/app/pages/api/ai/connections.ts +23 -0
- package/src/app/pages/api/auth/[...nextauth].ts +4 -0
- package/src/app/pages/api/auth/request-reset.ts +53 -0
- package/src/app/pages/api/auth/reset-password.ts +29 -0
- package/src/app/pages/api/docs/search/pages.json.ts +25 -0
- package/src/app/pages/api/install.ts +102 -0
- package/src/app/pages/api/mcp.ts +56 -0
- package/src/app/pages/api/oauth/device/approve.ts +23 -0
- package/src/app/pages/api/oauth/device/index.ts +41 -0
- package/src/app/pages/api/oauth/revoke.ts +31 -0
- package/src/app/pages/api/oauth/token.ts +31 -0
- package/src/app/pages/api/registry/components/[id]/files/[...filePath].ts +1 -1
- package/src/app/pages/api/registry/components/[id].ts +2 -2
- package/src/app/pages/api/registry/components/index.ts +1 -1
- package/src/app/pages/api/registry/health.ts +4 -3
- package/src/app/pages/api/registry/pages/[...id].ts +20 -0
- package/src/app/pages/api/registry/pages/index.ts +19 -0
- package/src/app/pages/api/registry/patterns/[id]/files/[...filePath].ts +1 -1
- package/src/app/pages/api/registry/patterns/[id].ts +2 -2
- package/src/app/pages/api/registry/patterns/index.ts +1 -1
- package/src/app/pages/api/registry/transfer/[kind]/[id].ts +3 -3
- package/src/app/pages/api/registry/transfer/[kind]/index.ts +21 -0
- package/src/app/pages/api/registry/transfer/assets/[collection].ts +2 -1
- package/src/app/pages/api/registry/transfer/assets/blobs/[hash].ts +2 -1
- package/src/app/pages/api/registry/transfer/assets/blobs/have.ts +2 -2
- package/src/app/pages/api/registry/transfer/tokens/[...setId].ts +2 -2
- package/src/app/pages/api/sync/upload.ts +21 -0
- package/src/app/pages/assets/logos.tsx +4 -1
- package/src/app/pages/cli/device.tsx +143 -0
- package/src/app/pages/foundations/icons/index.tsx +7 -5
- package/src/app/pages/foundations/icons/{[name] → library/[name]}/index.tsx +8 -8
- package/src/app/pages/foundations/logo.tsx +5 -4
- package/src/app/pages/index/index.tsx +14 -0
- package/src/app/pages/index.tsx +31 -5
- package/src/app/pages/install.tsx +336 -0
- package/src/app/pages/login.tsx +117 -0
- package/src/app/pages/reset-password.tsx +159 -0
- package/src/app/types/next-auth.d.ts +27 -0
- package/src/app-builder/build.ts +225 -86
- package/src/app-builder/client-config.ts +18 -14
- package/src/app-builder/config-diff/strategies/pattern.ts +1 -1
- package/src/app-builder/nav-shell.ts +8 -13
- package/src/app-builder/paths.ts +25 -1
- package/src/app-builder/static-export.ts +27 -0
- package/src/app-builder/vercel-output.ts +6 -6
- package/src/app-builder/watchers/component.ts +3 -3
- package/src/app-builder/watchers/utils.ts +2 -3
- package/src/app-builder/watchers.ts +63 -57
- package/src/artifacts/index.ts +8 -1
- package/src/artifacts/url.ts +32 -0
- package/src/cache/build-cache.ts +16 -15
- package/src/catalog/README.md +95 -0
- package/src/catalog/define.ts +79 -0
- package/src/catalog/implementation.ts +145 -0
- package/src/catalog/index.ts +31 -0
- package/src/catalog/normalize.ts +145 -0
- package/src/catalog/previews.ts +114 -0
- package/src/catalog/renderers.ts +94 -0
- package/src/catalog/types.ts +82 -0
- package/src/cli/README.md +1 -1
- package/src/cli/auth/browser.ts +29 -0
- package/src/cli/auth/device.ts +186 -0
- package/src/cli/auth/store.ts +194 -0
- package/src/cli/create.ts +58 -3
- package/src/cli/make.ts +22 -74
- package/src/cli/scaffold.ts +39 -222
- package/src/cli.ts +31 -7
- package/src/commands/README.md +1 -1
- package/src/commands/build/app.ts +2 -3
- package/src/commands/build/components.ts +2 -3
- package/src/commands/build/index.ts +2 -3
- package/src/commands/checkout/index.ts +29 -50
- package/src/commands/compat/deprecations.ts +79 -0
- package/src/commands/compat/push-args.ts +106 -0
- package/src/commands/db/migrate.ts +2 -3
- package/src/commands/dev/index.ts +2 -3
- package/src/commands/eject/config.ts +2 -3
- package/src/commands/eject/pages.ts +2 -3
- package/src/commands/eject/theme.ts +2 -3
- package/src/commands/fetch/index.ts +2 -3
- package/src/commands/index.ts +8 -2
- package/src/commands/login/index.ts +61 -0
- package/src/commands/logout/index.ts +104 -0
- package/src/commands/make/component.ts +2 -3
- package/src/commands/make/page.ts +4 -5
- package/src/commands/publish/index.ts +32 -49
- package/src/commands/pull/index.ts +32 -0
- package/src/commands/push/index.ts +115 -0
- package/src/commands/scaffold/index.ts +2 -3
- package/src/commands/start/index.ts +2 -3
- package/src/commands/types.ts +13 -1
- package/src/commands/utils.ts +107 -2
- package/src/commands/validate/components.ts +2 -3
- package/src/config/README.md +63 -2
- package/src/config/catalog-include.ts +227 -0
- package/src/config/defaults.ts +26 -13
- package/src/config/env.ts +41 -0
- package/src/config/errors.ts +7 -0
- package/src/config/from-env.ts +26 -0
- package/src/config/helpers.ts +4 -2
- package/src/config/index.ts +10 -2
- package/src/config/loader.ts +208 -43
- package/src/config/normalizers/page.ts +4 -4
- package/src/config/resolve-env.ts +107 -0
- package/src/config/runtime.ts +212 -226
- package/src/config/validator.ts +4 -6
- package/src/handlebars.ts +24 -0
- package/src/index.d.ts +2 -2
- package/src/index.ts +325 -72
- package/src/nav/resolver.ts +3 -1
- package/src/nav/workspace.ts +2 -2
- package/src/pattern.ts +14 -0
- package/src/pipeline/index.ts +1 -1
- package/src/react.ts +52 -0
- package/src/registry/asset-storage/adapters/vercel-blob.ts +1 -1
- package/src/registry/asset-storage/define.ts +1 -1
- package/src/registry/asset-storage/resolve.ts +7 -4
- package/src/registry/auth/access-tokens.ts +222 -0
- package/src/registry/auth/action-tokens.ts +225 -0
- package/src/registry/auth/ai-keys.ts +62 -0
- package/src/registry/auth/crypto.ts +75 -0
- package/src/registry/auth/database.ts +15 -0
- package/src/registry/auth/device-authorizations.ts +223 -0
- package/src/registry/auth/gravatar.ts +6 -0
- package/src/registry/auth/index.ts +105 -0
- package/src/registry/auth/installation.ts +117 -0
- package/src/registry/auth/password.ts +46 -0
- package/src/registry/auth/rate-limits.ts +84 -0
- package/src/registry/auth/sync-secret.ts +67 -0
- package/src/registry/auth/types.ts +57 -0
- package/src/registry/auth/user-record.ts +25 -0
- package/src/registry/auth/users.ts +145 -0
- package/src/registry/auth/validation.ts +42 -0
- package/src/registry/checkout/assets.ts +28 -9
- package/src/registry/checkout/index.ts +582 -130
- package/src/registry/checkout/tokens.ts +16 -8
- package/src/registry/client.ts +7 -1
- package/src/registry/connection.ts +91 -19
- package/src/registry/content-kinds.ts +39 -0
- package/src/registry/db/client.ts +34 -14
- package/src/registry/db/driver.ts +66 -0
- package/src/registry/db/index.ts +16 -5
- package/src/registry/db/migrate.ts +5 -5
- package/src/registry/db/schema.ts +225 -25
- package/src/registry/publish/assets.ts +47 -37
- package/src/registry/publish/errors.ts +3 -3
- package/src/registry/publish/index.ts +286 -27
- package/src/registry/publish/package.ts +14 -1
- package/src/registry/publish/tokens.ts +35 -26
- package/src/registry/selection.ts +63 -0
- package/src/registry/transfer.ts +14 -0
- package/src/store/filesystem.ts +6 -6
- package/src/store/registry.ts +131 -15
- package/src/transformers/plugins/csf-render.ts +4 -2
- package/src/transformers/plugins/ssr-render.ts +66 -19
- package/src/transformers/preview/component/api.ts +13 -1
- package/src/transformers/preview/component/artifacts.ts +8 -4
- package/src/transformers/preview/component/builder.ts +17 -4
- package/src/transformers/preview/component/css.ts +99 -60
- package/src/transformers/preview/component/html.ts +30 -19
- package/src/transformers/preview/component/javascript.ts +1 -3
- package/src/transformers/preview/pattern/builder.ts +33 -20
- package/src/transformers/preview/pattern/html.ts +3 -1
- package/src/transformers/preview/types.ts +31 -3
- package/src/transformers/utils/build.ts +80 -0
- package/src/transformers/utils/module.ts +4 -2
- package/src/types/config.ts +168 -45
- package/src/utils/README.md +1 -0
- package/src/utils/markdown.ts +11 -0
- package/src/utils/menu-shell.ts +14 -7
- package/src/utils/pages.ts +52 -0
- package/src/utils/path.ts +15 -6
- package/templates/default/README.md.tpl +68 -1
- package/templates/default/components/button/button.react.handoff.js.tpl +19 -23
- package/templates/default/components/button/button.react.handoff.ts.tpl +22 -22
- package/templates/default/env.tpl +10 -0
- package/templates/default/gitignore.tpl +26 -3
- package/templates/default/handoff.config.js.tpl +21 -166
- package/templates/default/handoff.config.ts.tpl +21 -150
- package/templates/default/handoff.config.with-examples.js.tpl +22 -164
- package/templates/default/handoff.config.with-examples.ts.tpl +22 -148
- package/templates/default/package.json.tpl +6 -1
- package/templates/default/vercel.json.tpl +4 -0
- package/config/docs/foundations/logos.md +0 -7
- package/config/templates/component/template.json +0 -49
- package/config/templates/template.html +0 -7
- package/dist/commands/make/template.d.ts +0 -8
- package/dist/commands/make/template.js +0 -47
- package/dist/config/normalizers/declaration.d.ts +0 -11
- package/dist/config/normalizers/declaration.js +0 -122
- package/dist/config/normalizers/pattern.d.ts +0 -8
- package/dist/config/normalizers/pattern.js +0 -41
- package/dist/declarations/helpers.d.ts +0 -6
- package/dist/declarations/helpers.js +0 -19
- package/dist/declarations/index.d.ts +0 -2
- package/dist/declarations/index.js +0 -9
- package/dist/declarations/types.d.ts +0 -60
- package/dist/registry/db/adapter.d.ts +0 -43
- package/dist/registry/db/adapter.js +0 -59
- package/src/app/lib/api/redact.ts +0 -46
- package/src/commands/make/template.ts +0 -47
- package/src/config/normalizers/declaration.ts +0 -179
- package/src/config/normalizers/pattern.ts +0 -59
- package/src/declarations/helpers.ts +0 -36
- package/src/declarations/index.ts +0 -19
- package/src/declarations/types.ts +0 -70
- package/src/registry/db/adapter.ts +0 -74
- /package/dist/{declarations → catalog}/types.js +0 -0
|
@@ -36,6 +36,18 @@ export declare class HandoffBuildError extends Error {
|
|
|
36
36
|
* deployable, so it is not keyed by project id.
|
|
37
37
|
*/
|
|
38
38
|
export declare const getRegistryBuildOutputPath: (handoff: Handoff) => string;
|
|
39
|
+
/**
|
|
40
|
+
* Root for Next's file tracing. Every traced path in the standalone bundle is relative to this root.
|
|
41
|
+
*
|
|
42
|
+
* The tracer copies only the files inside this root. It must contain the staged app (see
|
|
43
|
+
* {@link getAppPath}), or Next emits no standalone bundle. It must also contain every
|
|
44
|
+
* `node_modules` that the required runtime dependencies resolve from, or the bundle cannot start
|
|
45
|
+
* (see {@link assertRegistryRuntimeDepsTraced}).
|
|
46
|
+
*
|
|
47
|
+
* `workingPath` satisfies both conditions only when handoff-app is installed in the same package as
|
|
48
|
+
* the config, and nothing is hoisted above it.
|
|
49
|
+
*/
|
|
50
|
+
export declare const resolveRegistryTracingRoot: (handoff: Handoff) => string;
|
|
39
51
|
/**
|
|
40
52
|
* Build the Next.js documentation application for the resolved target. The `static` target builds
|
|
41
53
|
* and exports the local workspace (default); the `registry` target packages the deployable dynamic
|
|
@@ -1,4 +1,27 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
2
25
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
26
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
27
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -12,17 +35,20 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
12
35
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
36
|
};
|
|
14
37
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.devApp = exports.watchApp = exports.getRegistryBuildOutputPath = exports.HandoffBuildError = exports.DEFAULT_BUILD_TARGET = void 0;
|
|
38
|
+
exports.devApp = exports.watchApp = exports.resolveRegistryTracingRoot = exports.getRegistryBuildOutputPath = exports.HandoffBuildError = exports.DEFAULT_BUILD_TARGET = void 0;
|
|
39
|
+
const p = __importStar(require("@clack/prompts"));
|
|
16
40
|
const cross_spawn_1 = __importDefault(require("cross-spawn"));
|
|
17
41
|
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
18
42
|
const path_1 = __importDefault(require("path"));
|
|
43
|
+
const connections_1 = require("../ai/connections");
|
|
44
|
+
const config_1 = require("../config");
|
|
19
45
|
const components_1 = require("../pipeline/components");
|
|
20
46
|
const patterns_1 = require("../pipeline/patterns");
|
|
47
|
+
const resolve_1 = require("../registry/asset-storage/resolve");
|
|
48
|
+
const driver_1 = require("../registry/db/driver");
|
|
21
49
|
const builder_1 = __importDefault(require("../transformers/preview/component/builder"));
|
|
22
50
|
const css_1 = require("../transformers/preview/component/css");
|
|
23
51
|
const javascript_1 = require("../transformers/preview/component/javascript");
|
|
24
|
-
const adapter_1 = require("../registry/db/adapter");
|
|
25
|
-
const resolve_1 = require("../registry/asset-storage/resolve");
|
|
26
52
|
const logger_1 = require("../utils/logger");
|
|
27
53
|
const client_config_1 = require("./client-config");
|
|
28
54
|
const nav_shell_1 = require("./nav-shell");
|
|
@@ -78,6 +104,51 @@ const assertStaticBuildAllowed = (handoff) => {
|
|
|
78
104
|
'or package the registry app with `handoff-app build --target registry`.');
|
|
79
105
|
}
|
|
80
106
|
};
|
|
107
|
+
/**
|
|
108
|
+
* Run the Next.js production build while keeping its delayed output out of the successful CLI flow.
|
|
109
|
+
* Captured output is replayed only when the child fails so compiler diagnostics remain available.
|
|
110
|
+
*/
|
|
111
|
+
const runNextBuild = (appPath, target, errorLabel) => __awaiter(void 0, void 0, void 0, function* () {
|
|
112
|
+
const spinner = p.spinner();
|
|
113
|
+
spinner.start('Building Next.js app...');
|
|
114
|
+
const stdout = [];
|
|
115
|
+
const stderr = [];
|
|
116
|
+
yield new Promise((resolve, reject) => {
|
|
117
|
+
var _a, _b;
|
|
118
|
+
const buildProcess = (0, cross_spawn_1.default)('npx', ['next', 'build'], {
|
|
119
|
+
cwd: appPath,
|
|
120
|
+
stdio: ['inherit', 'pipe', 'pipe'],
|
|
121
|
+
env: Object.assign(Object.assign({}, process.env), { NODE_ENV: 'production', HANDOFF_BUILD_TARGET: target }),
|
|
122
|
+
});
|
|
123
|
+
(_a = buildProcess.stdout) === null || _a === void 0 ? void 0 : _a.on('data', (chunk) => stdout.push(Buffer.from(chunk)));
|
|
124
|
+
(_b = buildProcess.stderr) === null || _b === void 0 ? void 0 : _b.on('data', (chunk) => stderr.push(Buffer.from(chunk)));
|
|
125
|
+
let settled = false;
|
|
126
|
+
const fail = (message) => {
|
|
127
|
+
if (settled)
|
|
128
|
+
return;
|
|
129
|
+
settled = true;
|
|
130
|
+
spinner.stop('Next.js app build failed');
|
|
131
|
+
logger_1.Logger.childProcessBuffer(Buffer.concat(stdout));
|
|
132
|
+
logger_1.Logger.childProcessBuffer(Buffer.concat(stderr));
|
|
133
|
+
reject(new Error(message));
|
|
134
|
+
};
|
|
135
|
+
buildProcess.once('error', (error) => {
|
|
136
|
+
fail(`${errorLabel} failed to start\nSpawn error: ${error.message}`);
|
|
137
|
+
});
|
|
138
|
+
buildProcess.once('close', (code, signal) => {
|
|
139
|
+
if (settled)
|
|
140
|
+
return;
|
|
141
|
+
if (code === 0) {
|
|
142
|
+
settled = true;
|
|
143
|
+
spinner.stop('Next.js app built successfully');
|
|
144
|
+
resolve();
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
const reason = signal ? ` because it was terminated by signal ${signal}` : ` with exit code ${code}`;
|
|
148
|
+
fail(`${errorLabel} failed${reason}`);
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
});
|
|
81
152
|
/**
|
|
82
153
|
* Output directory for the packaged registry app. Lives under the configurable sites output
|
|
83
154
|
* directory (`sitesOutputDirectory`, default `out`) alongside the static target's `out/<projectId>`
|
|
@@ -87,6 +158,45 @@ const assertStaticBuildAllowed = (handoff) => {
|
|
|
87
158
|
*/
|
|
88
159
|
const getRegistryBuildOutputPath = (handoff) => path_1.default.resolve(handoff.workingPath, handoff.sitesDirectory, 'registry');
|
|
89
160
|
exports.getRegistryBuildOutputPath = getRegistryBuildOutputPath;
|
|
161
|
+
const commonAncestorPath = (paths) => {
|
|
162
|
+
const [first, ...rest] = paths.map((entry) => path_1.default.resolve(entry).split(path_1.default.sep));
|
|
163
|
+
let shared = first;
|
|
164
|
+
for (const candidate of rest) {
|
|
165
|
+
const next = [];
|
|
166
|
+
for (let index = 0; index < Math.min(shared.length, candidate.length) && shared[index] === candidate[index]; index += 1) {
|
|
167
|
+
next.push(shared[index]);
|
|
168
|
+
}
|
|
169
|
+
shared = next;
|
|
170
|
+
}
|
|
171
|
+
return shared.join(path_1.default.sep) || path_1.default.sep;
|
|
172
|
+
};
|
|
173
|
+
/**
|
|
174
|
+
* Root for Next's file tracing. Every traced path in the standalone bundle is relative to this root.
|
|
175
|
+
*
|
|
176
|
+
* The tracer copies only the files inside this root. It must contain the staged app (see
|
|
177
|
+
* {@link getAppPath}), or Next emits no standalone bundle. It must also contain every
|
|
178
|
+
* `node_modules` that the required runtime dependencies resolve from, or the bundle cannot start
|
|
179
|
+
* (see {@link assertRegistryRuntimeDepsTraced}).
|
|
180
|
+
*
|
|
181
|
+
* `workingPath` satisfies both conditions only when handoff-app is installed in the same package as
|
|
182
|
+
* the config, and nothing is hoisted above it.
|
|
183
|
+
*/
|
|
184
|
+
const resolveRegistryTracingRoot = (handoff) => {
|
|
185
|
+
const anchors = [path_1.default.resolve(handoff.workingPath), path_1.default.resolve(handoff.modulePath)];
|
|
186
|
+
// Resolve each module instead of assuming its location. A hoisted or linked dependency otherwise
|
|
187
|
+
// drops out of the trace.
|
|
188
|
+
for (const moduleName of getRequiredRegistryRuntimeModules(handoff)) {
|
|
189
|
+
try {
|
|
190
|
+
const resolved = require.resolve(`${moduleName}/package.json`, { paths: [handoff.modulePath, handoff.workingPath] });
|
|
191
|
+
anchors.push(fs_extra_1.default.realpathSync(path_1.default.dirname(resolved)));
|
|
192
|
+
}
|
|
193
|
+
catch (_a) {
|
|
194
|
+
// The assertion after assembly reports a module that does not resolve.
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return commonAncestorPath(anchors);
|
|
198
|
+
};
|
|
199
|
+
exports.resolveRegistryTracingRoot = resolveRegistryTracingRoot;
|
|
90
200
|
/**
|
|
91
201
|
* Performs cleanup of the application directory by removing the existing app directory if it exists.
|
|
92
202
|
*/
|
|
@@ -103,7 +213,7 @@ const cleanupAppDirectory = (handoff) => __awaiter(void 0, void 0, void 0, funct
|
|
|
103
213
|
* @returns The path to the prepared application directory
|
|
104
214
|
*/
|
|
105
215
|
const initializeProjectApp = (handoff_1, ...args_1) => __awaiter(void 0, [handoff_1, ...args_1], void 0, function* (handoff, options = {}) {
|
|
106
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
216
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
107
217
|
const includeWorkspaceArtifacts = (_a = options.includeWorkspaceArtifacts) !== null && _a !== void 0 ? _a : true;
|
|
108
218
|
const runtimeMode = (_e = (_b = options.runtimeModeOverride) !== null && _b !== void 0 ? _b : (_d = (_c = handoff.config) === null || _c === void 0 ? void 0 : _c.runtime) === null || _d === void 0 ? void 0 : _d.mode) !== null && _e !== void 0 ? _e : 'workspace';
|
|
109
219
|
const srcPath = path_1.default.resolve(handoff.modulePath, 'src', 'app');
|
|
@@ -142,14 +252,16 @@ const initializeProjectApp = (handoff_1, ...args_1) => __awaiter(void 0, [handof
|
|
|
142
252
|
const escapedProjectId = escapeForSingleQuotedJsString(handoffProjectId);
|
|
143
253
|
const escapedWorkingPath = escapeForSingleQuotedJsString(handoffWorkingPath);
|
|
144
254
|
const escapedModulePath = escapeForSingleQuotedJsString(handoffModulePath);
|
|
255
|
+
// Baked here so the template and the assembly step use the same root.
|
|
256
|
+
const escapedTracingRoot = escapeForSingleQuotedJsString((0, exports.resolveRegistryTracingRoot)(handoff));
|
|
145
257
|
const escapedExportPath = escapeForSingleQuotedJsString(handoffExportPath);
|
|
146
258
|
const escapedWebsocketPort = escapeForSingleQuotedJsString(String(handoffWebsocketPort));
|
|
147
259
|
// Resolved runtime mode + registry connection inputs (names only) baked into the Next bundle so the
|
|
148
260
|
// deployed registry app resolves its mode/DB env-var name without any build-machine filesystem.
|
|
149
261
|
const escapedRuntimeMode = escapeForSingleQuotedJsString(runtimeMode);
|
|
150
|
-
const
|
|
151
|
-
const
|
|
152
|
-
const
|
|
262
|
+
const escapedMcpEnabled = escapeForSingleQuotedJsString(String((0, config_1.isMcpEnabled)(handoff.config)));
|
|
263
|
+
const escapedRegistryDriver = escapeForSingleQuotedJsString((0, driver_1.resolveRegistryDriver)(handoff.config));
|
|
264
|
+
const escapedDatabaseUrlEnv = escapeForSingleQuotedJsString((0, driver_1.resolveDatabaseUrlEnv)(handoff.config));
|
|
153
265
|
// Asset storage selection baked (provider + module + env-var names + non-secret options JSON).
|
|
154
266
|
const assetStorage = (0, resolve_1.resolveAssetStorageFromConfig)(handoff.config);
|
|
155
267
|
const escapedAssetStorageAdapter = escapeForSingleQuotedJsString(assetStorage.adapterKind);
|
|
@@ -157,22 +269,35 @@ const initializeProjectApp = (handoff_1, ...args_1) => __awaiter(void 0, [handof
|
|
|
157
269
|
const escapedAssetStorageTokenEnv = escapeForSingleQuotedJsString(assetStorage.tokenEnv);
|
|
158
270
|
const escapedAssetStorageMaxInline = escapeForSingleQuotedJsString(String(assetStorage.maxInlineBytes));
|
|
159
271
|
const escapedAssetStorageOptions = escapeForSingleQuotedJsString(JSON.stringify((_k = assetStorage.options) !== null && _k !== void 0 ? _k : {}));
|
|
272
|
+
// AI assistant selection baked (enabled flag + declared connections + default model). Connections
|
|
273
|
+
// carry env-var names and non-secret options only; keys are read from their named env var at
|
|
274
|
+
// request time, and a deployment can extend or replace the list through HANDOFF_AI_CONNECTIONS.
|
|
275
|
+
const ai = (0, connections_1.resolveAiFromConfig)(handoff.config);
|
|
276
|
+
const escapedAiEnabled = escapeForSingleQuotedJsString(String(ai.enabled));
|
|
277
|
+
const escapedAiConnections = escapeForSingleQuotedJsString(JSON.stringify(ai.connections));
|
|
278
|
+
const escapedAiDefaultModel = escapeForSingleQuotedJsString((_l = ai.defaultModel) !== null && _l !== void 0 ? _l : '');
|
|
279
|
+
const escapedAiProviderModules = escapeForSingleQuotedJsString(JSON.stringify(ai.connections.map((connection) => connection.module).filter((module) => Boolean(module))));
|
|
160
280
|
const placeholderValues = {
|
|
161
281
|
'%HANDOFF_PROJECT_ID%': escapedProjectId,
|
|
162
282
|
'%HANDOFF_APP_BASE_PATH%': escapedAppBasePath,
|
|
163
283
|
'%HANDOFF_WORKING_PATH%': escapedWorkingPath,
|
|
164
284
|
'%HANDOFF_MODULE_PATH%': escapedModulePath,
|
|
285
|
+
'%HANDOFF_TRACING_ROOT%': escapedTracingRoot,
|
|
165
286
|
'%HANDOFF_EXPORT_PATH%': escapedExportPath,
|
|
166
287
|
'%HANDOFF_WEBSOCKET_PORT%': escapedWebsocketPort,
|
|
167
288
|
'%HANDOFF_RUNTIME_MODE%': escapedRuntimeMode,
|
|
168
|
-
'%
|
|
289
|
+
'%HANDOFF_MCP_ENABLED%': escapedMcpEnabled,
|
|
290
|
+
'%HANDOFF_REGISTRY_DRIVER%': escapedRegistryDriver,
|
|
169
291
|
'%HANDOFF_REGISTRY_DATABASE_URL_ENV%': escapedDatabaseUrlEnv,
|
|
170
|
-
'%HANDOFF_REGISTRY_API_TOKEN_ENV%': escapedApiTokenEnv,
|
|
171
292
|
'%HANDOFF_ASSET_STORAGE_ADAPTER%': escapedAssetStorageAdapter,
|
|
172
293
|
'%HANDOFF_ASSET_STORAGE_MODULE%': escapedAssetStorageModule,
|
|
173
294
|
'%HANDOFF_ASSET_STORAGE_TOKEN_ENV%': escapedAssetStorageTokenEnv,
|
|
174
295
|
'%HANDOFF_ASSET_STORAGE_MAX_INLINE_BYTES%': escapedAssetStorageMaxInline,
|
|
175
296
|
'%HANDOFF_ASSET_STORAGE_OPTIONS%': escapedAssetStorageOptions,
|
|
297
|
+
'%HANDOFF_AI_ENABLED%': escapedAiEnabled,
|
|
298
|
+
'%HANDOFF_AI_BAKED_CONNECTIONS%': escapedAiConnections,
|
|
299
|
+
'%HANDOFF_AI_DEFAULT_MODEL%': escapedAiDefaultModel,
|
|
300
|
+
'%HANDOFF_AI_PROVIDER_MODULES%': escapedAiProviderModules,
|
|
176
301
|
};
|
|
177
302
|
let nextConfigContent = yield fs_extra_1.default.readFile(nextConfigPath, 'utf-8');
|
|
178
303
|
for (const [placeholder, value] of Object.entries(placeholderValues)) {
|
|
@@ -216,20 +341,7 @@ const buildApp = (handoff_1, ...args_1) => __awaiter(void 0, [handoff_1, ...args
|
|
|
216
341
|
(0, static_export_1.validateReferencedArtifacts)(handoff);
|
|
217
342
|
// Build app. The static target drives Next's `output: 'export'` via HANDOFF_BUILD_TARGET so the
|
|
218
343
|
// export gate is tied to the resolved target, not to NODE_ENV.
|
|
219
|
-
|
|
220
|
-
cwd: appPath,
|
|
221
|
-
stdio: ['inherit', 'pipe', 'pipe'],
|
|
222
|
-
env: Object.assign(Object.assign({}, process.env), { NODE_ENV: 'production', HANDOFF_BUILD_TARGET: target }),
|
|
223
|
-
});
|
|
224
|
-
logger_1.Logger.childProcessBuffer(buildResult.stdout);
|
|
225
|
-
logger_1.Logger.childProcessBuffer(buildResult.stderr);
|
|
226
|
-
if (buildResult.status !== 0) {
|
|
227
|
-
let errorMsg = `Next.js build failed with exit code ${buildResult.status}`;
|
|
228
|
-
if (buildResult.error) {
|
|
229
|
-
errorMsg += `\nSpawn error: ${buildResult.error.message}`;
|
|
230
|
-
}
|
|
231
|
-
throw new Error(errorMsg);
|
|
232
|
-
}
|
|
344
|
+
yield runNextBuild(appPath, target, 'Next.js build');
|
|
233
345
|
// Reproduce the docs read API (`/api/docs/*`) as route-shaped static files in the export output,
|
|
234
346
|
// since `output: 'export'` disables the live API routes.
|
|
235
347
|
const exportDir = path_1.default.resolve(appPath, 'out');
|
|
@@ -280,7 +392,22 @@ const findStandaloneServerDir = (root) => {
|
|
|
280
392
|
* Write a deployment guide next to the packaged registry app describing how to run it on Vercel,
|
|
281
393
|
* a custom Node server, or in a container, and which env vars it requires at deploy time.
|
|
282
394
|
*/
|
|
283
|
-
const writeRegistryDeploymentReadme = (outputRoot, entryRelativePath, databaseUrlEnv) => __awaiter(void 0, void 0, void 0, function* () {
|
|
395
|
+
const writeRegistryDeploymentReadme = (outputRoot, entryRelativePath, databaseUrlEnv, ai) => __awaiter(void 0, void 0, void 0, function* () {
|
|
396
|
+
const serviceKeyEnvs = [...new Set(ai.connections.map((connection) => connection.apiKeyEnv).filter(Boolean))];
|
|
397
|
+
const needsKeySecret = ai.connections.some((connection) => connection.credential === 'user');
|
|
398
|
+
const aiSection = !ai.enabled
|
|
399
|
+
? ''
|
|
400
|
+
: `
|
|
401
|
+
## AI assistant
|
|
402
|
+
|
|
403
|
+
This build serves the docs assistant at \`/api/ai/*\`.
|
|
404
|
+
|
|
405
|
+
${serviceKeyEnvs.map((name) => `- \`${name}\` — API key for a declared AI connection, read at request time.`).join('\n') || '- No service-key connection is declared, so no provider key is required here.'}
|
|
406
|
+
${needsKeySecret ? '- `HANDOFF_AI_KEY_SECRET` — a long, random secret that encrypts the API keys readers save for themselves. Readers cannot save a key without it.\n' : ''}
|
|
407
|
+
\`HANDOFF_AI_CONNECTIONS\` optionally carries a JSON array of connections, read at request time and
|
|
408
|
+
merged over the list this build baked in, keyed by \`id\`. Use it to add or repoint a provider
|
|
409
|
+
without rebuilding.
|
|
410
|
+
`;
|
|
284
411
|
const readme = `# Handoff Registry App
|
|
285
412
|
|
|
286
413
|
A self-contained, deployable Next.js **standalone** build produced by
|
|
@@ -295,8 +422,12 @@ and \`.next/static/\` already copied alongside so the server serves them.
|
|
|
295
422
|
## Required environment variables (supplied at deploy time, never baked in)
|
|
296
423
|
|
|
297
424
|
- \`${databaseUrlEnv}\` — PostgreSQL/Neon connection string, read at request time.
|
|
298
|
-
- \`
|
|
425
|
+
- \`AUTH_SECRET\` — a long, random secret used to sign browser sessions.
|
|
426
|
+
- \`AUTH_URL\` — the canonical public registry URL, including the configured base path.
|
|
299
427
|
|
|
428
|
+
Optional email delivery uses \`RESEND_API_KEY\` and \`AUTH_FROM_EMAIL\`. Without them, invitation
|
|
429
|
+
links are shown once to an administrator for manual delivery.
|
|
430
|
+
${aiSection}
|
|
300
431
|
## Database migrations
|
|
301
432
|
|
|
302
433
|
Apply migrations from the \`handoff-app\` CLI as a controlled release step (e.g. in your CI/CD
|
|
@@ -306,10 +437,33 @@ pipeline) before deploying new code:
|
|
|
306
437
|
${databaseUrlEnv}="postgres://…" handoff-app db:migrate
|
|
307
438
|
\`\`\`
|
|
308
439
|
|
|
309
|
-
\`db:migrate\` reads your project config + DB env vars, resolves the same database
|
|
440
|
+
\`db:migrate\` reads your project config + DB env vars, resolves the same database driver the app was
|
|
310
441
|
built with, and applies the package-owned migration set. It runs independently of \`build\` and of
|
|
311
442
|
starting the server, so run it as a release/one-shot job.
|
|
312
443
|
|
|
444
|
+
## Complete the one-time installation
|
|
445
|
+
|
|
446
|
+
After migrations and deployment, open \`/install\` immediately and create the initial administrator.
|
|
447
|
+
The installer verifies the deployment but never changes the schema. An exposed, uninstalled registry
|
|
448
|
+
can be claimed by its first visitor, so do not leave this step unattended.
|
|
449
|
+
|
|
450
|
+
Once installation completes, sign in and authorize a workspace. Either approve the CLI in the
|
|
451
|
+
browser:
|
|
452
|
+
|
|
453
|
+
\`\`\`bash
|
|
454
|
+
handoff-app login --url https://registry.example.com
|
|
455
|
+
\`\`\`
|
|
456
|
+
|
|
457
|
+
or create a token under Account > Access tokens and set it in the workspace environment:
|
|
458
|
+
|
|
459
|
+
\`\`\`bash
|
|
460
|
+
HANDOFF_REGISTRY_URL=https://registry.example.com
|
|
461
|
+
HANDOFF_REGISTRY_ACCESS_TOKEN=hnd_…
|
|
462
|
+
\`\`\`
|
|
463
|
+
|
|
464
|
+
Both produce the same revocable, user-owned credential. The former
|
|
465
|
+
\`HANDOFF_REGISTRY_API_TOKEN\` fixed server secret is no longer accepted.
|
|
466
|
+
|
|
313
467
|
## Run it (self-hosting)
|
|
314
468
|
|
|
315
469
|
Standalone is the documented artifact for self-hosting on a Node.js server, VPS, Docker, or
|
|
@@ -352,15 +506,25 @@ containers, custom Node servers, and other non-Vercel hosts.
|
|
|
352
506
|
});
|
|
353
507
|
/**
|
|
354
508
|
* Resolve the set of npm packages the packaged registry app must be able to `require`/`import` at
|
|
355
|
-
* runtime, given the configured database
|
|
356
|
-
* runtime; `drizzle-orm` backs both the request-time DB client and the migration runner; the
|
|
357
|
-
*
|
|
509
|
+
* runtime, given the configured database driver. `next`/`react`/`react-dom` run the server and React
|
|
510
|
+
* runtime; `drizzle-orm` backs both the request-time DB client and the migration runner; the MCP SDK
|
|
511
|
+
* (and its `zod` peer) is only needed when `/api/mcp/` is enabled; the driver package is
|
|
512
|
+
* driver-specific (the Neon serverless driver also needs `ws` for its Node WebSocket transport).
|
|
358
513
|
*/
|
|
359
514
|
const getRequiredRegistryRuntimeModules = (handoff) => {
|
|
360
515
|
var _a;
|
|
361
|
-
const base = ['next', 'react', 'react-dom', 'drizzle-orm'];
|
|
362
|
-
const
|
|
363
|
-
|
|
516
|
+
const base = ['next', 'next-auth', 'react', 'react-dom', 'drizzle-orm'];
|
|
517
|
+
const ai = (0, connections_1.resolveAiFromConfig)(handoff.config);
|
|
518
|
+
// The assistant runs the MCP tools in-process, so it needs the MCP SDK whether or not the HTTP
|
|
519
|
+
// endpoint is served.
|
|
520
|
+
if ((0, config_1.isMcpEnabled)(handoff.config) || ai.enabled) {
|
|
521
|
+
base.push('@modelcontextprotocol/sdk', 'zod');
|
|
522
|
+
}
|
|
523
|
+
if (ai.enabled) {
|
|
524
|
+
base.push('ai', '@ai-sdk/openai-compatible');
|
|
525
|
+
}
|
|
526
|
+
const driver = (0, driver_1.resolveRegistryDriver)(handoff.config);
|
|
527
|
+
const driverModules = driver === 'neon' ? ['@neondatabase/serverless', 'ws'] : ['pg'];
|
|
364
528
|
// Asset-storage SDKs the deployed registry must be able to load at request time. The pre-packaged
|
|
365
529
|
// Vercel Blob adapter needs `@vercel/blob`; a custom adapter may declare its installed SDK
|
|
366
530
|
// package(s) via `assetStorage.options.sdkModules` so the trace/assertion covers them.
|
|
@@ -373,7 +537,7 @@ const getRequiredRegistryRuntimeModules = (handoff) => {
|
|
|
373
537
|
if (Array.isArray(sdkModules)) {
|
|
374
538
|
storage.push(...sdkModules.filter((mod) => typeof mod === 'string'));
|
|
375
539
|
}
|
|
376
|
-
return [...base, ...
|
|
540
|
+
return [...base, ...driverModules, ...storage];
|
|
377
541
|
};
|
|
378
542
|
/**
|
|
379
543
|
* Build-time guard against the empty-`node_modules` regression (the artifact would otherwise boot-fail
|
|
@@ -411,14 +575,11 @@ const assertRegistryRuntimeDepsTraced = (handoff, entryDir) => {
|
|
|
411
575
|
*/
|
|
412
576
|
const assembleRegistryStandalone = (handoff, appPath, standaloneRoot, entryDir) => __awaiter(void 0, void 0, void 0, function* () {
|
|
413
577
|
yield fs_extra_1.default.copy(standaloneRoot, entryDir, { overwrite: true });
|
|
414
|
-
// Locate the server entry
|
|
415
|
-
//
|
|
416
|
-
//
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
// skips `node_modules` (so it cannot find this nested entry) and only covers a hypothetical
|
|
420
|
-
// non-nested layout.
|
|
421
|
-
const relAppDir = path_1.default.relative(handoff.workingPath, appPath);
|
|
578
|
+
// Locate the server entry in the assembled package. Traced files keep their path relative to the
|
|
579
|
+
// tracing root, so the server entry nests under the traced `node_modules`. The recursive fallback
|
|
580
|
+
// skips `node_modules`, so it covers only a non-nested layout.
|
|
581
|
+
const tracingRoot = (0, exports.resolveRegistryTracingRoot)(handoff);
|
|
582
|
+
const relAppDir = path_1.default.relative(tracingRoot, appPath);
|
|
422
583
|
let serverDir = path_1.default.resolve(entryDir, relAppDir);
|
|
423
584
|
if (!fs_extra_1.default.existsSync(path_1.default.join(serverDir, 'server.js'))) {
|
|
424
585
|
const located = findStandaloneServerDir(entryDir);
|
|
@@ -438,7 +599,7 @@ const assembleRegistryStandalone = (handoff, appPath, standaloneRoot, entryDir)
|
|
|
438
599
|
// so we must NOT remove the first path segment (`node_modules`) — that would delete every traced
|
|
439
600
|
// dependency. Remove only the `.handoff` staging container (the parent of the staged app dir),
|
|
440
601
|
// leaving `node_modules/` and the real `node_modules/handoff-app/` package intact.
|
|
441
|
-
const stagingContainer = path_1.default.resolve(entryDir, path_1.default.relative(
|
|
602
|
+
const stagingContainer = path_1.default.resolve(entryDir, path_1.default.relative(tracingRoot, path_1.default.dirname(appPath)));
|
|
442
603
|
if (path_1.default.basename(stagingContainer) === '.handoff' && fs_extra_1.default.existsSync(stagingContainer)) {
|
|
443
604
|
yield fs_extra_1.default.remove(stagingContainer);
|
|
444
605
|
}
|
|
@@ -461,6 +622,16 @@ const assembleRegistryStandalone = (handoff, appPath, standaloneRoot, entryDir)
|
|
|
461
622
|
yield fs_extra_1.default.copy(src, path_1.default.join(entryDir, configFile), { overwrite: true });
|
|
462
623
|
}
|
|
463
624
|
}
|
|
625
|
+
// Next copies the `package.json` of the tracing root into the bundle without change. The generated
|
|
626
|
+
// `server.js` is CommonJS, so an ESM manifest stops the bundle from starting. That manifest also
|
|
627
|
+
// names scripts and dev dependencies that the bundle does not ship.
|
|
628
|
+
const manifestPath = path_1.default.join(entryDir, 'package.json');
|
|
629
|
+
const inheritedManifest = (yield fs_extra_1.default.pathExists(manifestPath))
|
|
630
|
+
? yield fs_extra_1.default.readJson(manifestPath).catch(() => ({}))
|
|
631
|
+
: {};
|
|
632
|
+
delete inheritedManifest.scripts;
|
|
633
|
+
delete inheritedManifest.devDependencies;
|
|
634
|
+
yield fs_extra_1.default.writeJson(manifestPath, Object.assign(Object.assign({}, inheritedManifest), { type: 'commonjs' }), { spaces: 2 });
|
|
464
635
|
// Fail loudly at build time if the trace did not capture the runtime deps, rather than shipping a
|
|
465
636
|
// broken artifact that only crashes on an isolated deploy. Covers both deliverables (this is the
|
|
466
637
|
// shared assembly step for `standalone` and `vercel`).
|
|
@@ -482,7 +653,7 @@ const assembleRegistryStandalone = (handoff, appPath, standaloneRoot, entryDir)
|
|
|
482
653
|
* - `vercel` → the Vercel Build Output API directory (`.vercel/output`) at the repo root: the
|
|
483
654
|
* traced bundle wrapped as a Node function plus CDN static assets and a route table.
|
|
484
655
|
*
|
|
485
|
-
* Mode is forced to `registry`; the database
|
|
656
|
+
* Mode is forced to `registry`; the database driver is honored from config (single-sourced so build
|
|
486
657
|
* and `db:migrate` never diverge). No connection-string value is ever baked — only env-var *names*.
|
|
487
658
|
*/
|
|
488
659
|
const buildRegistryApp = (handoff_1, ...args_1) => __awaiter(void 0, [handoff_1, ...args_1], void 0, function* (handoff, buildPackage = 'standalone') {
|
|
@@ -495,15 +666,15 @@ const buildRegistryApp = (handoff_1, ...args_1) => __awaiter(void 0, [handoff_1,
|
|
|
495
666
|
if (sourceMode !== 'registry') {
|
|
496
667
|
logger_1.Logger.info(`Source runtime.mode is "${sourceMode}"; forcing "registry" mode in the packaged registry app.`);
|
|
497
668
|
}
|
|
498
|
-
// The
|
|
669
|
+
// The driver stays single-sourced from config (never flipped by the package flag), so build and
|
|
499
670
|
// `db:migrate` always resolve the same one. `pg` uses long-lived TCP connections that pool poorly on
|
|
500
671
|
// serverless; warn (non-fatally) so the operator points DATABASE_URL at a pooled endpoint or selects
|
|
501
|
-
// the Neon
|
|
672
|
+
// the Neon driver. The connection-string value is not available at build time, so this cannot be
|
|
502
673
|
// validated — it is guidance only and never fails the build.
|
|
503
|
-
if (buildPackage === 'vercel' && (0,
|
|
504
|
-
logger_1.Logger.warn('Registry Vercel build uses the "pg"
|
|
674
|
+
if (buildPackage === 'vercel' && (0, driver_1.resolveRegistryDriver)(handoff.config) === 'pg') {
|
|
675
|
+
logger_1.Logger.warn('Registry Vercel build uses the "pg" driver (standard TCP connections), which pools poorly on ' +
|
|
505
676
|
'serverless and can exhaust the database connection limit. Point DATABASE_URL at a pooled endpoint ' +
|
|
506
|
-
'(PgBouncer / transaction pooling), or set runtime.registry.database.
|
|
677
|
+
'(PgBouncer / transaction pooling), or set runtime.registry.database.driver: "neon" for a ' +
|
|
507
678
|
'serverless-native HTTP/WebSocket driver. The build will continue.');
|
|
508
679
|
}
|
|
509
680
|
// Stage the app without any workspace-derived artifacts — the registry serves from the database.
|
|
@@ -524,27 +695,16 @@ const buildRegistryApp = (handoff_1, ...args_1) => __awaiter(void 0, [handoff_1,
|
|
|
524
695
|
yield fs_extra_1.default.remove((0, vercel_output_1.getVercelOutputPath)(handoff));
|
|
525
696
|
// Build the dynamic app. `output: 'standalone'` (driven by HANDOFF_BUILD_TARGET) traces the runtime
|
|
526
697
|
// and the selected Postgres/Neon driver into a self-contained bundle — never a static export.
|
|
527
|
-
|
|
528
|
-
cwd: appPath,
|
|
529
|
-
stdio: ['inherit', 'pipe', 'pipe'],
|
|
530
|
-
env: Object.assign(Object.assign({}, process.env), { NODE_ENV: 'production', HANDOFF_BUILD_TARGET: 'registry' }),
|
|
531
|
-
});
|
|
532
|
-
logger_1.Logger.childProcessBuffer(buildResult.stdout);
|
|
533
|
-
logger_1.Logger.childProcessBuffer(buildResult.stderr);
|
|
534
|
-
if (buildResult.status !== 0) {
|
|
535
|
-
let errorMsg = `Registry app build failed with exit code ${buildResult.status}`;
|
|
536
|
-
if (buildResult.error) {
|
|
537
|
-
errorMsg += `\nSpawn error: ${buildResult.error.message}`;
|
|
538
|
-
}
|
|
539
|
-
throw new Error(errorMsg);
|
|
540
|
-
}
|
|
698
|
+
yield runNextBuild(appPath, 'registry', 'Registry app build');
|
|
541
699
|
// Assemble the deployable package. Standalone tracing is rooted at the package (modulePath), so the
|
|
542
700
|
// app's traced files land under `<relAppDir>` inside the standalone tree; static assets and public
|
|
543
701
|
// files are not traced and must be copied alongside the server entry.
|
|
544
702
|
const standaloneRoot = path_1.default.resolve(appPath, '.next', 'standalone');
|
|
545
703
|
if (!fs_extra_1.default.existsSync(standaloneRoot)) {
|
|
546
|
-
throw new Error(`Registry build did not produce a standalone bundle at "${standaloneRoot}".
|
|
547
|
-
|
|
704
|
+
throw new Error(`Registry build did not produce a standalone bundle at "${standaloneRoot}". Next emits one only ` +
|
|
705
|
+
`when the app being built sits inside \`outputFileTracingRoot\` (resolved here to ` +
|
|
706
|
+
`"${(0, exports.resolveRegistryTracingRoot)(handoff)}"), so check that the staged app at "${appPath}" is ` +
|
|
707
|
+
'inside that root, and that the registry build target still sets Next `output: "standalone"`.');
|
|
548
708
|
}
|
|
549
709
|
// Final assembly branches on the resolved package. Both lay out
|
|
550
710
|
// the same traced standalone bundle; they differ only in where it lands and how it is wrapped.
|
|
@@ -561,7 +721,7 @@ const buildRegistryApp = (handoff_1, ...args_1) => __awaiter(void 0, [handoff_1,
|
|
|
561
721
|
// `handoff-app` source/CLI (`handoff-app db:migrate`) as a controlled release step (e.g. CI/CD),
|
|
562
722
|
// never from the deployed bundle. See the generated README for the migrate-then-deploy flow.
|
|
563
723
|
const entryRelativePath = path_1.default.relative(output, serverEntry).split(path_1.default.sep).join('/');
|
|
564
|
-
yield writeRegistryDeploymentReadme(output, entryRelativePath, (0,
|
|
724
|
+
yield writeRegistryDeploymentReadme(output, entryRelativePath, (0, driver_1.resolveDatabaseUrlEnv)(handoff.config), (0, connections_1.resolveAiFromConfig)(handoff.config));
|
|
565
725
|
logger_1.Logger.success(`Packaged registry app at ${output} (start: \`node ${entryRelativePath}\`, migrate: \`handoff-app db:migrate\`).`);
|
|
566
726
|
});
|
|
567
727
|
/**
|
|
@@ -628,14 +788,12 @@ const watchApp = (handoff) => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
628
788
|
pendingHandlers: new Map(),
|
|
629
789
|
runtimeComponentsWatcher: null,
|
|
630
790
|
runtimeConfigurationWatcher: null,
|
|
631
|
-
|
|
632
|
-
patternDirectoriesWatcher: null,
|
|
791
|
+
catalogDirectoriesWatcher: null,
|
|
633
792
|
};
|
|
634
793
|
(0, watchers_1.watchPublicDirectory)(handoff, wss, state, chokidarConfig);
|
|
635
794
|
(0, watchers_1.watchRuntimeComponents)(handoff, state, (0, watchers_1.getRuntimeComponentsPathsToWatch)(handoff));
|
|
636
795
|
(0, watchers_1.watchRuntimeConfiguration)(handoff, state);
|
|
637
|
-
(0, watchers_1.
|
|
638
|
-
(0, watchers_1.watchPatternDirectories)(handoff, state, chokidarConfig);
|
|
796
|
+
(0, watchers_1.watchCatalogDirectories)(handoff, state, chokidarConfig);
|
|
639
797
|
(0, watchers_1.watchGlobalEntries)(handoff, state, chokidarConfig);
|
|
640
798
|
(0, watchers_1.watchPages)(handoff, chokidarConfig);
|
|
641
799
|
});
|
|
@@ -17,7 +17,8 @@ const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
|
17
17
|
const path_1 = __importDefault(require("path"));
|
|
18
18
|
const config_1 = require("../config");
|
|
19
19
|
const resolve_1 = require("../registry/asset-storage/resolve");
|
|
20
|
-
const
|
|
20
|
+
const connection_1 = require("../registry/connection");
|
|
21
|
+
const driver_1 = require("../registry/db/driver");
|
|
21
22
|
const paths_1 = require("./paths");
|
|
22
23
|
/**
|
|
23
24
|
* Publishes the tokens API files to the public directory.
|
|
@@ -55,7 +56,7 @@ exports.generateTokensApi = generateTokensApi;
|
|
|
55
56
|
* Build the server-only runtime config consumed by the docs read API.
|
|
56
57
|
*
|
|
57
58
|
* The browser-facing `client.config.json` carries only the resolved mode; the server additionally
|
|
58
|
-
* needs the registry connection *inputs* (selected
|
|
59
|
+
* needs the registry connection *inputs* (selected driver + the *name* of the database-URL env
|
|
59
60
|
* var) to back the registry-mode docs read API. These are non-secret — the connection-string value
|
|
60
61
|
* itself is never persisted, only resolved from the env var at request time.
|
|
61
62
|
*/
|
|
@@ -64,10 +65,10 @@ const buildServerRuntimeConfig = (config, modeOverride) => {
|
|
|
64
65
|
const assetStorage = (0, resolve_1.resolveAssetStorageFromConfig)(config);
|
|
65
66
|
return {
|
|
66
67
|
mode: (_b = modeOverride !== null && modeOverride !== void 0 ? modeOverride : (_a = config === null || config === void 0 ? void 0 : config.runtime) === null || _a === void 0 ? void 0 : _a.mode) !== null && _b !== void 0 ? _b : 'workspace',
|
|
68
|
+
mcp: (0, config_1.isMcpEnabled)(config),
|
|
67
69
|
registry: {
|
|
68
|
-
|
|
69
|
-
databaseUrlEnv: (0,
|
|
70
|
-
apiTokenEnv: (0, adapter_1.resolveApiTokenEnv)(config),
|
|
70
|
+
driver: (0, driver_1.resolveRegistryDriver)(config),
|
|
71
|
+
databaseUrlEnv: (0, driver_1.resolveDatabaseUrlEnv)(config),
|
|
71
72
|
},
|
|
72
73
|
assetStorage: {
|
|
73
74
|
adapter: assetStorage.adapterKind,
|
|
@@ -84,17 +85,20 @@ const buildServerRuntimeConfig = (config, modeOverride) => {
|
|
|
84
85
|
* connection inputs from. Both are always written together so they never drift.
|
|
85
86
|
*/
|
|
86
87
|
const persistClientConfig = (handoff_1, ...args_1) => __awaiter(void 0, [handoff_1, ...args_1], void 0, function* (handoff, options = {}) {
|
|
88
|
+
var _a;
|
|
87
89
|
const appPath = (0, paths_1.getAppPath)(handoff);
|
|
88
90
|
// Ensure directory exists
|
|
89
91
|
yield fs_extra_1.default.ensureDir(appPath);
|
|
90
92
|
const clientConfig = (0, config_1.getClientConfig)(handoff.config);
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
93
|
+
const mode = (_a = options.runtimeModeOverride) !== null && _a !== void 0 ? _a : clientConfig.runtime.mode;
|
|
94
|
+
// A registry build target is never a connected workspace, so it must bake `connected: false`
|
|
95
|
+
// even when packaged from a connected project. Otherwise a workspace is connected whenever a
|
|
96
|
+
// registry URL resolves — from config/env or a saved device login — so `login` alone surfaces
|
|
97
|
+
// the publish/checkout UI without also requiring HANDOFF_REGISTRY_URL.
|
|
98
|
+
const connected = mode === 'registry'
|
|
99
|
+
? false
|
|
100
|
+
: Boolean((yield (0, connection_1.resolveAuthenticatedRegistryConnection)(handoff.config, handoff.workingPath, handoff.getProfile())).url);
|
|
101
|
+
clientConfig.runtime = Object.assign(Object.assign({}, clientConfig.runtime), { mode, connected });
|
|
98
102
|
yield fs_extra_1.default.writeJson(path_1.default.resolve(appPath, 'client.config.json'), { config: clientConfig }, { spaces: 2 });
|
|
99
103
|
yield fs_extra_1.default.writeJson(path_1.default.resolve(appPath, 'runtime.server.json'), buildServerRuntimeConfig(handoff.config, options.runtimeModeOverride), { spaces: 2 });
|
|
100
104
|
});
|
|
@@ -43,12 +43,12 @@ const snapshot_1 = require("../snapshot");
|
|
|
43
43
|
* components. Outer key is component id, inner key is synthetic preview key.
|
|
44
44
|
*/
|
|
45
45
|
const snapshotPatternSynthetics = (handoff, patternId) => {
|
|
46
|
-
var _a, _b, _c
|
|
47
|
-
const components = (
|
|
46
|
+
var _a, _b, _c;
|
|
47
|
+
const components = (_b = (_a = handoff.runtimeConfig) === null || _a === void 0 ? void 0 : _a.entities.components) !== null && _b !== void 0 ? _b : {};
|
|
48
48
|
const prefix = `__pattern_${patternId}_`;
|
|
49
49
|
const result = new Map();
|
|
50
50
|
for (const [componentId, component] of Object.entries(components)) {
|
|
51
|
-
const previews = (
|
|
51
|
+
const previews = (_c = component.internalPatternPreviews) !== null && _c !== void 0 ? _c : {};
|
|
52
52
|
const entries = new Map();
|
|
53
53
|
for (const [key, preview] of Object.entries(previews)) {
|
|
54
54
|
if (key.startsWith(prefix)) {
|
|
@@ -14,10 +14,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.generateNavShell = exports.generateDefaultPages = exports.DEFAULT_PAGES_RELATIVE_PATH = exports.NAV_SHELL_RELATIVE_PATH = void 0;
|
|
16
16
|
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
17
|
-
const gray_matter_1 = __importDefault(require("gray-matter"));
|
|
18
17
|
const path_1 = __importDefault(require("path"));
|
|
18
|
+
const markdown_1 = require("../utils/markdown");
|
|
19
19
|
const menu_shell_1 = require("../utils/menu-shell");
|
|
20
20
|
const logger_1 = require("../utils/logger");
|
|
21
|
+
const pages_1 = require("../utils/pages");
|
|
21
22
|
/**
|
|
22
23
|
* Relative path (within the staged Next app) of the baked navigation shell. The docs read API
|
|
23
24
|
* (`pages/api/docs/nav.json.ts`) imports this statically so it is bundled into the route chunk and
|
|
@@ -27,21 +28,13 @@ const logger_1 = require("../utils/logger");
|
|
|
27
28
|
exports.NAV_SHELL_RELATIVE_PATH = path_1.default.join('generated', 'nav-shell.json');
|
|
28
29
|
/** Baked package-default markdown used as the registry catch-all's runtime fallback. */
|
|
29
30
|
exports.DEFAULT_PAGES_RELATIVE_PATH = path_1.default.join('generated', 'default-pages.json');
|
|
30
|
-
/**
|
|
31
|
-
const collectDefaultPages = (root
|
|
32
|
-
if (!fs_extra_1.default.existsSync(root))
|
|
33
|
-
return {};
|
|
31
|
+
/** Collect package defaults for registry fallbacks, including the dedicated root home page. */
|
|
32
|
+
const collectDefaultPages = (root) => {
|
|
34
33
|
const pages = {};
|
|
35
|
-
for (const
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}
|
|
40
|
-
else if (entry.endsWith('.md') && entry !== 'index.md') {
|
|
41
|
-
const id = [...relativeParts, entry.replace(/\.md$/, '')].join('/');
|
|
42
|
-
const { data, content } = (0, gray_matter_1.default)(fs_extra_1.default.readFileSync(absolutePath, 'utf8'));
|
|
43
|
-
pages[id] = { metadata: data, content };
|
|
44
|
-
}
|
|
34
|
+
for (const segments of (0, pages_1.collectPageSlugSegments)(root, { includeRootIndex: true })) {
|
|
35
|
+
const id = segments.join('/');
|
|
36
|
+
const { data, content } = (0, markdown_1.parseMarkdown)(fs_extra_1.default.readFileSync(path_1.default.resolve(root, `${id}.md`), 'utf8'));
|
|
37
|
+
pages[id] = { metadata: data, content };
|
|
45
38
|
}
|
|
46
39
|
return pages;
|
|
47
40
|
};
|