@posthog/wizard 2.7.0 → 2.9.0
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 +11 -0
- package/dist/bin.js +289 -162
- package/dist/bin.js.map +1 -1
- package/dist/src/__tests__/cli.test.js +92 -59
- package/dist/src/__tests__/cli.test.js.map +1 -1
- package/dist/src/__tests__/wizard-abort.test.js +34 -13
- package/dist/src/__tests__/wizard-abort.test.js.map +1 -1
- package/dist/src/frameworks/android/android-wizard-agent.js +2 -2
- package/dist/src/frameworks/android/android-wizard-agent.js.map +1 -1
- package/dist/src/frameworks/angular/angular-wizard-agent.js +2 -2
- package/dist/src/frameworks/angular/angular-wizard-agent.js.map +1 -1
- package/dist/src/frameworks/astro/astro-wizard-agent.js +2 -2
- package/dist/src/frameworks/astro/astro-wizard-agent.js.map +1 -1
- package/dist/src/frameworks/django/django-wizard-agent.js +2 -2
- package/dist/src/frameworks/django/django-wizard-agent.js.map +1 -1
- package/dist/src/frameworks/fastapi/fastapi-wizard-agent.js +2 -2
- package/dist/src/frameworks/fastapi/fastapi-wizard-agent.js.map +1 -1
- package/dist/src/frameworks/flask/flask-wizard-agent.js +2 -2
- package/dist/src/frameworks/flask/flask-wizard-agent.js.map +1 -1
- package/dist/src/frameworks/javascript-node/javascript-node-wizard-agent.js +2 -2
- package/dist/src/frameworks/javascript-node/javascript-node-wizard-agent.js.map +1 -1
- package/dist/src/frameworks/javascript-web/javascript-web-wizard-agent.js +2 -2
- package/dist/src/frameworks/javascript-web/javascript-web-wizard-agent.js.map +1 -1
- package/dist/src/frameworks/laravel/laravel-wizard-agent.js +2 -2
- package/dist/src/frameworks/laravel/laravel-wizard-agent.js.map +1 -1
- package/dist/src/frameworks/nextjs/nextjs-wizard-agent.js +2 -2
- package/dist/src/frameworks/nextjs/nextjs-wizard-agent.js.map +1 -1
- package/dist/src/frameworks/nuxt/nuxt-wizard-agent.js +2 -2
- package/dist/src/frameworks/nuxt/nuxt-wizard-agent.js.map +1 -1
- package/dist/src/frameworks/python/python-wizard-agent.js +2 -2
- package/dist/src/frameworks/python/python-wizard-agent.js.map +1 -1
- package/dist/src/frameworks/rails/rails-wizard-agent.js +2 -2
- package/dist/src/frameworks/rails/rails-wizard-agent.js.map +1 -1
- package/dist/src/frameworks/react-native/react-native-wizard-agent.js +2 -2
- package/dist/src/frameworks/react-native/react-native-wizard-agent.js.map +1 -1
- package/dist/src/frameworks/react-router/react-router-wizard-agent.js +2 -2
- package/dist/src/frameworks/react-router/react-router-wizard-agent.js.map +1 -1
- package/dist/src/frameworks/ruby/ruby-wizard-agent.js +2 -2
- package/dist/src/frameworks/ruby/ruby-wizard-agent.js.map +1 -1
- package/dist/src/frameworks/svelte/svelte-wizard-agent.js +2 -2
- package/dist/src/frameworks/svelte/svelte-wizard-agent.js.map +1 -1
- package/dist/src/frameworks/swift/swift-wizard-agent.js +2 -2
- package/dist/src/frameworks/swift/swift-wizard-agent.js.map +1 -1
- package/dist/src/frameworks/tanstack-router/tanstack-router-wizard-agent.js +2 -2
- package/dist/src/frameworks/tanstack-router/tanstack-router-wizard-agent.js.map +1 -1
- package/dist/src/frameworks/tanstack-start/tanstack-start-wizard-agent.js +2 -2
- package/dist/src/frameworks/tanstack-start/tanstack-start-wizard-agent.js.map +1 -1
- package/dist/src/frameworks/vue/vue-wizard-agent.js +2 -2
- package/dist/src/frameworks/vue/vue-wizard-agent.js.map +1 -1
- package/dist/src/lib/__tests__/agent-interface.test.js +29 -1
- package/dist/src/lib/__tests__/agent-interface.test.js.map +1 -1
- package/dist/src/lib/agent/__tests__/agent-prompt.test.js +57 -0
- package/dist/src/lib/agent/__tests__/agent-prompt.test.js.map +1 -0
- package/dist/src/lib/{agent-interface.d.ts → agent/agent-interface.d.ts} +18 -6
- package/dist/src/lib/{agent-interface.js → agent/agent-interface.js} +63 -13
- package/dist/src/lib/agent/agent-interface.js.map +1 -0
- package/dist/src/lib/agent/agent-prompt.d.ts +23 -0
- package/dist/src/lib/agent/agent-prompt.js +47 -0
- package/dist/src/lib/agent/agent-prompt.js.map +1 -0
- package/dist/src/lib/agent/agent-runner.d.ts +78 -0
- package/dist/src/lib/agent/agent-runner.js +323 -0
- package/dist/src/lib/agent/agent-runner.js.map +1 -0
- package/dist/src/lib/agent/commandments.js.map +1 -0
- package/dist/src/lib/constants.d.ts +10 -1
- package/dist/src/lib/constants.js +13 -1
- package/dist/src/lib/constants.js.map +1 -1
- package/dist/src/lib/detection/__tests__/context.test.js +72 -0
- package/dist/src/lib/detection/__tests__/context.test.js.map +1 -0
- package/dist/src/lib/detection/__tests__/features.test.d.ts +1 -0
- package/dist/src/lib/detection/__tests__/features.test.js +75 -0
- package/dist/src/lib/detection/__tests__/features.test.js.map +1 -0
- package/dist/src/lib/detection/__tests__/package-manager.test.d.ts +1 -0
- package/dist/src/lib/{__tests__/package-manager-detection.test.js → detection/__tests__/package-manager.test.js} +25 -25
- package/dist/src/lib/detection/__tests__/package-manager.test.js.map +1 -0
- package/dist/src/lib/detection/context.d.ts +31 -0
- package/dist/src/lib/detection/context.js +92 -0
- package/dist/src/lib/detection/context.js.map +1 -0
- package/dist/src/lib/detection/features.d.ts +16 -0
- package/dist/src/lib/detection/features.js +56 -0
- package/dist/src/lib/detection/features.js.map +1 -0
- package/dist/src/lib/detection/framework.d.ts +14 -0
- package/dist/src/lib/detection/framework.js +35 -0
- package/dist/src/lib/detection/framework.js.map +1 -0
- package/dist/src/lib/detection/index.d.ts +3 -0
- package/dist/src/lib/detection/index.js +11 -0
- package/dist/src/lib/detection/index.js.map +1 -0
- package/dist/src/lib/{package-manager-detection.js → detection/package-manager.js} +3 -3
- package/dist/src/lib/detection/package-manager.js.map +1 -0
- package/dist/src/lib/framework-config.d.ts +1 -1
- package/dist/src/lib/framework-config.js.map +1 -1
- package/dist/src/lib/health-checks/endpoints.js +2 -1
- package/dist/src/lib/health-checks/endpoints.js.map +1 -1
- package/dist/src/lib/middleware/benchmark.js +1 -1
- package/dist/src/lib/middleware/benchmark.js.map +1 -1
- package/dist/src/lib/middleware/benchmarks/compaction-tracker.js +1 -1
- package/dist/src/lib/middleware/benchmarks/compaction-tracker.js.map +1 -1
- package/dist/src/lib/middleware/benchmarks/json-writer.js +1 -1
- package/dist/src/lib/middleware/benchmarks/json-writer.js.map +1 -1
- package/dist/src/lib/middleware/benchmarks/summary.js +1 -1
- package/dist/src/lib/middleware/benchmarks/summary.js.map +1 -1
- package/dist/src/lib/middleware/config.js +1 -1
- package/dist/src/lib/middleware/config.js.map +1 -1
- package/dist/src/lib/version.d.ts +1 -1
- package/dist/src/lib/version.js +1 -1
- package/dist/src/lib/version.js.map +1 -1
- package/dist/src/lib/wizard-session.d.ts +20 -7
- package/dist/src/lib/wizard-session.js +4 -0
- package/dist/src/lib/wizard-session.js.map +1 -1
- package/dist/src/lib/wizard-tools.d.ts +28 -1
- package/dist/src/lib/wizard-tools.js +24 -0
- package/dist/src/lib/wizard-tools.js.map +1 -1
- package/dist/src/lib/workflows/__tests__/agent-skill.test.d.ts +1 -0
- package/dist/src/lib/workflows/__tests__/agent-skill.test.js +66 -0
- package/dist/src/lib/workflows/__tests__/agent-skill.test.js.map +1 -0
- package/dist/src/lib/workflows/__tests__/revenue-analytics-detect.test.d.ts +1 -0
- package/dist/src/lib/workflows/__tests__/revenue-analytics-detect.test.js +101 -0
- package/dist/src/lib/workflows/__tests__/revenue-analytics-detect.test.js.map +1 -0
- package/dist/src/lib/workflows/__tests__/workflow-registry.test.d.ts +1 -0
- package/dist/src/lib/workflows/__tests__/workflow-registry.test.js +32 -0
- package/dist/src/lib/workflows/__tests__/workflow-registry.test.js.map +1 -0
- package/dist/src/lib/workflows/__tests__/workflow-step.test.d.ts +1 -0
- package/dist/src/lib/workflows/__tests__/workflow-step.test.js +54 -0
- package/dist/src/lib/workflows/__tests__/workflow-step.test.js.map +1 -0
- package/dist/src/lib/workflows/agent-skill/index.d.ts +44 -0
- package/dist/src/lib/workflows/agent-skill/index.js +47 -0
- package/dist/src/lib/workflows/agent-skill/index.js.map +1 -0
- package/dist/src/lib/workflows/agent-skill/steps.d.ts +8 -0
- package/dist/src/lib/workflows/agent-skill/steps.js +32 -0
- package/dist/src/lib/workflows/agent-skill/steps.js.map +1 -0
- package/dist/src/lib/workflows/posthog-integration/detect.d.ts +12 -0
- package/dist/src/lib/workflows/posthog-integration/detect.js +57 -0
- package/dist/src/lib/workflows/posthog-integration/detect.js.map +1 -0
- package/dist/src/lib/workflows/posthog-integration/index.d.ts +3 -0
- package/dist/src/lib/workflows/posthog-integration/index.js +152 -0
- package/dist/src/lib/workflows/posthog-integration/index.js.map +1 -0
- package/dist/src/lib/workflows/posthog-integration/steps.d.ts +9 -0
- package/dist/src/lib/workflows/posthog-integration/steps.js +100 -0
- package/dist/src/lib/workflows/posthog-integration/steps.js.map +1 -0
- package/dist/src/lib/workflows/revenue-analytics/detect.d.ts +40 -0
- package/dist/src/lib/workflows/revenue-analytics/detect.js +156 -0
- package/dist/src/lib/workflows/revenue-analytics/detect.js.map +1 -0
- package/dist/src/lib/workflows/revenue-analytics/index.d.ts +4 -0
- package/dist/src/lib/workflows/revenue-analytics/index.js +30 -0
- package/dist/src/lib/workflows/revenue-analytics/index.js.map +1 -0
- package/dist/src/lib/workflows/revenue-analytics/steps.d.ts +8 -0
- package/dist/src/lib/workflows/revenue-analytics/steps.js +48 -0
- package/dist/src/lib/workflows/revenue-analytics/steps.js.map +1 -0
- package/dist/src/lib/workflows/workflow-registry.d.ts +18 -0
- package/dist/src/lib/workflows/workflow-registry.js +32 -0
- package/dist/src/lib/workflows/workflow-registry.js.map +1 -0
- package/dist/src/lib/workflows/workflow-step.d.ts +126 -0
- package/dist/src/lib/workflows/workflow-step.js +28 -0
- package/dist/src/lib/workflows/workflow-step.js.map +1 -0
- package/dist/src/steps/add-mcp-server-to-clients/index.d.ts +2 -1
- package/dist/src/steps/add-mcp-server-to-clients/index.js.map +1 -1
- package/dist/src/ui/logging-ui.d.ts +6 -3
- package/dist/src/ui/logging-ui.js +7 -0
- package/dist/src/ui/logging-ui.js.map +1 -1
- package/dist/src/ui/tui/__tests__/flows.test.d.ts +1 -0
- package/dist/src/ui/tui/__tests__/flows.test.js +115 -0
- package/dist/src/ui/tui/__tests__/flows.test.js.map +1 -0
- package/dist/src/ui/tui/__tests__/router.test.d.ts +1 -0
- package/dist/src/ui/tui/__tests__/router.test.js +87 -0
- package/dist/src/ui/tui/__tests__/router.test.js.map +1 -0
- package/dist/src/ui/tui/__tests__/store.test.js +100 -10
- package/dist/src/ui/tui/__tests__/store.test.js.map +1 -1
- package/dist/src/ui/tui/flows.d.ts +17 -6
- package/dist/src/ui/tui/flows.js +28 -52
- package/dist/src/ui/tui/flows.js.map +1 -1
- package/dist/src/ui/tui/ink-ui.d.ts +6 -3
- package/dist/src/ui/tui/ink-ui.js +7 -0
- package/dist/src/ui/tui/ink-ui.js.map +1 -1
- package/dist/src/ui/tui/primitives/ProgressList.d.ts +3 -1
- package/dist/src/ui/tui/primitives/ProgressList.js +2 -2
- package/dist/src/ui/tui/primitives/ProgressList.js.map +1 -1
- package/dist/src/ui/tui/router.js +1 -1
- package/dist/src/ui/tui/router.js.map +1 -1
- package/dist/src/ui/tui/screen-registry.js +2 -0
- package/dist/src/ui/tui/screen-registry.js.map +1 -1
- package/dist/src/ui/tui/screens/ManagedSettingsScreen.js.map +1 -1
- package/dist/src/ui/tui/screens/OutroScreen.js +1 -1
- package/dist/src/ui/tui/screens/OutroScreen.js.map +1 -1
- package/dist/src/ui/tui/screens/RevenueIntroScreen.d.ts +16 -0
- package/dist/src/ui/tui/screens/RevenueIntroScreen.js +64 -0
- package/dist/src/ui/tui/screens/RevenueIntroScreen.js.map +1 -0
- package/dist/src/ui/tui/screens/RunScreen.js +1 -1
- package/dist/src/ui/tui/screens/RunScreen.js.map +1 -1
- package/dist/src/ui/tui/screens/SettingsOverrideScreen.js.map +1 -1
- package/dist/src/ui/tui/screens/health/HealthCheckScreen.js +2 -2
- package/dist/src/ui/tui/screens/health/HealthCheckScreen.js.map +1 -1
- package/dist/src/ui/tui/start-tui.js +2 -2
- package/dist/src/ui/tui/start-tui.js.map +1 -1
- package/dist/src/ui/tui/store.d.ts +46 -21
- package/dist/src/ui/tui/store.js +105 -47
- package/dist/src/ui/tui/store.js.map +1 -1
- package/dist/src/ui/wizard-ui.d.ts +13 -3
- package/dist/src/ui/wizard-ui.js.map +1 -1
- package/dist/src/utils/__tests__/provisioning.test.d.ts +1 -0
- package/dist/src/utils/__tests__/provisioning.test.js +192 -0
- package/dist/src/utils/__tests__/provisioning.test.js.map +1 -0
- package/dist/src/utils/file-utils.d.ts +8 -0
- package/dist/src/utils/file-utils.js +32 -0
- package/dist/src/utils/file-utils.js.map +1 -1
- package/dist/src/utils/provisioning.d.ts +25 -0
- package/dist/src/utils/provisioning.js +191 -0
- package/dist/src/utils/provisioning.js.map +1 -0
- package/dist/src/utils/setup-utils.d.ts +4 -1
- package/dist/src/utils/setup-utils.js +46 -2
- package/dist/src/utils/setup-utils.js.map +1 -1
- package/dist/src/utils/types.d.ts +4 -0
- package/dist/src/utils/types.js.map +1 -1
- package/dist/src/utils/wizard-abort.d.ts +3 -0
- package/dist/src/utils/wizard-abort.js +5 -3
- package/dist/src/utils/wizard-abort.js.map +1 -1
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/dist/src/__tests__/run.test.js +0 -95
- package/dist/src/__tests__/run.test.js.map +0 -1
- package/dist/src/lib/__tests__/package-manager-detection.test.js.map +0 -1
- package/dist/src/lib/agent-interface.js.map +0 -1
- package/dist/src/lib/agent-runner.d.ts +0 -9
- package/dist/src/lib/agent-runner.js +0 -383
- package/dist/src/lib/agent-runner.js.map +0 -1
- package/dist/src/lib/commandments.js.map +0 -1
- package/dist/src/lib/package-manager-detection.js.map +0 -1
- package/dist/src/run.d.ts +0 -22
- package/dist/src/run.js +0 -152
- package/dist/src/run.js.map +0 -1
- /package/dist/src/{__tests__/run.test.d.ts → lib/agent/__tests__/agent-prompt.test.d.ts} +0 -0
- /package/dist/src/lib/{commandments.d.ts → agent/commandments.d.ts} +0 -0
- /package/dist/src/lib/{commandments.js → agent/commandments.js} +0 -0
- /package/dist/src/lib/{__tests__/package-manager-detection.test.d.ts → detection/__tests__/context.test.d.ts} +0 -0
- /package/dist/src/lib/{package-manager-detection.d.ts → detection/package-manager.d.ts} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../../../src/ui/tui/store.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * WizardStore — Nanostore-backed reactive store for the TUI.\n * React components subscribe via useSyncExternalStore.\n *\n * Navigation is delegated to WizardRouter.\n * The active screen is derived from session state — not imperatively set.\n * Overlays (settings-override, port-conflict) are the only imperative navigation.\n *\n * All session mutations that affect screen resolution go through\n * explicit setters so emitChange() is always called.\n */\n\nimport { atom, map } from 'nanostores';\nimport { TaskStatus } from '../wizard-ui.js';\nimport {\n type WizardSession,\n type OutroData,\n type DiscoveredFeature,\n AdditionalFeature,\n McpOutcome,\n RunPhase,\n buildSession,\n} from '../../lib/wizard-session.js';\nimport type { SettingsConflict } from '../../lib/agent-interface.js';\nimport {\n WizardRouter,\n type ScreenName,\n Screen,\n Overlay,\n Flow,\n} from './router.js';\nimport { analytics, sessionProperties } from '../../utils/analytics.js';\nimport {\n evaluateWizardReadiness,\n WizardReadiness,\n} from '../../lib/health-checks/readiness.js';\n\nexport { TaskStatus, Screen, Overlay, Flow, RunPhase, McpOutcome };\nexport type { ScreenName, OutroData, WizardSession };\n\nexport interface TaskItem {\n label: string;\n activeForm?: string;\n status: TaskStatus;\n /** Legacy compat */\n done: boolean;\n}\n\nexport interface PlannedEvent {\n name: string;\n description: string;\n}\n\nexport class WizardStore {\n // ── Internal nanostore atoms ─────────────────────────────────────\n private $session = map<WizardSession>(buildSession({}));\n private $statusMessages = atom<string[]>([]);\n private $statusExpanded = atom(false);\n private $tasks = atom<TaskItem[]>([]);\n private $eventPlan = atom<PlannedEvent[]>([]);\n private $learnCardBlockIdx = atom(0);\n private $learnCardComplete = atom(false);\n private $version = atom(0);\n\n /** Last screen seen — used to detect screen transitions for analytics. */\n private _lastScreen: ScreenName | null = null;\n\n /** Hooks run when transitioning onto a screen. */\n private _enterScreenHooks = new Map<ScreenName, (() => void)[]>();\n\n version = '';\n\n /** Navigation router — resolves active screen from session state. */\n readonly router: WizardRouter;\n\n /**\n * Setup promise — IntroScreen resolves this when the user confirms.\n * bin.ts awaits it before calling runWizard.\n */\n private _resolveSetup!: () => void;\n readonly setupComplete: Promise<void> = new Promise((resolve) => {\n this._resolveSetup = resolve;\n });\n\n /** Blocks agent execution until the settings-override overlay is dismissed. */\n private _resolveSettingsOverride: (() => void) | null = null;\n private _backupAndFixSettings: (() => boolean) | null = null;\n\n /** Blocks OAuth flow until the port-conflict overlay is dismissed. */\n private _resolvePortConflict: (() => void) | null = null;\n\n /**\n * Resolves when the health-check screen is done — either auto-advanced\n * (healthy) or user-dismissed (outage). bin.ts awaits this before runWizard().\n */\n private _resolveHealthGate!: () => void;\n readonly healthGateComplete: Promise<void> = new Promise((resolve) => {\n this._resolveHealthGate = resolve;\n });\n\n constructor(flow: Flow = Flow.Wizard) {\n this.router = new WizardRouter(flow);\n\n // Fire health check immediately for Wizard flow so results arrive\n // while the user is still on IntroScreen.\n if (flow === Flow.Wizard) {\n this._initHealthCheck();\n } else {\n this._resolveHealthGate();\n }\n }\n\n /**\n * Kick off the health check. Stores the result and resolves the\n * health gate if non-blocking.\n */\n private _initHealthCheck(): void {\n evaluateWizardReadiness()\n .then((readiness) => {\n this.setReadinessResult(readiness);\n if (readiness.decision !== WizardReadiness.No) {\n this._resolveHealthGate();\n }\n })\n .catch(() => {\n this.setReadinessResult({\n decision: WizardReadiness.Yes,\n health: {} as never,\n reasons: [],\n });\n this._resolveHealthGate();\n });\n }\n\n // ── State accessors (read from atoms) ────────────────────────────\n\n get session(): WizardSession {\n return this.$session.get();\n }\n\n set session(value: WizardSession) {\n this.$session.set(value);\n }\n\n get statusMessages(): string[] {\n return this.$statusMessages.get();\n }\n\n get tasks(): TaskItem[] {\n return this.$tasks.get();\n }\n\n get eventPlan(): PlannedEvent[] {\n return this.$eventPlan.get();\n }\n\n get statusExpanded(): boolean {\n return this.$statusExpanded.get();\n }\n\n toggleStatusExpanded(): void {\n this.$statusExpanded.set(!this.$statusExpanded.get());\n this.emitChange();\n }\n\n setStatusExpanded(expanded: boolean): void {\n if (this.$statusExpanded.get() !== expanded) {\n this.$statusExpanded.set(expanded);\n this.emitChange();\n }\n }\n\n // ── Session setters ─────────────────────────────────────────────\n // Every setter that affects screen resolution calls emitChange().\n // Business logic calls these instead of mutating session directly.\n\n /** Unblocks bin.ts via the setupComplete promise. */\n completeSetup(): void {\n this.$session.setKey('setupConfirmed', true);\n analytics.wizardCapture('setup confirmed', sessionProperties(this.session));\n this._resolveSetup();\n this.emitChange();\n }\n\n setRunPhase(phase: RunPhase): void {\n this.$session.setKey('runPhase', phase);\n this.emitChange();\n }\n\n setCredentials(credentials: WizardSession['credentials']): void {\n this.$session.setKey('credentials', credentials);\n analytics.wizardCapture('auth complete', {\n project_id: credentials?.projectId,\n });\n this.emitChange();\n }\n\n setFrameworkConfig(\n integration: WizardSession['integration'],\n config: WizardSession['frameworkConfig'],\n ): void {\n this.$session.setKey('integration', integration);\n this.$session.setKey('frameworkConfig', config);\n this.$session.setKey('unsupportedVersion', null);\n this.emitChange();\n }\n\n setDetectionComplete(): void {\n this.$session.setKey('detectionComplete', true);\n this.emitChange();\n }\n\n setDetectedFramework(label: string): void {\n this.$session.setKey('detectedFrameworkLabel', label);\n this.emitChange();\n }\n\n setUnsupportedVersion(info: {\n current: string;\n minimum: string;\n docsUrl: string;\n }): void {\n this.$session.setKey('unsupportedVersion', info);\n this.emitChange();\n }\n\n setLoginUrl(url: string | null): void {\n this.$session.setKey('loginUrl', url);\n this.emitChange();\n }\n\n setReadinessResult(\n result:\n | import('../../lib/health-checks/readiness.js').WizardReadinessResult\n | null,\n ): void {\n this.$session.setKey('readinessResult', result);\n this.emitChange();\n }\n\n /** User dismissed the blocking outage screen. Unblocks bin.ts. */\n dismissOutage(): void {\n this.$session.setKey('outageDismissed', true);\n this._resolveHealthGate();\n this.emitChange();\n }\n\n /**\n * Push the settings-override overlay and return a promise that blocks\n * until the user dismisses it via backupAndFixSettingsOverride().\n */\n showSettingsOverride(\n conflicts: SettingsConflict[],\n backupAndFix: () => boolean,\n ): Promise<void> {\n const allKeys = conflicts.flatMap((c) => c.keys);\n this.$session.setKey('settingsOverrideKeys', allKeys);\n this.$session.setKey('settingsConflicts', conflicts);\n this._backupAndFixSettings = backupAndFix;\n\n const hasReadOnly = conflicts.some((c) => !c.writable);\n if (hasReadOnly) {\n this.pushOverlay(Overlay.ManagedSettings);\n } else {\n this.pushOverlay(Overlay.SettingsOverride);\n }\n\n return new Promise((resolve) => {\n this._resolveSettingsOverride = resolve;\n });\n }\n\n /**\n * Push the port-conflict overlay and return a promise that blocks\n * until the user kills the blocking process or exits.\n */\n showPortConflict(processInfo: {\n command: string;\n pid: string;\n user: string;\n }): Promise<void> {\n this.$session.setKey('portConflictProcess', processInfo);\n this.pushOverlay(Overlay.PortConflict);\n return new Promise((resolve) => {\n this._resolvePortConflict = resolve;\n });\n }\n\n /** Dismiss the port-conflict overlay after the user kills the process. */\n resolvePortConflict(): void {\n this.$session.setKey('portConflictProcess', null);\n this.popOverlay();\n this._resolvePortConflict?.();\n this._resolvePortConflict = null;\n }\n\n /**\n * Back up .claude/settings.json. Dismisses the overlay on success.\n */\n backupAndFixSettingsOverride(): boolean {\n const ok = this._backupAndFixSettings?.() ?? false;\n if (ok) {\n this.$session.setKey('settingsOverrideKeys', null);\n this.$session.setKey('settingsConflicts', null);\n this.popOverlay();\n this._resolveSettingsOverride?.();\n this._resolveSettingsOverride = null;\n this._backupAndFixSettings = null;\n }\n return ok;\n }\n\n /** Push the auth-error overlay (no dismiss — user must exit). */\n showAuthError(): void {\n this.pushOverlay(Overlay.AuthError);\n }\n\n addDiscoveredFeature(feature: DiscoveredFeature): void {\n if (!this.session.discoveredFeatures.includes(feature)) {\n this.session.discoveredFeatures.push(feature);\n this.emitChange();\n }\n }\n\n /**\n * Enable an additional feature: enqueue it for the stop hook\n * and set any feature-specific session flags.\n */\n enableFeature(feature: AdditionalFeature): void {\n if (!this.session.additionalFeatureQueue.includes(feature)) {\n this.session.additionalFeatureQueue.push(feature);\n }\n // Feature-specific flags\n if (feature === AdditionalFeature.LLM) {\n this.session.llmOptIn = true;\n }\n analytics.wizardCapture('feature enabled', { feature });\n this.emitChange();\n }\n\n setMcpComplete(\n outcome: McpOutcome = McpOutcome.Skipped,\n installedClients: string[] = [],\n ): void {\n this.$session.setKey('mcpComplete', true);\n this.$session.setKey('mcpOutcome', outcome);\n this.$session.setKey('mcpInstalledClients', installedClients);\n analytics.wizardCapture('mcp complete', {\n mcp_outcome: outcome,\n mcp_installed_clients: installedClients,\n ...sessionProperties(this.session),\n });\n this.emitChange();\n }\n\n setSkillsComplete(kept: boolean): void {\n this.$session.setKey('skillsComplete', true);\n analytics.wizardCapture('skills complete', {\n skills_kept: kept,\n ...sessionProperties(this.session),\n });\n this.emitChange();\n }\n\n setOutroDismissed(): void {\n this.$session.setKey('outroDismissed', true);\n this.emitChange();\n }\n\n setOutroData(data: OutroData): void {\n this.$session.setKey('outroData', data);\n this.emitChange();\n }\n\n setFrameworkContext(key: string, value: unknown): void {\n const ctx = { ...this.$session.get().frameworkContext, [key]: value };\n this.$session.setKey('frameworkContext', ctx);\n this.emitChange();\n }\n\n // ── Derived state ───────────────────────────────────────────────\n\n /**\n * The screen that should be rendered right now.\n * Derived from session state via the router.\n */\n get currentScreen(): ScreenName {\n return this.router.resolve(this.session);\n }\n\n /** Direction hint for screen transitions. */\n get lastNavDirection(): 'push' | 'pop' | null {\n return this.router.lastNavDirection;\n }\n\n // ── Change notification ─────────────────────────────────────────\n\n getVersion(): number {\n return this.$version.get();\n }\n\n /**\n * Notify React that state has changed.\n * The router re-resolves the active screen on next render.\n */\n emitChange(): void {\n this.router._setDirection('push');\n this.$version.set(this.$version.get() + 1);\n this._detectTransition();\n }\n\n // ── Overlay navigation ──────────────────────────────────────────\n\n pushOverlay(overlay: Overlay): void {\n this.router._setDirection('push');\n this.router.pushOverlay(overlay);\n this.$version.set(this.$version.get() + 1);\n this._detectTransition();\n }\n\n popOverlay(): void {\n this.router._setDirection('pop');\n this.router.popOverlay();\n this.$version.set(this.$version.get() + 1);\n this._detectTransition();\n }\n\n // ── Screen transition analytics ─────────────────────────────────\n\n /**\n * Register a callback to run when transitioning onto the given screen.\n * Fires after every transition that lands on this screen.\n */\n onEnterScreen(screen: ScreenName, fn: () => void): void {\n const list = this._enterScreenHooks.get(screen) ?? [];\n list.push(fn);\n this._enterScreenHooks.set(screen, list);\n }\n\n /**\n * Detect screen transitions, run enter-screen hooks, and fire analytics.\n * Called at the end of emitChange/pushOverlay/popOverlay.\n */\n private _detectTransition(): void {\n const next = this.router.resolve(this.session);\n const prev = this._lastScreen;\n if (prev !== null && next !== prev) {\n const hooks = this._enterScreenHooks.get(next);\n if (hooks) {\n for (const fn of hooks) fn();\n }\n analytics.wizardCapture(`screen ${next}`, {\n from_screen: prev,\n ...sessionProperties(this.session),\n });\n }\n this._lastScreen = next;\n }\n\n // ── Agent observation state ─────────────────────────────────────\n\n pushStatus(message: string): void {\n const msgs = this.$statusMessages.get();\n // Skip consecutive duplicate messages\n if (msgs.length > 0 && msgs[msgs.length - 1] === message) return;\n this.$statusMessages.set([...msgs, message]);\n this.emitChange();\n }\n\n setTasks(tasks: TaskItem[]): void {\n this.$tasks.set(tasks);\n this.emitChange();\n }\n\n updateTask(index: number, done: boolean): void {\n const tasks = this.$tasks.get();\n if (tasks[index]) {\n const updated = [...tasks];\n updated[index] = {\n ...updated[index],\n done,\n status: done ? TaskStatus.Completed : TaskStatus.Pending,\n };\n this.$tasks.set(updated);\n this.emitChange();\n }\n }\n\n setEventPlan(events: PlannedEvent[]): void {\n this.$eventPlan.set(events);\n this.emitChange();\n }\n\n get learnCardBlockIdx(): number {\n return this.$learnCardBlockIdx.get();\n }\n\n setLearnCardBlockIdx(idx: number): void {\n this.$learnCardBlockIdx.set(idx);\n }\n\n get learnCardComplete(): boolean {\n return this.$learnCardComplete.get();\n }\n\n setLearnCardComplete(): void {\n this.$learnCardComplete.set(true);\n this.emitChange();\n }\n\n syncTodos(\n todos: Array<{ content: string; status: string; activeForm?: string }>,\n ): void {\n const incoming = todos.map((t) => ({\n label: t.content,\n activeForm: t.activeForm,\n status: (t.status as TaskStatus) || TaskStatus.Pending,\n done: t.status === TaskStatus.Completed,\n }));\n\n const incomingLabels = new Set(incoming.map((t) => t.label));\n\n const retained = this.$tasks\n .get()\n .filter((t) => t.done && !incomingLabels.has(t.label));\n\n this.$tasks.set([...retained, ...incoming]);\n this.emitChange();\n }\n\n // ── React integration ───────────────────────────────────────────\n\n subscribe(callback: () => void): () => void {\n return this.$version.listen(() => callback());\n }\n\n getSnapshot(): number {\n return this.$version.get();\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../../../src/ui/tui/store.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * WizardStore — Nanostore-backed reactive store for the TUI.\n * React components subscribe via useSyncExternalStore.\n *\n * The active screen is derived from session state — WizardRouter walks\n * the flow and shows the first step whose `isComplete` is still false.\n *\n * Define a step `gate` if your screen needs to await user interactions.\n * bin.ts calls `await store.getGate(stepId)` to pause until the gate\n * predicate becomes true.\n *\n * All session mutations that affect screen resolution go through\n * explicit setters so emitChange() is always called.\n */\n\nimport { atom, map } from 'nanostores';\nimport { TaskStatus } from '../wizard-ui.js';\nimport {\n type WizardSession,\n type OutroData,\n type DiscoveredFeature,\n AdditionalFeature,\n McpOutcome,\n RunPhase,\n buildSession,\n} from '../../lib/wizard-session.js';\nimport type { SettingsConflict } from '../../lib/agent/agent-interface.js';\nimport type { WizardReadinessResult } from '../../lib/health-checks/readiness.js';\nimport {\n WizardRouter,\n type ScreenName,\n Screen,\n Overlay,\n Flow,\n} from './router.js';\nimport { analytics, sessionProperties } from '../../utils/analytics.js';\nimport type {\n StoreInitContext,\n WorkflowReadyContext,\n} from '../../lib/workflows/workflow-step.js';\nimport { WORKFLOW_STEPS } from './flows.js';\n\nexport { TaskStatus, Screen, Overlay, Flow, RunPhase, McpOutcome };\nexport type { ScreenName, OutroData, WizardSession };\n\nexport interface TaskItem {\n label: string;\n activeForm?: string;\n status: TaskStatus;\n /** Legacy compat */\n done: boolean;\n}\n\nexport interface PlannedEvent {\n name: string;\n description: string;\n}\n\ninterface GateEntry {\n predicate: (session: WizardSession) => boolean;\n promise: Promise<void>;\n resolve: () => void;\n resolved: boolean;\n}\n\nexport class WizardStore {\n // ── Internal nanostore atoms ─────────────────────────────────────\n private $session = map<WizardSession>(buildSession({}));\n private $statusMessages = atom<string[]>([]);\n private $statusExpanded = atom(false);\n private $tasks = atom<TaskItem[]>([]);\n private $eventPlan = atom<PlannedEvent[]>([]);\n private $learnCardBlockIdx = atom(0);\n private $learnCardComplete = atom(false);\n private $version = atom(0);\n\n /** Last screen seen — used to detect screen transitions for analytics. */\n private _lastScreen: ScreenName | null = null;\n\n /** Hooks run when transitioning onto a screen. */\n private _enterScreenHooks = new Map<ScreenName, (() => void)[]>();\n\n /** Gate promises derived from workflow step definitions. */\n private _gates = new Map<string, GateEntry>();\n\n version = '';\n\n /** Navigation router — resolves active screen from session state. */\n readonly router: WizardRouter;\n\n /** Blocks agent execution until the settings-override overlay is dismissed. */\n private _resolveSettingsOverride: (() => void) | null = null;\n private _backupAndFixSettings: (() => boolean) | null = null;\n\n /** Blocks OAuth flow until the port-conflict overlay is dismissed. */\n private _resolvePortConflict: (() => void) | null = null;\n\n constructor(flow: Flow = Flow.PostHogIntegration) {\n this.router = new WizardRouter(flow);\n this._initFromWorkflow(flow);\n }\n\n /**\n * Scan workflow steps for gate predicates and onInit callbacks.\n * Creates gate promises and fires init work.\n */\n private _initFromWorkflow(flow: Flow): void {\n const steps = WORKFLOW_STEPS[flow];\n if (!steps) return;\n\n // Create gate promises from steps that define them\n for (const step of steps) {\n if (step.gate) {\n let resolve!: () => void;\n const promise = new Promise<void>((r) => {\n resolve = r;\n });\n this._gates.set(step.id, {\n predicate: step.gate,\n promise,\n resolve,\n resolved: false,\n });\n }\n }\n\n // Run onInit callbacks with a minimal context interface.\n // Arrow functions capture `this` from _initFromWorkflow so we don't\n // need to alias it.\n const getSession = (): WizardSession => this.session;\n const ctx: StoreInitContext = {\n get session() {\n return getSession();\n },\n setReadinessResult: (r) => this.setReadinessResult(r),\n setFrameworkContext: (k, v) => this.setFrameworkContext(k, v),\n emitChange: () => this.emitChange(),\n };\n for (const step of steps) {\n step.onInit?.(ctx);\n }\n }\n\n /**\n * Run all `onReady` hooks declared by the current flow's steps, in\n * order. Must be called after `store.session = session` so hooks see\n * the real installDir. bin.ts calls this generically — it doesn't\n * need to know which workflow has which pre-flow work.\n */\n async runReadyHooks(): Promise<void> {\n const steps = WORKFLOW_STEPS[this.router.activeFlow];\n if (!steps) return;\n const ctx: WorkflowReadyContext = {\n session: this.session,\n setFrameworkContext: (k, v) => this.setFrameworkContext(k, v),\n setFrameworkConfig: (i, c) => this.setFrameworkConfig(i, c),\n setDetectedFramework: (l) => this.setDetectedFramework(l),\n setUnsupportedVersion: (info) => this.setUnsupportedVersion(info),\n addDiscoveredFeature: (f) => this.addDiscoveredFeature(f),\n setDetectionComplete: () => this.setDetectionComplete(),\n };\n for (const step of steps) {\n if (step.onReady) {\n await step.onReady(ctx);\n }\n }\n }\n\n // ── Gate API ────────────────────────────────────────────────────\n\n /**\n * Get a gate promise by step ID — the primary blocking checkpoint API\n * for bin.ts. `await store.getGate('...')` parks the caller until the\n * corresponding workflow step's gate predicate flips to true (if the\n * predicate stays false, the caller stays parked indefinitely — the\n * TUI keeps rendering so the user can resolve whatever is blocking).\n *\n * If the workflow doesn't define a step with this ID, or the step\n * has no `gate` predicate, this returns an already-resolved promise\n * so bin.ts flows straight through. This lets workflows opt in to\n * gates on a per-step basis without bin.ts needing to know which\n * gates exist in which flow.\n */\n getGate(stepId: string): Promise<void> {\n return this._gates.get(stepId)?.promise ?? Promise.resolve();\n }\n\n /**\n * Re-evaluate every gate predicate against the current session and\n * resolve any whose predicate now returns true. Called after every\n * emitChange(), so gates unblock as soon as the session mutation\n * that satisfies them lands. Gates only resolve once — a predicate\n * that goes true → false → true will NOT re-block a caller that\n * already awaited through.\n */\n private _checkGates(): void {\n for (const [, gate] of this._gates) {\n if (!gate.resolved && gate.predicate(this.session)) {\n gate.resolved = true;\n gate.resolve();\n }\n }\n }\n\n // ── State accessors (read from atoms) ────────────────────────────\n\n get session(): WizardSession {\n return this.$session.get();\n }\n\n set session(value: WizardSession) {\n this.$session.set(value);\n }\n\n get statusMessages(): string[] {\n return this.$statusMessages.get();\n }\n\n get tasks(): TaskItem[] {\n return this.$tasks.get();\n }\n\n get eventPlan(): PlannedEvent[] {\n return this.$eventPlan.get();\n }\n\n get statusExpanded(): boolean {\n return this.$statusExpanded.get();\n }\n\n toggleStatusExpanded(): void {\n this.$statusExpanded.set(!this.$statusExpanded.get());\n this.emitChange();\n }\n\n setStatusExpanded(expanded: boolean): void {\n if (this.$statusExpanded.get() !== expanded) {\n this.$statusExpanded.set(expanded);\n this.emitChange();\n }\n }\n\n // ── Session setters ─────────────────────────────────────────────\n // Every setter that affects screen resolution calls emitChange().\n // Business logic calls these instead of mutating session directly.\n\n /** Sets setupConfirmed. Gate resolves via _checkGates(). */\n completeSetup(): void {\n this.$session.setKey('setupConfirmed', true);\n analytics.wizardCapture('setup confirmed', sessionProperties(this.session));\n this.emitChange();\n }\n\n setRunPhase(phase: RunPhase): void {\n this.$session.setKey('runPhase', phase);\n this.emitChange();\n }\n\n setCredentials(credentials: WizardSession['credentials']): void {\n this.$session.setKey('credentials', credentials);\n analytics.wizardCapture('auth complete', {\n project_id: credentials?.projectId,\n });\n this.emitChange();\n }\n\n setFrameworkConfig(\n integration: WizardSession['integration'],\n config: WizardSession['frameworkConfig'],\n ): void {\n this.$session.setKey('integration', integration);\n this.$session.setKey('frameworkConfig', config);\n this.$session.setKey('unsupportedVersion', null);\n this.emitChange();\n }\n\n setDetectionComplete(): void {\n this.$session.setKey('detectionComplete', true);\n this.emitChange();\n }\n\n setDetectedFramework(label: string): void {\n this.$session.setKey('detectedFrameworkLabel', label);\n this.emitChange();\n }\n\n setUnsupportedVersion(info: {\n current: string;\n minimum: string;\n docsUrl: string;\n }): void {\n this.$session.setKey('unsupportedVersion', info);\n this.emitChange();\n }\n\n setLoginUrl(url: string | null): void {\n this.$session.setKey('loginUrl', url);\n this.emitChange();\n }\n\n setReadinessResult(result: WizardReadinessResult | null): void {\n this.$session.setKey('readinessResult', result);\n this.emitChange();\n }\n\n /** User dismissed the blocking outage screen. Gate resolves via _checkGates(). */\n dismissOutage(): void {\n this.$session.setKey('outageDismissed', true);\n this.emitChange();\n }\n\n /**\n * Push the settings-override overlay and return a promise that blocks\n * until the user dismisses it via backupAndFixSettingsOverride().\n */\n showSettingsOverride(\n conflicts: SettingsConflict[],\n backupAndFix: () => boolean,\n ): Promise<void> {\n const allKeys = conflicts.flatMap((c) => c.keys);\n this.$session.setKey('settingsOverrideKeys', allKeys);\n this.$session.setKey('settingsConflicts', conflicts);\n this._backupAndFixSettings = backupAndFix;\n\n const hasReadOnly = conflicts.some((c) => !c.writable);\n if (hasReadOnly) {\n this.pushOverlay(Overlay.ManagedSettings);\n } else {\n this.pushOverlay(Overlay.SettingsOverride);\n }\n\n return new Promise((resolve) => {\n this._resolveSettingsOverride = resolve;\n });\n }\n\n /**\n * Push the port-conflict overlay and return a promise that blocks\n * until the user kills the blocking process or exits.\n */\n showPortConflict(processInfo: {\n command: string;\n pid: string;\n user: string;\n }): Promise<void> {\n this.$session.setKey('portConflictProcess', processInfo);\n this.pushOverlay(Overlay.PortConflict);\n return new Promise((resolve) => {\n this._resolvePortConflict = resolve;\n });\n }\n\n /** Dismiss the port-conflict overlay after the user kills the process. */\n resolvePortConflict(): void {\n this.$session.setKey('portConflictProcess', null);\n this.popOverlay();\n this._resolvePortConflict?.();\n this._resolvePortConflict = null;\n }\n\n /**\n * Back up .claude/settings.json. Dismisses the overlay on success.\n */\n backupAndFixSettingsOverride(): boolean {\n const ok = this._backupAndFixSettings?.() ?? false;\n if (ok) {\n this.$session.setKey('settingsOverrideKeys', null);\n this.$session.setKey('settingsConflicts', null);\n this.popOverlay();\n this._resolveSettingsOverride?.();\n this._resolveSettingsOverride = null;\n this._backupAndFixSettings = null;\n }\n return ok;\n }\n\n /** Push the auth-error overlay (no dismiss — user must exit). */\n showAuthError(): void {\n this.pushOverlay(Overlay.AuthError);\n }\n\n addDiscoveredFeature(feature: DiscoveredFeature): void {\n if (!this.session.discoveredFeatures.includes(feature)) {\n this.session.discoveredFeatures.push(feature);\n this.emitChange();\n }\n }\n\n /**\n * Enable an additional feature: enqueue it for the stop hook\n * and set any feature-specific session flags.\n */\n enableFeature(feature: AdditionalFeature): void {\n if (!this.session.additionalFeatureQueue.includes(feature)) {\n this.session.additionalFeatureQueue.push(feature);\n }\n // Feature-specific flags\n if (feature === AdditionalFeature.LLM) {\n this.session.llmOptIn = true;\n }\n analytics.wizardCapture('feature enabled', { feature });\n this.emitChange();\n }\n\n setMcpComplete(\n outcome: McpOutcome = McpOutcome.Skipped,\n installedClients: string[] = [],\n ): void {\n this.$session.setKey('mcpComplete', true);\n this.$session.setKey('mcpOutcome', outcome);\n this.$session.setKey('mcpInstalledClients', installedClients);\n analytics.wizardCapture('mcp complete', {\n mcp_outcome: outcome,\n mcp_installed_clients: installedClients,\n ...sessionProperties(this.session),\n });\n this.emitChange();\n }\n\n setSkillsComplete(kept: boolean): void {\n this.$session.setKey('skillsComplete', true);\n analytics.wizardCapture('skills complete', {\n skills_kept: kept,\n ...sessionProperties(this.session),\n });\n this.emitChange();\n }\n\n setOutroDismissed(): void {\n this.$session.setKey('outroDismissed', true);\n this.emitChange();\n }\n\n setOutroData(data: OutroData): void {\n this.$session.setKey('outroData', data);\n this.emitChange();\n }\n\n setFrameworkContext(key: string, value: unknown): void {\n const ctx = { ...this.$session.get().frameworkContext, [key]: value };\n this.$session.setKey('frameworkContext', ctx);\n this.emitChange();\n }\n\n // ── Derived state ───────────────────────────────────────────────\n\n /**\n * The screen that should be rendered right now.\n * Derived from session state via the router.\n */\n get currentScreen(): ScreenName {\n return this.router.resolve(this.session);\n }\n\n /** Direction hint for screen transitions. */\n get lastNavDirection(): 'push' | 'pop' | null {\n return this.router.lastNavDirection;\n }\n\n // ── Change notification ─────────────────────────────────────────\n\n getVersion(): number {\n return this.$version.get();\n }\n\n /**\n * Notify React that state has changed.\n * The router re-resolves the active screen on next render.\n * Gate predicates are checked and resolved if ready.\n */\n emitChange(): void {\n this.router._setDirection('push');\n this.$version.set(this.$version.get() + 1);\n this._checkGates();\n this._detectTransition();\n }\n\n // ── Overlay navigation ──────────────────────────────────────────\n\n pushOverlay(overlay: Overlay): void {\n this.router._setDirection('push');\n this.router.pushOverlay(overlay);\n this.$version.set(this.$version.get() + 1);\n this._detectTransition();\n }\n\n popOverlay(): void {\n this.router._setDirection('pop');\n this.router.popOverlay();\n this.$version.set(this.$version.get() + 1);\n this._detectTransition();\n }\n\n // ── Screen transition analytics ─────────────────────────────────\n\n /**\n * Register a callback to run when transitioning onto the given screen.\n * Fires after every transition that lands on this screen.\n */\n onEnterScreen(screen: ScreenName, fn: () => void): void {\n const list = this._enterScreenHooks.get(screen) ?? [];\n list.push(fn);\n this._enterScreenHooks.set(screen, list);\n }\n\n /**\n * Detect screen transitions, run enter-screen hooks, and fire analytics.\n * Called at the end of emitChange/pushOverlay/popOverlay.\n */\n private _detectTransition(): void {\n const next = this.router.resolve(this.session);\n const prev = this._lastScreen;\n if (prev !== null && next !== prev) {\n const hooks = this._enterScreenHooks.get(next);\n if (hooks) {\n for (const fn of hooks) fn();\n }\n analytics.wizardCapture(`screen ${next}`, {\n from_screen: prev,\n ...sessionProperties(this.session),\n });\n }\n this._lastScreen = next;\n }\n\n // ── Agent observation state ─────────────────────────────────────\n\n pushStatus(message: string): void {\n const msgs = this.$statusMessages.get();\n // Skip consecutive duplicate messages\n if (msgs.length > 0 && msgs[msgs.length - 1] === message) return;\n this.$statusMessages.set([...msgs, message]);\n this.emitChange();\n }\n\n setTasks(tasks: TaskItem[]): void {\n this.$tasks.set(tasks);\n this.emitChange();\n }\n\n updateTask(index: number, done: boolean): void {\n const tasks = this.$tasks.get();\n if (tasks[index]) {\n const updated = [...tasks];\n updated[index] = {\n ...updated[index],\n done,\n status: done ? TaskStatus.Completed : TaskStatus.Pending,\n };\n this.$tasks.set(updated);\n this.emitChange();\n }\n }\n\n setEventPlan(events: PlannedEvent[]): void {\n this.$eventPlan.set(events);\n this.emitChange();\n }\n\n get learnCardBlockIdx(): number {\n return this.$learnCardBlockIdx.get();\n }\n\n setLearnCardBlockIdx(idx: number): void {\n this.$learnCardBlockIdx.set(idx);\n }\n\n get learnCardComplete(): boolean {\n return this.$learnCardComplete.get();\n }\n\n setLearnCardComplete(): void {\n this.$learnCardComplete.set(true);\n this.emitChange();\n }\n\n syncTodos(\n todos: Array<{ content: string; status: string; activeForm?: string }>,\n ): void {\n const incoming = todos.map((t) => ({\n label: t.content,\n activeForm: t.activeForm,\n status: (t.status as TaskStatus) || TaskStatus.Pending,\n done: t.status === TaskStatus.Completed,\n }));\n\n const incomingLabels = new Set(incoming.map((t) => t.label));\n\n const retained = this.$tasks\n .get()\n .filter((t) => t.done && !incomingLabels.has(t.label));\n\n this.$tasks.set([...retained, ...incoming]);\n this.emitChange();\n }\n\n // ── React integration ───────────────────────────────────────────\n\n subscribe(callback: () => void): () => void {\n return this.$version.listen(() => callback());\n }\n\n getSnapshot(): number {\n return this.$version.get();\n }\n}\n"]}
|
|
@@ -7,7 +7,9 @@
|
|
|
7
7
|
* No prompt methods — the TUI screens own all user input.
|
|
8
8
|
* Session-mutating methods trigger reactive screen resolution in the TUI.
|
|
9
9
|
*/
|
|
10
|
-
import type { SettingsConflict } from '../lib/agent-interface';
|
|
10
|
+
import type { SettingsConflict } from '../lib/agent/agent-interface';
|
|
11
|
+
import type { WizardReadinessResult } from '../lib/health-checks/readiness.js';
|
|
12
|
+
import type { OutroData } from '../lib/wizard-session';
|
|
11
13
|
export declare enum TaskStatus {
|
|
12
14
|
Pending = "pending",
|
|
13
15
|
InProgress = "in_progress",
|
|
@@ -20,7 +22,15 @@ export interface SpinnerHandle {
|
|
|
20
22
|
}
|
|
21
23
|
export interface WizardUI {
|
|
22
24
|
intro(message: string): void;
|
|
25
|
+
/** Success outro with a plain text message. */
|
|
23
26
|
outro(message: string): void;
|
|
27
|
+
/**
|
|
28
|
+
* Error outro. Sets structured outroData and transitions run phase so
|
|
29
|
+
* the router advances to the outro screen. Use for abort/failure paths
|
|
30
|
+
* that need a custom error render — do NOT build the outroData by
|
|
31
|
+
* mutating session directly (nanostore holds a shallow copy).
|
|
32
|
+
*/
|
|
33
|
+
outroError(data: OutroData): void;
|
|
24
34
|
cancel(message: string): void;
|
|
25
35
|
log: {
|
|
26
36
|
info(message: string): void;
|
|
@@ -42,9 +52,9 @@ export interface WizardUI {
|
|
|
42
52
|
projectId: number;
|
|
43
53
|
}): void;
|
|
44
54
|
/** Show blocking service outage (pushes outage overlay in TUI). Blocks until dismissed. */
|
|
45
|
-
showBlockingOutage(result:
|
|
55
|
+
showBlockingOutage(result: WizardReadinessResult): Promise<void>;
|
|
46
56
|
/** Store non-blocking readiness warnings (shown as Health tab in RunScreen). */
|
|
47
|
-
setReadinessWarnings(result:
|
|
57
|
+
setReadinessWarnings(result: WizardReadinessResult): void;
|
|
48
58
|
/** Warn that another process is blocking the OAuth port (pushes overlay in TUI). */
|
|
49
59
|
showPortConflict(processInfo: {
|
|
50
60
|
command: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wizard-ui.js","sourceRoot":"","sources":["../../../src/ui/wizard-ui.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;;
|
|
1
|
+
{"version":3,"file":"wizard-ui.js","sourceRoot":"","sources":["../../../src/ui/wizard-ui.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;;AAMH,IAAY,UAIX;AAJD,WAAY,UAAU;IACpB,iCAAmB,CAAA;IACnB,wCAA0B,CAAA;IAC1B,qCAAuB,CAAA;AACzB,CAAC,EAJW,UAAU,0BAAV,UAAU,QAIrB","sourcesContent":["/**\n * WizardUI — abstraction layer for all user-facing operations.\n *\n * Business logic calls `getUI()` instead of importing the store directly.\n * Implementations: InkUI (TUI), LoggingUI (CI).\n *\n * No prompt methods — the TUI screens own all user input.\n * Session-mutating methods trigger reactive screen resolution in the TUI.\n */\n\nimport type { SettingsConflict } from '../lib/agent/agent-interface';\nimport type { WizardReadinessResult } from '../lib/health-checks/readiness.js';\nimport type { OutroData } from '../lib/wizard-session';\n\nexport enum TaskStatus {\n Pending = 'pending',\n InProgress = 'in_progress',\n Completed = 'completed',\n}\n\nexport interface SpinnerHandle {\n start(message?: string): void;\n stop(message?: string): void;\n message(msg?: string): void;\n}\n\nexport interface WizardUI {\n // ── Lifecycle messages ────────────────────────────────────────────\n intro(message: string): void;\n /** Success outro with a plain text message. */\n outro(message: string): void;\n /**\n * Error outro. Sets structured outroData and transitions run phase so\n * the router advances to the outro screen. Use for abort/failure paths\n * that need a custom error render — do NOT build the outroData by\n * mutating session directly (nanostore holds a shallow copy).\n */\n outroError(data: OutroData): void;\n cancel(message: string): void;\n\n // ── Logging ───────────────────────────────────────────────────────\n log: {\n info(message: string): void;\n warn(message: string): void;\n error(message: string): void;\n success(message: string): void;\n step(message: string): void;\n };\n\n note(message: string): void;\n pushStatus(message: string): void;\n\n // ── Spinner ───────────────────────────────────────────────────────\n spinner(): SpinnerHandle;\n\n // ── Session state (triggers reactive screen resolution in TUI) ────\n /** Signal that the main work (agent run) has started. */\n startRun(): void;\n\n /** Store OAuth/API credentials. Resolves past AuthScreen in TUI. */\n setCredentials(credentials: {\n accessToken: string;\n projectApiKey: string;\n host: string;\n projectId: number;\n }): void;\n\n /** Show blocking service outage (pushes outage overlay in TUI). Blocks until dismissed. */\n showBlockingOutage(result: WizardReadinessResult): Promise<void>;\n\n /** Store non-blocking readiness warnings (shown as Health tab in RunScreen). */\n setReadinessWarnings(result: WizardReadinessResult): void;\n\n /** Warn that another process is blocking the OAuth port (pushes overlay in TUI). */\n showPortConflict(processInfo: {\n command: string;\n pid: string;\n user: string;\n }): Promise<void>;\n\n showSettingsOverride(\n conflicts: SettingsConflict[],\n backupAndFix: () => boolean,\n ): Promise<void>;\n\n /** Show auth error overlay when Anthropic API returns 401. */\n showAuthError(): void;\n\n // ── Display state ──────────────────────────────────────────────────\n /** Set the detected framework label (e.g., \"Django with Wagtail CMS\") */\n setDetectedFramework(label: string): void;\n\n /** Register a callback to run when the TUI transitions onto the given screen. */\n onEnterScreen(screen: string, fn: () => void): void;\n\n setLoginUrl(url: string | null): void;\n\n // ── Todo tracking from SDK TodoWrite events ───────────────────────\n syncTodos(\n todos: Array<{ content: string; status: string; activeForm?: string }>,\n ): void;\n\n // ── Event plan from .posthog-events.json ────────────────────\n setEventPlan(events: Array<{ name: string; description: string }>): void;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const axios_1 = __importDefault(require("axios"));
|
|
7
|
+
const provisioning_1 = require("../provisioning");
|
|
8
|
+
jest.mock('axios');
|
|
9
|
+
jest.mock('../debug', () => ({ logToFile: jest.fn() }));
|
|
10
|
+
jest.mock('../analytics', () => ({
|
|
11
|
+
analytics: { captureException: jest.fn() },
|
|
12
|
+
}));
|
|
13
|
+
const mockedAxios = axios_1.default;
|
|
14
|
+
describe('provisionNewAccount', () => {
|
|
15
|
+
beforeEach(() => {
|
|
16
|
+
jest.clearAllMocks();
|
|
17
|
+
});
|
|
18
|
+
it('completes the full PKCE flow and returns credentials', async () => {
|
|
19
|
+
// Step 1: account_requests
|
|
20
|
+
mockedAxios.post.mockResolvedValueOnce({
|
|
21
|
+
data: {
|
|
22
|
+
id: 'req_1',
|
|
23
|
+
type: 'oauth',
|
|
24
|
+
oauth: { code: 'test_code_123' },
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
// Step 2: oauth/token
|
|
28
|
+
mockedAxios.post.mockResolvedValueOnce({
|
|
29
|
+
data: {
|
|
30
|
+
token_type: 'bearer',
|
|
31
|
+
access_token: 'pha_test_access',
|
|
32
|
+
refresh_token: 'phr_test_refresh',
|
|
33
|
+
expires_in: 3600,
|
|
34
|
+
account: { id: 'org_123' },
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
// Step 3: resources
|
|
38
|
+
mockedAxios.post.mockResolvedValueOnce({
|
|
39
|
+
data: {
|
|
40
|
+
status: 'complete',
|
|
41
|
+
id: '42',
|
|
42
|
+
service_id: 'analytics',
|
|
43
|
+
complete: {
|
|
44
|
+
access_configuration: {
|
|
45
|
+
api_key: 'phc_test_key',
|
|
46
|
+
host: 'https://us.posthog.com',
|
|
47
|
+
personal_api_key: 'phx_test_pat',
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
const result = await (0, provisioning_1.provisionNewAccount)('user@example.com', 'Test User');
|
|
53
|
+
expect(result).toEqual({
|
|
54
|
+
accessToken: 'pha_test_access',
|
|
55
|
+
refreshToken: 'phr_test_refresh',
|
|
56
|
+
projectApiKey: 'phc_test_key',
|
|
57
|
+
host: 'https://us.posthog.com',
|
|
58
|
+
personalApiKey: 'phx_test_pat',
|
|
59
|
+
projectId: '42',
|
|
60
|
+
accountId: 'org_123',
|
|
61
|
+
});
|
|
62
|
+
expect(mockedAxios.post).toHaveBeenCalledTimes(3);
|
|
63
|
+
// Verify account_requests call
|
|
64
|
+
const accountCall = mockedAxios.post.mock.calls[0];
|
|
65
|
+
expect(accountCall[0]).toContain('/account_requests');
|
|
66
|
+
expect(accountCall[1]).toMatchObject({
|
|
67
|
+
email: 'user@example.com',
|
|
68
|
+
name: 'Test User',
|
|
69
|
+
code_challenge_method: 'S256',
|
|
70
|
+
configuration: { region: 'US' },
|
|
71
|
+
});
|
|
72
|
+
expect(accountCall[1].code_challenge).toBeTruthy();
|
|
73
|
+
expect(accountCall[1].client_id).toBeTruthy();
|
|
74
|
+
// Verify token exchange includes code_verifier
|
|
75
|
+
const tokenCall = mockedAxios.post.mock.calls[1];
|
|
76
|
+
expect(tokenCall[0]).toContain('/oauth/token');
|
|
77
|
+
expect(tokenCall[1]).toContain('code_verifier=');
|
|
78
|
+
expect(tokenCall[1]).toContain('grant_type=authorization_code');
|
|
79
|
+
// Verify resources call uses bearer token
|
|
80
|
+
const resourceCall = mockedAxios.post.mock.calls[2];
|
|
81
|
+
expect(resourceCall[0]).toContain('/resources');
|
|
82
|
+
expect(resourceCall[2]?.headers?.Authorization).toBe('Bearer pha_test_access');
|
|
83
|
+
});
|
|
84
|
+
it('throws when account already exists', async () => {
|
|
85
|
+
mockedAxios.post.mockResolvedValueOnce({
|
|
86
|
+
data: {
|
|
87
|
+
id: 'req_2',
|
|
88
|
+
type: 'requires_auth',
|
|
89
|
+
requires_auth: { type: 'redirect', redirect: { url: 'https://...' } },
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
await expect((0, provisioning_1.provisionNewAccount)('existing@example.com', '')).rejects.toThrow('already associated');
|
|
93
|
+
});
|
|
94
|
+
it('throws on API error response', async () => {
|
|
95
|
+
mockedAxios.post.mockResolvedValueOnce({
|
|
96
|
+
data: {
|
|
97
|
+
id: 'req_3',
|
|
98
|
+
type: 'error',
|
|
99
|
+
error: { code: 'forbidden', message: 'Account creation disabled' },
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
await expect((0, provisioning_1.provisionNewAccount)('blocked@example.com', '')).rejects.toThrow('Account creation disabled');
|
|
103
|
+
});
|
|
104
|
+
it('throws when resource provisioning fails', async () => {
|
|
105
|
+
mockedAxios.post
|
|
106
|
+
.mockResolvedValueOnce({
|
|
107
|
+
data: { id: 'req_4', type: 'oauth', oauth: { code: 'code_4' } },
|
|
108
|
+
})
|
|
109
|
+
.mockResolvedValueOnce({
|
|
110
|
+
data: {
|
|
111
|
+
token_type: 'bearer',
|
|
112
|
+
access_token: 'pha_4',
|
|
113
|
+
refresh_token: 'phr_4',
|
|
114
|
+
expires_in: 3600,
|
|
115
|
+
},
|
|
116
|
+
})
|
|
117
|
+
.mockResolvedValueOnce({
|
|
118
|
+
data: { status: 'error', id: '0', service_id: 'analytics' },
|
|
119
|
+
});
|
|
120
|
+
await expect((0, provisioning_1.provisionNewAccount)('fail@example.com', '')).rejects.toThrow('did not complete');
|
|
121
|
+
});
|
|
122
|
+
it('sends correct region parameter', async () => {
|
|
123
|
+
mockedAxios.post
|
|
124
|
+
.mockResolvedValueOnce({
|
|
125
|
+
data: { id: 'req_5', type: 'oauth', oauth: { code: 'code_5' } },
|
|
126
|
+
})
|
|
127
|
+
.mockResolvedValueOnce({
|
|
128
|
+
data: {
|
|
129
|
+
token_type: 'bearer',
|
|
130
|
+
access_token: 'pha_5',
|
|
131
|
+
refresh_token: 'phr_5',
|
|
132
|
+
expires_in: 3600,
|
|
133
|
+
},
|
|
134
|
+
})
|
|
135
|
+
.mockResolvedValueOnce({
|
|
136
|
+
data: {
|
|
137
|
+
status: 'complete',
|
|
138
|
+
id: '99',
|
|
139
|
+
service_id: 'analytics',
|
|
140
|
+
complete: {
|
|
141
|
+
access_configuration: {
|
|
142
|
+
api_key: 'phc_eu',
|
|
143
|
+
host: 'https://eu.posthog.com',
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
});
|
|
148
|
+
const result = await (0, provisioning_1.provisionNewAccount)('eu@example.com', '', 'EU');
|
|
149
|
+
const accountCall = mockedAxios.post.mock.calls[0];
|
|
150
|
+
expect(accountCall[1].configuration).toEqual({
|
|
151
|
+
region: 'EU',
|
|
152
|
+
});
|
|
153
|
+
expect(result.host).toBe('https://eu.posthog.com');
|
|
154
|
+
});
|
|
155
|
+
it('includes timeouts on all requests', async () => {
|
|
156
|
+
mockedAxios.post
|
|
157
|
+
.mockResolvedValueOnce({
|
|
158
|
+
data: { id: 'req_6', type: 'oauth', oauth: { code: 'code_6' } },
|
|
159
|
+
})
|
|
160
|
+
.mockResolvedValueOnce({
|
|
161
|
+
data: {
|
|
162
|
+
token_type: 'bearer',
|
|
163
|
+
access_token: 'pha_6',
|
|
164
|
+
refresh_token: 'phr_6',
|
|
165
|
+
expires_in: 3600,
|
|
166
|
+
},
|
|
167
|
+
})
|
|
168
|
+
.mockResolvedValueOnce({
|
|
169
|
+
data: {
|
|
170
|
+
status: 'complete',
|
|
171
|
+
id: '1',
|
|
172
|
+
service_id: 'analytics',
|
|
173
|
+
complete: {
|
|
174
|
+
access_configuration: {
|
|
175
|
+
api_key: 'phc_t',
|
|
176
|
+
host: 'https://us.posthog.com',
|
|
177
|
+
},
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
});
|
|
181
|
+
await (0, provisioning_1.provisionNewAccount)('timeout@example.com', '');
|
|
182
|
+
// account_requests and resources have config at index 2
|
|
183
|
+
const accountConfig = mockedAxios.post.mock.calls[0][2];
|
|
184
|
+
const resourceConfig = mockedAxios.post.mock.calls[2][2];
|
|
185
|
+
expect(accountConfig?.timeout).toBe(30_000);
|
|
186
|
+
expect(resourceConfig?.timeout).toBe(30_000);
|
|
187
|
+
// token exchange has config at index 2 (URL-encoded body is at index 1)
|
|
188
|
+
const tokenConfig = mockedAxios.post.mock.calls[1][2];
|
|
189
|
+
expect(tokenConfig?.timeout).toBe(30_000);
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
//# sourceMappingURL=provisioning.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provisioning.test.js","sourceRoot":"","sources":["../../../../src/utils/__tests__/provisioning.test.ts"],"names":[],"mappings":"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","sourcesContent":["import axios from 'axios';\nimport { provisionNewAccount } from '../provisioning';\n\njest.mock('axios');\njest.mock('../debug', () => ({ logToFile: jest.fn() }));\njest.mock('../analytics', () => ({\n analytics: { captureException: jest.fn() },\n}));\n\nconst mockedAxios = axios as jest.Mocked<typeof axios>;\n\ndescribe('provisionNewAccount', () => {\n beforeEach(() => {\n jest.clearAllMocks();\n });\n\n it('completes the full PKCE flow and returns credentials', async () => {\n // Step 1: account_requests\n mockedAxios.post.mockResolvedValueOnce({\n data: {\n id: 'req_1',\n type: 'oauth',\n oauth: { code: 'test_code_123' },\n },\n });\n\n // Step 2: oauth/token\n mockedAxios.post.mockResolvedValueOnce({\n data: {\n token_type: 'bearer',\n access_token: 'pha_test_access',\n refresh_token: 'phr_test_refresh',\n expires_in: 3600,\n account: { id: 'org_123' },\n },\n });\n\n // Step 3: resources\n mockedAxios.post.mockResolvedValueOnce({\n data: {\n status: 'complete',\n id: '42',\n service_id: 'analytics',\n complete: {\n access_configuration: {\n api_key: 'phc_test_key',\n host: 'https://us.posthog.com',\n personal_api_key: 'phx_test_pat',\n },\n },\n },\n });\n\n const result = await provisionNewAccount('user@example.com', 'Test User');\n\n expect(result).toEqual({\n accessToken: 'pha_test_access',\n refreshToken: 'phr_test_refresh',\n projectApiKey: 'phc_test_key',\n host: 'https://us.posthog.com',\n personalApiKey: 'phx_test_pat',\n projectId: '42',\n accountId: 'org_123',\n });\n\n expect(mockedAxios.post).toHaveBeenCalledTimes(3);\n\n // Verify account_requests call\n const accountCall = mockedAxios.post.mock.calls[0];\n expect(accountCall[0]).toContain('/account_requests');\n expect(accountCall[1]).toMatchObject({\n email: 'user@example.com',\n name: 'Test User',\n code_challenge_method: 'S256',\n configuration: { region: 'US' },\n });\n expect(\n (accountCall[1] as Record<string, unknown>).code_challenge,\n ).toBeTruthy();\n expect((accountCall[1] as Record<string, unknown>).client_id).toBeTruthy();\n\n // Verify token exchange includes code_verifier\n const tokenCall = mockedAxios.post.mock.calls[1];\n expect(tokenCall[0]).toContain('/oauth/token');\n expect(tokenCall[1]).toContain('code_verifier=');\n expect(tokenCall[1]).toContain('grant_type=authorization_code');\n\n // Verify resources call uses bearer token\n const resourceCall = mockedAxios.post.mock.calls[2];\n expect(resourceCall[0]).toContain('/resources');\n expect(resourceCall[2]?.headers?.Authorization).toBe(\n 'Bearer pha_test_access',\n );\n });\n\n it('throws when account already exists', async () => {\n mockedAxios.post.mockResolvedValueOnce({\n data: {\n id: 'req_2',\n type: 'requires_auth',\n requires_auth: { type: 'redirect', redirect: { url: 'https://...' } },\n },\n });\n\n await expect(\n provisionNewAccount('existing@example.com', ''),\n ).rejects.toThrow('already associated');\n });\n\n it('throws on API error response', async () => {\n mockedAxios.post.mockResolvedValueOnce({\n data: {\n id: 'req_3',\n type: 'error',\n error: { code: 'forbidden', message: 'Account creation disabled' },\n },\n });\n\n await expect(\n provisionNewAccount('blocked@example.com', ''),\n ).rejects.toThrow('Account creation disabled');\n });\n\n it('throws when resource provisioning fails', async () => {\n mockedAxios.post\n .mockResolvedValueOnce({\n data: { id: 'req_4', type: 'oauth', oauth: { code: 'code_4' } },\n })\n .mockResolvedValueOnce({\n data: {\n token_type: 'bearer',\n access_token: 'pha_4',\n refresh_token: 'phr_4',\n expires_in: 3600,\n },\n })\n .mockResolvedValueOnce({\n data: { status: 'error', id: '0', service_id: 'analytics' },\n });\n\n await expect(provisionNewAccount('fail@example.com', '')).rejects.toThrow(\n 'did not complete',\n );\n });\n\n it('sends correct region parameter', async () => {\n mockedAxios.post\n .mockResolvedValueOnce({\n data: { id: 'req_5', type: 'oauth', oauth: { code: 'code_5' } },\n })\n .mockResolvedValueOnce({\n data: {\n token_type: 'bearer',\n access_token: 'pha_5',\n refresh_token: 'phr_5',\n expires_in: 3600,\n },\n })\n .mockResolvedValueOnce({\n data: {\n status: 'complete',\n id: '99',\n service_id: 'analytics',\n complete: {\n access_configuration: {\n api_key: 'phc_eu',\n host: 'https://eu.posthog.com',\n },\n },\n },\n });\n\n const result = await provisionNewAccount('eu@example.com', '', 'EU');\n\n const accountCall = mockedAxios.post.mock.calls[0];\n expect((accountCall[1] as Record<string, unknown>).configuration).toEqual({\n region: 'EU',\n });\n expect(result.host).toBe('https://eu.posthog.com');\n });\n\n it('includes timeouts on all requests', async () => {\n mockedAxios.post\n .mockResolvedValueOnce({\n data: { id: 'req_6', type: 'oauth', oauth: { code: 'code_6' } },\n })\n .mockResolvedValueOnce({\n data: {\n token_type: 'bearer',\n access_token: 'pha_6',\n refresh_token: 'phr_6',\n expires_in: 3600,\n },\n })\n .mockResolvedValueOnce({\n data: {\n status: 'complete',\n id: '1',\n service_id: 'analytics',\n complete: {\n access_configuration: {\n api_key: 'phc_t',\n host: 'https://us.posthog.com',\n },\n },\n },\n });\n\n await provisionNewAccount('timeout@example.com', '');\n\n // account_requests and resources have config at index 2\n const accountConfig = mockedAxios.post.mock.calls[0][2] as\n | Record<string, unknown>\n | undefined;\n const resourceConfig = mockedAxios.post.mock.calls[2][2] as\n | Record<string, unknown>\n | undefined;\n expect(accountConfig?.timeout).toBe(30_000);\n expect(resourceConfig?.timeout).toBe(30_000);\n // token exchange has config at index 2 (URL-encoded body is at index 1)\n const tokenConfig = mockedAxios.post.mock.calls[1][2] as\n | Record<string, unknown>\n | undefined;\n expect(tokenConfig?.timeout).toBe(30_000);\n });\n});\n"]}
|
|
@@ -1,2 +1,10 @@
|
|
|
1
1
|
import type { WizardOptions } from './types';
|
|
2
2
|
export declare function getDotGitignore({ installDir, }: Pick<WizardOptions, 'installDir'>): string | undefined;
|
|
3
|
+
/**
|
|
4
|
+
* Directory names to skip when recursively scanning a project tree.
|
|
5
|
+
* Used by detection logic (e.g. finding all package.json files) to avoid
|
|
6
|
+
* dependency directories, build output, virtual environments, etc.
|
|
7
|
+
*
|
|
8
|
+
* For fast-glob `ignore` patterns, map this to `**\/<name>/**`.
|
|
9
|
+
*/
|
|
10
|
+
export declare const IGNORED_DIRS: Set<string>;
|
|
@@ -3,6 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.IGNORED_DIRS = void 0;
|
|
6
7
|
exports.getDotGitignore = getDotGitignore;
|
|
7
8
|
const path_1 = __importDefault(require("path"));
|
|
8
9
|
const fs_1 = __importDefault(require("fs"));
|
|
@@ -14,4 +15,35 @@ function getDotGitignore({ installDir, }) {
|
|
|
14
15
|
}
|
|
15
16
|
return undefined;
|
|
16
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* Directory names to skip when recursively scanning a project tree.
|
|
20
|
+
* Used by detection logic (e.g. finding all package.json files) to avoid
|
|
21
|
+
* dependency directories, build output, virtual environments, etc.
|
|
22
|
+
*
|
|
23
|
+
* For fast-glob `ignore` patterns, map this to `**\/<name>/**`.
|
|
24
|
+
*/
|
|
25
|
+
exports.IGNORED_DIRS = new Set([
|
|
26
|
+
'node_modules',
|
|
27
|
+
'.git',
|
|
28
|
+
'.next',
|
|
29
|
+
'.nuxt',
|
|
30
|
+
'.svelte-kit',
|
|
31
|
+
'.turbo',
|
|
32
|
+
'.cache',
|
|
33
|
+
'.parcel-cache',
|
|
34
|
+
'dist',
|
|
35
|
+
'build',
|
|
36
|
+
'out',
|
|
37
|
+
'coverage',
|
|
38
|
+
'.coverage',
|
|
39
|
+
'venv',
|
|
40
|
+
'.venv',
|
|
41
|
+
'__pycache__',
|
|
42
|
+
'.pytest_cache',
|
|
43
|
+
'vendor',
|
|
44
|
+
'target',
|
|
45
|
+
'.gradle',
|
|
46
|
+
'.idea',
|
|
47
|
+
'.vscode',
|
|
48
|
+
]);
|
|
17
49
|
//# sourceMappingURL=file-utils.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-utils.js","sourceRoot":"","sources":["../../../src/utils/file-utils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"file-utils.js","sourceRoot":"","sources":["../../../src/utils/file-utils.ts"],"names":[],"mappings":";;;;;;AAIA,0CAWC;AAfD,gDAAwB;AACxB,4CAAoB;AAGpB,SAAgB,eAAe,CAAC,EAC9B,UAAU,GACwB;IAClC,MAAM,aAAa,GAAG,cAAI,CAAC,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;IAC1D,MAAM,eAAe,GAAG,YAAE,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;IAErD,IAAI,eAAe,EAAE,CAAC;QACpB,OAAO,aAAa,CAAC;IACvB,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;;GAMG;AACU,QAAA,YAAY,GAAG,IAAI,GAAG,CAAS;IAC1C,cAAc;IACd,MAAM;IACN,OAAO;IACP,OAAO;IACP,aAAa;IACb,QAAQ;IACR,QAAQ;IACR,eAAe;IACf,MAAM;IACN,OAAO;IACP,KAAK;IACL,UAAU;IACV,WAAW;IACX,MAAM;IACN,OAAO;IACP,aAAa;IACb,eAAe;IACf,QAAQ;IACR,QAAQ;IACR,SAAS;IACT,OAAO;IACP,SAAS;CACV,CAAC,CAAC","sourcesContent":["import path from 'path';\nimport fs from 'fs';\nimport type { WizardOptions } from './types';\n\nexport function getDotGitignore({\n installDir,\n}: Pick<WizardOptions, 'installDir'>) {\n const gitignorePath = path.join(installDir, '.gitignore');\n const gitignoreExists = fs.existsSync(gitignorePath);\n\n if (gitignoreExists) {\n return gitignorePath;\n }\n\n return undefined;\n}\n\n/**\n * Directory names to skip when recursively scanning a project tree.\n * Used by detection logic (e.g. finding all package.json files) to avoid\n * dependency directories, build output, virtual environments, etc.\n *\n * For fast-glob `ignore` patterns, map this to `**\\/<name>/**`.\n */\nexport const IGNORED_DIRS = new Set<string>([\n 'node_modules',\n '.git',\n '.next',\n '.nuxt',\n '.svelte-kit',\n '.turbo',\n '.cache',\n '.parcel-cache',\n 'dist',\n 'build',\n 'out',\n 'coverage',\n '.coverage',\n 'venv',\n '.venv',\n '__pycache__',\n '.pytest_cache',\n 'vendor',\n 'target',\n '.gradle',\n '.idea',\n '.vscode',\n]);\n"]}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provisioning API client for creating new PostHog accounts.
|
|
3
|
+
*
|
|
4
|
+
* Uses the agentic provisioning API with PKCE auth:
|
|
5
|
+
* 1. POST /account_requests - create account, get auth code
|
|
6
|
+
* 2. POST /oauth/token - exchange code for tokens (with PKCE)
|
|
7
|
+
* 3. POST /resources - provision project, get API key
|
|
8
|
+
*/
|
|
9
|
+
export interface ProvisioningResult {
|
|
10
|
+
accessToken: string;
|
|
11
|
+
refreshToken: string;
|
|
12
|
+
projectApiKey: string;
|
|
13
|
+
host: string;
|
|
14
|
+
personalApiKey?: string;
|
|
15
|
+
projectId: string;
|
|
16
|
+
accountId: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Create a new PostHog account and provision a project via the provisioning API.
|
|
20
|
+
*
|
|
21
|
+
* This is the "no browser" signup path: the wizard collects the email,
|
|
22
|
+
* calls the provisioning API to create the account, and gets back
|
|
23
|
+
* credentials without opening a browser.
|
|
24
|
+
*/
|
|
25
|
+
export declare function provisionNewAccount(email: string, name: string, region?: 'US' | 'EU'): Promise<ProvisioningResult>;
|