@agent-native/core 0.79.11 → 0.79.15
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/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +25 -0
- package/corpus/core/docs/content/locales/zh-TW/a2a-protocol.md +68 -68
- package/corpus/core/docs/content/locales/zh-TW/actions.md +82 -82
- package/corpus/core/docs/content/locales/zh-TW/agent-mentions.md +22 -22
- package/corpus/core/docs/content/locales/zh-TW/agent-surfaces.md +82 -82
- package/corpus/core/docs/content/locales/zh-TW/agent-teams.md +29 -29
- package/corpus/core/docs/content/locales/zh-TW/agent-web-surfaces.md +11 -11
- package/corpus/core/docs/content/locales/zh-TW/audit-log.md +16 -16
- package/corpus/core/docs/content/locales/zh-TW/authentication.md +32 -32
- package/corpus/core/docs/content/locales/zh-TW/automations.md +32 -32
- package/corpus/core/docs/content/locales/zh-TW/blueprint-installer.md +19 -19
- package/corpus/core/docs/content/locales/zh-TW/cli-adapters.md +17 -17
- package/corpus/core/docs/content/locales/zh-TW/client.md +62 -62
- package/corpus/core/docs/content/locales/zh-TW/cloneable-saas.md +32 -32
- package/corpus/core/docs/content/locales/zh-TW/code-agents-ui.md +91 -91
- package/corpus/core/docs/content/locales/zh-TW/components.md +51 -51
- package/corpus/core/docs/content/locales/zh-TW/context-awareness.md +66 -66
- package/corpus/core/docs/content/locales/zh-TW/creating-templates.md +39 -39
- package/corpus/core/docs/content/locales/zh-TW/cross-app-sso.md +29 -29
- package/corpus/core/docs/content/locales/zh-TW/database.md +21 -21
- package/corpus/core/docs/content/locales/zh-TW/deployment.md +37 -37
- package/corpus/core/docs/content/locales/zh-TW/dispatch.md +43 -43
- package/corpus/core/docs/content/locales/zh-TW/drop-in-agent.md +34 -34
- package/corpus/core/docs/content/locales/zh-TW/durable-resume.md +18 -18
- package/corpus/core/docs/content/locales/zh-TW/embedding-sdk.md +73 -73
- package/corpus/core/docs/content/locales/zh-TW/evals.md +16 -16
- package/corpus/core/docs/content/locales/zh-TW/extensions.md +81 -81
- package/corpus/core/docs/content/locales/zh-TW/external-agents.md +146 -146
- package/corpus/core/docs/content/locales/zh-TW/faq.md +43 -43
- package/corpus/core/docs/content/locales/zh-TW/file-uploads.md +11 -11
- package/corpus/core/docs/content/locales/zh-TW/frames.md +33 -33
- package/corpus/core/docs/content/locales/zh-TW/getting-started.md +28 -28
- package/corpus/core/docs/content/locales/zh-TW/harness-agents.md +78 -78
- package/corpus/core/docs/content/locales/zh-TW/human-approval.md +27 -27
- package/corpus/core/docs/content/locales/zh-TW/internationalization.md +19 -19
- package/corpus/core/docs/content/locales/zh-TW/key-concepts.md +68 -68
- package/corpus/core/docs/content/locales/zh-TW/local-file-mode.md +50 -50
- package/corpus/core/docs/content/locales/zh-TW/mcp-apps.md +38 -38
- package/corpus/core/docs/content/locales/zh-TW/mcp-clients.md +67 -67
- package/corpus/core/docs/content/locales/zh-TW/mcp-protocol.md +50 -50
- package/corpus/core/docs/content/locales/zh-TW/messaging.md +99 -99
- package/corpus/core/docs/content/locales/zh-TW/migration-workbench.md +6 -6
- package/corpus/core/docs/content/locales/zh-TW/multi-app-workspace.md +39 -39
- package/corpus/core/docs/content/locales/zh-TW/multi-tenancy.md +7 -7
- package/corpus/core/docs/content/locales/zh-TW/native-chat-ui.md +38 -38
- package/corpus/core/docs/content/locales/zh-TW/notifications.md +23 -23
- package/corpus/core/docs/content/locales/zh-TW/observability.md +49 -49
- package/corpus/core/docs/content/locales/zh-TW/observational-memory.md +23 -23
- package/corpus/core/docs/content/locales/zh-TW/onboarding.md +40 -40
- package/corpus/core/docs/content/locales/zh-TW/plan-plugin.md +37 -37
- package/corpus/core/docs/content/locales/zh-TW/pr-visual-recap.md +72 -72
- package/corpus/core/docs/content/locales/zh-TW/processors.md +17 -17
- package/corpus/core/docs/content/locales/zh-TW/progress.md +15 -15
- package/corpus/core/docs/content/locales/zh-TW/pure-agent-apps.md +10 -10
- package/corpus/core/docs/content/locales/zh-TW/real-time-collaboration.md +103 -103
- package/corpus/core/docs/content/locales/zh-TW/recurring-jobs.md +19 -19
- package/corpus/core/docs/content/locales/zh-TW/routing.md +9 -9
- package/corpus/core/docs/content/locales/zh-TW/sandbox-adapters.md +48 -48
- package/corpus/core/docs/content/locales/zh-TW/security.md +49 -49
- package/corpus/core/docs/content/locales/zh-TW/server.md +47 -47
- package/corpus/core/docs/content/locales/zh-TW/sharing.md +22 -22
- package/corpus/core/docs/content/locales/zh-TW/skills-guide.md +46 -46
- package/corpus/core/docs/content/locales/zh-TW/template-analytics.md +40 -40
- package/corpus/core/docs/content/locales/zh-TW/template-assets.md +69 -69
- package/corpus/core/docs/content/locales/zh-TW/template-brain.md +81 -81
- package/corpus/core/docs/content/locales/zh-TW/template-calendar.md +40 -40
- package/corpus/core/docs/content/locales/zh-TW/template-chat.md +27 -27
- package/corpus/core/docs/content/locales/zh-TW/template-clips.md +85 -85
- package/corpus/core/docs/content/locales/zh-TW/template-content.md +65 -66
- package/corpus/core/docs/content/locales/zh-TW/template-design.md +29 -29
- package/corpus/core/docs/content/locales/zh-TW/template-dispatch.md +51 -51
- package/corpus/core/docs/content/locales/zh-TW/template-forms.md +25 -25
- package/corpus/core/docs/content/locales/zh-TW/template-mail.md +71 -71
- package/corpus/core/docs/content/locales/zh-TW/template-plan.md +92 -92
- package/corpus/core/docs/content/locales/zh-TW/template-slides.md +52 -52
- package/corpus/core/docs/content/locales/zh-TW/template-videos.md +30 -30
- package/corpus/core/docs/content/locales/zh-TW/tracking.md +29 -29
- package/corpus/core/docs/content/locales/zh-TW/using-your-agent.md +18 -18
- package/corpus/core/docs/content/locales/zh-TW/voice-input.md +19 -19
- package/corpus/core/docs/content/locales/zh-TW/what-is-agent-native.md +61 -61
- package/corpus/core/docs/content/locales/zh-TW/workspace-connections.md +41 -41
- package/corpus/core/docs/content/locales/zh-TW/workspace-management.md +27 -27
- package/corpus/core/docs/content/locales/zh-TW/workspace.md +58 -58
- package/corpus/core/docs/content/locales/zh-TW/writing-agent-instructions.md +41 -41
- package/corpus/core/docs/content/template-clips.md +48 -2
- package/corpus/core/package.json +2 -1
- package/corpus/core/src/client/AgentPanel.tsx +27 -3
- package/corpus/core/src/deploy/build.ts +738 -57
- package/corpus/core/src/deploy/route-discovery.ts +1 -1
- package/corpus/core/src/server/edge.ts +50 -0
- package/corpus/core/src/styles/agent-native.css +93 -0
- package/corpus/core/src/templates/default/app/i18n/zh-TW.ts +44 -44
- package/corpus/core/src/vite/client.ts +1 -0
- package/corpus/templates/analytics/app/components/layout/Layout.tsx +5 -3
- package/corpus/templates/analytics/app/i18n/zh-TW.ts +69 -70
- package/corpus/templates/analytics/changelog/2026-06-27-traditional-chinese-copy-uses-taiwan-terminology.md +6 -0
- package/corpus/templates/assets/app/components/layout/Layout.tsx +3 -3
- package/corpus/templates/assets/app/i18n/zh-TW.ts +82 -82
- package/corpus/templates/assets/changelog/2026-06-27-traditional-chinese-copy-uses-taiwan-terminology.md +6 -0
- package/corpus/templates/brain/app/components/layout/Layout.tsx +6 -4
- package/corpus/templates/brain/app/i18n/zh-TW.ts +90 -90
- package/corpus/templates/brain/changelog/2026-06-27-traditional-chinese-copy-uses-taiwan-terminology.md +6 -0
- package/corpus/templates/calendar/app/components/layout/AppLayout.tsx +1 -1
- package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +1 -1
- package/corpus/templates/calendar/app/i18n/zh-TW.ts +57 -57
- package/corpus/templates/calendar/changelog/2026-06-27-traditional-chinese-copy-uses-taiwan-terminology.md +6 -0
- package/corpus/templates/calendar/server/lib/booking-og-fonts.ts +20 -6
- package/corpus/templates/calendar/server/lib/booking-og-image.ts +17 -9
- package/corpus/templates/chat/app/components/layout/Layout.tsx +5 -3
- package/corpus/templates/chat/app/i18n/zh-TW.ts +3 -3
- package/corpus/templates/chat/changelog/2026-06-27-traditional-chinese-copy-uses-taiwan-terminology.md +6 -0
- package/corpus/templates/clips/AGENTS.md +6 -0
- package/corpus/templates/clips/actions/delete-recording-permanent.ts +7 -1
- package/corpus/templates/clips/actions/get-recording-player-data.ts +44 -2
- package/corpus/templates/clips/actions/navigate.ts +2 -0
- package/corpus/templates/clips/actions/save-bug-report-context.ts +173 -0
- package/corpus/templates/clips/actions/view-screen.ts +58 -7
- package/corpus/templates/clips/app/components/recorder/storage-setup-card.tsx +9 -3
- package/corpus/templates/clips/app/hooks/use-navigation-state.ts +17 -0
- package/corpus/templates/clips/app/i18n/ar-SA.ts +31 -0
- package/corpus/templates/clips/app/i18n/de-DE.ts +32 -0
- package/corpus/templates/clips/app/i18n/en-US.ts +32 -0
- package/corpus/templates/clips/app/i18n/es-ES.ts +32 -0
- package/corpus/templates/clips/app/i18n/fr-FR.ts +32 -0
- package/corpus/templates/clips/app/i18n/hi-IN.ts +32 -0
- package/corpus/templates/clips/app/i18n/ja-JP.ts +31 -0
- package/corpus/templates/clips/app/i18n/ko-KR.ts +32 -0
- package/corpus/templates/clips/app/i18n/pt-BR.ts +32 -0
- package/corpus/templates/clips/app/i18n/zh-CN.ts +30 -0
- package/corpus/templates/clips/app/i18n/zh-TW.ts +461 -451
- package/corpus/templates/clips/app/routes/bug-report.done.tsx +126 -0
- package/corpus/templates/clips/app/routes/bug-report.tsx +222 -0
- package/corpus/templates/clips/app/routes/record.tsx +104 -12
- package/corpus/templates/clips/changelog/2026-06-26-brief-network-blips-no-longer-block-recording-or-wrongly-pro.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-26-bug-report-recordings-can-keep-redacted-host-app-context-wit.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-26-bug-report-widgets-can-launch-clips-recordings-from-embedded.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-26-desktop-recording-keeps-connected-users-out-of-the-storage-s.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-26-if-a-recording-can-t-be-uploaded-the-chrome-extension-now-sa.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-27-traditional-chinese-copy-uses-taiwan-terminology.md +6 -0
- package/corpus/templates/clips/chrome-extension/public/manifest.json +9 -2
- package/corpus/templates/clips/chrome-extension/src/background.ts +43 -0
- package/corpus/templates/clips/chrome-extension/src/offscreen.ts +111 -6
- package/corpus/templates/clips/chrome-extension/src/popup.ts +18 -7
- package/corpus/templates/clips/desktop/src/app.tsx +53 -19
- package/corpus/templates/clips/server/db/schema.ts +26 -0
- package/corpus/templates/clips/server/lib/public-agent-context.ts +51 -0
- package/corpus/templates/clips/server/plugins/auth.ts +1 -0
- package/corpus/templates/clips/server/plugins/db.ts +28 -0
- package/corpus/templates/clips/server/routes/api/agent-context.json.get.ts +4 -1
- package/corpus/templates/clips/shared/bug-report.ts +161 -0
- package/corpus/templates/content/app/components/layout/Layout.tsx +10 -8
- package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +1 -1
- package/corpus/templates/content/app/i18n/zh-TW.ts +67 -66
- package/corpus/templates/content/changelog/2026-06-27-traditional-chinese-copy-uses-taiwan-terminology.md +6 -0
- package/corpus/templates/design/app/components/layout/Layout.tsx +3 -3
- package/corpus/templates/design/app/i18n/zh-TW.ts +44 -44
- package/corpus/templates/design/changelog/2026-06-27-traditional-chinese-copy-uses-taiwan-terminology.md +6 -0
- package/corpus/templates/dispatch/app/i18n/zh-TW.ts +5 -4
- package/corpus/templates/dispatch/changelog/2026-06-27-traditional-chinese-copy-uses-taiwan-terminology.md +6 -0
- package/corpus/templates/forms/app/components/layout/Layout.tsx +4 -2
- package/corpus/templates/forms/app/components/layout/Sidebar.tsx +1 -1
- package/corpus/templates/forms/app/i18n/zh-TW.ts +48 -48
- package/corpus/templates/forms/changelog/2026-06-27-traditional-chinese-copy-uses-taiwan-terminology.md +6 -0
- package/corpus/templates/macros/app/components/layout/AppLayout.tsx +3 -3
- package/corpus/templates/macros/app/i18n/zh-TW.ts +5 -5
- package/corpus/templates/macros/changelog/2026-06-27-traditional-chinese-copy-uses-taiwan-terminology.md +6 -0
- package/corpus/templates/mail/app/i18n/zh-TW.ts +83 -83
- package/corpus/templates/mail/changelog/2026-06-27-traditional-chinese-copy-uses-taiwan-terminology.md +6 -0
- package/corpus/templates/plan/app/components/layout/Layout.tsx +5 -3
- package/corpus/templates/plan/app/i18n/zh-TW.ts +69 -69
- package/corpus/templates/plan/changelog/2026-06-27-traditional-chinese-copy-uses-taiwan-terminology.md +6 -0
- package/corpus/templates/slides/app/components/layout/Layout.tsx +3 -3
- package/corpus/templates/slides/app/i18n/zh-TW.ts +64 -64
- package/corpus/templates/slides/changelog/2026-06-27-traditional-chinese-copy-uses-taiwan-terminology.md +6 -0
- package/corpus/templates/videos/app/components/layout/Layout.tsx +2 -2
- package/corpus/templates/videos/app/i18n/zh-TW.ts +54 -54
- package/corpus/templates/videos/changelog/2026-06-27-traditional-chinese-copy-uses-taiwan-terminology.md +6 -0
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +14 -4
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/deploy/build.d.ts +29 -2
- package/dist/deploy/build.d.ts.map +1 -1
- package/dist/deploy/build.js +587 -51
- package/dist/deploy/build.js.map +1 -1
- package/dist/deploy/route-discovery.d.ts +1 -1
- package/dist/deploy/route-discovery.js +1 -1
- package/dist/deploy/route-discovery.js.map +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +2 -2
- package/dist/notifications/routes.d.ts +2 -2
- package/dist/observability/routes.d.ts +7 -7
- package/dist/resources/handlers.d.ts +2 -2
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/edge.d.ts +11 -0
- package/dist/server/edge.d.ts.map +1 -0
- package/dist/server/edge.js +11 -0
- package/dist/server/edge.js.map +1 -0
- package/dist/styles/agent-native.css +93 -0
- package/dist/templates/default/app/i18n/zh-TW.ts +44 -44
- package/dist/vite/client.d.ts.map +1 -1
- package/dist/vite/client.js +1 -0
- package/dist/vite/client.js.map +1 -1
- package/docs/content/locales/zh-TW/a2a-protocol.md +68 -68
- package/docs/content/locales/zh-TW/actions.md +82 -82
- package/docs/content/locales/zh-TW/agent-mentions.md +22 -22
- package/docs/content/locales/zh-TW/agent-surfaces.md +82 -82
- package/docs/content/locales/zh-TW/agent-teams.md +29 -29
- package/docs/content/locales/zh-TW/agent-web-surfaces.md +11 -11
- package/docs/content/locales/zh-TW/audit-log.md +16 -16
- package/docs/content/locales/zh-TW/authentication.md +32 -32
- package/docs/content/locales/zh-TW/automations.md +32 -32
- package/docs/content/locales/zh-TW/blueprint-installer.md +19 -19
- package/docs/content/locales/zh-TW/cli-adapters.md +17 -17
- package/docs/content/locales/zh-TW/client.md +62 -62
- package/docs/content/locales/zh-TW/cloneable-saas.md +32 -32
- package/docs/content/locales/zh-TW/code-agents-ui.md +91 -91
- package/docs/content/locales/zh-TW/components.md +51 -51
- package/docs/content/locales/zh-TW/context-awareness.md +66 -66
- package/docs/content/locales/zh-TW/creating-templates.md +39 -39
- package/docs/content/locales/zh-TW/cross-app-sso.md +29 -29
- package/docs/content/locales/zh-TW/database.md +21 -21
- package/docs/content/locales/zh-TW/deployment.md +37 -37
- package/docs/content/locales/zh-TW/dispatch.md +43 -43
- package/docs/content/locales/zh-TW/drop-in-agent.md +34 -34
- package/docs/content/locales/zh-TW/durable-resume.md +18 -18
- package/docs/content/locales/zh-TW/embedding-sdk.md +73 -73
- package/docs/content/locales/zh-TW/evals.md +16 -16
- package/docs/content/locales/zh-TW/extensions.md +81 -81
- package/docs/content/locales/zh-TW/external-agents.md +146 -146
- package/docs/content/locales/zh-TW/faq.md +43 -43
- package/docs/content/locales/zh-TW/file-uploads.md +11 -11
- package/docs/content/locales/zh-TW/frames.md +33 -33
- package/docs/content/locales/zh-TW/getting-started.md +28 -28
- package/docs/content/locales/zh-TW/harness-agents.md +78 -78
- package/docs/content/locales/zh-TW/human-approval.md +27 -27
- package/docs/content/locales/zh-TW/internationalization.md +19 -19
- package/docs/content/locales/zh-TW/key-concepts.md +68 -68
- package/docs/content/locales/zh-TW/local-file-mode.md +50 -50
- package/docs/content/locales/zh-TW/mcp-apps.md +38 -38
- package/docs/content/locales/zh-TW/mcp-clients.md +67 -67
- package/docs/content/locales/zh-TW/mcp-protocol.md +50 -50
- package/docs/content/locales/zh-TW/messaging.md +99 -99
- package/docs/content/locales/zh-TW/migration-workbench.md +6 -6
- package/docs/content/locales/zh-TW/multi-app-workspace.md +39 -39
- package/docs/content/locales/zh-TW/multi-tenancy.md +7 -7
- package/docs/content/locales/zh-TW/native-chat-ui.md +38 -38
- package/docs/content/locales/zh-TW/notifications.md +23 -23
- package/docs/content/locales/zh-TW/observability.md +49 -49
- package/docs/content/locales/zh-TW/observational-memory.md +23 -23
- package/docs/content/locales/zh-TW/onboarding.md +40 -40
- package/docs/content/locales/zh-TW/plan-plugin.md +37 -37
- package/docs/content/locales/zh-TW/pr-visual-recap.md +72 -72
- package/docs/content/locales/zh-TW/processors.md +17 -17
- package/docs/content/locales/zh-TW/progress.md +15 -15
- package/docs/content/locales/zh-TW/pure-agent-apps.md +10 -10
- package/docs/content/locales/zh-TW/real-time-collaboration.md +103 -103
- package/docs/content/locales/zh-TW/recurring-jobs.md +19 -19
- package/docs/content/locales/zh-TW/routing.md +9 -9
- package/docs/content/locales/zh-TW/sandbox-adapters.md +48 -48
- package/docs/content/locales/zh-TW/security.md +49 -49
- package/docs/content/locales/zh-TW/server.md +47 -47
- package/docs/content/locales/zh-TW/sharing.md +22 -22
- package/docs/content/locales/zh-TW/skills-guide.md +46 -46
- package/docs/content/locales/zh-TW/template-analytics.md +40 -40
- package/docs/content/locales/zh-TW/template-assets.md +69 -69
- package/docs/content/locales/zh-TW/template-brain.md +81 -81
- package/docs/content/locales/zh-TW/template-calendar.md +40 -40
- package/docs/content/locales/zh-TW/template-chat.md +27 -27
- package/docs/content/locales/zh-TW/template-clips.md +85 -85
- package/docs/content/locales/zh-TW/template-content.md +65 -66
- package/docs/content/locales/zh-TW/template-design.md +29 -29
- package/docs/content/locales/zh-TW/template-dispatch.md +51 -51
- package/docs/content/locales/zh-TW/template-forms.md +25 -25
- package/docs/content/locales/zh-TW/template-mail.md +71 -71
- package/docs/content/locales/zh-TW/template-plan.md +92 -92
- package/docs/content/locales/zh-TW/template-slides.md +52 -52
- package/docs/content/locales/zh-TW/template-videos.md +30 -30
- package/docs/content/locales/zh-TW/tracking.md +29 -29
- package/docs/content/locales/zh-TW/using-your-agent.md +18 -18
- package/docs/content/locales/zh-TW/voice-input.md +19 -19
- package/docs/content/locales/zh-TW/what-is-agent-native.md +61 -61
- package/docs/content/locales/zh-TW/workspace-connections.md +41 -41
- package/docs/content/locales/zh-TW/workspace-management.md +27 -27
- package/docs/content/locales/zh-TW/workspace.md +58 -58
- package/docs/content/locales/zh-TW/writing-agent-instructions.md +41 -41
- package/docs/content/template-clips.md +48 -2
- package/package.json +2 -1
- package/src/templates/default/app/i18n/zh-TW.ts +44 -44
package/dist/deploy/build.js
CHANGED
|
@@ -64,6 +64,323 @@ export const CLOUDFLARE_WORKER_ESBUILD_EXTERNALS = [
|
|
|
64
64
|
"@sparticuz/chromium-min",
|
|
65
65
|
"fsevents",
|
|
66
66
|
];
|
|
67
|
+
export const CLOUDFLARE_WORKER_STUB_MODULES = {
|
|
68
|
+
"better-sqlite3": "export default {}; export const Database = class {}; export const watch = () => ({ close() {} });\n",
|
|
69
|
+
"node-pty": "export default {}; export const watch = () => ({ close() {} });\n",
|
|
70
|
+
chokidar: "export default {}; export const watch = () => ({ close() {} });\n",
|
|
71
|
+
fsevents: "export default {}; export const watch = () => ({ close() {} });\n",
|
|
72
|
+
dotenv: "export default {}; export const config = () => ({ parsed: {} });\n",
|
|
73
|
+
"@anthropic-ai/sdk": "export default class Anthropic {}\n",
|
|
74
|
+
"@anthropic-ai/tokenizer": "export default {}; export const countTokens = undefined;\n",
|
|
75
|
+
"@sentry/node": [
|
|
76
|
+
"export const init = () => {};",
|
|
77
|
+
"const scope = {",
|
|
78
|
+
" setUser() {},",
|
|
79
|
+
" setTag() {},",
|
|
80
|
+
" setExtra() {},",
|
|
81
|
+
" setContext() {},",
|
|
82
|
+
" setLevel() {},",
|
|
83
|
+
" getScopeData() { return {}; },",
|
|
84
|
+
"};",
|
|
85
|
+
"export const getIsolationScope = () => scope;",
|
|
86
|
+
"export const withScope = (fn) => fn(scope);",
|
|
87
|
+
"export const captureException = () => undefined;",
|
|
88
|
+
"export default { init, getIsolationScope, withScope, captureException };",
|
|
89
|
+
"",
|
|
90
|
+
].join("\n"),
|
|
91
|
+
"@resvg/resvg-js": [
|
|
92
|
+
"export class Resvg {",
|
|
93
|
+
' constructor() { throw new Error("@resvg/resvg-js unavailable in Cloudflare Pages worker"); }',
|
|
94
|
+
"}",
|
|
95
|
+
"export default { Resvg };",
|
|
96
|
+
"",
|
|
97
|
+
].join("\n"),
|
|
98
|
+
"playwright-core": [
|
|
99
|
+
"const unavailable = async () => { throw new Error('playwright-core unavailable in Cloudflare Pages worker'); };",
|
|
100
|
+
"export const chromium = { launch: unavailable };",
|
|
101
|
+
"export const firefox = { launch: unavailable };",
|
|
102
|
+
"export const webkit = { launch: unavailable };",
|
|
103
|
+
"export default { chromium, firefox, webkit };",
|
|
104
|
+
"",
|
|
105
|
+
].join("\n"),
|
|
106
|
+
"@sparticuz/chromium-min": [
|
|
107
|
+
"const chromium = {",
|
|
108
|
+
" args: [],",
|
|
109
|
+
" setGraphicsMode: false,",
|
|
110
|
+
" executablePath: async () => { throw new Error('@sparticuz/chromium-min unavailable in Cloudflare Pages worker'); },",
|
|
111
|
+
"};",
|
|
112
|
+
"export default chromium;",
|
|
113
|
+
"",
|
|
114
|
+
].join("\n"),
|
|
115
|
+
"@google/genai": [
|
|
116
|
+
"export class GoogleGenAI {",
|
|
117
|
+
" constructor() { throw new Error('@google/genai unavailable in Cloudflare Pages worker'); }",
|
|
118
|
+
"}",
|
|
119
|
+
"export default { GoogleGenAI };",
|
|
120
|
+
"",
|
|
121
|
+
].join("\n"),
|
|
122
|
+
"pdf-parse": [
|
|
123
|
+
"export class PDFParse {",
|
|
124
|
+
" constructor() { throw new Error('pdf-parse unavailable in Cloudflare Pages worker'); }",
|
|
125
|
+
"}",
|
|
126
|
+
"export default { PDFParse };",
|
|
127
|
+
"",
|
|
128
|
+
].join("\n"),
|
|
129
|
+
"pdfjs-dist": "export default {}; export const getDocument = () => { throw new Error('pdfjs-dist unavailable in Cloudflare Pages worker'); };\n",
|
|
130
|
+
"chartjs-node-canvas": [
|
|
131
|
+
"export class ChartJSNodeCanvas {",
|
|
132
|
+
" constructor() { throw new Error('chartjs-node-canvas unavailable in Cloudflare Pages worker'); }",
|
|
133
|
+
"}",
|
|
134
|
+
"export default { ChartJSNodeCanvas };",
|
|
135
|
+
"",
|
|
136
|
+
].join("\n"),
|
|
137
|
+
"@napi-rs/canvas": "export default {}; export const createCanvas = () => { throw new Error('@napi-rs/canvas unavailable in Cloudflare Pages worker'); };\n",
|
|
138
|
+
mermaid: "export default {}; export const mermaidAPI = {};\n",
|
|
139
|
+
"@excalidraw/excalidraw": "export default {}; export const MainMenu = {}; export const WelcomeScreen = {};\n",
|
|
140
|
+
"@excalidraw/mermaid-to-excalidraw": "export default async () => ({ elements: [], files: {} });\n",
|
|
141
|
+
};
|
|
142
|
+
function cloudflareNodeBuiltinStubSource(moduleName, namedExports, overrides = []) {
|
|
143
|
+
const overridden = new Set(overrides.flatMap((source) => Array.from(source.matchAll(/\bexport const ([A-Za-z_$][\w$]*)/g)).map((match) => match[1])));
|
|
144
|
+
const exports = Array.from(new Set(namedExports))
|
|
145
|
+
.filter((name) => !overridden.has(name))
|
|
146
|
+
.sort();
|
|
147
|
+
return [
|
|
148
|
+
`const unavailable = (name) => (..._args) => { throw new Error(name + " is unavailable in Cloudflare Pages workers"); };`,
|
|
149
|
+
`const proxy = new Proxy({}, { get(_target, prop) { return unavailable("${moduleName}." + String(prop)); } });`,
|
|
150
|
+
...overrides,
|
|
151
|
+
...exports.map((name) => `export const ${name} = unavailable("${moduleName}.${name}");`),
|
|
152
|
+
"export default proxy;",
|
|
153
|
+
"",
|
|
154
|
+
].join("\n");
|
|
155
|
+
}
|
|
156
|
+
export const CLOUDFLARE_WORKER_NODE_BUILTIN_STUB_MODULES = {
|
|
157
|
+
child_process: cloudflareNodeBuiltinStubSource("child_process", [
|
|
158
|
+
"exec",
|
|
159
|
+
"execFile",
|
|
160
|
+
"execFileSync",
|
|
161
|
+
"execSync",
|
|
162
|
+
"fork",
|
|
163
|
+
"spawn",
|
|
164
|
+
"spawnSync",
|
|
165
|
+
]),
|
|
166
|
+
cluster: cloudflareNodeBuiltinStubSource("cluster", [
|
|
167
|
+
"disconnect",
|
|
168
|
+
"fork",
|
|
169
|
+
"isMaster",
|
|
170
|
+
"isPrimary",
|
|
171
|
+
"isWorker",
|
|
172
|
+
"setupMaster",
|
|
173
|
+
"setupPrimary",
|
|
174
|
+
"worker",
|
|
175
|
+
"workers",
|
|
176
|
+
]),
|
|
177
|
+
dgram: cloudflareNodeBuiltinStubSource("dgram", ["createSocket"]),
|
|
178
|
+
dns: cloudflareNodeBuiltinStubSource("dns", [
|
|
179
|
+
"lookup",
|
|
180
|
+
"promises",
|
|
181
|
+
"resolve",
|
|
182
|
+
"resolve4",
|
|
183
|
+
"resolve6",
|
|
184
|
+
]),
|
|
185
|
+
"dns/promises": cloudflareNodeBuiltinStubSource("dns/promises", [
|
|
186
|
+
"lookup",
|
|
187
|
+
"resolve",
|
|
188
|
+
"resolve4",
|
|
189
|
+
"resolve6",
|
|
190
|
+
]),
|
|
191
|
+
domain: cloudflareNodeBuiltinStubSource("domain", ["create"]),
|
|
192
|
+
fs: cloudflareNodeBuiltinStubSource("fs", [
|
|
193
|
+
"access",
|
|
194
|
+
"accessSync",
|
|
195
|
+
"appendFile",
|
|
196
|
+
"appendFileSync",
|
|
197
|
+
"chmod",
|
|
198
|
+
"chmodSync",
|
|
199
|
+
"close",
|
|
200
|
+
"closeSync",
|
|
201
|
+
"copyFile",
|
|
202
|
+
"copyFileSync",
|
|
203
|
+
"cp",
|
|
204
|
+
"cpSync",
|
|
205
|
+
"createReadStream",
|
|
206
|
+
"createWriteStream",
|
|
207
|
+
"existsSync",
|
|
208
|
+
"lstat",
|
|
209
|
+
"lstatSync",
|
|
210
|
+
"mkdir",
|
|
211
|
+
"mkdirSync",
|
|
212
|
+
"open",
|
|
213
|
+
"openSync",
|
|
214
|
+
"readFile",
|
|
215
|
+
"readFileSync",
|
|
216
|
+
"readdir",
|
|
217
|
+
"readdirSync",
|
|
218
|
+
"readlink",
|
|
219
|
+
"readlinkSync",
|
|
220
|
+
"realpath",
|
|
221
|
+
"realpathSync",
|
|
222
|
+
"rename",
|
|
223
|
+
"renameSync",
|
|
224
|
+
"rm",
|
|
225
|
+
"rmSync",
|
|
226
|
+
"stat",
|
|
227
|
+
"statSync",
|
|
228
|
+
"symlink",
|
|
229
|
+
"symlinkSync",
|
|
230
|
+
"unlink",
|
|
231
|
+
"unlinkSync",
|
|
232
|
+
"watch",
|
|
233
|
+
"writeFile",
|
|
234
|
+
"writeFileSync",
|
|
235
|
+
], [
|
|
236
|
+
"export const constants = {};",
|
|
237
|
+
"export const promises = {};",
|
|
238
|
+
"export const existsSync = () => false;",
|
|
239
|
+
"export const readdirSync = () => [];",
|
|
240
|
+
"export const realpathSync = (value) => value;",
|
|
241
|
+
"export const mkdirSync = () => undefined;",
|
|
242
|
+
"export const rmSync = () => undefined;",
|
|
243
|
+
]),
|
|
244
|
+
"fs/promises": cloudflareNodeBuiltinStubSource("fs/promises", [
|
|
245
|
+
"access",
|
|
246
|
+
"appendFile",
|
|
247
|
+
"chmod",
|
|
248
|
+
"copyFile",
|
|
249
|
+
"cp",
|
|
250
|
+
"lstat",
|
|
251
|
+
"mkdir",
|
|
252
|
+
"readFile",
|
|
253
|
+
"readdir",
|
|
254
|
+
"readlink",
|
|
255
|
+
"realpath",
|
|
256
|
+
"rename",
|
|
257
|
+
"rm",
|
|
258
|
+
"stat",
|
|
259
|
+
"symlink",
|
|
260
|
+
"unlink",
|
|
261
|
+
"writeFile",
|
|
262
|
+
]),
|
|
263
|
+
http: cloudflareNodeBuiltinStubSource("http", [
|
|
264
|
+
"Agent",
|
|
265
|
+
"ClientRequest",
|
|
266
|
+
"IncomingMessage",
|
|
267
|
+
"ServerResponse",
|
|
268
|
+
"createServer",
|
|
269
|
+
"get",
|
|
270
|
+
"request",
|
|
271
|
+
]),
|
|
272
|
+
http2: cloudflareNodeBuiltinStubSource("http2", [
|
|
273
|
+
"Http2ServerRequest",
|
|
274
|
+
"Http2ServerResponse",
|
|
275
|
+
"constants",
|
|
276
|
+
"connect",
|
|
277
|
+
"createSecureServer",
|
|
278
|
+
"createServer",
|
|
279
|
+
]),
|
|
280
|
+
https: cloudflareNodeBuiltinStubSource("https", [
|
|
281
|
+
"Agent",
|
|
282
|
+
"createServer",
|
|
283
|
+
"get",
|
|
284
|
+
"request",
|
|
285
|
+
]),
|
|
286
|
+
inspector: cloudflareNodeBuiltinStubSource("inspector", [
|
|
287
|
+
"Session",
|
|
288
|
+
"close",
|
|
289
|
+
"open",
|
|
290
|
+
"url",
|
|
291
|
+
"waitForDebugger",
|
|
292
|
+
]),
|
|
293
|
+
module: cloudflareNodeBuiltinStubSource("module", ["Module", "builtinModules", "createRequire", "syncBuiltinESMExports"], [
|
|
294
|
+
"export const builtinModules = [];",
|
|
295
|
+
"export const createRequire = () => globalThis.require ?? ((specifier) => { throw new Error('Cannot require: ' + specifier); });",
|
|
296
|
+
]),
|
|
297
|
+
net: cloudflareNodeBuiltinStubSource("net", [
|
|
298
|
+
"Socket",
|
|
299
|
+
"connect",
|
|
300
|
+
"createConnection",
|
|
301
|
+
"createServer",
|
|
302
|
+
]),
|
|
303
|
+
os: cloudflareNodeBuiltinStubSource("os", [
|
|
304
|
+
"arch",
|
|
305
|
+
"cpus",
|
|
306
|
+
"endianness",
|
|
307
|
+
"freemem",
|
|
308
|
+
"homedir",
|
|
309
|
+
"hostname",
|
|
310
|
+
"networkInterfaces",
|
|
311
|
+
"platform",
|
|
312
|
+
"release",
|
|
313
|
+
"tmpdir",
|
|
314
|
+
"totalmem",
|
|
315
|
+
"type",
|
|
316
|
+
"userInfo",
|
|
317
|
+
], [
|
|
318
|
+
'export const EOL = "\\n";',
|
|
319
|
+
'export const arch = () => "x64";',
|
|
320
|
+
"export const cpus = () => [];",
|
|
321
|
+
'export const endianness = () => "LE";',
|
|
322
|
+
"export const freemem = () => 0;",
|
|
323
|
+
'export const homedir = () => "/tmp";',
|
|
324
|
+
'export const hostname = () => "cloudflare-worker";',
|
|
325
|
+
"export const networkInterfaces = () => ({});",
|
|
326
|
+
'export const platform = () => "linux";',
|
|
327
|
+
'export const release = () => "";',
|
|
328
|
+
'export const tmpdir = () => "/tmp";',
|
|
329
|
+
"export const totalmem = () => 0;",
|
|
330
|
+
'export const type = () => "Worker";',
|
|
331
|
+
"export const userInfo = () => ({ username: 'worker', homedir: '/tmp' });",
|
|
332
|
+
]),
|
|
333
|
+
readline: cloudflareNodeBuiltinStubSource("readline", [
|
|
334
|
+
"Interface",
|
|
335
|
+
"clearLine",
|
|
336
|
+
"clearScreenDown",
|
|
337
|
+
"createInterface",
|
|
338
|
+
"cursorTo",
|
|
339
|
+
"emitKeypressEvents",
|
|
340
|
+
"moveCursor",
|
|
341
|
+
]),
|
|
342
|
+
repl: cloudflareNodeBuiltinStubSource("repl", ["start"]),
|
|
343
|
+
sqlite: cloudflareNodeBuiltinStubSource("sqlite", ["DatabaseSync"]),
|
|
344
|
+
sys: cloudflareNodeBuiltinStubSource("sys", [
|
|
345
|
+
"debug",
|
|
346
|
+
"deprecate",
|
|
347
|
+
"error",
|
|
348
|
+
"inspect",
|
|
349
|
+
"log",
|
|
350
|
+
"print",
|
|
351
|
+
"puts",
|
|
352
|
+
]),
|
|
353
|
+
tls: cloudflareNodeBuiltinStubSource("tls", [
|
|
354
|
+
"TLSSocket",
|
|
355
|
+
"connect",
|
|
356
|
+
"createSecureContext",
|
|
357
|
+
"createServer",
|
|
358
|
+
]),
|
|
359
|
+
trace_events: cloudflareNodeBuiltinStubSource("trace_events", [
|
|
360
|
+
"createTracing",
|
|
361
|
+
"getEnabledCategories",
|
|
362
|
+
]),
|
|
363
|
+
tty: cloudflareNodeBuiltinStubSource("tty", [
|
|
364
|
+
"ReadStream",
|
|
365
|
+
"WriteStream",
|
|
366
|
+
"isatty",
|
|
367
|
+
]),
|
|
368
|
+
v8: cloudflareNodeBuiltinStubSource("v8", [
|
|
369
|
+
"deserialize",
|
|
370
|
+
"getHeapStatistics",
|
|
371
|
+
"serialize",
|
|
372
|
+
]),
|
|
373
|
+
vm: cloudflareNodeBuiltinStubSource("vm", [
|
|
374
|
+
"Script",
|
|
375
|
+
"compileFunction",
|
|
376
|
+
"createContext",
|
|
377
|
+
"runInContext",
|
|
378
|
+
"runInNewContext",
|
|
379
|
+
"runInThisContext",
|
|
380
|
+
]),
|
|
381
|
+
wasi: cloudflareNodeBuiltinStubSource("wasi", ["WASI"]),
|
|
382
|
+
worker_threads: cloudflareNodeBuiltinStubSource("worker_threads", ["MessageChannel", "MessagePort", "Worker", "isMainThread", "parentPort"], ["export const isMainThread = true;", "export const parentPort = null;"]),
|
|
383
|
+
};
|
|
67
384
|
function normalizeConfiguredAppBasePath() {
|
|
68
385
|
return normalizeAppBasePath(process.env.VITE_APP_BASE_PATH || process.env.APP_BASE_PATH);
|
|
69
386
|
}
|
|
@@ -76,6 +393,7 @@ const NODE_ONLY_PLUGINS = new Set([
|
|
|
76
393
|
// observability there; the framework default is the Node SDK.
|
|
77
394
|
"sentry",
|
|
78
395
|
]);
|
|
396
|
+
const EDGE_SERVER_ENTRYPOINT = "@agent-native/core/server/edge";
|
|
79
397
|
function isNodeOnlyPlugin(filePath) {
|
|
80
398
|
const basename = path.basename(filePath, path.extname(filePath));
|
|
81
399
|
return NODE_ONLY_PLUGINS.has(basename);
|
|
@@ -83,7 +401,7 @@ function isNodeOnlyPlugin(filePath) {
|
|
|
83
401
|
export function generateProvidedPluginsNitroPluginSource(pluginStems) {
|
|
84
402
|
const stems = [...new Set(pluginStems.filter(Boolean))].sort();
|
|
85
403
|
return `// AUTO-GENERATED by @agent-native/core deploy build
|
|
86
|
-
import { markDefaultPluginProvided } from "
|
|
404
|
+
import { markDefaultPluginProvided } from "${EDGE_SERVER_ENTRYPOINT}";
|
|
87
405
|
|
|
88
406
|
const pluginStems = ${JSON.stringify(stems)};
|
|
89
407
|
|
|
@@ -130,10 +448,11 @@ export function addImmutableAssetRouteRulesForClientBuild(routeRules, clientDir,
|
|
|
130
448
|
* If a workspace core is present (monorepo with `agent-native.workspaceCore`
|
|
131
449
|
* configured and the named package resolves), any plugin slot that the
|
|
132
450
|
* workspace core exports is imported from there instead of from
|
|
133
|
-
* `@agent-native/core/server`. This is the middle layer of the three-layer
|
|
451
|
+
* `@agent-native/core/server/edge`. This is the middle layer of the three-layer
|
|
134
452
|
* inheritance model: app local > workspace core > framework default.
|
|
135
453
|
*/
|
|
136
|
-
export function generateWorkerEntry(routes, pluginPaths, defaultPluginStems = [], actions = [], workspaceCore = null, immutableAssetPaths = [], builtAppBasePath = normalizeConfiguredAppBasePath()) {
|
|
454
|
+
export function generateWorkerEntry(routes, pluginPaths, defaultPluginStems = [], actions = [], workspaceCore = null, immutableAssetPaths = [], builtAppBasePath = normalizeConfiguredAppBasePath(), options = {}) {
|
|
455
|
+
const includeReactRouterSsr = options.includeReactRouterSsr ?? true;
|
|
137
456
|
const routeImports = [];
|
|
138
457
|
const routeRegistrations = [];
|
|
139
458
|
for (let i = 0; i < routes.length; i++) {
|
|
@@ -206,11 +525,11 @@ export function generateWorkerEntry(routes, pluginPaths, defaultPluginStems = []
|
|
|
206
525
|
pluginImports.push(`import { ${workspaceExportName} as ${varName} } from ${JSON.stringify(`${workspaceCore.packageName}/server`)};`);
|
|
207
526
|
}
|
|
208
527
|
else {
|
|
209
|
-
// Fall back to the framework default from
|
|
528
|
+
// Fall back to the framework default from the edge-safe core entrypoint.
|
|
210
529
|
const defaultExportName = DEFAULT_PLUGIN_REGISTRY[stem];
|
|
211
530
|
if (!defaultExportName)
|
|
212
531
|
continue;
|
|
213
|
-
pluginImports.push(`import { ${defaultExportName} as ${varName} } from "
|
|
532
|
+
pluginImports.push(`import { ${defaultExportName} as ${varName} } from "${EDGE_SERVER_ENTRYPOINT}";`);
|
|
214
533
|
}
|
|
215
534
|
pluginCalls.push(` if (typeof ${varName} === "function") {
|
|
216
535
|
await ${varName}(nitroApp);
|
|
@@ -225,13 +544,13 @@ export function generateWorkerEntry(routes, pluginPaths, defaultPluginStems = []
|
|
|
225
544
|
]
|
|
226
545
|
: [];
|
|
227
546
|
if (generatedPluginMarks.length > 0) {
|
|
228
|
-
pluginImports.unshift(`import { markDefaultPluginProvided as markGeneratedPluginProvided } from "
|
|
547
|
+
pluginImports.unshift(`import { markDefaultPluginProvided as markGeneratedPluginProvided } from "${EDGE_SERVER_ENTRYPOINT}";`);
|
|
229
548
|
}
|
|
230
549
|
return `
|
|
231
550
|
// Auto-generated worker entry point for ${preset}
|
|
232
551
|
import { H3, defineEventHandler, readBody, toResponse } from "h3";
|
|
233
|
-
import { createRequestHandler } from "react-router";
|
|
234
|
-
import * as serverBuild from "./server-build.js";
|
|
552
|
+
${includeReactRouterSsr ? 'import { createRequestHandler } from "react-router";' : ""}
|
|
553
|
+
${includeReactRouterSsr ? 'import * as serverBuild from "./server-build.js";' : ""}
|
|
235
554
|
|
|
236
555
|
function normalizeAppBasePath(value) {
|
|
237
556
|
if (!value || value === "/") return "";
|
|
@@ -547,6 +866,52 @@ function requestWithPathname(request, pathname) {
|
|
|
547
866
|
return new Request(url, request);
|
|
548
867
|
}
|
|
549
868
|
|
|
869
|
+
function isStaticAppShellRequest(request) {
|
|
870
|
+
if (request.method !== "GET" && request.method !== "HEAD") return false;
|
|
871
|
+
const p = stripAppBasePath(new URL(request.url).pathname);
|
|
872
|
+
if (
|
|
873
|
+
p.startsWith("/.well-known/") ||
|
|
874
|
+
p.startsWith("/_agent-native/") ||
|
|
875
|
+
isApiPath(p) ||
|
|
876
|
+
p === "/favicon.ico" ||
|
|
877
|
+
p === "/favicon.png" ||
|
|
878
|
+
/\\.\\w+$/.test(p)
|
|
879
|
+
) {
|
|
880
|
+
return false;
|
|
881
|
+
}
|
|
882
|
+
return true;
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
async function fetchStaticAppShell(request, env) {
|
|
886
|
+
if (!env?.ASSETS || !isStaticAppShellRequest(request)) return null;
|
|
887
|
+
const basePath = getAppBasePath();
|
|
888
|
+
const p = stripAppBasePath(new URL(request.url).pathname);
|
|
889
|
+
const shellRequest = requestWithPathname(
|
|
890
|
+
requestWithMethod(request, "GET"),
|
|
891
|
+
"/index.html",
|
|
892
|
+
);
|
|
893
|
+
let response;
|
|
894
|
+
try {
|
|
895
|
+
response = await env.ASSETS.fetch(shellRequest);
|
|
896
|
+
} catch {
|
|
897
|
+
return null;
|
|
898
|
+
}
|
|
899
|
+
if (response.status === 404) return null;
|
|
900
|
+
if (request.method === "HEAD") {
|
|
901
|
+
return rewriteMountedResponse(
|
|
902
|
+
new Response(null, {
|
|
903
|
+
status: response.status,
|
|
904
|
+
statusText: response.statusText,
|
|
905
|
+
headers: response.headers,
|
|
906
|
+
}),
|
|
907
|
+
basePath,
|
|
908
|
+
p,
|
|
909
|
+
request,
|
|
910
|
+
);
|
|
911
|
+
}
|
|
912
|
+
return rewriteMountedResponse(response, basePath, p, request);
|
|
913
|
+
}
|
|
914
|
+
|
|
550
915
|
// API route handlers
|
|
551
916
|
${routeImports.join("\n")}
|
|
552
917
|
|
|
@@ -602,7 +967,8 @@ ${routeRegistrations.join("\n")}
|
|
|
602
967
|
// Register action routes (/_agent-native/actions/*)
|
|
603
968
|
${actionRegistrations.join("\n")}
|
|
604
969
|
|
|
605
|
-
|
|
970
|
+
${includeReactRouterSsr
|
|
971
|
+
? ` // SSR catch-all for React Router
|
|
606
972
|
const rrHandler = createRequestHandler(() => serverBuild);
|
|
607
973
|
app.all("/**", defineEventHandler(async (event) => {
|
|
608
974
|
const basePath = getAppBasePath();
|
|
@@ -633,7 +999,8 @@ ${actionRegistrations.join("\n")}
|
|
|
633
999
|
);
|
|
634
1000
|
}
|
|
635
1001
|
return rewriteMountedResponse(await rrHandler(request), basePath, p, request);
|
|
636
|
-
}))
|
|
1002
|
+
}));`
|
|
1003
|
+
: ""}
|
|
637
1004
|
|
|
638
1005
|
_handler = app.fetch.bind(app);
|
|
639
1006
|
return _handler;
|
|
@@ -672,11 +1039,166 @@ export default {
|
|
|
672
1039
|
}
|
|
673
1040
|
|
|
674
1041
|
const handler = await getHandler();
|
|
675
|
-
|
|
1042
|
+
const response = await handler(requestWithMountedApiPrefixStripped(request));
|
|
1043
|
+
${includeReactRouterSsr
|
|
1044
|
+
? " return response;"
|
|
1045
|
+
: ` if (response.status === 404) {
|
|
1046
|
+
const shellResponse = await fetchStaticAppShell(request, env);
|
|
1047
|
+
if (shellResponse) return shellResponse;
|
|
1048
|
+
}
|
|
1049
|
+
return response;`}
|
|
676
1050
|
}
|
|
677
1051
|
};
|
|
678
1052
|
`;
|
|
679
1053
|
}
|
|
1054
|
+
function escapeHtmlAttribute(value) {
|
|
1055
|
+
return value
|
|
1056
|
+
.replaceAll("&", "&")
|
|
1057
|
+
.replaceAll('"', """)
|
|
1058
|
+
.replaceAll("<", "<")
|
|
1059
|
+
.replaceAll(">", ">");
|
|
1060
|
+
}
|
|
1061
|
+
function findReactRouterManifest(distDir) {
|
|
1062
|
+
const assetsDir = path.join(distDir, "assets");
|
|
1063
|
+
const manifestFile = fs
|
|
1064
|
+
.readdirSync(assetsDir)
|
|
1065
|
+
.find((file) => /^manifest-[\w-]+\.js$/.test(file));
|
|
1066
|
+
if (!manifestFile) {
|
|
1067
|
+
throw new Error(`React Router client manifest not found in ${assetsDir}`);
|
|
1068
|
+
}
|
|
1069
|
+
const source = fs.readFileSync(path.join(assetsDir, manifestFile), "utf8");
|
|
1070
|
+
const match = source.match(/^window\.__reactRouterManifest=(.*);?\s*$/);
|
|
1071
|
+
if (!match) {
|
|
1072
|
+
throw new Error(`Could not parse React Router manifest ${manifestFile}`);
|
|
1073
|
+
}
|
|
1074
|
+
return JSON.parse(match[1].replace(/;$/, ""));
|
|
1075
|
+
}
|
|
1076
|
+
function collectModulePreloads(manifest, route) {
|
|
1077
|
+
const paths = new Set();
|
|
1078
|
+
const add = (value) => {
|
|
1079
|
+
if (value)
|
|
1080
|
+
paths.add(value);
|
|
1081
|
+
};
|
|
1082
|
+
add(manifest.url);
|
|
1083
|
+
add(manifest.entry.module);
|
|
1084
|
+
manifest.entry.imports?.forEach(add);
|
|
1085
|
+
add(route.module);
|
|
1086
|
+
route.imports?.forEach(add);
|
|
1087
|
+
add(route.clientActionModule);
|
|
1088
|
+
add(route.clientLoaderModule);
|
|
1089
|
+
add(route.clientMiddlewareModule);
|
|
1090
|
+
add(route.hydrateFallbackModule);
|
|
1091
|
+
return [...paths];
|
|
1092
|
+
}
|
|
1093
|
+
function collectStylesheetLinks(manifest, route) {
|
|
1094
|
+
return [...new Set([...(manifest.entry.css ?? []), ...(route.css ?? [])])];
|
|
1095
|
+
}
|
|
1096
|
+
function generateRouteModuleImportScript(manifest, route) {
|
|
1097
|
+
const modules = [
|
|
1098
|
+
["route0", route.module],
|
|
1099
|
+
["route0_clientAction", route.clientActionModule],
|
|
1100
|
+
["route0_clientLoader", route.clientLoaderModule],
|
|
1101
|
+
["route0_clientMiddleware", route.clientMiddlewareModule],
|
|
1102
|
+
["route0_hydrateFallback", route.hydrateFallbackModule],
|
|
1103
|
+
];
|
|
1104
|
+
const imports = modules
|
|
1105
|
+
.filter(([, modulePath]) => modulePath)
|
|
1106
|
+
.map(([name, modulePath]) => `import * as ${name} from ${JSON.stringify(modulePath)};`);
|
|
1107
|
+
const parts = modules
|
|
1108
|
+
.filter(([, modulePath]) => modulePath)
|
|
1109
|
+
.map(([name]) => `...${name}`);
|
|
1110
|
+
return [
|
|
1111
|
+
`import ${JSON.stringify(manifest.url)};`,
|
|
1112
|
+
...imports,
|
|
1113
|
+
`window.__reactRouterRouteModules = {${JSON.stringify(route.id)}:{${parts.join(",")}}};`,
|
|
1114
|
+
`import(${JSON.stringify(manifest.entry.module)});`,
|
|
1115
|
+
].join("\n");
|
|
1116
|
+
}
|
|
1117
|
+
const EMPTY_REACT_ROUTER_TURBO_STREAM = '[{"_1":2,"_3":-5,"_4":-5},"loaderData",{},"actionData","errors"]\n';
|
|
1118
|
+
// Manifest fallbacks cannot execute server loaders, so root loaders get the
|
|
1119
|
+
// framework's default locale shape to keep hydration from reading undefined.
|
|
1120
|
+
const DEFAULT_ROOT_LOADER_REACT_ROUTER_TURBO_STREAM = '[{"_1":2,"_3":-5,"_4":-5},"loaderData",{"_5":6},"actionData","errors","root",{"_7":8,"_9":10,"_11":12,"_13":14},"locale","en-US","preference",{"_7":15},"dir","ltr","messages",{},"system"]\n';
|
|
1121
|
+
export function generateCloudflarePagesStaticShellFromManifest(manifest, basePath = normalizeConfiguredAppBasePath()) {
|
|
1122
|
+
const rootRoute = manifest.routes.root;
|
|
1123
|
+
if (!rootRoute) {
|
|
1124
|
+
throw new Error("React Router manifest is missing the root route");
|
|
1125
|
+
}
|
|
1126
|
+
const modulePreloads = collectModulePreloads(manifest, rootRoute)
|
|
1127
|
+
.map((href) => `<link rel="modulepreload" href="${escapeHtmlAttribute(href)}"/>`)
|
|
1128
|
+
.join("");
|
|
1129
|
+
const stylesheets = collectStylesheetLinks(manifest, rootRoute)
|
|
1130
|
+
.map((href) => `<link rel="stylesheet" href="${escapeHtmlAttribute(href)}"/>`)
|
|
1131
|
+
.join("");
|
|
1132
|
+
const routeModuleScript = generateRouteModuleImportScript(manifest, rootRoute);
|
|
1133
|
+
const context = {
|
|
1134
|
+
basename: basePath || "/",
|
|
1135
|
+
future: { unstable_optimizeDeps: false },
|
|
1136
|
+
routeDiscovery: { mode: "initial" },
|
|
1137
|
+
ssr: true,
|
|
1138
|
+
isSpaMode: true,
|
|
1139
|
+
};
|
|
1140
|
+
const encodedInitialState = rootRoute.hasLoader
|
|
1141
|
+
? DEFAULT_ROOT_LOADER_REACT_ROUTER_TURBO_STREAM
|
|
1142
|
+
: EMPTY_REACT_ROUTER_TURBO_STREAM;
|
|
1143
|
+
return `<!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/><link rel="manifest" href="/manifest.json"/><link rel="icon" type="image/svg+xml" href="/favicon.svg"/>${modulePreloads}${stylesheets}</head><body><div style="display:flex;align-items:center;justify-content:center;height:100vh;width:100%"><svg role="status" aria-label="Loading" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="animation:an-spin 1s linear infinite;opacity:0.7"><path d="M21 12a9 9 0 1 1-6.219-8.56"></path></svg><style>@keyframes an-spin { to { transform: rotate(360deg) } } @media (prefers-color-scheme: dark) { html { background: #09090b; color: #fafafa } }</style></div><script>window.__reactRouterContext = ${JSON.stringify(context)};window.__reactRouterContext.stream = new ReadableStream({start(controller){window.__reactRouterContext.streamController = controller;}}).pipeThrough(new TextEncoderStream());</script><script type="module" async="">${routeModuleScript}</script><!--$--><script>window.__reactRouterContext.streamController.enqueue(${JSON.stringify(encodedInitialState)});</script><!--$--><script>window.__reactRouterContext.streamController.close();</script><!--/$--><!--/$--></body></html>`;
|
|
1144
|
+
}
|
|
1145
|
+
function writeCloudflarePagesStaticShell({ serverDir, distDir, tmpDir, }) {
|
|
1146
|
+
const serverEntry = path.join(serverDir, "index.js");
|
|
1147
|
+
if (!fs.existsSync(serverEntry)) {
|
|
1148
|
+
throw new Error(`React Router server build not found at ${serverEntry}`);
|
|
1149
|
+
}
|
|
1150
|
+
const outFile = path.join(distDir, "index.html");
|
|
1151
|
+
const renderScript = path.join(tmpDir, "render-cloudflare-static-shell.mjs");
|
|
1152
|
+
const basePath = normalizeConfiguredAppBasePath();
|
|
1153
|
+
fs.writeFileSync(renderScript, `
|
|
1154
|
+
import fs from "node:fs";
|
|
1155
|
+
import { createRequire } from "node:module";
|
|
1156
|
+
import { pathToFileURL } from "node:url";
|
|
1157
|
+
|
|
1158
|
+
const cwd = ${JSON.stringify(cwd)};
|
|
1159
|
+
const serverEntry = ${JSON.stringify(serverEntry)};
|
|
1160
|
+
const outFile = ${JSON.stringify(outFile)};
|
|
1161
|
+
const basePath = ${JSON.stringify(basePath)};
|
|
1162
|
+
|
|
1163
|
+
const requireFromApp = createRequire(cwd + "/package.json");
|
|
1164
|
+
const reactRouterEntry = requireFromApp.resolve("react-router");
|
|
1165
|
+
const { createRequestHandler } = await import(pathToFileURL(reactRouterEntry).href);
|
|
1166
|
+
const serverBuild = await import(pathToFileURL(serverEntry).href);
|
|
1167
|
+
const handler = createRequestHandler(serverBuild, "production");
|
|
1168
|
+
const pathname = basePath ? basePath + "/" : "/";
|
|
1169
|
+
const response = await handler(
|
|
1170
|
+
new Request(new URL(pathname, "https://agent-native.local"), {
|
|
1171
|
+
headers: { "X-React-Router-SPA-Mode": "yes" },
|
|
1172
|
+
}),
|
|
1173
|
+
);
|
|
1174
|
+
const html = await response.text();
|
|
1175
|
+
|
|
1176
|
+
if (!html || !html.includes("__reactRouterContext") || !html.includes("entry.client")) {
|
|
1177
|
+
throw new Error("React Router did not render a usable Cloudflare Pages static shell");
|
|
1178
|
+
}
|
|
1179
|
+
|
|
1180
|
+
fs.writeFileSync(outFile, html);
|
|
1181
|
+
process.exit(0);
|
|
1182
|
+
`);
|
|
1183
|
+
try {
|
|
1184
|
+
execFileSync(process.execPath, [renderScript], {
|
|
1185
|
+
cwd,
|
|
1186
|
+
env: {
|
|
1187
|
+
...process.env,
|
|
1188
|
+
NODE_ENV: process.env.NODE_ENV || "production",
|
|
1189
|
+
IS_RR_BUILD_REQUEST: "yes",
|
|
1190
|
+
},
|
|
1191
|
+
stdio: "inherit",
|
|
1192
|
+
});
|
|
1193
|
+
console.log("[deploy] Wrote Cloudflare Pages static app shell.");
|
|
1194
|
+
}
|
|
1195
|
+
catch (error) {
|
|
1196
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1197
|
+
console.warn(`[deploy] React Router static shell render failed; using manifest fallback. ${message}`);
|
|
1198
|
+
fs.writeFileSync(outFile, generateCloudflarePagesStaticShellFromManifest(findReactRouterManifest(distDir), basePath));
|
|
1199
|
+
console.log("[deploy] Wrote Cloudflare Pages static app shell fallback.");
|
|
1200
|
+
}
|
|
1201
|
+
}
|
|
680
1202
|
/**
|
|
681
1203
|
* Build for Cloudflare Pages.
|
|
682
1204
|
* Output structure:
|
|
@@ -702,10 +1224,13 @@ async function buildCloudflarePages() {
|
|
|
702
1224
|
fs.mkdirSync(distDir, { recursive: true });
|
|
703
1225
|
// Copy client assets to dist/
|
|
704
1226
|
copyDir(clientDir, distDir);
|
|
1227
|
+
const tmpDir = path.join(cwd, ".deploy-tmp");
|
|
1228
|
+
fs.mkdirSync(tmpDir, { recursive: true });
|
|
1229
|
+
writeCloudflarePagesStaticShell({ serverDir, distDir, tmpDir });
|
|
705
1230
|
// Exclude _worker.js from being served as a public asset
|
|
706
1231
|
fs.writeFileSync(path.join(distDir, ".assetsignore"), "_worker.js\n");
|
|
707
|
-
// Write
|
|
708
|
-
//
|
|
1232
|
+
// Write package metadata inside _worker.js/ for the ES module worker that
|
|
1233
|
+
// Wrangler compiles and uploads for Cloudflare Pages.
|
|
709
1234
|
fs.mkdirSync(path.join(distDir, "_worker.js"), { recursive: true });
|
|
710
1235
|
fs.writeFileSync(path.join(distDir, "_worker.js", "package.json"), JSON.stringify({ main: "index.js", type: "module" }));
|
|
711
1236
|
// Create empty stub for native modules that wrangler's bundler needs to resolve
|
|
@@ -718,30 +1243,35 @@ async function buildCloudflarePages() {
|
|
|
718
1243
|
const actions = await discoverActionFiles(cwd);
|
|
719
1244
|
const missingDefaults = await getMissingDefaultPlugins(cwd);
|
|
720
1245
|
const workspaceCore = await getWorkspaceCoreExports(cwd);
|
|
1246
|
+
const includeReactRouterSsr = false;
|
|
721
1247
|
const workspaceSlotCount = workspaceCore
|
|
722
1248
|
? Object.keys(workspaceCore.plugins).length
|
|
723
1249
|
: 0;
|
|
724
1250
|
console.log(`[deploy] ${routes.length} API routes, ${actions.length} actions, ${plugins.length} plugins (${plugins.filter((p) => isNodeOnlyPlugin(p)).length} skipped as Node-only), ${missingDefaults.length} auto-mounted defaults${workspaceCore ? `, workspace-core ${workspaceCore.packageName} (${workspaceSlotCount} plugin slots)` : ""}`);
|
|
725
1251
|
// Generate the worker entry
|
|
726
1252
|
const immutableAssetPaths = collectImmutableAssetPaths(clientDir);
|
|
727
|
-
const entrySource = generateWorkerEntry(routes, plugins, missingDefaults, actions, workspaceCore, immutableAssetPaths);
|
|
1253
|
+
const entrySource = generateWorkerEntry(routes, plugins, missingDefaults, actions, workspaceCore, immutableAssetPaths, normalizeConfiguredAppBasePath(), { includeReactRouterSsr });
|
|
728
1254
|
// Create _worker.js output directory
|
|
729
1255
|
const workerOutDir = path.join(distDir, "_worker.js");
|
|
730
1256
|
fs.mkdirSync(workerOutDir, { recursive: true });
|
|
731
1257
|
// Write the worker entry
|
|
732
1258
|
const entryFile = path.join(workerOutDir, "index.js");
|
|
733
|
-
// Rewrite the server-build import to point at the copied files
|
|
734
|
-
|
|
1259
|
+
// Rewrite the server-build import to point at the copied files when this
|
|
1260
|
+
// worker intentionally includes React Router SSR.
|
|
1261
|
+
const adjustedEntry = includeReactRouterSsr
|
|
1262
|
+
? entrySource.replace(`import * as serverBuild from "./server-build.js";`, `import * as serverBuild from "./server/index.js";`)
|
|
1263
|
+
: entrySource;
|
|
735
1264
|
// Write a temp file for esbuild to bundle everything into a single worker entry.
|
|
736
|
-
//
|
|
737
|
-
|
|
738
|
-
|
|
1265
|
+
// When React Router SSR is enabled, the server build is copied to tmp so
|
|
1266
|
+
// esbuild can resolve it. Cloudflare Pages currently uses a static app shell
|
|
1267
|
+
// instead so the worker stays under the platform bundle size limit.
|
|
739
1268
|
// Name the entry "index.js" so esbuild outputs index.js in the outdir,
|
|
740
1269
|
// matching the _worker.js/index.js entry point that Cloudflare Pages expects.
|
|
741
1270
|
const tmpEntry = path.join(tmpDir, "index.js");
|
|
742
1271
|
fs.writeFileSync(tmpEntry, adjustedEntry);
|
|
743
|
-
|
|
744
|
-
|
|
1272
|
+
if (includeReactRouterSsr) {
|
|
1273
|
+
copyDir(serverDir, path.join(tmpDir, "server"));
|
|
1274
|
+
}
|
|
745
1275
|
// Create a require shim so CJS require("fs") calls resolve via ESM imports.
|
|
746
1276
|
// This is injected via esbuild --inject to replace its broken __require shim.
|
|
747
1277
|
fs.writeFileSync(path.join(tmpDir, "_require-shim.js"), generateRequireShim());
|
|
@@ -761,21 +1291,22 @@ async function buildCloudflarePages() {
|
|
|
761
1291
|
// Create stub modules for native/Node-only deps that can't run on Workers.
|
|
762
1292
|
// These get resolved by esbuild instead of the real modules, avoiding bundling
|
|
763
1293
|
// native code that would fail on the Workers runtime.
|
|
764
|
-
const stubModules = [
|
|
765
|
-
"better-sqlite3",
|
|
766
|
-
"node-pty",
|
|
767
|
-
"chokidar",
|
|
768
|
-
"fsevents",
|
|
769
|
-
"dotenv",
|
|
770
|
-
"@anthropic-ai/sdk",
|
|
771
|
-
];
|
|
772
1294
|
const stubDir = path.join(tmpDir, "node_modules");
|
|
773
|
-
for (const mod of
|
|
1295
|
+
for (const [mod, source] of Object.entries(CLOUDFLARE_WORKER_STUB_MODULES)) {
|
|
774
1296
|
const modDir = path.join(stubDir, mod);
|
|
775
1297
|
fs.mkdirSync(modDir, { recursive: true });
|
|
776
|
-
fs.writeFileSync(path.join(modDir, "index.js"),
|
|
1298
|
+
fs.writeFileSync(path.join(modDir, "index.js"), source);
|
|
777
1299
|
fs.writeFileSync(path.join(modDir, "package.json"), JSON.stringify({ name: mod, main: "index.js", type: "module" }));
|
|
778
1300
|
}
|
|
1301
|
+
const stubAliases = Object.keys(CLOUDFLARE_WORKER_STUB_MODULES).map((mod) => `--alias:${mod}=${path.join(stubDir, mod, "index.js")}`);
|
|
1302
|
+
const nodeBuiltinStubDir = path.join(tmpDir, "node-builtin-stubs");
|
|
1303
|
+
fs.mkdirSync(nodeBuiltinStubDir, { recursive: true });
|
|
1304
|
+
const nodeBuiltinStubAliases = [];
|
|
1305
|
+
for (const [mod, source] of Object.entries(CLOUDFLARE_WORKER_NODE_BUILTIN_STUB_MODULES).sort(([a], [b]) => b.length - a.length)) {
|
|
1306
|
+
const stubFile = path.join(nodeBuiltinStubDir, `${mod.replace(/\W+/g, "_")}.js`);
|
|
1307
|
+
fs.writeFileSync(stubFile, source);
|
|
1308
|
+
nodeBuiltinStubAliases.push(`--alias:${mod}=${stubFile}`, `--alias:node:${mod}=${stubFile}`);
|
|
1309
|
+
}
|
|
779
1310
|
const esbuildBin = findEsbuild();
|
|
780
1311
|
// Externalize node builtins (both bare and node: prefixed) — the require
|
|
781
1312
|
// shim handles bare ones. Also alias every `node:*` specifier to its bare
|
|
@@ -789,8 +1320,15 @@ async function buildCloudflarePages() {
|
|
|
789
1320
|
// Only externalize bare names. node:* externals would otherwise pin
|
|
790
1321
|
// the prefix in output; instead we alias node:* → bare so anything that
|
|
791
1322
|
// resolves past alias land as bare externals.
|
|
792
|
-
const
|
|
793
|
-
const
|
|
1323
|
+
const nodeBuiltinStubs = new Set(Object.keys(CLOUDFLARE_WORKER_NODE_BUILTIN_STUB_MODULES));
|
|
1324
|
+
const nodeExternals = builtinNames
|
|
1325
|
+
.filter((n) => !nodeBuiltinStubs.has(n))
|
|
1326
|
+
.sort((a, b) => b.length - a.length)
|
|
1327
|
+
.map((n) => `--external:${n}`);
|
|
1328
|
+
const nodeAliases = builtinNames
|
|
1329
|
+
.filter((n) => !nodeBuiltinStubs.has(n))
|
|
1330
|
+
.sort((a, b) => b.length - a.length)
|
|
1331
|
+
.map((n) => `--alias:node:${n}=${n}`);
|
|
794
1332
|
// Hard externalize large client-only / node-only libraries so they don't
|
|
795
1333
|
// bloat the edge worker. These are never executed in the CF Pages runtime
|
|
796
1334
|
// — mermaid/excalidraw render in the browser, pdf-parse and @google/genai
|
|
@@ -802,7 +1340,7 @@ async function buildCloudflarePages() {
|
|
|
802
1340
|
// files. Both import sites degrade gracefully when the runtime import
|
|
803
1341
|
// fails: context-xray token counts fall back to char/4 estimates and the
|
|
804
1342
|
// OG image route falls back to SVG.
|
|
805
|
-
const heavyClientExternals = CLOUDFLARE_WORKER_ESBUILD_EXTERNALS.map((p) => `--external:${p}`);
|
|
1343
|
+
const heavyClientExternals = CLOUDFLARE_WORKER_ESBUILD_EXTERNALS.filter((p) => !Object.hasOwn(CLOUDFLARE_WORKER_STUB_MODULES, p)).map((p) => `--external:${p}`);
|
|
806
1344
|
execFileSync(esbuildBin, [
|
|
807
1345
|
tmpEntry,
|
|
808
1346
|
"--bundle",
|
|
@@ -828,6 +1366,8 @@ async function buildCloudflarePages() {
|
|
|
828
1366
|
// Externalize node: builtins — CF Workers runtime provides them
|
|
829
1367
|
...nodeExternals,
|
|
830
1368
|
...heavyClientExternals,
|
|
1369
|
+
...stubAliases,
|
|
1370
|
+
...nodeBuiltinStubAliases,
|
|
831
1371
|
// Rewrite node:* -> bare names so chunks never contain node: imports
|
|
832
1372
|
...nodeAliases,
|
|
833
1373
|
], { stdio: "inherit", cwd });
|
|
@@ -913,6 +1453,7 @@ const NODE_BUILTINS = [
|
|
|
913
1453
|
"dgram",
|
|
914
1454
|
"diagnostics_channel",
|
|
915
1455
|
"dns",
|
|
1456
|
+
"dns/promises",
|
|
916
1457
|
"domain",
|
|
917
1458
|
"events",
|
|
918
1459
|
"fs",
|
|
@@ -956,22 +1497,12 @@ export function getNodeBuiltinNames() {
|
|
|
956
1497
|
* Injected via esbuild --inject so CJS deps work on Workers runtime.
|
|
957
1498
|
*/
|
|
958
1499
|
function generateRequireShim() {
|
|
959
|
-
// Shim
|
|
960
|
-
//
|
|
961
|
-
//
|
|
962
|
-
//
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
// Some builtins exist only as runtime polyfills under nodejs_compat
|
|
966
|
-
// (some are no-op stubs). That's fine — the `import` returns whatever
|
|
967
|
-
// the runtime provides; failures only surface when callers actually USE
|
|
968
|
-
// the unsupported APIs at request time, which is the same as if the
|
|
969
|
-
// shim wasn't there.
|
|
970
|
-
//
|
|
971
|
-
// `sqlite` is excluded because it's Node 22+ only and Workers'
|
|
972
|
-
// nodejs_compat doesn't expose it yet — importing it makes the whole
|
|
973
|
-
// bundle fail to load.
|
|
974
|
-
const shimmed = NODE_BUILTINS.filter((name) => name !== "sqlite");
|
|
1500
|
+
// Shim Node builtins that Cloudflare Pages can import, and return lazy
|
|
1501
|
+
// unavailable proxies for builtins that Pages Functions reject at upload
|
|
1502
|
+
// time (child_process, fs, net, etc.). This lets optional Node-only code stay
|
|
1503
|
+
// present in the shared bundle without making worker initialization fail.
|
|
1504
|
+
const stubbed = new Set(Object.keys(CLOUDFLARE_WORKER_NODE_BUILTIN_STUB_MODULES));
|
|
1505
|
+
const shimmed = NODE_BUILTINS.filter((name) => !stubbed.has(name));
|
|
975
1506
|
// Bare module names — CF Pages Functions runs under nodejs_compat v1,
|
|
976
1507
|
// which rejects "node:fs" and only accepts "fs". The post-build pass in
|
|
977
1508
|
// buildCloudflarePages() also strips any `node:` prefix that esbuild or
|
|
@@ -988,8 +1519,13 @@ function generateRequireShim() {
|
|
|
988
1519
|
const entries = shimmed
|
|
989
1520
|
.map((m) => `"${m}":__${m.replace("/", "_")}`)
|
|
990
1521
|
.join(",");
|
|
1522
|
+
const stubEntries = Array.from(stubbed)
|
|
1523
|
+
.sort()
|
|
1524
|
+
.map((m) => `"${m}":__unavailable("${m}")`)
|
|
1525
|
+
.join(",");
|
|
1526
|
+
const allEntries = [entries, stubEntries].filter(Boolean).join(",");
|
|
991
1527
|
const messageChannelPolyfill = `if(typeof MessageChannel==="undefined"){globalThis.MessageChannel=class{constructor(){const a={onmessage:null},b={onmessage:null};a.postMessage=d=>{if(b.onmessage)setTimeout(()=>b.onmessage({data:d}),0)};b.postMessage=d=>{if(a.onmessage)setTimeout(()=>a.onmessage({data:d}),0)};this.port1=a;this.port2=b}}}`;
|
|
992
|
-
return `${imports}\n${messageChannelPolyfill}\nconst __mods={${
|
|
1528
|
+
return `${imports}\n${messageChannelPolyfill}\nconst __unavailable=(m)=>new Proxy({}, { get(_target, prop) { return (..._args) => { throw new Error(m + "." + String(prop) + " is unavailable in Cloudflare Pages workers"); }; } });\nconst __mods={${allEntries}};export var require=globalThis.require||function(m){const r=__mods[m];if(r!==undefined)return r;throw new Error("Cannot require: "+m)};\n`;
|
|
993
1529
|
}
|
|
994
1530
|
function findEsbuild() {
|
|
995
1531
|
// Try to resolve esbuild's binary via Node module resolution
|