workos 0.2.1 → 0.3.2
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/.claude-plugin/plugin.json +3 -3
- package/README.md +3 -2
- package/dist/bin.js +42 -20
- package/dist/bin.js.map +1 -1
- package/dist/cli.config.d.ts +6 -3
- package/dist/cli.config.js +8 -3
- package/dist/cli.config.js.map +1 -1
- package/dist/commands/install-skill.js.map +1 -0
- package/dist/{src/commands → commands}/install.js +8 -12
- package/dist/commands/install.js.map +1 -0
- package/dist/{src/commands → commands}/login.js +3 -2
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/logout.js.map +1 -0
- package/dist/craft-pre-release.sh +10 -0
- package/dist/dashboard/components/AnimatedLogo.js.map +1 -0
- package/dist/dashboard/components/CompletionView.js.map +1 -0
- package/dist/dashboard/components/ConfirmPrompt.js.map +1 -0
- package/dist/dashboard/components/CredentialsForm.js.map +1 -0
- package/dist/dashboard/components/Dashboard.js.map +1 -0
- package/dist/{src/dashboard → dashboard}/components/DashboardLayout.d.ts +2 -2
- package/dist/dashboard/components/DashboardLayout.js.map +1 -0
- package/dist/{src/dashboard → dashboard}/components/DiffPanel.d.ts +2 -2
- package/dist/dashboard/components/DiffPanel.js.map +1 -0
- package/dist/dashboard/components/InlinePrompt.js.map +1 -0
- package/dist/{src/dashboard → dashboard}/components/OutputPanel.d.ts +2 -2
- package/dist/dashboard/components/OutputPanel.js.map +1 -0
- package/dist/dashboard/components/Panel.js.map +1 -0
- package/dist/dashboard/components/TextInput.js.map +1 -0
- package/dist/dashboard/components/WelcomeArt.js.map +1 -0
- package/dist/dashboard/hooks/useAnimation.js.map +1 -0
- package/dist/dashboard/hooks/useKeyboard.js.map +1 -0
- package/dist/dashboard/hooks/useTerminalSize.js.map +1 -0
- package/dist/{src/dashboard → dashboard}/index.d.ts +2 -2
- package/dist/dashboard/index.js.map +1 -0
- package/dist/dashboard/lib/diff-utils.js.map +1 -0
- package/dist/dashboard/lib/logo-frames.js.map +1 -0
- package/dist/dashboard/lib/welcome-art.js.map +1 -0
- package/dist/dashboard/types.d.ts +5 -0
- package/dist/dashboard/types.js.map +1 -0
- package/dist/{src/lib → lib}/adapters/cli-adapter.d.ts +5 -5
- package/dist/{src/lib → lib}/adapters/cli-adapter.js +5 -5
- package/dist/lib/adapters/cli-adapter.js.map +1 -0
- package/dist/{src/lib → lib}/adapters/dashboard-adapter.d.ts +4 -4
- package/dist/lib/adapters/dashboard-adapter.js.map +1 -0
- package/dist/{src/lib → lib}/adapters/index.d.ts +1 -1
- package/dist/lib/adapters/index.js.map +1 -0
- package/dist/{src/lib → lib}/adapters/types.d.ts +4 -4
- package/dist/lib/adapters/types.js.map +1 -0
- package/dist/{src/lib → lib}/agent-interface.d.ts +15 -9
- package/dist/{src/lib → lib}/agent-interface.js +146 -61
- package/dist/lib/agent-interface.js.map +1 -0
- package/dist/{src/lib → lib}/agent-runner.d.ts +2 -2
- package/dist/{src/lib → lib}/agent-runner.js +4 -4
- package/dist/lib/agent-runner.js.map +1 -0
- package/dist/{src/lib → lib}/ai-content.d.ts +6 -2
- package/dist/lib/ai-content.js +130 -0
- package/dist/lib/ai-content.js.map +1 -0
- package/dist/lib/api.js.map +1 -0
- package/dist/lib/background-refresh.d.ts +29 -0
- package/dist/lib/background-refresh.js +95 -0
- package/dist/lib/background-refresh.js.map +1 -0
- package/dist/{src/lib → lib}/config.d.ts +6 -6
- package/dist/lib/config.js.map +1 -0
- package/dist/{src/lib → lib}/constants.d.ts +1 -1
- package/dist/{src/lib → lib}/constants.js +1 -1
- package/dist/lib/constants.js.map +1 -0
- package/dist/lib/credential-discovery.js.map +1 -0
- package/dist/lib/credential-proxy.d.ts +36 -0
- package/dist/lib/credential-proxy.js +298 -0
- package/dist/lib/credential-proxy.js.map +1 -0
- package/dist/{src/lib → lib}/credentials.d.ts +6 -0
- package/dist/{src/lib → lib}/credentials.js +33 -0
- package/dist/lib/credentials.js.map +1 -0
- package/dist/{src/lib → lib}/device-auth.d.ts +1 -0
- package/dist/{src/lib → lib}/device-auth.js +2 -1
- package/dist/lib/device-auth.js.map +1 -0
- package/dist/lib/ensure-auth.d.ts +22 -0
- package/dist/lib/ensure-auth.js +83 -0
- package/dist/lib/ensure-auth.js.map +1 -0
- package/dist/lib/env-writer.js.map +1 -0
- package/dist/{src/lib → lib}/events.d.ts +8 -8
- package/dist/{src/lib → lib}/events.js +3 -3
- package/dist/{src/lib → lib}/events.js.map +1 -1
- package/dist/{src/lib → lib}/framework-config.d.ts +2 -2
- package/dist/{src/lib → lib}/framework-config.js +1 -1
- package/dist/lib/framework-config.js.map +1 -0
- package/dist/lib/helper-functions.js.map +1 -0
- package/dist/{src/lib/wizard-core.d.ts → lib/installer-core.d.ts} +21 -17
- package/dist/{src/lib/wizard-core.js → lib/installer-core.js} +19 -17
- package/dist/lib/installer-core.js.map +1 -0
- package/dist/{src/lib/wizard-core.types.d.ts → lib/installer-core.types.d.ts} +9 -9
- package/dist/lib/installer-core.types.js +2 -0
- package/dist/lib/installer-core.types.js.map +1 -0
- package/dist/lib/port-detection.js.map +1 -0
- package/dist/lib/post-install.js.map +1 -0
- package/dist/lib/progress-tracker.js.map +1 -0
- package/dist/lib/run-with-core.d.ts +2 -0
- package/dist/{src/lib → lib}/run-with-core.js +38 -48
- package/dist/lib/run-with-core.js.map +1 -0
- package/dist/lib/safe-tools.js.map +1 -0
- package/dist/{src/lib → lib}/settings.d.ts +3 -0
- package/dist/{src/lib → lib}/settings.js +1 -1
- package/dist/lib/settings.js.map +1 -0
- package/dist/lib/staging-api.js.map +1 -0
- package/dist/lib/token-refresh-client.d.ts +23 -0
- package/dist/lib/token-refresh-client.js +88 -0
- package/dist/lib/token-refresh-client.js.map +1 -0
- package/dist/{src/lib → lib}/token-refresh.js +1 -1
- package/dist/lib/token-refresh.js.map +1 -0
- package/dist/lib/validation/build-validator.js.map +1 -0
- package/dist/lib/validation/index.js.map +1 -0
- package/dist/lib/validation/types.js.map +1 -0
- package/dist/lib/validation/validator.js.map +1 -0
- package/dist/{src/lib → lib}/workos-management.js +3 -3
- package/dist/lib/workos-management.js.map +1 -0
- package/dist/nextjs/nextjs-installer-agent.d.ts +6 -0
- package/dist/{src/nextjs/nextjs-wizard-agent.js → nextjs/nextjs-installer-agent.js} +6 -6
- package/dist/nextjs/nextjs-installer-agent.js.map +1 -0
- package/dist/{src/nextjs → nextjs}/utils.d.ts +2 -2
- package/dist/nextjs/utils.js.map +1 -0
- package/dist/react/react-installer-agent.d.ts +2 -0
- package/dist/{src/react/react-wizard-agent.js → react/react-installer-agent.js} +4 -4
- package/dist/react/react-installer-agent.js.map +1 -0
- package/dist/react-router/react-router-installer-agent.d.ts +6 -0
- package/dist/{src/react-router/react-router-wizard-agent.js → react-router/react-router-installer-agent.js} +6 -6
- package/dist/react-router/react-router-installer-agent.js.map +1 -0
- package/dist/{src/react-router → react-router}/utils.d.ts +2 -2
- package/dist/react-router/utils.js.map +1 -0
- package/dist/{src/run.d.ts → run.d.ts} +2 -1
- package/dist/{src/run.js → run.js} +5 -4
- package/dist/run.js.map +1 -0
- package/dist/{src/steps → steps}/add-or-update-environment-variables.js +5 -5
- package/dist/steps/add-or-update-environment-variables.js.map +1 -0
- package/dist/steps/index.js.map +1 -0
- package/dist/{src/steps → steps}/run-prettier.d.ts +2 -2
- package/dist/{src/steps → steps}/run-prettier.js +1 -1
- package/dist/steps/run-prettier.js.map +1 -0
- package/dist/{src/steps → steps}/upload-environment-variables/EnvironmentProvider.d.ts +3 -3
- package/dist/steps/upload-environment-variables/EnvironmentProvider.js.map +1 -0
- package/dist/{src/steps → steps}/upload-environment-variables/index.d.ts +2 -2
- package/dist/{src/steps → steps}/upload-environment-variables/index.js +3 -3
- package/dist/steps/upload-environment-variables/index.js.map +1 -0
- package/dist/{src/steps → steps}/upload-environment-variables/providers/vercel.d.ts +2 -2
- package/dist/steps/upload-environment-variables/providers/vercel.js.map +1 -0
- package/dist/tanstack-start/tanstack-start-installer-agent.d.ts +2 -0
- package/dist/{src/tanstack-start/tanstack-start-wizard-agent.js → tanstack-start/tanstack-start-installer-agent.js} +4 -4
- package/dist/tanstack-start/tanstack-start-installer-agent.js.map +1 -0
- package/dist/telemetry.js.map +1 -0
- package/dist/{src/utils → utils}/analytics.js +8 -8
- package/dist/utils/analytics.js.map +1 -0
- package/dist/utils/bash.js.map +1 -0
- package/dist/{src/utils → utils}/clack-utils.d.ts +9 -9
- package/dist/{src/utils → utils}/clack-utils.js +8 -8
- package/dist/utils/clack-utils.js.map +1 -0
- package/dist/utils/clack.js.map +1 -0
- package/dist/utils/cli-symbols.js.map +1 -0
- package/dist/{src/utils → utils}/debug.js +1 -1
- package/dist/utils/debug.js.map +1 -0
- package/dist/utils/env-parser.js.map +1 -0
- package/dist/utils/environment.d.ts +4 -0
- package/dist/{src/utils → utils}/environment.js +1 -1
- package/dist/utils/environment.js.map +1 -0
- package/dist/{src/utils → utils}/errors.js +1 -1
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/git-utils.js.map +1 -0
- package/dist/utils/logging.js.map +1 -0
- package/dist/utils/package-json.js.map +1 -0
- package/dist/{src/utils → utils}/package-manager.d.ts +4 -4
- package/dist/utils/package-manager.js.map +1 -0
- package/dist/utils/redact.js.map +1 -0
- package/dist/utils/semver.js.map +1 -0
- package/dist/utils/string.js.map +1 -0
- package/dist/{src/utils → utils}/telemetry-client.js +6 -2
- package/dist/utils/telemetry-client.js.map +1 -0
- package/dist/{src/utils → utils}/telemetry-types.d.ts +5 -5
- package/dist/utils/telemetry-types.js +6 -0
- package/dist/utils/telemetry-types.js.map +1 -0
- package/dist/{src/utils → utils}/types.d.ts +7 -2
- package/dist/{src/utils → utils}/types.js.map +1 -1
- package/dist/utils/urls.js.map +1 -0
- package/dist/utils/vendor/is-unicorn-supported.js.map +1 -0
- package/dist/vanilla-js/vanilla-js-installer-agent.d.ts +2 -0
- package/dist/{src/vanilla-js/vanilla-js-wizard-agent.js → vanilla-js/vanilla-js-installer-agent.js} +4 -4
- package/dist/vanilla-js/vanilla-js-installer-agent.js.map +1 -0
- package/package.json +11 -7
- package/dist/src/commands/install-skill.js.map +0 -1
- package/dist/src/commands/install.js.map +0 -1
- package/dist/src/commands/login.js.map +0 -1
- package/dist/src/commands/logout.js.map +0 -1
- package/dist/src/dashboard/components/AnimatedLogo.js.map +0 -1
- package/dist/src/dashboard/components/CompletionView.js.map +0 -1
- package/dist/src/dashboard/components/ConfirmPrompt.js.map +0 -1
- package/dist/src/dashboard/components/CredentialsForm.js.map +0 -1
- package/dist/src/dashboard/components/Dashboard.js.map +0 -1
- package/dist/src/dashboard/components/DashboardLayout.js.map +0 -1
- package/dist/src/dashboard/components/DiffPanel.js.map +0 -1
- package/dist/src/dashboard/components/InlinePrompt.js.map +0 -1
- package/dist/src/dashboard/components/OutputPanel.js.map +0 -1
- package/dist/src/dashboard/components/Panel.js.map +0 -1
- package/dist/src/dashboard/components/TextInput.js.map +0 -1
- package/dist/src/dashboard/components/WelcomeArt.js.map +0 -1
- package/dist/src/dashboard/hooks/useAnimation.js.map +0 -1
- package/dist/src/dashboard/hooks/useKeyboard.js.map +0 -1
- package/dist/src/dashboard/hooks/useTerminalSize.js.map +0 -1
- package/dist/src/dashboard/index.js.map +0 -1
- package/dist/src/dashboard/lib/diff-utils.js.map +0 -1
- package/dist/src/dashboard/lib/logo-frames.js.map +0 -1
- package/dist/src/dashboard/lib/welcome-art.js.map +0 -1
- package/dist/src/dashboard/types.d.ts +0 -5
- package/dist/src/dashboard/types.js.map +0 -1
- package/dist/src/lib/__tests__/test-utils.d.ts +0 -40
- package/dist/src/lib/__tests__/test-utils.js +0 -108
- package/dist/src/lib/__tests__/test-utils.js.map +0 -1
- package/dist/src/lib/adapters/cli-adapter.js.map +0 -1
- package/dist/src/lib/adapters/dashboard-adapter.js.map +0 -1
- package/dist/src/lib/adapters/index.js.map +0 -1
- package/dist/src/lib/adapters/types.js.map +0 -1
- package/dist/src/lib/agent-interface.js.map +0 -1
- package/dist/src/lib/agent-runner.js.map +0 -1
- package/dist/src/lib/ai-content.js +0 -68
- package/dist/src/lib/ai-content.js.map +0 -1
- package/dist/src/lib/api.js.map +0 -1
- package/dist/src/lib/config.js.map +0 -1
- package/dist/src/lib/constants.js.map +0 -1
- package/dist/src/lib/credential-discovery.js.map +0 -1
- package/dist/src/lib/credentials.js.map +0 -1
- package/dist/src/lib/device-auth.js.map +0 -1
- package/dist/src/lib/env-writer.js.map +0 -1
- package/dist/src/lib/framework-config.js.map +0 -1
- package/dist/src/lib/helper-functions.js.map +0 -1
- package/dist/src/lib/port-detection.js.map +0 -1
- package/dist/src/lib/post-install.js.map +0 -1
- package/dist/src/lib/progress-tracker.js.map +0 -1
- package/dist/src/lib/run-with-core.d.ts +0 -2
- package/dist/src/lib/run-with-core.js.map +0 -1
- package/dist/src/lib/safe-tools.js.map +0 -1
- package/dist/src/lib/settings.js.map +0 -1
- package/dist/src/lib/staging-api.js.map +0 -1
- package/dist/src/lib/token-refresh.js.map +0 -1
- package/dist/src/lib/validation/build-validator.js.map +0 -1
- package/dist/src/lib/validation/index.js.map +0 -1
- package/dist/src/lib/validation/types.js.map +0 -1
- package/dist/src/lib/validation/validator.js.map +0 -1
- package/dist/src/lib/wizard-core.js.map +0 -1
- package/dist/src/lib/wizard-core.types.js +0 -2
- package/dist/src/lib/wizard-core.types.js.map +0 -1
- package/dist/src/lib/workos-management.js.map +0 -1
- package/dist/src/nextjs/nextjs-wizard-agent.d.ts +0 -6
- package/dist/src/nextjs/nextjs-wizard-agent.js.map +0 -1
- package/dist/src/nextjs/utils.js.map +0 -1
- package/dist/src/react/react-wizard-agent.d.ts +0 -2
- package/dist/src/react/react-wizard-agent.js.map +0 -1
- package/dist/src/react-router/react-router-wizard-agent.d.ts +0 -6
- package/dist/src/react-router/react-router-wizard-agent.js.map +0 -1
- package/dist/src/react-router/utils.js.map +0 -1
- package/dist/src/run.js.map +0 -1
- package/dist/src/steps/add-or-update-environment-variables.js.map +0 -1
- package/dist/src/steps/index.js.map +0 -1
- package/dist/src/steps/run-prettier.js.map +0 -1
- package/dist/src/steps/upload-environment-variables/EnvironmentProvider.js.map +0 -1
- package/dist/src/steps/upload-environment-variables/index.js.map +0 -1
- package/dist/src/steps/upload-environment-variables/providers/vercel.js.map +0 -1
- package/dist/src/tanstack-start/tanstack-start-wizard-agent.d.ts +0 -2
- package/dist/src/tanstack-start/tanstack-start-wizard-agent.js.map +0 -1
- package/dist/src/telemetry.js.map +0 -1
- package/dist/src/utils/analytics.js.map +0 -1
- package/dist/src/utils/bash.js.map +0 -1
- package/dist/src/utils/clack-utils.js.map +0 -1
- package/dist/src/utils/clack.js.map +0 -1
- package/dist/src/utils/cli-symbols.js.map +0 -1
- package/dist/src/utils/debug.js.map +0 -1
- package/dist/src/utils/env-parser.js.map +0 -1
- package/dist/src/utils/environment.d.ts +0 -4
- package/dist/src/utils/environment.js.map +0 -1
- package/dist/src/utils/errors.js.map +0 -1
- package/dist/src/utils/git-utils.js.map +0 -1
- package/dist/src/utils/logging.js.map +0 -1
- package/dist/src/utils/package-json.js.map +0 -1
- package/dist/src/utils/package-manager.js.map +0 -1
- package/dist/src/utils/redact.js.map +0 -1
- package/dist/src/utils/semver.js.map +0 -1
- package/dist/src/utils/string.js.map +0 -1
- package/dist/src/utils/telemetry-client.js.map +0 -1
- package/dist/src/utils/telemetry-types.js +0 -6
- package/dist/src/utils/telemetry-types.js.map +0 -1
- package/dist/src/utils/urls.js.map +0 -1
- package/dist/src/utils/vendor/is-unicorn-supported.js.map +0 -1
- package/dist/src/vanilla-js/vanilla-js-wizard-agent.d.ts +0 -2
- package/dist/src/vanilla-js/vanilla-js-wizard-agent.js.map +0 -1
- package/dist/src/version.d.ts +0 -1
- package/dist/src/version.js +0 -2
- package/dist/src/version.js.map +0 -1
- /package/dist/{src/commands → commands}/install-skill.d.ts +0 -0
- /package/dist/{src/commands → commands}/install-skill.js +0 -0
- /package/dist/{src/commands → commands}/install.d.ts +0 -0
- /package/dist/{src/commands → commands}/login.d.ts +0 -0
- /package/dist/{src/commands → commands}/logout.d.ts +0 -0
- /package/dist/{src/commands → commands}/logout.js +0 -0
- /package/dist/{src/dashboard → dashboard}/components/AnimatedLogo.d.ts +0 -0
- /package/dist/{src/dashboard → dashboard}/components/AnimatedLogo.js +0 -0
- /package/dist/{src/dashboard → dashboard}/components/CompletionView.d.ts +0 -0
- /package/dist/{src/dashboard → dashboard}/components/CompletionView.js +0 -0
- /package/dist/{src/dashboard → dashboard}/components/ConfirmPrompt.d.ts +0 -0
- /package/dist/{src/dashboard → dashboard}/components/ConfirmPrompt.js +0 -0
- /package/dist/{src/dashboard → dashboard}/components/CredentialsForm.d.ts +0 -0
- /package/dist/{src/dashboard → dashboard}/components/CredentialsForm.js +0 -0
- /package/dist/{src/dashboard → dashboard}/components/Dashboard.d.ts +0 -0
- /package/dist/{src/dashboard → dashboard}/components/Dashboard.js +0 -0
- /package/dist/{src/dashboard → dashboard}/components/DashboardLayout.js +0 -0
- /package/dist/{src/dashboard → dashboard}/components/DiffPanel.js +0 -0
- /package/dist/{src/dashboard → dashboard}/components/InlinePrompt.d.ts +0 -0
- /package/dist/{src/dashboard → dashboard}/components/InlinePrompt.js +0 -0
- /package/dist/{src/dashboard → dashboard}/components/OutputPanel.js +0 -0
- /package/dist/{src/dashboard → dashboard}/components/Panel.d.ts +0 -0
- /package/dist/{src/dashboard → dashboard}/components/Panel.js +0 -0
- /package/dist/{src/dashboard → dashboard}/components/TextInput.d.ts +0 -0
- /package/dist/{src/dashboard → dashboard}/components/TextInput.js +0 -0
- /package/dist/{src/dashboard → dashboard}/components/WelcomeArt.d.ts +0 -0
- /package/dist/{src/dashboard → dashboard}/components/WelcomeArt.js +0 -0
- /package/dist/{src/dashboard → dashboard}/hooks/useAnimation.d.ts +0 -0
- /package/dist/{src/dashboard → dashboard}/hooks/useAnimation.js +0 -0
- /package/dist/{src/dashboard → dashboard}/hooks/useKeyboard.d.ts +0 -0
- /package/dist/{src/dashboard → dashboard}/hooks/useKeyboard.js +0 -0
- /package/dist/{src/dashboard → dashboard}/hooks/useTerminalSize.d.ts +0 -0
- /package/dist/{src/dashboard → dashboard}/hooks/useTerminalSize.js +0 -0
- /package/dist/{src/dashboard → dashboard}/index.js +0 -0
- /package/dist/{src/dashboard → dashboard}/lib/diff-utils.d.ts +0 -0
- /package/dist/{src/dashboard → dashboard}/lib/diff-utils.js +0 -0
- /package/dist/{src/dashboard → dashboard}/lib/logo-frames.d.ts +0 -0
- /package/dist/{src/dashboard → dashboard}/lib/logo-frames.js +0 -0
- /package/dist/{src/dashboard → dashboard}/lib/welcome-art.d.ts +0 -0
- /package/dist/{src/dashboard → dashboard}/lib/welcome-art.js +0 -0
- /package/dist/{src/dashboard → dashboard}/types.js +0 -0
- /package/dist/{src/lib → lib}/adapters/dashboard-adapter.js +0 -0
- /package/dist/{src/lib → lib}/adapters/index.js +0 -0
- /package/dist/{src/lib → lib}/adapters/types.js +0 -0
- /package/dist/{src/lib → lib}/api.d.ts +0 -0
- /package/dist/{src/lib → lib}/api.js +0 -0
- /package/dist/{src/lib → lib}/config.js +0 -0
- /package/dist/{src/lib → lib}/credential-discovery.d.ts +0 -0
- /package/dist/{src/lib → lib}/credential-discovery.js +0 -0
- /package/dist/{src/lib → lib}/env-writer.d.ts +0 -0
- /package/dist/{src/lib → lib}/env-writer.js +0 -0
- /package/dist/{src/lib → lib}/helper-functions.d.ts +0 -0
- /package/dist/{src/lib → lib}/helper-functions.js +0 -0
- /package/dist/{src/lib → lib}/port-detection.d.ts +0 -0
- /package/dist/{src/lib → lib}/port-detection.js +0 -0
- /package/dist/{src/lib → lib}/post-install.d.ts +0 -0
- /package/dist/{src/lib → lib}/post-install.js +0 -0
- /package/dist/{src/lib → lib}/progress-tracker.d.ts +0 -0
- /package/dist/{src/lib → lib}/progress-tracker.js +0 -0
- /package/dist/{src/lib → lib}/safe-tools.d.ts +0 -0
- /package/dist/{src/lib → lib}/safe-tools.js +0 -0
- /package/dist/{src/lib → lib}/staging-api.d.ts +0 -0
- /package/dist/{src/lib → lib}/staging-api.js +0 -0
- /package/dist/{src/lib → lib}/token-refresh.d.ts +0 -0
- /package/dist/{src/lib → lib}/validation/build-validator.d.ts +0 -0
- /package/dist/{src/lib → lib}/validation/build-validator.js +0 -0
- /package/dist/{src/lib → lib}/validation/index.d.ts +0 -0
- /package/dist/{src/lib → lib}/validation/index.js +0 -0
- /package/dist/{src/lib → lib}/validation/types.d.ts +0 -0
- /package/dist/{src/lib → lib}/validation/types.js +0 -0
- /package/dist/{src/lib → lib}/validation/validator.d.ts +0 -0
- /package/dist/{src/lib → lib}/validation/validator.js +0 -0
- /package/dist/{src/lib → lib}/workos-management.d.ts +0 -0
- /package/dist/{src/nextjs → nextjs}/utils.js +0 -0
- /package/dist/{src/react-router → react-router}/utils.js +0 -0
- /package/dist/{src/steps → steps}/add-or-update-environment-variables.d.ts +0 -0
- /package/dist/{src/steps → steps}/index.d.ts +0 -0
- /package/dist/{src/steps → steps}/index.js +0 -0
- /package/dist/{src/steps → steps}/upload-environment-variables/EnvironmentProvider.js +0 -0
- /package/dist/{src/steps → steps}/upload-environment-variables/providers/vercel.js +0 -0
- /package/dist/{src/telemetry.d.ts → telemetry.d.ts} +0 -0
- /package/dist/{src/telemetry.js → telemetry.js} +0 -0
- /package/dist/{src/utils → utils}/analytics.d.ts +0 -0
- /package/dist/{src/utils → utils}/bash.d.ts +0 -0
- /package/dist/{src/utils → utils}/bash.js +0 -0
- /package/dist/{src/utils → utils}/clack.d.ts +0 -0
- /package/dist/{src/utils → utils}/clack.js +0 -0
- /package/dist/{src/utils → utils}/cli-symbols.d.ts +0 -0
- /package/dist/{src/utils → utils}/cli-symbols.js +0 -0
- /package/dist/{src/utils → utils}/debug.d.ts +0 -0
- /package/dist/{src/utils → utils}/env-parser.d.ts +0 -0
- /package/dist/{src/utils → utils}/env-parser.js +0 -0
- /package/dist/{src/utils → utils}/errors.d.ts +0 -0
- /package/dist/{src/utils → utils}/git-utils.d.ts +0 -0
- /package/dist/{src/utils → utils}/git-utils.js +0 -0
- /package/dist/{src/utils → utils}/logging.d.ts +0 -0
- /package/dist/{src/utils → utils}/logging.js +0 -0
- /package/dist/{src/utils → utils}/package-json.d.ts +0 -0
- /package/dist/{src/utils → utils}/package-json.js +0 -0
- /package/dist/{src/utils → utils}/package-manager.js +0 -0
- /package/dist/{src/utils → utils}/redact.d.ts +0 -0
- /package/dist/{src/utils → utils}/redact.js +0 -0
- /package/dist/{src/utils → utils}/semver.d.ts +0 -0
- /package/dist/{src/utils → utils}/semver.js +0 -0
- /package/dist/{src/utils → utils}/string.d.ts +0 -0
- /package/dist/{src/utils → utils}/string.js +0 -0
- /package/dist/{src/utils → utils}/telemetry-client.d.ts +0 -0
- /package/dist/{src/utils → utils}/types.js +0 -0
- /package/dist/{src/utils → utils}/urls.d.ts +0 -0
- /package/dist/{src/utils → utils}/urls.js +0 -0
- /package/dist/{src/utils → utils}/vendor/is-unicorn-supported.d.ts +0 -0
- /package/dist/{src/utils → utils}/vendor/is-unicorn-supported.js +0 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import Anthropic from '@anthropic-ai/sdk';
|
|
2
|
+
import { startCredentialProxy } from './credential-proxy.js';
|
|
3
|
+
import { getLlmGatewayUrl, getAuthkitDomain, getCliAuthClientId, getConfig } from './settings.js';
|
|
4
|
+
import { getCredentials } from './credentials.js';
|
|
5
|
+
import { logInfo, logError } from '../utils/debug.js';
|
|
6
|
+
/**
|
|
7
|
+
* Execute an API call through a short-lived credential proxy.
|
|
8
|
+
* Handles proxy lifecycle automatically.
|
|
9
|
+
*/
|
|
10
|
+
async function withProxy(fn) {
|
|
11
|
+
const gatewayUrl = getLlmGatewayUrl();
|
|
12
|
+
const creds = getCredentials();
|
|
13
|
+
if (!creds?.refreshToken) {
|
|
14
|
+
// No refresh token - use credentials directly (legacy mode)
|
|
15
|
+
logInfo('[ai-content] No refresh token, using credentials directly');
|
|
16
|
+
const client = new Anthropic({
|
|
17
|
+
baseURL: gatewayUrl,
|
|
18
|
+
apiKey: 'gateway', // SDK requires something, gateway uses Authorization header
|
|
19
|
+
defaultHeaders: creds?.accessToken ? { Authorization: `Bearer ${creds.accessToken}` } : undefined,
|
|
20
|
+
});
|
|
21
|
+
return fn(client);
|
|
22
|
+
}
|
|
23
|
+
// Start short-lived proxy
|
|
24
|
+
const proxy = await startCredentialProxy({
|
|
25
|
+
upstreamUrl: gatewayUrl,
|
|
26
|
+
refresh: {
|
|
27
|
+
authkitDomain: getAuthkitDomain(),
|
|
28
|
+
clientId: getCliAuthClientId(),
|
|
29
|
+
refreshThresholdMs: getConfig().proxy.refreshThresholdMs,
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
logInfo(`[ai-content] Started proxy at ${proxy.url}`);
|
|
33
|
+
try {
|
|
34
|
+
const client = new Anthropic({
|
|
35
|
+
baseURL: proxy.url,
|
|
36
|
+
apiKey: 'proxy', // SDK requires something, proxy handles real auth
|
|
37
|
+
});
|
|
38
|
+
return await fn(client);
|
|
39
|
+
}
|
|
40
|
+
finally {
|
|
41
|
+
await proxy.stop();
|
|
42
|
+
logInfo('[ai-content] Stopped proxy');
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Execute an API call directly to Anthropic (--direct mode).
|
|
47
|
+
*/
|
|
48
|
+
async function withDirect(fn) {
|
|
49
|
+
// SDK reads ANTHROPIC_API_KEY from env automatically
|
|
50
|
+
const client = new Anthropic();
|
|
51
|
+
return fn(client);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Generate a concise commit message for the AuthKit integration.
|
|
55
|
+
* Falls back to a default message if AI generation fails.
|
|
56
|
+
*/
|
|
57
|
+
export async function generateCommitMessage(integration, files, options = {}) {
|
|
58
|
+
const executor = options.direct ? withDirect : withProxy;
|
|
59
|
+
try {
|
|
60
|
+
return await executor(async (client) => {
|
|
61
|
+
const response = await client.messages.create({
|
|
62
|
+
model: 'claude-sonnet-4-20250514',
|
|
63
|
+
max_tokens: 100,
|
|
64
|
+
messages: [
|
|
65
|
+
{
|
|
66
|
+
role: 'user',
|
|
67
|
+
content: `Generate a concise git commit message for adding WorkOS AuthKit to a ${integration} project. Changed files: ${files.slice(0, 10).join(', ')}. Use conventional commit format (feat:). One line only, under 72 chars.`,
|
|
68
|
+
},
|
|
69
|
+
],
|
|
70
|
+
});
|
|
71
|
+
const text = response.content[0];
|
|
72
|
+
if (text.type === 'text') {
|
|
73
|
+
return text.text.trim();
|
|
74
|
+
}
|
|
75
|
+
throw new Error('Unexpected response format');
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
logError('[ai-content] Failed to generate commit message:', error);
|
|
80
|
+
return `feat: add WorkOS AuthKit integration for ${integration}`;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Generate a PR description for the AuthKit integration.
|
|
85
|
+
* Falls back to a default template if AI generation fails.
|
|
86
|
+
*/
|
|
87
|
+
export async function generatePrDescription(integration, files, commitMessage, options = {}) {
|
|
88
|
+
const executor = options.direct ? withDirect : withProxy;
|
|
89
|
+
try {
|
|
90
|
+
return await executor(async (client) => {
|
|
91
|
+
const response = await client.messages.create({
|
|
92
|
+
model: 'claude-sonnet-4-20250514',
|
|
93
|
+
max_tokens: 500,
|
|
94
|
+
messages: [
|
|
95
|
+
{
|
|
96
|
+
role: 'user',
|
|
97
|
+
content: `Generate a GitHub PR description for: "${commitMessage}"
|
|
98
|
+
|
|
99
|
+
Framework: ${integration}
|
|
100
|
+
Files changed: ${files.join(', ')}
|
|
101
|
+
|
|
102
|
+
Include:
|
|
103
|
+
- Brief summary (2-3 sentences)
|
|
104
|
+
- Key changes bullet list
|
|
105
|
+
- Link to WorkOS AuthKit docs: https://workos.com/docs/user-management
|
|
106
|
+
|
|
107
|
+
Keep it concise. Markdown format.`,
|
|
108
|
+
},
|
|
109
|
+
],
|
|
110
|
+
});
|
|
111
|
+
const text = response.content[0];
|
|
112
|
+
if (text.type === 'text') {
|
|
113
|
+
return text.text.trim();
|
|
114
|
+
}
|
|
115
|
+
throw new Error('Unexpected response format');
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
catch (error) {
|
|
119
|
+
logError('[ai-content] Failed to generate PR description:', error);
|
|
120
|
+
return `## Summary
|
|
121
|
+
Added WorkOS AuthKit integration for ${integration}.
|
|
122
|
+
|
|
123
|
+
## Changes
|
|
124
|
+
${files.map((f) => `- ${f}`).join('\n')}
|
|
125
|
+
|
|
126
|
+
## Documentation
|
|
127
|
+
https://workos.com/docs/user-management`;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=ai-content.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai-content.js","sourceRoot":"","sources":["../../src/lib/ai-content.ts"],"names":[],"mappings":"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","sourcesContent":["import Anthropic from '@anthropic-ai/sdk';\nimport { startCredentialProxy } from './credential-proxy.js';\nimport { getLlmGatewayUrl, getAuthkitDomain, getCliAuthClientId, getConfig } from './settings.js';\nimport { getCredentials } from './credentials.js';\nimport { logInfo, logError } from '../utils/debug.js';\n\nexport interface AiContentOptions {\n /** Use direct Anthropic API instead of llm-gateway */\n direct?: boolean;\n}\n\n/**\n * Execute an API call through a short-lived credential proxy.\n * Handles proxy lifecycle automatically.\n */\nasync function withProxy<T>(fn: (client: Anthropic) => Promise<T>): Promise<T> {\n const gatewayUrl = getLlmGatewayUrl();\n const creds = getCredentials();\n\n if (!creds?.refreshToken) {\n // No refresh token - use credentials directly (legacy mode)\n logInfo('[ai-content] No refresh token, using credentials directly');\n const client = new Anthropic({\n baseURL: gatewayUrl,\n apiKey: 'gateway', // SDK requires something, gateway uses Authorization header\n defaultHeaders: creds?.accessToken ? { Authorization: `Bearer ${creds.accessToken}` } : undefined,\n });\n return fn(client);\n }\n\n // Start short-lived proxy\n const proxy = await startCredentialProxy({\n upstreamUrl: gatewayUrl,\n refresh: {\n authkitDomain: getAuthkitDomain(),\n clientId: getCliAuthClientId(),\n refreshThresholdMs: getConfig().proxy.refreshThresholdMs,\n },\n });\n\n logInfo(`[ai-content] Started proxy at ${proxy.url}`);\n\n try {\n const client = new Anthropic({\n baseURL: proxy.url,\n apiKey: 'proxy', // SDK requires something, proxy handles real auth\n });\n return await fn(client);\n } finally {\n await proxy.stop();\n logInfo('[ai-content] Stopped proxy');\n }\n}\n\n/**\n * Execute an API call directly to Anthropic (--direct mode).\n */\nasync function withDirect<T>(fn: (client: Anthropic) => Promise<T>): Promise<T> {\n // SDK reads ANTHROPIC_API_KEY from env automatically\n const client = new Anthropic();\n return fn(client);\n}\n\n/**\n * Generate a concise commit message for the AuthKit integration.\n * Falls back to a default message if AI generation fails.\n */\nexport async function generateCommitMessage(\n integration: string,\n files: string[],\n options: AiContentOptions = {},\n): Promise<string> {\n const executor = options.direct ? withDirect : withProxy;\n\n try {\n return await executor(async (client) => {\n const response = await client.messages.create({\n model: 'claude-sonnet-4-20250514',\n max_tokens: 100,\n messages: [\n {\n role: 'user',\n content: `Generate a concise git commit message for adding WorkOS AuthKit to a ${integration} project. Changed files: ${files.slice(0, 10).join(', ')}. Use conventional commit format (feat:). One line only, under 72 chars.`,\n },\n ],\n });\n\n const text = response.content[0];\n if (text.type === 'text') {\n return text.text.trim();\n }\n throw new Error('Unexpected response format');\n });\n } catch (error) {\n logError('[ai-content] Failed to generate commit message:', error);\n return `feat: add WorkOS AuthKit integration for ${integration}`;\n }\n}\n\n/**\n * Generate a PR description for the AuthKit integration.\n * Falls back to a default template if AI generation fails.\n */\nexport async function generatePrDescription(\n integration: string,\n files: string[],\n commitMessage: string,\n options: AiContentOptions = {},\n): Promise<string> {\n const executor = options.direct ? withDirect : withProxy;\n\n try {\n return await executor(async (client) => {\n const response = await client.messages.create({\n model: 'claude-sonnet-4-20250514',\n max_tokens: 500,\n messages: [\n {\n role: 'user',\n content: `Generate a GitHub PR description for: \"${commitMessage}\"\n\nFramework: ${integration}\nFiles changed: ${files.join(', ')}\n\nInclude:\n- Brief summary (2-3 sentences)\n- Key changes bullet list\n- Link to WorkOS AuthKit docs: https://workos.com/docs/user-management\n\nKeep it concise. Markdown format.`,\n },\n ],\n });\n\n const text = response.content[0];\n if (text.type === 'text') {\n return text.text.trim();\n }\n throw new Error('Unexpected response format');\n });\n } catch (error) {\n logError('[ai-content] Failed to generate PR description:', error);\n return `## Summary\nAdded WorkOS AuthKit integration for ${integration}.\n\n## Changes\n${files.map((f) => `- ${f}`).join('\\n')}\n\n## Documentation\nhttps://workos.com/docs/user-management`;\n }\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/lib/api.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from 'zod';\nimport { analytics } from '../utils/analytics.js';\n\nexport const ApiUserSchema = z.object({\n distinct_id: z.string(),\n organizations: z.array(\n z.object({\n id: z.uuid(),\n }),\n ),\n team: z.object({\n id: z.number(),\n organization: z.uuid(),\n }),\n organization: z.object({\n id: z.uuid(),\n }),\n});\n\nexport const ApiProjectSchema = z.object({\n id: z.number(),\n uuid: z.uuid(),\n organization: z.uuid(),\n api_token: z.string(),\n name: z.string(),\n});\n\nexport type ApiUser = z.infer<typeof ApiUserSchema>;\nexport type ApiProject = z.infer<typeof ApiProjectSchema>;\n\nclass ApiError extends Error {\n constructor(\n message: string,\n public readonly statusCode?: number,\n public readonly endpoint?: string,\n ) {\n super(message);\n this.name = 'ApiError';\n }\n}\n\nexport async function fetchUserData(accessToken: string, baseUrl: string): Promise<ApiUser> {\n const endpoint = '/api/users/@me/';\n try {\n const response = await fetch(`${baseUrl}${endpoint}`, {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n },\n });\n\n if (!response.ok) {\n throw await createFetchError(response, endpoint);\n }\n\n const data = await response.json();\n return ApiUserSchema.parse(data);\n } catch (error) {\n const apiError = handleApiError(error, 'fetch user data', endpoint);\n analytics.captureException(apiError, {\n endpoint,\n baseUrl,\n });\n throw apiError;\n }\n}\n\nexport async function fetchProjectData(accessToken: string, projectId: number, baseUrl: string): Promise<ApiProject> {\n const endpoint = `/api/projects/${projectId}/`;\n try {\n const response = await fetch(`${baseUrl}${endpoint}`, {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n },\n });\n\n if (!response.ok) {\n throw await createFetchError(response, endpoint);\n }\n\n const data = await response.json();\n return ApiProjectSchema.parse(data);\n } catch (error) {\n const apiError = handleApiError(error, 'fetch project data', endpoint);\n analytics.captureException(apiError, {\n endpoint,\n baseUrl,\n projectId,\n });\n throw apiError;\n }\n}\n\ninterface FetchError extends Error {\n status: number;\n endpoint: string;\n detail?: string;\n}\n\nasync function createFetchError(response: Response, endpoint: string): Promise<FetchError> {\n let detail: string | undefined;\n try {\n const data: unknown = await response.json();\n if (typeof data === 'object' && data !== null && 'detail' in data) {\n detail = String((data as { detail: unknown }).detail);\n }\n } catch {\n // Response wasn't JSON\n }\n\n const error = new Error(`HTTP ${response.status}`) as FetchError;\n error.status = response.status;\n error.endpoint = endpoint;\n error.detail = detail;\n return error;\n}\n\nfunction isFetchError(error: unknown): error is FetchError {\n return error instanceof Error && 'status' in error && typeof (error as FetchError).status === 'number';\n}\n\nfunction handleApiError(error: unknown, operation: string, endpoint: string): ApiError {\n if (isFetchError(error)) {\n const { status, detail } = error;\n\n if (status === 401) {\n return new ApiError(`Authentication failed while trying to ${operation}`, status, endpoint);\n }\n\n if (status === 403) {\n return new ApiError(`Access denied while trying to ${operation}`, status, endpoint);\n }\n\n if (status === 404) {\n return new ApiError(`Resource not found while trying to ${operation}`, status, endpoint);\n }\n\n const message = detail || `Failed to ${operation}`;\n return new ApiError(message, status, endpoint);\n }\n\n if (error instanceof z.ZodError) {\n return new ApiError(`Invalid response format while trying to ${operation}`);\n }\n\n return new ApiError(\n `Unexpected error while trying to ${operation}: ${error instanceof Error ? error.message : 'Unknown error'}`,\n );\n}\n"]}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Background token refresh loop.
|
|
3
|
+
* Runs in main wizard process, refreshes tokens before expiry,
|
|
4
|
+
* writes to credentials file for proxy to read.
|
|
5
|
+
*/
|
|
6
|
+
export interface BackgroundRefreshOptions {
|
|
7
|
+
/** AuthKit domain for refresh endpoint */
|
|
8
|
+
authkitDomain: string;
|
|
9
|
+
/** OAuth client ID */
|
|
10
|
+
clientId: string;
|
|
11
|
+
/** Check interval in ms (default: 30000) */
|
|
12
|
+
intervalMs?: number;
|
|
13
|
+
/** Refresh threshold in ms before expiry (default: 120000 = 2 min) */
|
|
14
|
+
refreshThresholdMs?: number;
|
|
15
|
+
/** Callback when refresh fails permanently */
|
|
16
|
+
onRefreshExpired?: () => void;
|
|
17
|
+
/** Callback when refresh succeeds */
|
|
18
|
+
onRefreshSuccess?: () => void;
|
|
19
|
+
}
|
|
20
|
+
export interface BackgroundRefreshHandle {
|
|
21
|
+
/** Stop the refresh loop */
|
|
22
|
+
stop: () => void;
|
|
23
|
+
/** Check if the loop is running */
|
|
24
|
+
isRunning: () => boolean;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Start background token refresh loop.
|
|
28
|
+
*/
|
|
29
|
+
export declare function startBackgroundRefresh(options: BackgroundRefreshOptions): BackgroundRefreshHandle;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Background token refresh loop.
|
|
3
|
+
* Runs in main wizard process, refreshes tokens before expiry,
|
|
4
|
+
* writes to credentials file for proxy to read.
|
|
5
|
+
*/
|
|
6
|
+
import { logInfo, logError, logWarn } from '../utils/debug.js';
|
|
7
|
+
import { getCredentials, updateTokens } from './credentials.js';
|
|
8
|
+
import { refreshAccessToken, tokenNeedsRefresh } from './token-refresh-client.js';
|
|
9
|
+
import { analytics } from '../utils/analytics.js';
|
|
10
|
+
/**
|
|
11
|
+
* Start background token refresh loop.
|
|
12
|
+
*/
|
|
13
|
+
export function startBackgroundRefresh(options) {
|
|
14
|
+
const { authkitDomain, clientId, intervalMs = 30_000, refreshThresholdMs = 2 * 60 * 1000, onRefreshExpired, onRefreshSuccess, } = options;
|
|
15
|
+
let isRunning = true;
|
|
16
|
+
let intervalId = null;
|
|
17
|
+
let consecutiveFailures = 0;
|
|
18
|
+
const MAX_CONSECUTIVE_FAILURES = 3;
|
|
19
|
+
const checkAndRefresh = async () => {
|
|
20
|
+
if (!isRunning)
|
|
21
|
+
return;
|
|
22
|
+
const creds = getCredentials();
|
|
23
|
+
if (!creds?.refreshToken) {
|
|
24
|
+
logWarn('[background-refresh] No refresh token available');
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
if (!tokenNeedsRefresh(creds.expiresAt, refreshThresholdMs)) {
|
|
28
|
+
// Token still valid, nothing to do
|
|
29
|
+
const timeUntilExpiry = creds.expiresAt - Date.now();
|
|
30
|
+
logInfo(`[background-refresh] Token valid for ${Math.round(timeUntilExpiry / 1000)}s`);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
logInfo('[background-refresh] Token needs refresh, initiating...');
|
|
34
|
+
analytics.capture('installer.token.refresh', {
|
|
35
|
+
action: 'refresh_attempt',
|
|
36
|
+
trigger: 'proactive',
|
|
37
|
+
time_until_expiry_ms: creds.expiresAt - Date.now(),
|
|
38
|
+
});
|
|
39
|
+
const startTime = Date.now();
|
|
40
|
+
const result = await refreshAccessToken(authkitDomain, clientId);
|
|
41
|
+
if (result.success && result.accessToken && result.expiresAt) {
|
|
42
|
+
// Update credentials file atomically
|
|
43
|
+
updateTokens(result.accessToken, result.expiresAt, result.refreshToken);
|
|
44
|
+
consecutiveFailures = 0;
|
|
45
|
+
const durationMs = Date.now() - startTime;
|
|
46
|
+
logInfo(`[background-refresh] Token refreshed in ${durationMs}ms, new expiry: ${new Date(result.expiresAt).toISOString()}`);
|
|
47
|
+
analytics.capture('installer.token.refresh', {
|
|
48
|
+
action: 'refresh_success',
|
|
49
|
+
duration_ms: durationMs,
|
|
50
|
+
token_rotated: !!result.refreshToken,
|
|
51
|
+
});
|
|
52
|
+
onRefreshSuccess?.();
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
consecutiveFailures++;
|
|
56
|
+
logError(`[background-refresh] Refresh failed: ${result.error}`);
|
|
57
|
+
analytics.capture('installer.token.refresh', {
|
|
58
|
+
action: 'refresh_failure',
|
|
59
|
+
error_type: result.errorType || 'unknown',
|
|
60
|
+
error_message: result.error || 'Unknown error',
|
|
61
|
+
consecutive_failures: consecutiveFailures,
|
|
62
|
+
});
|
|
63
|
+
// Handle permanent failure (refresh token expired)
|
|
64
|
+
if (result.errorType === 'invalid_grant') {
|
|
65
|
+
logError('[background-refresh] Refresh token expired, stopping refresh loop');
|
|
66
|
+
stop();
|
|
67
|
+
onRefreshExpired?.();
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
// Handle too many consecutive transient failures
|
|
71
|
+
if (consecutiveFailures >= MAX_CONSECUTIVE_FAILURES) {
|
|
72
|
+
logError(`[background-refresh] ${MAX_CONSECUTIVE_FAILURES} consecutive failures, stopping`);
|
|
73
|
+
stop();
|
|
74
|
+
onRefreshExpired?.();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
const stop = () => {
|
|
79
|
+
isRunning = false;
|
|
80
|
+
if (intervalId) {
|
|
81
|
+
clearInterval(intervalId);
|
|
82
|
+
intervalId = null;
|
|
83
|
+
}
|
|
84
|
+
logInfo('[background-refresh] Stopped');
|
|
85
|
+
};
|
|
86
|
+
// Run immediately, then on interval
|
|
87
|
+
checkAndRefresh();
|
|
88
|
+
intervalId = setInterval(checkAndRefresh, intervalMs);
|
|
89
|
+
logInfo(`[background-refresh] Started, checking every ${intervalMs}ms`);
|
|
90
|
+
return {
|
|
91
|
+
stop,
|
|
92
|
+
isRunning: () => isRunning,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=background-refresh.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"background-refresh.js","sourceRoot":"","sources":["../../src/lib/background-refresh.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Background token refresh loop.\n * Runs in main wizard process, refreshes tokens before expiry,\n * writes to credentials file for proxy to read.\n */\n\nimport { logInfo, logError, logWarn } from '../utils/debug.js';\nimport { getCredentials, updateTokens } from './credentials.js';\nimport { refreshAccessToken, tokenNeedsRefresh } from './token-refresh-client.js';\nimport { analytics } from '../utils/analytics.js';\n\nexport interface BackgroundRefreshOptions {\n /** AuthKit domain for refresh endpoint */\n authkitDomain: string;\n /** OAuth client ID */\n clientId: string;\n /** Check interval in ms (default: 30000) */\n intervalMs?: number;\n /** Refresh threshold in ms before expiry (default: 120000 = 2 min) */\n refreshThresholdMs?: number;\n /** Callback when refresh fails permanently */\n onRefreshExpired?: () => void;\n /** Callback when refresh succeeds */\n onRefreshSuccess?: () => void;\n}\n\nexport interface BackgroundRefreshHandle {\n /** Stop the refresh loop */\n stop: () => void;\n /** Check if the loop is running */\n isRunning: () => boolean;\n}\n\n/**\n * Start background token refresh loop.\n */\nexport function startBackgroundRefresh(options: BackgroundRefreshOptions): BackgroundRefreshHandle {\n const {\n authkitDomain,\n clientId,\n intervalMs = 30_000,\n refreshThresholdMs = 2 * 60 * 1000,\n onRefreshExpired,\n onRefreshSuccess,\n } = options;\n\n let isRunning = true;\n let intervalId: NodeJS.Timeout | null = null;\n let consecutiveFailures = 0;\n const MAX_CONSECUTIVE_FAILURES = 3;\n\n const checkAndRefresh = async () => {\n if (!isRunning) return;\n\n const creds = getCredentials();\n\n if (!creds?.refreshToken) {\n logWarn('[background-refresh] No refresh token available');\n return;\n }\n\n if (!tokenNeedsRefresh(creds.expiresAt, refreshThresholdMs)) {\n // Token still valid, nothing to do\n const timeUntilExpiry = creds.expiresAt - Date.now();\n logInfo(`[background-refresh] Token valid for ${Math.round(timeUntilExpiry / 1000)}s`);\n return;\n }\n\n logInfo('[background-refresh] Token needs refresh, initiating...');\n\n analytics.capture('installer.token.refresh', {\n action: 'refresh_attempt',\n trigger: 'proactive',\n time_until_expiry_ms: creds.expiresAt - Date.now(),\n });\n\n const startTime = Date.now();\n const result = await refreshAccessToken(authkitDomain, clientId);\n\n if (result.success && result.accessToken && result.expiresAt) {\n // Update credentials file atomically\n updateTokens(result.accessToken, result.expiresAt, result.refreshToken);\n\n consecutiveFailures = 0;\n const durationMs = Date.now() - startTime;\n\n logInfo(\n `[background-refresh] Token refreshed in ${durationMs}ms, new expiry: ${new Date(result.expiresAt).toISOString()}`,\n );\n\n analytics.capture('installer.token.refresh', {\n action: 'refresh_success',\n duration_ms: durationMs,\n token_rotated: !!result.refreshToken,\n });\n\n onRefreshSuccess?.();\n } else {\n consecutiveFailures++;\n\n logError(`[background-refresh] Refresh failed: ${result.error}`);\n\n analytics.capture('installer.token.refresh', {\n action: 'refresh_failure',\n error_type: result.errorType || 'unknown',\n error_message: result.error || 'Unknown error',\n consecutive_failures: consecutiveFailures,\n });\n\n // Handle permanent failure (refresh token expired)\n if (result.errorType === 'invalid_grant') {\n logError('[background-refresh] Refresh token expired, stopping refresh loop');\n stop();\n onRefreshExpired?.();\n return;\n }\n\n // Handle too many consecutive transient failures\n if (consecutiveFailures >= MAX_CONSECUTIVE_FAILURES) {\n logError(`[background-refresh] ${MAX_CONSECUTIVE_FAILURES} consecutive failures, stopping`);\n stop();\n onRefreshExpired?.();\n }\n }\n };\n\n const stop = () => {\n isRunning = false;\n if (intervalId) {\n clearInterval(intervalId);\n intervalId = null;\n }\n logInfo('[background-refresh] Stopped');\n };\n\n // Run immediately, then on interval\n checkAndRefresh();\n intervalId = setInterval(checkAndRefresh, intervalMs);\n\n logInfo(`[background-refresh] Started, checking every ${intervalMs}ms`);\n\n return {\n stop,\n isRunning: () => isRunning,\n };\n}\n"]}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { InstallerOptions } from '../utils/types.js';
|
|
2
2
|
import { Integration } from './constants.js';
|
|
3
3
|
export declare const INTEGRATION_CONFIG: {
|
|
4
4
|
readonly nextjs: {
|
|
5
5
|
readonly name: "Next.js";
|
|
6
6
|
readonly filterPatterns: ["**/*.{tsx,ts,jsx,js,mjs,cjs}"];
|
|
7
7
|
readonly ignorePatterns: ["node_modules", "dist", "build", "public", "static", "next-env.d.*"];
|
|
8
|
-
readonly detect: (options: Pick<
|
|
8
|
+
readonly detect: (options: Pick<InstallerOptions, "installDir">) => Promise<boolean>;
|
|
9
9
|
readonly generateFilesRules: "";
|
|
10
10
|
readonly filterFilesRules: "";
|
|
11
11
|
readonly docsUrl: "https://workos.com/docs/user-management/authkit/nextjs";
|
|
@@ -16,7 +16,7 @@ export declare const INTEGRATION_CONFIG: {
|
|
|
16
16
|
readonly name: "React (SPA)";
|
|
17
17
|
readonly filterPatterns: ["**/*.{tsx,ts,jsx,js}"];
|
|
18
18
|
readonly ignorePatterns: ["node_modules", "dist", "build", "public", "static", "assets"];
|
|
19
|
-
readonly detect: (options: Pick<
|
|
19
|
+
readonly detect: (options: Pick<InstallerOptions, "installDir">) => Promise<boolean>;
|
|
20
20
|
readonly generateFilesRules: "";
|
|
21
21
|
readonly filterFilesRules: "";
|
|
22
22
|
readonly docsUrl: "https://workos.com/docs/user-management/authkit/react";
|
|
@@ -27,7 +27,7 @@ export declare const INTEGRATION_CONFIG: {
|
|
|
27
27
|
readonly name: "TanStack Start";
|
|
28
28
|
readonly filterPatterns: ["**/*.{tsx,ts,jsx,js}"];
|
|
29
29
|
readonly ignorePatterns: ["node_modules", "dist", "build", ".vinxi", ".output"];
|
|
30
|
-
readonly detect: (options: Pick<
|
|
30
|
+
readonly detect: (options: Pick<InstallerOptions, "installDir">) => Promise<boolean>;
|
|
31
31
|
readonly generateFilesRules: "";
|
|
32
32
|
readonly filterFilesRules: "";
|
|
33
33
|
readonly docsUrl: "https://workos.com/docs/user-management/authkit/tanstack-start";
|
|
@@ -38,7 +38,7 @@ export declare const INTEGRATION_CONFIG: {
|
|
|
38
38
|
readonly name: "React Router";
|
|
39
39
|
readonly filterPatterns: ["**/*.{tsx,ts,jsx,js}"];
|
|
40
40
|
readonly ignorePatterns: ["node_modules", "dist", "build", "public", "static", "assets"];
|
|
41
|
-
readonly detect: (options: Pick<
|
|
41
|
+
readonly detect: (options: Pick<InstallerOptions, "installDir">) => Promise<boolean>;
|
|
42
42
|
readonly generateFilesRules: "";
|
|
43
43
|
readonly filterFilesRules: "";
|
|
44
44
|
readonly docsUrl: "https://workos.com/docs/user-management/authkit/react-router";
|
|
@@ -49,7 +49,7 @@ export declare const INTEGRATION_CONFIG: {
|
|
|
49
49
|
readonly name: "Vanilla JavaScript";
|
|
50
50
|
readonly filterPatterns: ["**/*.{html,js,ts}"];
|
|
51
51
|
readonly ignorePatterns: ["node_modules", "dist", "build"];
|
|
52
|
-
readonly detect: (options: Pick<
|
|
52
|
+
readonly detect: (options: Pick<InstallerOptions, "installDir">) => Promise<true>;
|
|
53
53
|
readonly generateFilesRules: "";
|
|
54
54
|
readonly filterFilesRules: "";
|
|
55
55
|
readonly docsUrl: "https://workos.com/docs/user-management/authkit/javascript";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"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","sourcesContent":["import { getPackageDotJson } from '../utils/clack-utils.js';\nimport { hasPackageInstalled } from '../utils/package-json.js';\nimport type { InstallerOptions } from '../utils/types.js';\nimport { Integration } from './constants.js';\n\ntype IntegrationConfig = {\n name: string;\n filterPatterns: string[];\n ignorePatterns: string[];\n detect: (options: Pick<InstallerOptions, 'installDir'>) => Promise<boolean>;\n generateFilesRules: string;\n filterFilesRules: string;\n docsUrl: string;\n nextSteps: string;\n defaultChanges: string;\n};\n\nexport const INTEGRATION_CONFIG = {\n [Integration.nextjs]: {\n name: 'Next.js',\n filterPatterns: ['**/*.{tsx,ts,jsx,js,mjs,cjs}'],\n ignorePatterns: ['node_modules', 'dist', 'build', 'public', 'static', 'next-env.d.*'],\n detect: async (options) => {\n const packageJson = await getPackageDotJson(options);\n return hasPackageInstalled('next', packageJson);\n },\n generateFilesRules: '',\n filterFilesRules: '',\n docsUrl: 'https://workos.com/docs/user-management/authkit/nextjs',\n defaultChanges:\n '• Installed @workos/authkit-nextjs package\\n• Initialized WorkOS AuthKit with your credentials\\n• Created authentication routes and callbacks\\n• Added login/logout UI components',\n nextSteps:\n '• Customize the auth UI to match your app design\\n• Add protected routes using withAuth() middleware\\n• Access user session with getUser() in your components',\n },\n [Integration.react]: {\n name: 'React (SPA)',\n filterPatterns: ['**/*.{tsx,ts,jsx,js}'],\n ignorePatterns: ['node_modules', 'dist', 'build', 'public', 'static', 'assets'],\n detect: async (options) => {\n const packageJson = await getPackageDotJson(options);\n // Detect React without routing frameworks\n const hasReact = hasPackageInstalled('react', packageJson);\n const hasNext = hasPackageInstalled('next', packageJson);\n const hasReactRouter = hasPackageInstalled('react-router', packageJson);\n const hasTanstack = hasPackageInstalled('@tanstack/react-start', packageJson);\n return hasReact && !hasNext && !hasReactRouter && !hasTanstack;\n },\n generateFilesRules: '',\n filterFilesRules: '',\n docsUrl: 'https://workos.com/docs/user-management/authkit/react',\n defaultChanges:\n '• Installed @workos/authkit-react package\\n• Added AuthKitProvider to wrap your app\\n• Created login and callback components',\n nextSteps:\n '• Use useAuth() hook to access auth state in components\\n• Add protected routes with conditional rendering\\n• Customize auth UI to match your design',\n },\n [Integration.tanstackStart]: {\n name: 'TanStack Start',\n filterPatterns: ['**/*.{tsx,ts,jsx,js}'],\n ignorePatterns: ['node_modules', 'dist', 'build', '.vinxi', '.output'],\n detect: async (options) => {\n const packageJson = await getPackageDotJson(options);\n return hasPackageInstalled('@tanstack/react-start', packageJson);\n },\n generateFilesRules: '',\n filterFilesRules: '',\n docsUrl: 'https://workos.com/docs/user-management/authkit/tanstack-start',\n defaultChanges:\n '• Installed WorkOS AuthKit SDK package\\n• Added AuthKit middleware and routes\\n• Created authentication components',\n nextSteps:\n '• Use useAuth() hook to access auth state\\n• Add protected routes with authentication checks\\n• Customize auth UI to match your app',\n },\n [Integration.reactRouter]: {\n name: 'React Router',\n filterPatterns: ['**/*.{tsx,ts,jsx,js}'],\n ignorePatterns: ['node_modules', 'dist', 'build', 'public', 'static', 'assets'],\n detect: async (options) => {\n const packageJson = await getPackageDotJson(options);\n return hasPackageInstalled('react-router', packageJson);\n },\n generateFilesRules: '',\n filterFilesRules: '',\n docsUrl: 'https://workos.com/docs/user-management/authkit/react-router',\n defaultChanges:\n '• Installed @workos/authkit-react-router package\\n• Added AuthKitProvider with React Router integration\\n• Created auth routes and loaders',\n nextSteps:\n '• Use useAuth() hook in your components\\n• Add protected routes with loader functions\\n• Customize auth flow to match your needs',\n },\n [Integration.vanillaJs]: {\n name: 'Vanilla JavaScript',\n filterPatterns: ['**/*.{html,js,ts}'],\n ignorePatterns: ['node_modules', 'dist', 'build'],\n detect: async (options) => {\n // Fallback: if no framework detected, assume vanilla JS\n return true;\n },\n generateFilesRules: '',\n filterFilesRules: '',\n docsUrl: 'https://workos.com/docs/user-management/authkit/javascript',\n defaultChanges:\n '• Installed @workos/authkit-js package (or added CDN script)\\n• Created auth initialization and callback handling\\n• Added login button and auth state display',\n nextSteps:\n '• Integrate auth state into your existing UI\\n• Add logout functionality where needed\\n• Protect pages that require authentication',\n },\n} as const satisfies Record<Integration, IntegrationConfig>;\n\nexport const INTEGRATION_ORDER = [\n Integration.nextjs,\n Integration.tanstackStart,\n Integration.reactRouter,\n Integration.react,\n Integration.vanillaJs, // fallback\n] as const;\n"]}
|
|
@@ -21,7 +21,7 @@ export declare const WORKOS_DOCS_URL: string;
|
|
|
21
21
|
export declare const WORKOS_DASHBOARD_URL: string;
|
|
22
22
|
export declare const ISSUES_URL: string;
|
|
23
23
|
export declare const ANALYTICS_ENABLED: boolean;
|
|
24
|
-
export declare const
|
|
24
|
+
export declare const INSTALLER_INTERACTION_EVENT_NAME: string;
|
|
25
25
|
export declare const WORKOS_TELEMETRY_ENABLED: boolean;
|
|
26
26
|
export declare const OAUTH_PORT: number;
|
|
27
27
|
/**
|
|
@@ -36,7 +36,7 @@ export const WORKOS_DOCS_URL = settings.documentation.workosDocsUrl;
|
|
|
36
36
|
export const WORKOS_DASHBOARD_URL = settings.documentation.dashboardUrl;
|
|
37
37
|
export const ISSUES_URL = settings.documentation.issuesUrl;
|
|
38
38
|
export const ANALYTICS_ENABLED = settings.telemetry.enabled;
|
|
39
|
-
export const
|
|
39
|
+
export const INSTALLER_INTERACTION_EVENT_NAME = settings.telemetry.eventName;
|
|
40
40
|
export const WORKOS_TELEMETRY_ENABLED = process.env.WORKOS_TELEMETRY !== 'false';
|
|
41
41
|
export const OAUTH_PORT = settings.legacy.oauthPort;
|
|
42
42
|
/**
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/lib/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE1C,MAAM,CAAN,IAAY,WAMX;AAND,WAAY,WAAW;IACrB,gCAAiB,CAAA;IACjB,8BAAe,CAAA;IACf,+CAAgC,CAAA;IAChC,2CAA4B,CAAA;IAC5B,uCAAwB,CAAA;AAC1B,CAAC,EANW,WAAW,KAAX,WAAW,QAMtB;AAED,MAAM,UAAU,yBAAyB,CAAC,IAAY;IACpD,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,WAAW,CAAC,MAAM;YACrB,OAAO,SAAS,CAAC;QACnB,KAAK,WAAW,CAAC,KAAK;YACpB,OAAO,aAAa,CAAC;QACvB,KAAK,WAAW,CAAC,aAAa;YAC5B,OAAO,gBAAgB,CAAC;QAC1B,KAAK,WAAW,CAAC,WAAW;YAC1B,OAAO,cAAc,CAAC;QACxB,KAAK,WAAW,CAAC,SAAS;YACxB,OAAO,oBAAoB,CAAC;QAC9B;YACE,MAAM,IAAI,KAAK,CAAC,uBAAuB,IAAI,EAAE,CAAC,CAAC;IACnD,CAAC;AACH,CAAC;AAOD,MAAM,UAAU,qBAAqB;IACnC,OAAO,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,IAAY,EAAE,EAAE,CAAC,CAAC;QACrD,IAAI,EAAE,yBAAyB,CAAC,IAAI,CAAC;QACrC,KAAK,EAAE,IAAI;KACZ,CAAC,CAAC,CAAC;AACN,CAAC;AAOD,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;AAEnF,MAAM,QAAQ,GAAG,SAAS,EAAE,CAAC;AAE7B,MAAM,CAAC,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC;AAChD,MAAM,CAAC,MAAM,eAAe,GAAG,QAAQ,CAAC,aAAa,CAAC,aAAa,CAAC;AACpE,MAAM,CAAC,MAAM,oBAAoB,GAAG,QAAQ,CAAC,aAAa,CAAC,YAAY,CAAC;AACxE,MAAM,CAAC,MAAM,UAAU,GAAG,QAAQ,CAAC,aAAa,CAAC,SAAS,CAAC;AAC3D,MAAM,CAAC,MAAM,iBAAiB,GAAG,QAAQ,CAAC,SAAS,CAAC,OAAO,CAAC;AAC5D,MAAM,CAAC,MAAM,gCAAgC,GAAG,QAAQ,CAAC,SAAS,CAAC,SAAS,CAAC;AAC7E,MAAM,CAAC,MAAM,wBAAwB,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,KAAK,OAAO,CAAC;AACjF,MAAM,CAAC,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC;AAEpD;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAa;IACvC,oBAAoB;IACpB,YAAY;IACZ,aAAa;IACb,cAAc;IACd,aAAa;CACd,CAAC","sourcesContent":["import { getConfig } from './settings.js';\n\nexport enum Integration {\n nextjs = 'nextjs',\n react = 'react',\n tanstackStart = 'tanstack-start',\n reactRouter = 'react-router',\n vanillaJs = 'vanilla-js',\n}\n\nexport function getIntegrationDescription(type: string): string {\n switch (type) {\n case Integration.nextjs:\n return 'Next.js';\n case Integration.react:\n return 'React (SPA)';\n case Integration.tanstackStart:\n return 'TanStack Start';\n case Integration.reactRouter:\n return 'React Router';\n case Integration.vanillaJs:\n return 'Vanilla JavaScript';\n default:\n throw new Error(`Unknown integration ${type}`);\n }\n}\n\ntype IntegrationChoice = {\n name: string;\n value: string;\n};\n\nexport function getIntegrationChoices(): IntegrationChoice[] {\n return Object.keys(Integration).map((type: string) => ({\n name: getIntegrationDescription(type),\n value: type,\n }));\n}\n\nexport interface Args {\n debug: boolean;\n integration: Integration;\n}\n\nexport const IS_DEV = ['test', 'development'].includes(process.env.NODE_ENV ?? '');\n\nconst settings = getConfig();\n\nexport const DEBUG = settings.logging.debugMode;\nexport const WORKOS_DOCS_URL = settings.documentation.workosDocsUrl;\nexport const WORKOS_DASHBOARD_URL = settings.documentation.dashboardUrl;\nexport const ISSUES_URL = settings.documentation.issuesUrl;\nexport const ANALYTICS_ENABLED = settings.telemetry.enabled;\nexport const INSTALLER_INTERACTION_EVENT_NAME = settings.telemetry.eventName;\nexport const WORKOS_TELEMETRY_ENABLED = process.env.WORKOS_TELEMETRY !== 'false';\nexport const OAUTH_PORT = settings.legacy.oauthPort;\n\n/**\n * Common glob patterns to ignore when searching for files.\n * Used by both Next.js and React Router integrations.\n */\nexport const IGNORE_PATTERNS: string[] = [\n '**/node_modules/**',\n '**/dist/**',\n '**/build/**',\n '**/public/**',\n '**/.next/**',\n];\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credential-discovery.js","sourceRoot":"","sources":["../../src/lib/credential-discovery.ts"],"names":[],"mappings":"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","sourcesContent":["import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { logInfo } from '../utils/debug.js';\n\nexport interface DiscoveryResult {\n found: boolean;\n source?: 'env' | 'declined';\n clientId?: string;\n apiKey?: string;\n sourcePath?: string;\n}\n\nexport interface EnvFileInfo {\n exists: boolean;\n files: string[];\n}\n\nconst ENV_FILE_NAMES = ['.env.local', '.env.development.local', '.env.development', '.env'];\n\n// Only extract WorkOS variables - ignore everything else\nconst WORKOS_CLIENT_ID_PATTERN = /^WORKOS_CLIENT_ID=[\"']?([^\"'\\s#]+)[\"']?/m;\nconst WORKOS_API_KEY_PATTERN = /^WORKOS_API_KEY=[\"']?([^\"'\\s#]+)[\"']?/m;\n\n/**\n * Check if env files exist in the project directory (without reading contents).\n * Returns which files were found so the UI can prompt for consent.\n */\nexport async function checkForEnvFiles(projectDir: string): Promise<EnvFileInfo> {\n logInfo('[credential-discovery] Checking for env files in:', projectDir);\n const foundFiles: string[] = [];\n\n for (const fileName of ENV_FILE_NAMES) {\n const filePath = path.join(projectDir, fileName);\n try {\n await fs.access(filePath, fs.constants.R_OK);\n foundFiles.push(fileName);\n } catch {\n // continue\n }\n }\n\n logInfo('[credential-discovery] Found env files:', foundFiles);\n return {\n exists: foundFiles.length > 0,\n files: foundFiles,\n };\n}\n\n/**\n * Scan a single env file for WorkOS credentials.\n * Only extracts WORKOS_CLIENT_ID and WORKOS_API_KEY - ignores all other variables.\n */\nexport async function scanEnvFile(filePath: string): Promise<{ clientId?: string; apiKey?: string }> {\n const content = await fs.readFile(filePath, 'utf-8');\n\n // Filter out commented lines before matching\n const lines = content.split('\\n');\n const uncommentedContent = lines.filter((line) => !line.trim().startsWith('#')).join('\\n');\n\n const clientIdMatch = uncommentedContent.match(WORKOS_CLIENT_ID_PATTERN);\n const apiKeyMatch = uncommentedContent.match(WORKOS_API_KEY_PATTERN);\n\n return {\n clientId: clientIdMatch?.[1],\n apiKey: apiKeyMatch?.[1],\n };\n}\n\n/**\n * Validate client ID format.\n * WorkOS client IDs start with 'client_' prefix.\n */\nexport function isValidClientId(value: string): boolean {\n return value.startsWith('client_') && value.length > 10;\n}\n\n/**\n * Validate API key format.\n * WorkOS secret keys start with 'sk_' prefix.\n */\nexport function isValidApiKey(value: string): boolean {\n return value.startsWith('sk_') && value.length > 10;\n}\n\n/**\n * Discover WorkOS credentials from project env files.\n * Must be called AFTER user consent is given.\n *\n * Scans files in priority order: .env.local > .env.development.local > .env.development > .env\n * Returns first complete match (both clientId and apiKey preferred, but clientId-only is valid).\n */\nexport async function discoverCredentials(projectDir: string): Promise<DiscoveryResult> {\n logInfo('[credential-discovery] Scanning env files for WorkOS credentials');\n for (const fileName of ENV_FILE_NAMES) {\n const filePath = path.join(projectDir, fileName);\n\n try {\n const result = await scanEnvFile(filePath);\n\n const clientIdValid = result.clientId && isValidClientId(result.clientId);\n const apiKeyValid = result.apiKey && isValidApiKey(result.apiKey);\n\n if (result.clientId && !clientIdValid) {\n logInfo('[credential-discovery] Invalid clientId format in', fileName);\n }\n if (result.apiKey && !apiKeyValid) {\n logInfo('[credential-discovery] Invalid apiKey format in', fileName);\n }\n\n if (clientIdValid) {\n logInfo('[credential-discovery] Found valid credentials in', fileName);\n return {\n found: true,\n source: 'env',\n clientId: result.clientId,\n apiKey: apiKeyValid ? result.apiKey : undefined,\n sourcePath: fileName,\n };\n }\n } catch {\n // continue\n }\n }\n\n logInfo('[credential-discovery] No valid credentials found');\n return { found: false };\n}\n"]}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lightweight HTTP proxy that injects credentials from file into requests.
|
|
3
|
+
* Includes lazy token refresh - refreshes proactively when token is expiring soon.
|
|
4
|
+
*/
|
|
5
|
+
export interface RefreshConfig {
|
|
6
|
+
/** AuthKit domain for refresh endpoint */
|
|
7
|
+
authkitDomain: string;
|
|
8
|
+
/** OAuth client ID */
|
|
9
|
+
clientId: string;
|
|
10
|
+
/** Threshold in ms - refresh when token expires within this window (default: 60000 = 1 min) */
|
|
11
|
+
refreshThresholdMs?: number;
|
|
12
|
+
/** Callback when refresh succeeds */
|
|
13
|
+
onRefreshSuccess?: () => void;
|
|
14
|
+
/** Callback when refresh fails permanently (token expired, invalid_grant) */
|
|
15
|
+
onRefreshExpired?: () => void;
|
|
16
|
+
}
|
|
17
|
+
export interface CredentialProxyOptions {
|
|
18
|
+
/** Upstream URL to forward requests to */
|
|
19
|
+
upstreamUrl: string;
|
|
20
|
+
/** Optional: specific port to bind (default: random) */
|
|
21
|
+
port?: number;
|
|
22
|
+
/** Optional: refresh configuration for lazy token refresh */
|
|
23
|
+
refresh?: RefreshConfig;
|
|
24
|
+
}
|
|
25
|
+
export interface CredentialProxyHandle {
|
|
26
|
+
/** Port the proxy is listening on */
|
|
27
|
+
port: number;
|
|
28
|
+
/** Full URL for the proxy (e.g., http://localhost:54321) */
|
|
29
|
+
url: string;
|
|
30
|
+
/** Stop the proxy server */
|
|
31
|
+
stop: () => Promise<void>;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Start the credential injector proxy with optional lazy refresh.
|
|
35
|
+
*/
|
|
36
|
+
export declare function startCredentialProxy(options: CredentialProxyOptions): Promise<CredentialProxyHandle>;
|