skybridge 0.0.0-dev.cb51733 → 0.0.0-dev.cb83b5b
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/README.md +17 -14
- package/dist/cli/build-helpers.d.ts +11 -0
- package/dist/cli/build-helpers.js +115 -0
- package/dist/cli/build-helpers.js.map +1 -0
- package/dist/cli/build-helpers.test.js +156 -0
- package/dist/cli/build-helpers.test.js.map +1 -0
- package/dist/cli/build-steps.d.ts +2 -0
- package/dist/cli/build-steps.js +84 -0
- package/dist/cli/build-steps.js.map +1 -0
- package/dist/cli/build-steps.test.js +72 -0
- package/dist/cli/build-steps.test.js.map +1 -0
- package/dist/cli/detect-port.d.ts +2 -2
- package/dist/cli/detect-port.js +8 -20
- package/dist/cli/detect-port.js.map +1 -1
- package/dist/cli/header.d.ts +1 -1
- package/dist/cli/resolve-skybridge-config.d.ts +6 -0
- package/dist/cli/resolve-skybridge-config.js +28 -0
- package/dist/cli/resolve-skybridge-config.js.map +1 -0
- package/dist/cli/run-plain.d.ts +18 -0
- package/dist/cli/run-plain.js +90 -0
- package/dist/cli/run-plain.js.map +1 -0
- package/dist/cli/telemetry.js +2 -0
- package/dist/cli/telemetry.js.map +1 -1
- package/dist/cli/use-execute-steps.d.ts +1 -1
- package/dist/cli/use-nodemon.d.ts +25 -1
- package/dist/cli/use-nodemon.js +96 -63
- package/dist/cli/use-nodemon.js.map +1 -1
- package/dist/cli/use-typescript-check.d.ts +8 -2
- package/dist/cli/use-typescript-check.js +72 -67
- package/dist/cli/use-typescript-check.js.map +1 -1
- package/dist/commands/build.d.ts +0 -8
- package/dist/commands/build.js +9 -138
- package/dist/commands/build.js.map +1 -1
- package/dist/commands/dev.d.ts +1 -0
- package/dist/commands/dev.js +51 -3
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/start.js +7 -5
- package/dist/commands/start.js.map +1 -1
- package/dist/context-warnings.d.ts +5 -0
- package/dist/context-warnings.js +31 -0
- package/dist/context-warnings.js.map +1 -0
- package/dist/context-warnings.test.js +28 -0
- package/dist/context-warnings.test.js.map +1 -0
- package/dist/server/app.d.ts +211 -0
- package/dist/server/app.js +277 -0
- package/dist/server/app.js.map +1 -0
- package/dist/server/app.test.js +178 -0
- package/dist/server/app.test.js.map +1 -0
- package/dist/server/auth/discovery.d.ts +33 -0
- package/dist/server/auth/discovery.js +56 -0
- package/dist/server/auth/discovery.js.map +1 -0
- package/dist/server/auth/discovery.test.js +93 -0
- package/dist/server/auth/discovery.test.js.map +1 -0
- package/dist/server/auth/index.d.ts +48 -0
- package/dist/server/auth/index.js +2 -0
- package/dist/server/auth/index.js.map +1 -0
- package/dist/server/auth/providers/auth0.d.ts +40 -0
- package/dist/server/auth/providers/auth0.js +36 -0
- package/dist/server/auth/providers/auth0.js.map +1 -0
- package/dist/server/auth/providers/auth0.test.d.ts +1 -0
- package/dist/server/auth/providers/auth0.test.js +50 -0
- package/dist/server/auth/providers/auth0.test.js.map +1 -0
- package/dist/server/auth/providers/authplane.d.ts +49 -0
- package/dist/server/auth/providers/authplane.js +57 -0
- package/dist/server/auth/providers/authplane.js.map +1 -0
- package/dist/server/auth/providers/authplane.test.d.ts +1 -0
- package/dist/server/auth/providers/authplane.test.js +143 -0
- package/dist/server/auth/providers/authplane.test.js.map +1 -0
- package/dist/server/auth/providers/clerk.d.ts +51 -0
- package/dist/server/auth/providers/clerk.js +19 -0
- package/dist/server/auth/providers/clerk.js.map +1 -0
- package/dist/server/auth/providers/clerk.test.d.ts +1 -0
- package/dist/server/auth/providers/clerk.test.js +30 -0
- package/dist/server/auth/providers/clerk.test.js.map +1 -0
- package/dist/server/auth/providers/custom.d.ts +42 -0
- package/dist/server/auth/providers/custom.js +59 -0
- package/dist/server/auth/providers/custom.js.map +1 -0
- package/dist/server/auth/providers/custom.test.d.ts +1 -0
- package/dist/server/auth/providers/custom.test.js +161 -0
- package/dist/server/auth/providers/custom.test.js.map +1 -0
- package/dist/server/auth/providers/descope.d.ts +44 -0
- package/dist/server/auth/providers/descope.js +44 -0
- package/dist/server/auth/providers/descope.js.map +1 -0
- package/dist/server/auth/providers/descope.test.d.ts +1 -0
- package/dist/server/auth/providers/descope.test.js +62 -0
- package/dist/server/auth/providers/descope.test.js.map +1 -0
- package/dist/server/auth/providers/shared.d.ts +2 -0
- package/dist/server/auth/providers/shared.js +6 -0
- package/dist/server/auth/providers/shared.js.map +1 -0
- package/dist/server/auth/providers/shared.test.d.ts +1 -0
- package/dist/server/auth/providers/shared.test.js +10 -0
- package/dist/server/auth/providers/shared.test.js.map +1 -0
- package/dist/server/auth/providers/stytch.d.ts +25 -0
- package/dist/server/auth/providers/stytch.js +16 -0
- package/dist/server/auth/providers/stytch.js.map +1 -0
- package/dist/server/auth/providers/verify-spy.d.ts +12 -0
- package/dist/server/auth/providers/verify-spy.js +21 -0
- package/dist/server/auth/providers/verify-spy.js.map +1 -0
- package/dist/server/auth/providers/workos.d.ts +34 -0
- package/dist/server/auth/providers/workos.js +16 -0
- package/dist/server/auth/providers/workos.js.map +1 -0
- package/dist/server/auth/security-schemes.d.ts +23 -0
- package/dist/server/auth/security-schemes.js +64 -0
- package/dist/server/auth/security-schemes.js.map +1 -0
- package/dist/server/auth/security-schemes.test.d.ts +1 -0
- package/dist/server/auth/security-schemes.test.js +99 -0
- package/dist/server/auth/security-schemes.test.js.map +1 -0
- package/dist/server/auth/setup.d.ts +6 -0
- package/dist/server/auth/setup.js +91 -0
- package/dist/server/auth/setup.js.map +1 -0
- package/dist/server/auth/setup.test.d.ts +1 -0
- package/dist/server/auth/setup.test.js +514 -0
- package/dist/server/auth/setup.test.js.map +1 -0
- package/dist/server/auth/verify.d.ts +48 -0
- package/dist/server/auth/verify.js +62 -0
- package/dist/server/auth/verify.js.map +1 -0
- package/dist/server/auth/verify.test.d.ts +1 -0
- package/dist/server/auth/verify.test.js +165 -0
- package/dist/server/auth/verify.test.js.map +1 -0
- package/dist/server/auth-extra.test-d.js +130 -0
- package/dist/server/auth-extra.test-d.js.map +1 -0
- package/dist/server/auth.d.ts +43 -6
- package/dist/server/auth.js +4 -5
- package/dist/server/auth.js.map +1 -1
- package/dist/server/build-manifest.test.d.ts +1 -0
- package/dist/server/build-manifest.test.js +28 -0
- package/dist/server/build-manifest.test.js.map +1 -0
- package/dist/server/content-helpers.d.ts +1 -1
- package/dist/server/content-helpers.js.map +1 -1
- package/dist/server/events.d.ts +113 -0
- package/dist/server/events.js +318 -0
- package/dist/server/events.js.map +1 -0
- package/dist/server/events.test.d.ts +1 -0
- package/dist/server/events.test.js +172 -0
- package/dist/server/events.test.js.map +1 -0
- package/dist/server/express.d.ts +24 -3
- package/dist/server/express.js +45 -35
- package/dist/server/express.js.map +1 -1
- package/dist/server/express.test.js +273 -108
- package/dist/server/express.test.js.map +1 -1
- package/dist/server/file-ref.d.ts +1 -1
- package/dist/server/file-ref.js +1 -1
- package/dist/server/file-ref.js.map +1 -1
- package/dist/server/form-input.d.ts +120 -0
- package/dist/server/form-input.js +89 -0
- package/dist/server/form-input.js.map +1 -0
- package/dist/server/host.d.ts +2 -0
- package/dist/server/host.js +11 -0
- package/dist/server/host.js.map +1 -0
- package/dist/server/host.test.d.ts +1 -0
- package/dist/server/host.test.js +13 -0
- package/dist/server/host.test.js.map +1 -0
- package/dist/server/index.d.ts +19 -3
- package/dist/server/index.js +16 -2
- package/dist/server/index.js.map +1 -1
- package/dist/server/mcp-errors.test.d.ts +1 -0
- package/dist/server/mcp-errors.test.js +229 -0
- package/dist/server/mcp-errors.test.js.map +1 -0
- package/dist/server/metric.d.ts +5 -3
- package/dist/server/metric.js +5 -5
- package/dist/server/metric.js.map +1 -1
- package/dist/server/middleware.d.ts +35 -10
- package/dist/server/middleware.js +33 -0
- package/dist/server/middleware.js.map +1 -1
- package/dist/server/middleware.test-d.js +1 -1
- package/dist/server/middleware.test-d.js.map +1 -1
- package/dist/server/middleware.test.js +242 -134
- package/dist/server/middleware.test.js.map +1 -1
- package/dist/server/register-tool.test.d.ts +1 -0
- package/dist/server/register-tool.test.js +230 -0
- package/dist/server/register-tool.test.js.map +1 -0
- package/dist/server/requestOrigin.d.ts +7 -0
- package/dist/server/requestOrigin.js +25 -0
- package/dist/server/requestOrigin.js.map +1 -0
- package/dist/server/server.d.ts +397 -132
- package/dist/server/server.js +584 -341
- package/dist/server/server.js.map +1 -1
- package/dist/server/skills-integration.test.d.ts +1 -0
- package/dist/server/skills-integration.test.js +86 -0
- package/dist/server/skills-integration.test.js.map +1 -0
- package/dist/server/skills.d.ts +27 -0
- package/dist/server/skills.js +188 -0
- package/dist/server/skills.js.map +1 -0
- package/dist/server/skills.test.d.ts +1 -0
- package/dist/server/skills.test.js +243 -0
- package/dist/server/skills.test.js.map +1 -0
- package/dist/server/templateHelper.d.ts +1 -3
- package/dist/server/templateHelper.js.map +1 -1
- package/dist/server/templates.generated.js +28 -18
- package/dist/server/templates.generated.js.map +1 -1
- package/dist/server/tool-extra.test.d.ts +1 -0
- package/dist/server/tool-extra.test.js +167 -0
- package/dist/server/tool-extra.test.js.map +1 -0
- package/dist/server/view-name.test-d.d.ts +1 -0
- package/dist/server/view-name.test-d.js +8 -0
- package/dist/server/view-name.test-d.js.map +1 -0
- package/dist/server/view-resource-resolution.test.d.ts +6 -0
- package/dist/server/view-resource-resolution.test.js +211 -0
- package/dist/server/view-resource-resolution.test.js.map +1 -0
- package/dist/server/viewsDevServer.js +4 -1
- package/dist/server/viewsDevServer.js.map +1 -1
- package/dist/test/utils.d.ts +9 -11
- package/dist/test/utils.js +220 -201
- package/dist/test/utils.js.map +1 -1
- package/dist/test/view.test.js +105 -133
- package/dist/test/view.test.js.map +1 -1
- package/dist/views/index.d.ts +10 -0
- package/dist/views/index.js +3 -0
- package/dist/views/index.js.map +1 -0
- package/dist/{web/plugin → views}/scan-views.js +1 -1
- package/dist/views/scan-views.js.map +1 -0
- package/dist/views/scan-views.test.d.ts +1 -0
- package/dist/views/scan-views.test.js.map +1 -0
- package/dist/views/validate-view.d.ts +1 -0
- package/dist/{web/plugin → views}/validate-view.js +2 -2
- package/dist/views/validate-view.js.map +1 -0
- package/dist/views/validate-view.test.d.ts +1 -0
- package/dist/views/validate-view.test.js.map +1 -0
- package/dist/web/bridges/adaptor.d.ts +62 -0
- package/dist/web/bridges/adaptor.js +477 -0
- package/dist/web/bridges/adaptor.js.map +1 -0
- package/dist/web/bridges/adaptor.test.d.ts +1 -0
- package/dist/web/bridges/adaptor.test.js +281 -0
- package/dist/web/bridges/adaptor.test.js.map +1 -0
- package/dist/web/bridges/apps-sdk/bridge.d.ts +6 -2
- package/dist/web/bridges/apps-sdk/bridge.js +15 -4
- package/dist/web/bridges/apps-sdk/bridge.js.map +1 -1
- package/dist/web/bridges/apps-sdk/index.d.ts +0 -1
- package/dist/web/bridges/apps-sdk/index.js +0 -1
- package/dist/web/bridges/apps-sdk/index.js.map +1 -1
- package/dist/web/bridges/apps-sdk/types.d.ts +2 -3
- package/dist/web/bridges/apps-sdk/types.js.map +1 -1
- package/dist/web/bridges/apps-sdk/use-apps-sdk-context.d.ts +4 -4
- package/dist/web/bridges/apps-sdk/use-apps-sdk-context.js +4 -4
- package/dist/web/bridges/apps-sdk/use-apps-sdk-context.js.map +1 -1
- package/dist/web/bridges/get-adaptor.d.ts +4 -4
- package/dist/web/bridges/get-adaptor.js +6 -11
- package/dist/web/bridges/get-adaptor.js.map +1 -1
- package/dist/web/bridges/get-adaptor.test.d.ts +1 -0
- package/dist/web/bridges/get-adaptor.test.js +32 -0
- package/dist/web/bridges/get-adaptor.test.js.map +1 -0
- package/dist/web/bridges/mcp-app/bridge.d.ts +15 -3
- package/dist/web/bridges/mcp-app/bridge.js +80 -8
- package/dist/web/bridges/mcp-app/bridge.js.map +1 -1
- package/dist/web/bridges/mcp-app/bridge.test.d.ts +1 -0
- package/dist/web/bridges/mcp-app/bridge.test.js +17 -0
- package/dist/web/bridges/mcp-app/bridge.test.js.map +1 -0
- package/dist/web/bridges/mcp-app/index.d.ts +0 -1
- package/dist/web/bridges/mcp-app/index.js +0 -1
- package/dist/web/bridges/mcp-app/index.js.map +1 -1
- package/dist/web/bridges/mcp-app/types.d.ts +19 -2
- package/dist/web/bridges/mcp-app/types.js.map +1 -1
- package/dist/web/bridges/mcp-app/use-mcp-app-context.d.ts +2 -2
- package/dist/web/bridges/mcp-app/use-mcp-app-context.js +1 -1
- package/dist/web/bridges/mcp-app/use-mcp-app-context.js.map +1 -1
- package/dist/web/bridges/mcp-app/use-mcp-app-context.test.js +1 -1
- package/dist/web/bridges/mcp-app/use-mcp-app-context.test.js.map +1 -1
- package/dist/web/bridges/mcp-app/view-tools.test.d.ts +1 -0
- package/dist/web/bridges/mcp-app/view-tools.test.js +143 -0
- package/dist/web/bridges/mcp-app/view-tools.test.js.map +1 -0
- package/dist/web/bridges/types.d.ts +110 -9
- package/dist/web/bridges/types.js +14 -1
- package/dist/web/bridges/types.js.map +1 -1
- package/dist/web/bridges/types.test.d.ts +1 -0
- package/dist/web/bridges/types.test.js +19 -0
- package/dist/web/bridges/types.test.js.map +1 -0
- package/dist/web/components/modal-provider.d.ts +1 -1
- package/dist/web/components/modal-provider.js +4 -3
- package/dist/web/components/modal-provider.js.map +1 -1
- package/dist/web/create-store.test.js +10 -7
- package/dist/web/create-store.test.js.map +1 -1
- package/dist/web/data-llm.d.ts +1 -1
- package/dist/web/data-llm.js +3 -2
- package/dist/web/data-llm.js.map +1 -1
- package/dist/web/data-llm.test.js +26 -7
- package/dist/web/data-llm.test.js.map +1 -1
- package/dist/web/generate-helpers.d.ts +23 -19
- package/dist/web/generate-helpers.js +21 -17
- package/dist/web/generate-helpers.js.map +1 -1
- package/dist/web/generate-helpers.test-d.js +7 -5
- package/dist/web/generate-helpers.test-d.js.map +1 -1
- package/dist/web/generate-helpers.test.js +2 -2
- package/dist/web/generate-helpers.test.js.map +1 -1
- package/dist/web/hooks/index.d.ts +7 -1
- package/dist/web/hooks/index.js +7 -1
- package/dist/web/hooks/index.js.map +1 -1
- package/dist/web/hooks/openai-extensions.test.d.ts +1 -0
- package/dist/web/hooks/openai-extensions.test.js +107 -0
- package/dist/web/hooks/openai-extensions.test.js.map +1 -0
- package/dist/web/hooks/test/utils.d.ts +2 -1
- package/dist/web/hooks/test/utils.js +1 -1
- package/dist/web/hooks/test/utils.js.map +1 -1
- package/dist/web/hooks/use-call-tool.d.ts +2 -2
- package/dist/web/hooks/use-call-tool.js +15 -10
- package/dist/web/hooks/use-call-tool.js.map +1 -1
- package/dist/web/hooks/use-call-tool.test.js +50 -25
- package/dist/web/hooks/use-call-tool.test.js.map +1 -1
- package/dist/web/hooks/use-deep-link.d.ts +22 -0
- package/dist/web/hooks/use-deep-link.js +34 -0
- package/dist/web/hooks/use-deep-link.js.map +1 -0
- package/dist/web/hooks/use-display-mode.d.ts +1 -1
- package/dist/web/hooks/use-display-mode.js +1 -1
- package/dist/web/hooks/use-display-mode.js.map +1 -1
- package/dist/web/hooks/use-display-mode.test.js +57 -21
- package/dist/web/hooks/use-display-mode.test.js.map +1 -1
- package/dist/web/hooks/use-download.d.ts +1 -3
- package/dist/web/hooks/use-download.js +1 -2
- package/dist/web/hooks/use-download.js.map +1 -1
- package/dist/web/hooks/use-download.test.js +18 -10
- package/dist/web/hooks/use-download.test.js.map +1 -1
- package/dist/web/hooks/use-file-resource.d.ts +37 -0
- package/dist/web/hooks/use-file-resource.js +98 -0
- package/dist/web/hooks/use-file-resource.js.map +1 -0
- package/dist/web/hooks/use-file-resource.test.d.ts +1 -0
- package/dist/web/hooks/use-file-resource.test.js +65 -0
- package/dist/web/hooks/use-file-resource.test.js.map +1 -0
- package/dist/web/hooks/use-files.test.js +11 -3
- package/dist/web/hooks/use-files.test.js.map +1 -1
- package/dist/web/hooks/use-host.d.ts +44 -0
- package/dist/web/hooks/use-host.js +45 -0
- package/dist/web/hooks/use-host.js.map +1 -0
- package/dist/web/hooks/use-host.test.d.ts +1 -0
- package/dist/web/hooks/use-host.test.js +59 -0
- package/dist/web/hooks/use-host.test.js.map +1 -0
- package/dist/web/hooks/use-model-context.d.ts +44 -0
- package/dist/web/hooks/use-model-context.js +63 -0
- package/dist/web/hooks/use-model-context.js.map +1 -0
- package/dist/web/hooks/use-open-external.test.js +15 -5
- package/dist/web/hooks/use-open-external.test.js.map +1 -1
- package/dist/web/hooks/use-open-file.d.ts +20 -0
- package/dist/web/hooks/use-open-file.js +25 -0
- package/dist/web/hooks/use-open-file.js.map +1 -0
- package/dist/web/hooks/use-register-view-tool.d.ts +37 -0
- package/dist/web/hooks/use-register-view-tool.js +50 -0
- package/dist/web/hooks/use-register-view-tool.js.map +1 -0
- package/dist/web/hooks/use-request-close.test.js +35 -40
- package/dist/web/hooks/use-request-close.test.js.map +1 -1
- package/dist/web/hooks/use-request-modal.test.js +11 -1
- package/dist/web/hooks/use-request-modal.test.js.map +1 -1
- package/dist/web/hooks/use-request-size.d.ts +1 -1
- package/dist/web/hooks/use-request-size.js +1 -1
- package/dist/web/hooks/use-request-size.js.map +1 -1
- package/dist/web/hooks/use-request-size.test.js +35 -53
- package/dist/web/hooks/use-request-size.test.js.map +1 -1
- package/dist/web/hooks/use-send-follow-up-message.d.ts +8 -2
- package/dist/web/hooks/use-send-follow-up-message.js +6 -0
- package/dist/web/hooks/use-send-follow-up-message.js.map +1 -1
- package/dist/web/hooks/use-set-open-in-app-url.test.js +26 -12
- package/dist/web/hooks/use-set-open-in-app-url.test.js.map +1 -1
- package/dist/web/hooks/use-tool-info.d.ts +18 -19
- package/dist/web/hooks/use-tool-info.js +4 -8
- package/dist/web/hooks/use-tool-info.js.map +1 -1
- package/dist/web/hooks/use-tool-info.test-d.js +11 -34
- package/dist/web/hooks/use-tool-info.test-d.js.map +1 -1
- package/dist/web/hooks/use-tool-info.test.js +42 -37
- package/dist/web/hooks/use-tool-info.test.js.map +1 -1
- package/dist/web/hooks/use-user.d.ts +3 -2
- package/dist/web/hooks/use-user.js +4 -3
- package/dist/web/hooks/use-user.js.map +1 -1
- package/dist/web/hooks/use-user.test.js +85 -37
- package/dist/web/hooks/use-user.test.js.map +1 -1
- package/dist/web/hooks/use-view-state.js +19 -9
- package/dist/web/hooks/use-view-state.js.map +1 -1
- package/dist/web/hooks/use-view-state.test.js +39 -4
- package/dist/web/hooks/use-view-state.test.js.map +1 -1
- package/dist/web/hooks/use-viewport.d.ts +20 -0
- package/dist/web/hooks/use-viewport.js +21 -0
- package/dist/web/hooks/use-viewport.js.map +1 -0
- package/dist/web/hooks/use-viewport.test.d.ts +1 -0
- package/dist/web/hooks/use-viewport.test.js +109 -0
- package/dist/web/hooks/use-viewport.test.js.map +1 -0
- package/dist/web/mount-view.d.ts +3 -2
- package/dist/web/mount-view.js +6 -11
- package/dist/web/mount-view.js.map +1 -1
- package/package.json +35 -27
- package/dist/commands/build-helpers.d.ts +0 -26
- package/dist/commands/build-helpers.js +0 -93
- package/dist/commands/build-helpers.js.map +0 -1
- package/dist/commands/build-helpers.test.js +0 -116
- package/dist/commands/build-helpers.test.js.map +0 -1
- package/dist/web/bridges/apps-sdk/adaptor.d.ts +0 -28
- package/dist/web/bridges/apps-sdk/adaptor.js +0 -113
- package/dist/web/bridges/apps-sdk/adaptor.js.map +0 -1
- package/dist/web/bridges/mcp-app/adaptor.d.ts +0 -52
- package/dist/web/bridges/mcp-app/adaptor.js +0 -280
- package/dist/web/bridges/mcp-app/adaptor.js.map +0 -1
- package/dist/web/hooks/use-layout.d.ts +0 -24
- package/dist/web/hooks/use-layout.js +0 -25
- package/dist/web/hooks/use-layout.js.map +0 -1
- package/dist/web/hooks/use-layout.test.js +0 -96
- package/dist/web/hooks/use-layout.test.js.map +0 -1
- package/dist/web/plugin/data-llm.test.js +0 -81
- package/dist/web/plugin/data-llm.test.js.map +0 -1
- package/dist/web/plugin/plugin.d.ts +0 -33
- package/dist/web/plugin/plugin.js +0 -189
- package/dist/web/plugin/plugin.js.map +0 -1
- package/dist/web/plugin/scan-views.js.map +0 -1
- package/dist/web/plugin/scan-views.test.js.map +0 -1
- package/dist/web/plugin/transform-data-llm.d.ts +0 -12
- package/dist/web/plugin/transform-data-llm.js +0 -96
- package/dist/web/plugin/transform-data-llm.js.map +0 -1
- package/dist/web/plugin/transform-data-llm.test.js +0 -81
- package/dist/web/plugin/transform-data-llm.test.js.map +0 -1
- package/dist/web/plugin/validate-view.d.ts +0 -1
- package/dist/web/plugin/validate-view.js.map +0 -1
- package/dist/web/plugin/validate-view.test.js.map +0 -1
- /package/dist/{commands → cli}/build-helpers.test.d.ts +0 -0
- /package/dist/{web/hooks/use-layout.test.d.ts → cli/build-steps.test.d.ts} +0 -0
- /package/dist/{web/plugin/data-llm.test.d.ts → context-warnings.test.d.ts} +0 -0
- /package/dist/{web/plugin/scan-views.test.d.ts → server/app.test.d.ts} +0 -0
- /package/dist/{web/plugin/validate-view.test.d.ts → server/auth/discovery.test.d.ts} +0 -0
- /package/dist/{web/plugin/transform-data-llm.test.d.ts → server/auth-extra.test-d.d.ts} +0 -0
- /package/dist/{web/plugin → views}/scan-views.d.ts +0 -0
- /package/dist/{web/plugin → views}/scan-views.test.js +0 -0
- /package/dist/{web/plugin → views}/validate-view.test.js +0 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// @vitest-environment node
|
|
2
|
+
import { existsSync, mkdirSync, mkdtempSync, readFileSync, writeFileSync, } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { describe, expect, it } from "vitest";
|
|
6
|
+
import { getCommandSteps } from "./build-steps.js";
|
|
7
|
+
function mkTmp(prefix = "skybridge-build-steps-") {
|
|
8
|
+
return mkdtempSync(path.join(tmpdir(), prefix));
|
|
9
|
+
}
|
|
10
|
+
describe("getCommandSteps", () => {
|
|
11
|
+
it("omits the vite build step when no views are registered", async () => {
|
|
12
|
+
const root = mkTmp();
|
|
13
|
+
mkdirSync(path.join(root, "src"), { recursive: true });
|
|
14
|
+
writeFileSync(path.join(root, "vite.config.ts"), `import { defineConfig } from "vite";
|
|
15
|
+
import { skybridge } from "@skybridge/vite-plugin";
|
|
16
|
+
export default defineConfig({ plugins: [skybridge()] });`);
|
|
17
|
+
writeFileSync(path.join(root, "tsconfig.json"), JSON.stringify({ compilerOptions: { strict: true } }));
|
|
18
|
+
const steps = await getCommandSteps(root);
|
|
19
|
+
const labels = steps.map((step) => step.label);
|
|
20
|
+
expect(labels).not.toContain("Building views");
|
|
21
|
+
expect(labels).toContain("Emitting manifest module");
|
|
22
|
+
expect(labels.at(-1)).toBe("Emitting Vercel build output");
|
|
23
|
+
});
|
|
24
|
+
it("includes the vite build step when views are present", async () => {
|
|
25
|
+
const root = mkTmp();
|
|
26
|
+
mkdirSync(path.join(root, "src", "views"), { recursive: true });
|
|
27
|
+
writeFileSync(path.join(root, "src", "views", "hello.tsx"), "export default function Hello() { return null; }\n");
|
|
28
|
+
writeFileSync(path.join(root, "vite.config.ts"), `import { defineConfig } from "vite";
|
|
29
|
+
import { skybridge } from "@skybridge/vite-plugin";
|
|
30
|
+
export default defineConfig({ plugins: [skybridge()] });`);
|
|
31
|
+
writeFileSync(path.join(root, "tsconfig.json"), JSON.stringify({ compilerOptions: { strict: true } }));
|
|
32
|
+
const steps = await getCommandSteps(root);
|
|
33
|
+
const labels = steps.map((step) => step.label);
|
|
34
|
+
expect(labels).toContain("Building views");
|
|
35
|
+
});
|
|
36
|
+
it("copies public/ to dist/assets/ when no views but public dir exists", async () => {
|
|
37
|
+
const root = mkTmp();
|
|
38
|
+
mkdirSync(path.join(root, "src"), { recursive: true });
|
|
39
|
+
mkdirSync(path.join(root, "public", ".well-known"), { recursive: true });
|
|
40
|
+
writeFileSync(path.join(root, "public", ".well-known", "openai-apps-challenge"), "challenge-token");
|
|
41
|
+
writeFileSync(path.join(root, "public", "logo.png"), "fake-png");
|
|
42
|
+
writeFileSync(path.join(root, "vite.config.ts"), `import { defineConfig } from "vite";
|
|
43
|
+
import { skybridge } from "@skybridge/vite-plugin";
|
|
44
|
+
export default defineConfig({ plugins: [skybridge()] });`);
|
|
45
|
+
writeFileSync(path.join(root, "tsconfig.json"), JSON.stringify({ compilerOptions: { strict: true } }));
|
|
46
|
+
const steps = await getCommandSteps(root);
|
|
47
|
+
const labels = steps.map((step) => step.label);
|
|
48
|
+
expect(labels).not.toContain("Building views");
|
|
49
|
+
expect(labels).toContain("Copying public assets");
|
|
50
|
+
mkdirSync(path.join(root, "dist"), { recursive: true });
|
|
51
|
+
const copyStep = steps.find((s) => s.label === "Copying public assets");
|
|
52
|
+
await copyStep?.run?.();
|
|
53
|
+
expect(readFileSync(path.join(root, "dist", "assets", ".well-known", "openai-apps-challenge"), "utf-8")).toBe("challenge-token");
|
|
54
|
+
expect(readFileSync(path.join(root, "dist", "assets", "logo.png"), "utf-8")).toBe("fake-png");
|
|
55
|
+
});
|
|
56
|
+
it("emits an empty manifest module when there are no views", async () => {
|
|
57
|
+
const root = mkTmp();
|
|
58
|
+
mkdirSync(path.join(root, "src"), { recursive: true });
|
|
59
|
+
writeFileSync(path.join(root, "vite.config.ts"), `import { defineConfig } from "vite";
|
|
60
|
+
import { skybridge } from "@skybridge/vite-plugin";
|
|
61
|
+
export default defineConfig({ plugins: [skybridge()] });`);
|
|
62
|
+
const steps = await getCommandSteps(root);
|
|
63
|
+
const emitManifest = steps.find((step) => step.label === "Emitting manifest module");
|
|
64
|
+
expect(emitManifest?.run).toBeDefined();
|
|
65
|
+
mkdirSync(path.join(root, "dist"), { recursive: true });
|
|
66
|
+
await emitManifest?.run?.();
|
|
67
|
+
const manifestOut = path.join(root, "dist", "vite-manifest.js");
|
|
68
|
+
expect(existsSync(manifestOut)).toBe(true);
|
|
69
|
+
expect(readFileSync(manifestOut, "utf-8")).toBe("export default {};\n");
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
//# sourceMappingURL=build-steps.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-steps.test.js","sourceRoot":"","sources":["../../src/cli/build-steps.test.ts"],"names":[],"mappings":"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","sourcesContent":["// @vitest-environment node\nimport {\n existsSync,\n mkdirSync,\n mkdtempSync,\n readFileSync,\n writeFileSync,\n} from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport path from \"node:path\";\nimport { describe, expect, it } from \"vitest\";\nimport { getCommandSteps } from \"./build-steps.js\";\n\nfunction mkTmp(prefix = \"skybridge-build-steps-\") {\n return mkdtempSync(path.join(tmpdir(), prefix));\n}\n\ndescribe(\"getCommandSteps\", () => {\n it(\"omits the vite build step when no views are registered\", async () => {\n const root = mkTmp();\n mkdirSync(path.join(root, \"src\"), { recursive: true });\n writeFileSync(\n path.join(root, \"vite.config.ts\"),\n `import { defineConfig } from \"vite\";\nimport { skybridge } from \"@skybridge/vite-plugin\";\nexport default defineConfig({ plugins: [skybridge()] });`,\n );\n writeFileSync(\n path.join(root, \"tsconfig.json\"),\n JSON.stringify({ compilerOptions: { strict: true } }),\n );\n\n const steps = await getCommandSteps(root);\n const labels = steps.map((step) => step.label);\n\n expect(labels).not.toContain(\"Building views\");\n expect(labels).toContain(\"Emitting manifest module\");\n expect(labels.at(-1)).toBe(\"Emitting Vercel build output\");\n });\n\n it(\"includes the vite build step when views are present\", async () => {\n const root = mkTmp();\n mkdirSync(path.join(root, \"src\", \"views\"), { recursive: true });\n writeFileSync(\n path.join(root, \"src\", \"views\", \"hello.tsx\"),\n \"export default function Hello() { return null; }\\n\",\n );\n writeFileSync(\n path.join(root, \"vite.config.ts\"),\n `import { defineConfig } from \"vite\";\nimport { skybridge } from \"@skybridge/vite-plugin\";\nexport default defineConfig({ plugins: [skybridge()] });`,\n );\n writeFileSync(\n path.join(root, \"tsconfig.json\"),\n JSON.stringify({ compilerOptions: { strict: true } }),\n );\n\n const steps = await getCommandSteps(root);\n const labels = steps.map((step) => step.label);\n\n expect(labels).toContain(\"Building views\");\n });\n\n it(\"copies public/ to dist/assets/ when no views but public dir exists\", async () => {\n const root = mkTmp();\n mkdirSync(path.join(root, \"src\"), { recursive: true });\n mkdirSync(path.join(root, \"public\", \".well-known\"), { recursive: true });\n writeFileSync(\n path.join(root, \"public\", \".well-known\", \"openai-apps-challenge\"),\n \"challenge-token\",\n );\n writeFileSync(path.join(root, \"public\", \"logo.png\"), \"fake-png\");\n writeFileSync(\n path.join(root, \"vite.config.ts\"),\n `import { defineConfig } from \"vite\";\nimport { skybridge } from \"@skybridge/vite-plugin\";\nexport default defineConfig({ plugins: [skybridge()] });`,\n );\n writeFileSync(\n path.join(root, \"tsconfig.json\"),\n JSON.stringify({ compilerOptions: { strict: true } }),\n );\n\n const steps = await getCommandSteps(root);\n const labels = steps.map((step) => step.label);\n\n expect(labels).not.toContain(\"Building views\");\n expect(labels).toContain(\"Copying public assets\");\n\n mkdirSync(path.join(root, \"dist\"), { recursive: true });\n const copyStep = steps.find((s) => s.label === \"Copying public assets\");\n await copyStep?.run?.();\n\n expect(\n readFileSync(\n path.join(\n root,\n \"dist\",\n \"assets\",\n \".well-known\",\n \"openai-apps-challenge\",\n ),\n \"utf-8\",\n ),\n ).toBe(\"challenge-token\");\n expect(\n readFileSync(path.join(root, \"dist\", \"assets\", \"logo.png\"), \"utf-8\"),\n ).toBe(\"fake-png\");\n });\n\n it(\"emits an empty manifest module when there are no views\", async () => {\n const root = mkTmp();\n mkdirSync(path.join(root, \"src\"), { recursive: true });\n writeFileSync(\n path.join(root, \"vite.config.ts\"),\n `import { defineConfig } from \"vite\";\nimport { skybridge } from \"@skybridge/vite-plugin\";\nexport default defineConfig({ plugins: [skybridge()] });`,\n );\n\n const steps = await getCommandSteps(root);\n const emitManifest = steps.find(\n (step) => step.label === \"Emitting manifest module\",\n );\n expect(emitManifest?.run).toBeDefined();\n\n mkdirSync(path.join(root, \"dist\"), { recursive: true });\n await emitManifest?.run?.();\n\n const manifestOut = path.join(root, \"dist\", \"vite-manifest.js\");\n expect(existsSync(manifestOut)).toBe(true);\n expect(readFileSync(manifestOut, \"utf-8\")).toBe(\"export default {};\\n\");\n });\n});\n"]}
|
|
@@ -8,8 +8,8 @@ export declare function resolvePort(flagPort?: number): Promise<{
|
|
|
8
8
|
envWarning: string;
|
|
9
9
|
}>;
|
|
10
10
|
/**
|
|
11
|
-
* Returns the
|
|
12
|
-
*
|
|
11
|
+
* Returns the first available port at or after `startPort`, incrementing
|
|
12
|
+
* by one until a free port is found or `MAX_PORT_INCREMENT` is reached.
|
|
13
13
|
*
|
|
14
14
|
* @param host - Bind address for the check. Pass `"localhost"` for
|
|
15
15
|
* services that bind to 127.0.0.1 (e.g. Vite HMR). Omit for
|
package/dist/cli/detect-port.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import net from "node:net";
|
|
2
2
|
const DEFAULT_PORT = 3000;
|
|
3
|
+
const MAX_PORT_INCREMENT = 100;
|
|
3
4
|
export async function resolvePort(flagPort) {
|
|
4
5
|
if (flagPort && flagPort > 1) {
|
|
5
6
|
return { port: flagPort, fallback: false };
|
|
@@ -20,33 +21,20 @@ export async function resolvePort(flagPort) {
|
|
|
20
21
|
return { port, fallback: port !== DEFAULT_PORT };
|
|
21
22
|
}
|
|
22
23
|
/**
|
|
23
|
-
* Returns the
|
|
24
|
-
*
|
|
24
|
+
* Returns the first available port at or after `startPort`, incrementing
|
|
25
|
+
* by one until a free port is found or `MAX_PORT_INCREMENT` is reached.
|
|
25
26
|
*
|
|
26
27
|
* @param host - Bind address for the check. Pass `"localhost"` for
|
|
27
28
|
* services that bind to 127.0.0.1 (e.g. Vite HMR). Omit for
|
|
28
29
|
* services that bind to all interfaces (e.g. the HTTP server).
|
|
29
30
|
*/
|
|
30
31
|
export async function detectAvailablePort(startPort, host) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
for (let port = startPort; port < startPort + MAX_PORT_INCREMENT; port++) {
|
|
33
|
+
if (await isPortAvailable(port, host)) {
|
|
34
|
+
return port;
|
|
35
|
+
}
|
|
34
36
|
}
|
|
35
|
-
|
|
36
|
-
const server = net.createServer();
|
|
37
|
-
server.once("error", reject);
|
|
38
|
-
server.once("listening", () => {
|
|
39
|
-
const addr = server.address();
|
|
40
|
-
if (addr && typeof addr === "object") {
|
|
41
|
-
const { port } = addr;
|
|
42
|
-
server.close(() => resolve(port));
|
|
43
|
-
}
|
|
44
|
-
else {
|
|
45
|
-
server.close(() => reject(new Error("Failed to detect available port")));
|
|
46
|
-
}
|
|
47
|
-
});
|
|
48
|
-
server.listen(0, host);
|
|
49
|
-
});
|
|
37
|
+
throw new Error(`No available port found between ${startPort} and ${startPort + MAX_PORT_INCREMENT - 1}`);
|
|
50
38
|
}
|
|
51
39
|
function isPortAvailable(port, host) {
|
|
52
40
|
return new Promise((resolve) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"detect-port.js","sourceRoot":"","sources":["../../src/cli/detect-port.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,UAAU,CAAC;AAE3B,MAAM,YAAY,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"detect-port.js","sourceRoot":"","sources":["../../src/cli/detect-port.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,UAAU,CAAC;AAE3B,MAAM,YAAY,GAAG,IAAI,CAAC;AAC1B,MAAM,kBAAkB,GAAG,GAAG,CAAC;AAE/B,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,QAAiB;IACjD,IAAI,QAAQ,IAAI,QAAQ,GAAG,CAAC,EAAE,CAAC;QAC7B,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IAC7C,CAAC;IAED,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;IAChC,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;QAC9B,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;YAC3C,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;QAC3C,CAAC;QACD,OAAO;YACL,IAAI,EAAE,MAAM,mBAAmB,CAAC,YAAY,CAAC;YAC7C,QAAQ,EAAE,KAAK;YACf,UAAU,EAAE,iBAAiB,MAAM,+BAA+B;SACnE,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,mBAAmB,CAAC,YAAY,CAAC,CAAC;IACrD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,KAAK,YAAY,EAAE,CAAC;AACnD,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,SAAiB,EACjB,IAAa;IAEb,KAAK,IAAI,IAAI,GAAG,SAAS,EAAE,IAAI,GAAG,SAAS,GAAG,kBAAkB,EAAE,IAAI,EAAE,EAAE,CAAC;QACzE,IAAI,MAAM,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;YACtC,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IACD,MAAM,IAAI,KAAK,CACb,mCAAmC,SAAS,QAAQ,SAAS,GAAG,kBAAkB,GAAG,CAAC,EAAE,CACzF,CAAC;AACJ,CAAC;AAED,SAAS,eAAe,CAAC,IAAY,EAAE,IAAa;IAClD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,MAAM,GAAG,GAAG,CAAC,YAAY,EAAE,CAAC;QAElC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;QAC3C,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,EAAE;YAC5B,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QACpC,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["import net from \"node:net\";\n\nconst DEFAULT_PORT = 3000;\nconst MAX_PORT_INCREMENT = 100;\n\nexport async function resolvePort(flagPort?: number) {\n if (flagPort && flagPort > 1) {\n return { port: flagPort, fallback: false };\n }\n\n const rawEnv = process.env.PORT;\n if (rawEnv) {\n const parsed = Number(rawEnv);\n if (Number.isInteger(parsed) && parsed > 0) {\n return { port: parsed, fallback: false };\n }\n return {\n port: await detectAvailablePort(DEFAULT_PORT),\n fallback: false,\n envWarning: `Invalid PORT=\"${rawEnv}\", ignoring and using default`,\n };\n }\n\n const port = await detectAvailablePort(DEFAULT_PORT);\n return { port, fallback: port !== DEFAULT_PORT };\n}\n\n/**\n * Returns the first available port at or after `startPort`, incrementing\n * by one until a free port is found or `MAX_PORT_INCREMENT` is reached.\n *\n * @param host - Bind address for the check. Pass `\"localhost\"` for\n * services that bind to 127.0.0.1 (e.g. Vite HMR). Omit for\n * services that bind to all interfaces (e.g. the HTTP server).\n */\nexport async function detectAvailablePort(\n startPort: number,\n host?: string,\n): Promise<number> {\n for (let port = startPort; port < startPort + MAX_PORT_INCREMENT; port++) {\n if (await isPortAvailable(port, host)) {\n return port;\n }\n }\n throw new Error(\n `No available port found between ${startPort} and ${startPort + MAX_PORT_INCREMENT - 1}`,\n );\n}\n\nfunction isPortAvailable(port: number, host?: string): Promise<boolean> {\n return new Promise((resolve) => {\n const server = net.createServer();\n\n server.once(\"error\", () => resolve(false));\n server.once(\"listening\", () => {\n server.close(() => resolve(true));\n });\n\n server.listen(port, host);\n });\n}\n"]}
|
package/dist/cli/header.d.ts
CHANGED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export async function resolveSkybridgeConfig(root) {
|
|
2
|
+
const { loadConfigFromFile } = await import("vite");
|
|
3
|
+
const loaded = await loadConfigFromFile({ command: "build", mode: "production" }, undefined, root);
|
|
4
|
+
const isPluginCandidate = (value) => typeof value === "object" && value !== null;
|
|
5
|
+
const plugins = [];
|
|
6
|
+
const walk = (value) => {
|
|
7
|
+
if (Array.isArray(value)) {
|
|
8
|
+
value.forEach(walk);
|
|
9
|
+
}
|
|
10
|
+
else if (isPluginCandidate(value)) {
|
|
11
|
+
plugins.push(value);
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
walk(loaded?.config.plugins ?? []);
|
|
15
|
+
const api = plugins.find((p) => p.name === "skybridge")?.api;
|
|
16
|
+
const rawPublicDir = loaded?.config.publicDir;
|
|
17
|
+
const publicDir = rawPublicDir === false
|
|
18
|
+
? false
|
|
19
|
+
: typeof rawPublicDir === "string"
|
|
20
|
+
? rawPublicDir
|
|
21
|
+
: undefined;
|
|
22
|
+
return {
|
|
23
|
+
viewsDir: api?.viewsDir,
|
|
24
|
+
serverExternal: api?.serverExternal,
|
|
25
|
+
publicDir,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=resolve-skybridge-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-skybridge-config.js","sourceRoot":"","sources":["../../src/cli/resolve-skybridge-config.ts"],"names":[],"mappings":"AAMA,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,IAAY;IAEZ,MAAM,EAAE,kBAAkB,EAAE,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,CAAC;IACpD,MAAM,MAAM,GAAG,MAAM,kBAAkB,CACrC,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,EACxC,SAAS,EACT,IAAI,CACL,CAAC;IAEF,MAAM,iBAAiB,GAAG,CACxB,KAAc,EACqC,EAAE,CACrD,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC;IAE9C,MAAM,OAAO,GAAoD,EAAE,CAAC;IACpE,MAAM,IAAI,GAAG,CAAC,KAAc,EAAE,EAAE;QAC9B,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACzB,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACtB,CAAC;aAAM,IAAI,iBAAiB,CAAC,KAAK,CAAC,EAAE,CAAC;YACpC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;IACH,CAAC,CAAC;IACF,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;IACnC,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,CAAC,EAAE,GAAG,CAAC;IAC7D,MAAM,YAAY,GAAG,MAAM,EAAE,MAAM,CAAC,SAAS,CAAC;IAC9C,MAAM,SAAS,GACb,YAAY,KAAK,KAAK;QACpB,CAAC,CAAC,KAAK;QACP,CAAC,CAAC,OAAO,YAAY,KAAK,QAAQ;YAChC,CAAC,CAAC,YAAY;YACd,CAAC,CAAC,SAAS,CAAC;IAClB,OAAO;QACL,QAAQ,EAAE,GAAG,EAAE,QAAQ;QACvB,cAAc,EAAE,GAAG,EAAE,cAAc;QACnC,SAAS;KACV,CAAC;AACJ,CAAC","sourcesContent":["export interface SkybridgeConfig {\n viewsDir?: string;\n serverExternal?: string[];\n publicDir?: string | false;\n}\n\nexport async function resolveSkybridgeConfig(\n root: string,\n): Promise<SkybridgeConfig> {\n const { loadConfigFromFile } = await import(\"vite\");\n const loaded = await loadConfigFromFile(\n { command: \"build\", mode: \"production\" },\n undefined,\n root,\n );\n\n const isPluginCandidate = (\n value: unknown,\n ): value is { name?: string; api?: SkybridgeConfig } =>\n typeof value === \"object\" && value !== null;\n\n const plugins: Array<{ name?: string; api?: SkybridgeConfig }> = [];\n const walk = (value: unknown) => {\n if (Array.isArray(value)) {\n value.forEach(walk);\n } else if (isPluginCandidate(value)) {\n plugins.push(value);\n }\n };\n walk(loaded?.config.plugins ?? []);\n const api = plugins.find((p) => p.name === \"skybridge\")?.api;\n const rawPublicDir = loaded?.config.publicDir;\n const publicDir =\n rawPublicDir === false\n ? false\n : typeof rawPublicDir === \"string\"\n ? rawPublicDir\n : undefined;\n return {\n viewsDir: api?.viewsDir,\n serverExternal: api?.serverExternal,\n publicDir,\n };\n}\n"]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { TunnelManager } from "./tunnel.js";
|
|
2
|
+
export interface RunPlainOptions {
|
|
3
|
+
env: NodeJS.ProcessEnv;
|
|
4
|
+
port: number;
|
|
5
|
+
fallback: boolean;
|
|
6
|
+
version: string;
|
|
7
|
+
tunnel: boolean;
|
|
8
|
+
tunnelManager: TunnelManager;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Run `skybridge dev` without the Ink UI. The server's stdout is forwarded
|
|
12
|
+
* verbatim to the real stdout so it can be piped through a formatter
|
|
13
|
+
* (`skybridge dev --plain | bunyan`); everything else (banner, URLs, tunnel
|
|
14
|
+
* state, TypeScript errors, restarts) is written to stderr.
|
|
15
|
+
*
|
|
16
|
+
* Returns a cleanup function that tears down nodemon and the tsc watcher.
|
|
17
|
+
*/
|
|
18
|
+
export declare function runPlain(options: RunPlainOptions): () => void;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { CRASH_MESSAGE, startNodemon } from "./use-nodemon.js";
|
|
2
|
+
import { startTypeScriptCheck } from "./use-typescript-check.js";
|
|
3
|
+
// Banner/URLs/diagnostics go to stderr so a downstream pipe (e.g.
|
|
4
|
+
// `skybridge dev --plain | bunyan`) only ever sees the server's own stdout.
|
|
5
|
+
function info(message) {
|
|
6
|
+
process.stderr.write(`${message}\n`);
|
|
7
|
+
}
|
|
8
|
+
function describeTunnel(state, port) {
|
|
9
|
+
switch (state.status) {
|
|
10
|
+
case "starting":
|
|
11
|
+
return `🌍 ${state.message}`;
|
|
12
|
+
case "connected":
|
|
13
|
+
return `🌍 Exposed on ${state.url}/mcp\n→ Test with an LLM on Playground: ${state.url}/try`;
|
|
14
|
+
case "error":
|
|
15
|
+
return `🌍 Cannot open tunnel: ${state.message}\n→ Try manually: npx alpic tunnel --port ${port}`;
|
|
16
|
+
default:
|
|
17
|
+
return "";
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Run `skybridge dev` without the Ink UI. The server's stdout is forwarded
|
|
22
|
+
* verbatim to the real stdout so it can be piped through a formatter
|
|
23
|
+
* (`skybridge dev --plain | bunyan`); everything else (banner, URLs, tunnel
|
|
24
|
+
* state, TypeScript errors, restarts) is written to stderr.
|
|
25
|
+
*
|
|
26
|
+
* Returns a cleanup function that tears down nodemon and the tsc watcher.
|
|
27
|
+
*/
|
|
28
|
+
export function runPlain(options) {
|
|
29
|
+
const { env, port, fallback, version, tunnel, tunnelManager } = options;
|
|
30
|
+
// If the downstream formatter (e.g. `| bunyan`) exits, the next write raises
|
|
31
|
+
// EPIPE. Swallow it so a closed pipe doesn't crash the dev server.
|
|
32
|
+
const ignoreEpipe = (err) => {
|
|
33
|
+
if (err.code !== "EPIPE") {
|
|
34
|
+
throw err;
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
process.stdout.on("error", ignoreEpipe);
|
|
38
|
+
process.stderr.on("error", ignoreEpipe);
|
|
39
|
+
info(`⛰ Skybridge v${version}`);
|
|
40
|
+
info(fallback
|
|
41
|
+
? `🏠 3000 in use, running on http://localhost:${port}/mcp`
|
|
42
|
+
: `🏠 Running on http://localhost:${port}/mcp`);
|
|
43
|
+
info(`→ Test locally with DevTools: http://localhost:${port}/`);
|
|
44
|
+
if (!tunnel) {
|
|
45
|
+
info("🌍 Get a public URL and LLM Playground access with --tunnel.");
|
|
46
|
+
}
|
|
47
|
+
const stopNodemon = startNodemon(env, {
|
|
48
|
+
onStdout: (chunk) => process.stdout.write(chunk),
|
|
49
|
+
onStderr: (message) => info(message),
|
|
50
|
+
onRestart: (files) => info(`✓ Server restarted due to file changes: ${files.join(", ")}`),
|
|
51
|
+
onCrash: () => info(CRASH_MESSAGE),
|
|
52
|
+
});
|
|
53
|
+
let lastTsErrorKey = "";
|
|
54
|
+
const stopTypeScriptCheck = startTypeScriptCheck((errors) => {
|
|
55
|
+
// tsc re-emits on every save; only print when the error set actually changes.
|
|
56
|
+
const key = errors
|
|
57
|
+
.map((e) => `${e.file}:${e.line}:${e.col}:${e.message}`)
|
|
58
|
+
.join("|");
|
|
59
|
+
if (key === lastTsErrorKey) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
lastTsErrorKey = key;
|
|
63
|
+
if (errors.length === 0) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
info("⚠️ TypeScript errors found:");
|
|
67
|
+
for (const error of errors) {
|
|
68
|
+
info(` ${error.file}(${error.line},${error.col}): ${error.message}`);
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
const unsubscribeTunnel = tunnel
|
|
72
|
+
? tunnelManager.subscribe((state) => {
|
|
73
|
+
const message = describeTunnel(state, port);
|
|
74
|
+
if (message) {
|
|
75
|
+
info(message);
|
|
76
|
+
}
|
|
77
|
+
})
|
|
78
|
+
: () => { };
|
|
79
|
+
if (tunnel) {
|
|
80
|
+
tunnelManager.start();
|
|
81
|
+
}
|
|
82
|
+
return () => {
|
|
83
|
+
unsubscribeTunnel();
|
|
84
|
+
stopNodemon();
|
|
85
|
+
stopTypeScriptCheck();
|
|
86
|
+
process.stdout.off("error", ignoreEpipe);
|
|
87
|
+
process.stderr.off("error", ignoreEpipe);
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=run-plain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-plain.js","sourceRoot":"","sources":["../../src/cli/run-plain.ts"],"names":[],"mappings":"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","sourcesContent":["import type { TunnelManager, TunnelState } from \"./tunnel.js\";\nimport { CRASH_MESSAGE, startNodemon } from \"./use-nodemon.js\";\nimport { startTypeScriptCheck, type TsError } from \"./use-typescript-check.js\";\n\nexport interface RunPlainOptions {\n env: NodeJS.ProcessEnv;\n port: number;\n fallback: boolean;\n version: string;\n tunnel: boolean;\n tunnelManager: TunnelManager;\n}\n\n// Banner/URLs/diagnostics go to stderr so a downstream pipe (e.g.\n// `skybridge dev --plain | bunyan`) only ever sees the server's own stdout.\nfunction info(message: string): void {\n process.stderr.write(`${message}\\n`);\n}\n\nfunction describeTunnel(state: TunnelState, port: number): string {\n switch (state.status) {\n case \"starting\":\n return `🌍 ${state.message}`;\n case \"connected\":\n return `🌍 Exposed on ${state.url}/mcp\\n→ Test with an LLM on Playground: ${state.url}/try`;\n case \"error\":\n return `🌍 Cannot open tunnel: ${state.message}\\n→ Try manually: npx alpic tunnel --port ${port}`;\n default:\n return \"\";\n }\n}\n\n/**\n * Run `skybridge dev` without the Ink UI. The server's stdout is forwarded\n * verbatim to the real stdout so it can be piped through a formatter\n * (`skybridge dev --plain | bunyan`); everything else (banner, URLs, tunnel\n * state, TypeScript errors, restarts) is written to stderr.\n *\n * Returns a cleanup function that tears down nodemon and the tsc watcher.\n */\nexport function runPlain(options: RunPlainOptions): () => void {\n const { env, port, fallback, version, tunnel, tunnelManager } = options;\n\n // If the downstream formatter (e.g. `| bunyan`) exits, the next write raises\n // EPIPE. Swallow it so a closed pipe doesn't crash the dev server.\n const ignoreEpipe = (err: NodeJS.ErrnoException) => {\n if (err.code !== \"EPIPE\") {\n throw err;\n }\n };\n process.stdout.on(\"error\", ignoreEpipe);\n process.stderr.on(\"error\", ignoreEpipe);\n\n info(`⛰ Skybridge v${version}`);\n info(\n fallback\n ? `🏠 3000 in use, running on http://localhost:${port}/mcp`\n : `🏠 Running on http://localhost:${port}/mcp`,\n );\n info(`→ Test locally with DevTools: http://localhost:${port}/`);\n if (!tunnel) {\n info(\"🌍 Get a public URL and LLM Playground access with --tunnel.\");\n }\n\n const stopNodemon = startNodemon(env, {\n onStdout: (chunk) => process.stdout.write(chunk),\n onStderr: (message) => info(message),\n onRestart: (files) =>\n info(`✓ Server restarted due to file changes: ${files.join(\", \")}`),\n onCrash: () => info(CRASH_MESSAGE),\n });\n\n let lastTsErrorKey = \"\";\n const stopTypeScriptCheck = startTypeScriptCheck((errors: Array<TsError>) => {\n // tsc re-emits on every save; only print when the error set actually changes.\n const key = errors\n .map((e) => `${e.file}:${e.line}:${e.col}:${e.message}`)\n .join(\"|\");\n if (key === lastTsErrorKey) {\n return;\n }\n lastTsErrorKey = key;\n if (errors.length === 0) {\n return;\n }\n info(\"⚠️ TypeScript errors found:\");\n for (const error of errors) {\n info(` ${error.file}(${error.line},${error.col}): ${error.message}`);\n }\n });\n\n const unsubscribeTunnel = tunnel\n ? tunnelManager.subscribe((state) => {\n const message = describeTunnel(state, port);\n if (message) {\n info(message);\n }\n })\n : () => {};\n\n if (tunnel) {\n tunnelManager.start();\n }\n\n return () => {\n unsubscribeTunnel();\n stopNodemon();\n stopTypeScriptCheck();\n process.stdout.off(\"error\", ignoreEpipe);\n process.stderr.off(\"error\", ignoreEpipe);\n };\n}\n"]}
|
package/dist/cli/telemetry.js
CHANGED
|
@@ -3,6 +3,7 @@ import { homedir } from "node:os";
|
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import ci from "ci-info";
|
|
5
5
|
import { PostHog } from "posthog-node";
|
|
6
|
+
import { agent } from "std-env";
|
|
6
7
|
const POSTHOG_API_KEY = "phc_rQdkCYr0DO4NcZBQXZnUwsHAbau9zuNwKIpil9FQP6v";
|
|
7
8
|
const POSTHOG_HOST = "https://us.i.posthog.com";
|
|
8
9
|
const ENV_TELEMETRY_DISABLED = "SKYBRIDGE_TELEMETRY_DISABLED";
|
|
@@ -98,6 +99,7 @@ const hook = async ({ id: command, config: { version }, error, }) => {
|
|
|
98
99
|
machineId: getMachineId(),
|
|
99
100
|
sessionId: crypto.randomUUID(),
|
|
100
101
|
isCI: ci.isCI,
|
|
102
|
+
agent,
|
|
101
103
|
nodeVersion: process.version,
|
|
102
104
|
platform: process.platform,
|
|
103
105
|
outcome: error ? "failure" : "success",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"telemetry.js","sourceRoot":"","sources":["../../src/cli/telemetry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"telemetry.js","sourceRoot":"","sources":["../../src/cli/telemetry.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { Hook } from \"@oclif/core\";\nimport ci from \"ci-info\";\nimport { PostHog } from \"posthog-node\";\nimport { agent } from \"std-env\";\n\nconst POSTHOG_API_KEY = \"phc_rQdkCYr0DO4NcZBQXZnUwsHAbau9zuNwKIpil9FQP6v\";\nconst POSTHOG_HOST = \"https://us.i.posthog.com\";\n\nconst ENV_TELEMETRY_DISABLED = \"SKYBRIDGE_TELEMETRY_DISABLED\";\nconst ENV_TELEMETRY_DEBUG = \"SKYBRIDGE_TELEMETRY_DEBUG\";\nconst ENV_DO_NOT_TRACK = \"DO_NOT_TRACK\";\n\nconst GLOBAL_CONFIG_DIR = join(homedir(), \".skybridge\");\nconst GLOBAL_CONFIG_FILE = join(GLOBAL_CONFIG_DIR, \"config.json\");\n\ninterface GlobalConfig {\n machineId: string;\n telemetry: {\n enabled: boolean;\n };\n}\n\ninterface TelemetryEvent {\n version: string;\n machineId: string;\n sessionId: string;\n isCI: boolean;\n agent?: string;\n nodeVersion: string;\n platform: NodeJS.Platform;\n outcome: \"success\" | \"failure\";\n error?: string;\n}\n\nlet posthogClient: PostHog | null = null;\n\nfunction getPostHogClient(): PostHog {\n if (!posthogClient) {\n posthogClient = new PostHog(POSTHOG_API_KEY, {\n host: POSTHOG_HOST,\n flushAt: 1,\n flushInterval: 0,\n });\n }\n\n return posthogClient;\n}\n\nfunction readJsonFile<T>(filePath: string): T | null {\n try {\n if (existsSync(filePath)) {\n const content = readFileSync(filePath, \"utf-8\");\n return JSON.parse(content) as T;\n }\n } catch {\n // Ignore errors reading config\n }\n return null;\n}\n\nfunction writeJsonFile(filePath: string, data: unknown): void {\n try {\n const dir = join(filePath, \"..\");\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n writeFileSync(filePath, JSON.stringify(data, null, 2), \"utf-8\");\n } catch {\n // Ignore errors writing config\n }\n}\n\nfunction getGlobalConfig(): GlobalConfig {\n const existing = readJsonFile<GlobalConfig>(GLOBAL_CONFIG_FILE);\n if (existing?.machineId && existing?.telemetry !== undefined) {\n return existing;\n }\n\n const config: GlobalConfig = {\n machineId: existing?.machineId || crypto.randomUUID(),\n telemetry: {\n enabled: existing?.telemetry?.enabled ?? true,\n },\n };\n\n writeJsonFile(GLOBAL_CONFIG_FILE, config);\n return config;\n}\n\nexport function isEnabled(): boolean {\n if (\n process.env[ENV_TELEMETRY_DISABLED] === \"1\" ||\n process.env[ENV_TELEMETRY_DISABLED]?.toLowerCase() === \"true\"\n ) {\n return false;\n }\n\n if (\n process.env[ENV_DO_NOT_TRACK] === \"1\" ||\n process.env[ENV_DO_NOT_TRACK]?.toLowerCase() === \"true\"\n ) {\n return false;\n }\n\n if (ci.isCI) {\n return true;\n }\n\n const config = getGlobalConfig();\n return config.telemetry.enabled;\n}\n\nexport function isDebugMode(): boolean {\n return (\n process.env[ENV_TELEMETRY_DEBUG] === \"1\" ||\n process.env[ENV_TELEMETRY_DEBUG]?.toLowerCase() === \"true\"\n );\n}\n\nexport function setEnabled(enabled: boolean): void {\n const config = getGlobalConfig();\n config.telemetry.enabled = enabled;\n writeJsonFile(GLOBAL_CONFIG_FILE, config);\n}\n\nexport function getMachineId(): string {\n if (ci.isCI) {\n return ci.name ?? \"unknown-ci\";\n }\n\n return getGlobalConfig().machineId;\n}\n\nconst hook: Hook<\"finally\"> = async ({\n id: command,\n config: { version },\n error,\n}) => {\n if (!isEnabled()) {\n return;\n }\n\n const event: TelemetryEvent = {\n version,\n machineId: getMachineId(),\n sessionId: crypto.randomUUID(),\n isCI: ci.isCI,\n agent,\n nodeVersion: process.version,\n platform: process.platform,\n outcome: error ? \"failure\" : \"success\",\n error: error?.message,\n };\n\n if (isDebugMode()) {\n console.error(\n \"[Telemetry Debug] Would send event:\",\n JSON.stringify(event, null, 2),\n );\n return;\n }\n\n try {\n const client = getPostHogClient();\n client.capture({\n distinctId: event.machineId,\n event: command,\n properties: event,\n });\n } catch {\n // Silently ignore telemetry errors - never block CLI operation\n }\n};\n\nexport default hook;\n"]}
|
|
@@ -5,7 +5,7 @@ export interface CommandStep {
|
|
|
5
5
|
}
|
|
6
6
|
export declare const useExecuteSteps: (steps: CommandStep[]) => {
|
|
7
7
|
currentStep: number;
|
|
8
|
-
status: "error" | "
|
|
8
|
+
status: "error" | "running" | "success";
|
|
9
9
|
error: string | null;
|
|
10
10
|
execute: () => Promise<void>;
|
|
11
11
|
};
|
|
@@ -1,2 +1,26 @@
|
|
|
1
1
|
import type { PushMessage } from "./use-messages.js";
|
|
2
|
-
export declare
|
|
2
|
+
export declare const CRASH_MESSAGE = "\uD83D\uDCA5 Server crashed. Fix the error, then save a watched file to restart it.";
|
|
3
|
+
export interface NodemonHandlers {
|
|
4
|
+
/** A raw chunk of server stdout, forwarded untouched. */
|
|
5
|
+
onStdout: (chunk: Buffer) => void;
|
|
6
|
+
/** A (filtered) chunk of server stderr. */
|
|
7
|
+
onStderr: (message: string) => void;
|
|
8
|
+
/** The server restarted because the listed files changed. */
|
|
9
|
+
onRestart: (files: string[]) => void;
|
|
10
|
+
/**
|
|
11
|
+
* The server exited with a non-zero code. nodemon does not restart it on its
|
|
12
|
+
* own: it waits for the next file change.
|
|
13
|
+
*/
|
|
14
|
+
onCrash: () => void;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Boot nodemon and wire its stdout/stderr to the provided handlers. Returns a
|
|
18
|
+
* cleanup function that detaches the listeners and quits nodemon. Shared by the
|
|
19
|
+
* Ink-based dev UI (via {@link useNodemon}) and the `--plain` runner.
|
|
20
|
+
*/
|
|
21
|
+
export declare function startNodemon(env: NodeJS.ProcessEnv, handlers: NodemonHandlers): () => void;
|
|
22
|
+
/**
|
|
23
|
+
* Boot nodemon for the Ink dev UI. Returns whether the server is currently
|
|
24
|
+
* down after a crash, so the UI can stop advertising a URL nothing listens on.
|
|
25
|
+
*/
|
|
26
|
+
export declare function useNodemon(env: NodeJS.ProcessEnv, pushMessage: PushMessage): boolean;
|
package/dist/cli/use-nodemon.js
CHANGED
|
@@ -1,73 +1,106 @@
|
|
|
1
1
|
import { existsSync } from "node:fs";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
2
3
|
import { resolve } from "node:path";
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
import { useEffect, useState } from "react";
|
|
5
|
+
function loadNodemon() {
|
|
6
|
+
try {
|
|
7
|
+
return createRequire(import.meta.url)("nodemon");
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
throw new Error('skybridge dev needs the "nodemon" peer dependency. Install it with `npm install -D nodemon`.');
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export const CRASH_MESSAGE = "💥 Server crashed. Fix the error, then save a watched file to restart it.";
|
|
6
14
|
const SOURCEMAP_WARNING = /^Sourcemap for ".*" points to missing source files$/;
|
|
15
|
+
/**
|
|
16
|
+
* Boot nodemon and wire its stdout/stderr to the provided handlers. Returns a
|
|
17
|
+
* cleanup function that detaches the listeners and quits nodemon. Shared by the
|
|
18
|
+
* Ink-based dev UI (via {@link useNodemon}) and the `--plain` runner.
|
|
19
|
+
*/
|
|
20
|
+
export function startNodemon(env, handlers) {
|
|
21
|
+
const nodemon = loadNodemon();
|
|
22
|
+
const configFile = resolve(process.cwd(), "nodemon.json");
|
|
23
|
+
const config = existsSync(configFile)
|
|
24
|
+
? {
|
|
25
|
+
configFile,
|
|
26
|
+
}
|
|
27
|
+
: {
|
|
28
|
+
watch: ["src"],
|
|
29
|
+
ext: "ts,json,md",
|
|
30
|
+
exec: "tsx src/index.ts",
|
|
31
|
+
};
|
|
32
|
+
nodemon({ ...config, env, stdout: false });
|
|
33
|
+
const handleStdoutData = (chunk) => {
|
|
34
|
+
handlers.onStdout(chunk);
|
|
35
|
+
};
|
|
36
|
+
const handleStderrData = (chunk) => {
|
|
37
|
+
const message = chunk.toString().trim();
|
|
38
|
+
if (!message) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
// Node's source-map warnings for third-party deps (superjson, @mcp/sdk, …) — not actionable.
|
|
42
|
+
const filtered = message
|
|
43
|
+
.split("\n")
|
|
44
|
+
.filter((line) => !SOURCEMAP_WARNING.test(line))
|
|
45
|
+
.join("\n");
|
|
46
|
+
if (filtered) {
|
|
47
|
+
handlers.onStderr(filtered);
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
const setupStdoutListener = () => {
|
|
51
|
+
if (nodemon.stdout) {
|
|
52
|
+
nodemon.stdout.off("data", handleStdoutData);
|
|
53
|
+
nodemon.stdout.on("data", handleStdoutData);
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
const setupStderrListener = () => {
|
|
57
|
+
if (nodemon.stderr) {
|
|
58
|
+
nodemon.stderr.off("data", handleStderrData);
|
|
59
|
+
nodemon.stderr.on("data", handleStderrData);
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
const reattachListeners = () => {
|
|
63
|
+
setupStdoutListener();
|
|
64
|
+
setupStderrListener();
|
|
65
|
+
};
|
|
66
|
+
nodemon.on("readable", reattachListeners);
|
|
67
|
+
nodemon.on("crash", () => {
|
|
68
|
+
handlers.onCrash();
|
|
69
|
+
});
|
|
70
|
+
nodemon.on("restart", (files) => {
|
|
71
|
+
handlers.onRestart(files);
|
|
72
|
+
reattachListeners();
|
|
73
|
+
});
|
|
74
|
+
return () => {
|
|
75
|
+
if (nodemon.stdout) {
|
|
76
|
+
nodemon.stdout.off("data", handleStdoutData);
|
|
77
|
+
}
|
|
78
|
+
if (nodemon.stderr) {
|
|
79
|
+
nodemon.stderr.off("data", handleStderrData);
|
|
80
|
+
}
|
|
81
|
+
nodemon.emit("quit");
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Boot nodemon for the Ink dev UI. Returns whether the server is currently
|
|
86
|
+
* down after a crash, so the UI can stop advertising a URL nothing listens on.
|
|
87
|
+
*/
|
|
7
88
|
export function useNodemon(env, pushMessage) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
? {
|
|
12
|
-
configFile,
|
|
13
|
-
}
|
|
14
|
-
: {
|
|
15
|
-
watch: ["src"],
|
|
16
|
-
ext: "ts,json",
|
|
17
|
-
exec: "tsx src/server.ts",
|
|
18
|
-
};
|
|
19
|
-
nodemon({ ...config, env, stdout: false });
|
|
20
|
-
const handleStdoutData = (chunk) => {
|
|
89
|
+
const [crashed, setCrashed] = useState(false);
|
|
90
|
+
useEffect(() => startNodemon(env, {
|
|
91
|
+
onStdout: (chunk) => {
|
|
21
92
|
const message = chunk.toString().trim();
|
|
22
93
|
if (message) {
|
|
23
94
|
pushMessage(message, "log");
|
|
24
95
|
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
.filter((line) => !SOURCEMAP_WARNING.test(line))
|
|
35
|
-
.join("\n");
|
|
36
|
-
if (filtered) {
|
|
37
|
-
pushMessage(filtered, "error");
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
|
-
const setupStdoutListener = () => {
|
|
41
|
-
if (nodemon.stdout) {
|
|
42
|
-
nodemon.stdout.off("data", handleStdoutData);
|
|
43
|
-
nodemon.stdout.on("data", handleStdoutData);
|
|
44
|
-
}
|
|
45
|
-
};
|
|
46
|
-
const setupStderrListener = () => {
|
|
47
|
-
if (nodemon.stderr) {
|
|
48
|
-
nodemon.stderr.off("data", handleStderrData);
|
|
49
|
-
nodemon.stderr.on("data", handleStderrData);
|
|
50
|
-
}
|
|
51
|
-
};
|
|
52
|
-
nodemon.on("readable", () => {
|
|
53
|
-
setupStdoutListener();
|
|
54
|
-
setupStderrListener();
|
|
55
|
-
});
|
|
56
|
-
nodemon.on("restart", (files) => {
|
|
57
|
-
const restartMessage = `Server restarted due to file changes: ${files.join(", ")}`;
|
|
58
|
-
pushMessage(restartMessage, "restart");
|
|
59
|
-
setupStdoutListener();
|
|
60
|
-
setupStderrListener();
|
|
61
|
-
});
|
|
62
|
-
return () => {
|
|
63
|
-
if (nodemon.stdout) {
|
|
64
|
-
nodemon.stdout.off("data", handleStdoutData);
|
|
65
|
-
}
|
|
66
|
-
if (nodemon.stderr) {
|
|
67
|
-
nodemon.stderr.off("data", handleStderrData);
|
|
68
|
-
}
|
|
69
|
-
nodemon.emit("quit");
|
|
70
|
-
};
|
|
71
|
-
}, [env, pushMessage]);
|
|
96
|
+
},
|
|
97
|
+
onStderr: (message) => pushMessage(message, "error"),
|
|
98
|
+
onRestart: (files) => {
|
|
99
|
+
setCrashed(false);
|
|
100
|
+
pushMessage(`Server restarted due to file changes: ${files.join(", ")}`, "restart");
|
|
101
|
+
},
|
|
102
|
+
onCrash: () => setCrashed(true),
|
|
103
|
+
}), [env, pushMessage]);
|
|
104
|
+
return crashed;
|
|
72
105
|
}
|
|
73
106
|
//# sourceMappingURL=use-nodemon.js.map
|