@posthog/wizard 2.6.2 → 2.8.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.
Files changed (59) hide show
  1. package/dist/bin.js +5 -0
  2. package/dist/bin.js.map +1 -1
  3. package/dist/src/lib/__tests__/cloudflare-detection.test.d.ts +1 -0
  4. package/dist/src/lib/__tests__/cloudflare-detection.test.js +119 -0
  5. package/dist/src/lib/__tests__/cloudflare-detection.test.js.map +1 -0
  6. package/dist/src/lib/agent-runner.js +17 -3
  7. package/dist/src/lib/agent-runner.js.map +1 -1
  8. package/dist/src/lib/cloudflare-detection.d.ts +14 -0
  9. package/dist/src/lib/cloudflare-detection.js +74 -0
  10. package/dist/src/lib/cloudflare-detection.js.map +1 -0
  11. package/dist/src/lib/constants.d.ts +4 -1
  12. package/dist/src/lib/constants.js +4 -1
  13. package/dist/src/lib/constants.js.map +1 -1
  14. package/dist/src/lib/middleware/config.js +4 -4
  15. package/dist/src/lib/middleware/config.js.map +1 -1
  16. package/dist/src/lib/version.d.ts +1 -1
  17. package/dist/src/lib/version.js +1 -1
  18. package/dist/src/lib/version.js.map +1 -1
  19. package/dist/src/lib/wizard-session.d.ts +6 -0
  20. package/dist/src/lib/wizard-session.js +4 -0
  21. package/dist/src/lib/wizard-session.js.map +1 -1
  22. package/dist/src/run.d.ts +1 -0
  23. package/dist/src/run.js +6 -0
  24. package/dist/src/run.js.map +1 -1
  25. package/dist/src/steps/add-mcp-server-to-clients/defaults.js +5 -5
  26. package/dist/src/steps/add-mcp-server-to-clients/defaults.js.map +1 -1
  27. package/dist/src/ui/tui/__tests__/store.test.js +26 -2
  28. package/dist/src/ui/tui/__tests__/store.test.js.map +1 -1
  29. package/dist/src/ui/tui/flows.d.ts +1 -0
  30. package/dist/src/ui/tui/flows.js +6 -1
  31. package/dist/src/ui/tui/flows.js.map +1 -1
  32. package/dist/src/ui/tui/screen-registry.js +2 -0
  33. package/dist/src/ui/tui/screen-registry.js.map +1 -1
  34. package/dist/src/ui/tui/screens/OutroScreen.js +2 -2
  35. package/dist/src/ui/tui/screens/OutroScreen.js.map +1 -1
  36. package/dist/src/ui/tui/screens/SkillsScreen.d.ts +14 -0
  37. package/dist/src/ui/tui/screens/SkillsScreen.js +71 -0
  38. package/dist/src/ui/tui/screens/SkillsScreen.js.map +1 -0
  39. package/dist/src/ui/tui/store.d.ts +2 -0
  40. package/dist/src/ui/tui/store.js +12 -0
  41. package/dist/src/ui/tui/store.js.map +1 -1
  42. package/dist/src/utils/__tests__/provisioning.test.d.ts +1 -0
  43. package/dist/src/utils/__tests__/provisioning.test.js +192 -0
  44. package/dist/src/utils/__tests__/provisioning.test.js.map +1 -0
  45. package/dist/src/utils/debug.d.ts +6 -0
  46. package/dist/src/utils/debug.js +16 -0
  47. package/dist/src/utils/debug.js.map +1 -1
  48. package/dist/src/utils/oauth.js +1 -1
  49. package/dist/src/utils/oauth.js.map +1 -1
  50. package/dist/src/utils/provisioning.d.ts +25 -0
  51. package/dist/src/utils/provisioning.js +191 -0
  52. package/dist/src/utils/provisioning.js.map +1 -0
  53. package/dist/src/utils/setup-utils.d.ts +4 -1
  54. package/dist/src/utils/setup-utils.js +46 -2
  55. package/dist/src/utils/setup-utils.js.map +1 -1
  56. package/dist/src/utils/types.d.ts +4 -0
  57. package/dist/src/utils/types.js.map +1 -1
  58. package/npm-shrinkwrap.json +2 -2
  59. package/package.json +8 -4
@@ -257,6 +257,18 @@ export class WizardStore {
257
257
  });
258
258
  this.emitChange();
259
259
  }
260
+ setSkillsComplete(kept) {
261
+ this.$session.setKey('skillsComplete', true);
262
+ analytics.wizardCapture('skills complete', {
263
+ skills_kept: kept,
264
+ ...sessionProperties(this.session),
265
+ });
266
+ this.emitChange();
267
+ }
268
+ setOutroDismissed() {
269
+ this.$session.setKey('outroDismissed', true);
270
+ this.emitChange();
271
+ }
260
272
  setOutroData(data) {
261
273
  this.$session.setKey('outroData', data);
262
274
  this.emitChange();
@@ -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 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 * 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"]}
@@ -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"]}
@@ -7,6 +7,12 @@ export declare function configureLogFile(opts: {
7
7
  path?: string;
8
8
  enabled?: boolean;
9
9
  }): void;
10
+ /**
11
+ * Configure log path from environment variables.
12
+ *
13
+ * Uses POSTHOG_WIZARD_LOG_DIR when set, joined with posthog-wizard.log.
14
+ */
15
+ export declare function configureLogFileFromEnvironment(): void;
10
16
  /**
11
17
  * Initialize the log file with a run header.
12
18
  * Call this at the start of each wizard run.
@@ -1,12 +1,17 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.getLogFilePath = getLogFilePath;
4
7
  exports.configureLogFile = configureLogFile;
8
+ exports.configureLogFileFromEnvironment = configureLogFileFromEnvironment;
5
9
  exports.initLogFile = initLogFile;
6
10
  exports.logToFile = logToFile;
7
11
  exports.debug = debug;
8
12
  exports.enableDebugLogs = enableDebugLogs;
9
13
  const fs_1 = require("fs");
14
+ const path_1 = __importDefault(require("path"));
10
15
  const logging_1 = require("./logging");
11
16
  const ui_1 = require("../ui");
12
17
  let debugEnabled = false;
@@ -25,6 +30,17 @@ function configureLogFile(opts) {
25
30
  if (opts.enabled !== undefined)
26
31
  logEnabled = opts.enabled;
27
32
  }
33
+ /**
34
+ * Configure log path from environment variables.
35
+ *
36
+ * Uses POSTHOG_WIZARD_LOG_DIR when set, joined with posthog-wizard.log.
37
+ */
38
+ function configureLogFileFromEnvironment() {
39
+ const envLogDir = process.env.POSTHOG_WIZARD_LOG_DIR;
40
+ if (envLogDir) {
41
+ configureLogFile({ path: path_1.default.join(envLogDir, 'posthog-wizard.log') });
42
+ }
43
+ }
28
44
  /**
29
45
  * Initialize the log file with a run header.
30
46
  * Call this at the start of each wizard run.
@@ -1 +1 @@
1
- {"version":3,"file":"debug.js","sourceRoot":"","sources":["../../../src/utils/debug.ts"],"names":[],"mappings":";;AAQA,wCAEC;AAMD,4CAMC;AAOD,kCAUC;AAOD,8BASC;AAED,sBAQC;AAED,0CAEC;AArED,2BAAoC;AACpC,uCAA2C;AAC3C,8BAA8B;AAE9B,IAAI,YAAY,GAAG,KAAK,CAAC;AACzB,IAAI,WAAW,GAAG,yBAAyB,CAAC;AAC5C,IAAI,UAAU,GAAG,IAAI,CAAC;AAEtB,SAAgB,cAAc;IAC5B,OAAO,WAAW,CAAC;AACrB,CAAC;AAED;;;GAGG;AACH,SAAgB,gBAAgB,CAAC,IAGhC;IACC,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS;QAAE,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC;IACrD,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS;QAAE,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC;AAC5D,CAAC;AAED;;;;GAIG;AACH,SAAgB,WAAW;IACzB,IAAI,CAAC,UAAU;QAAE,OAAO;IACxB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,KAAK,GAAG,CAAC,MAAM,CAC5B,EAAE,CACH,yBAAyB,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,KAAK,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC;QAC1E,IAAA,mBAAc,EAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IACtC,CAAC;IAAC,MAAM,CAAC;QACP,4CAA4C;IAC9C,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,SAAgB,SAAS,CAAC,GAAG,IAAe;IAC1C,IAAI,CAAC,UAAU;QAAE,OAAO;IACxB,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC3C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAA,wBAAc,EAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACzD,IAAA,mBAAc,EAAC,WAAW,EAAE,IAAI,SAAS,KAAK,GAAG,IAAI,CAAC,CAAC;IACzD,CAAC;IAAC,MAAM,CAAC;QACP,oEAAoE;IACtE,CAAC;AACH,CAAC;AAED,SAAgB,KAAK,CAAC,GAAG,IAAe;IACtC,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO;IACT,CAAC;IAED,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAA,wBAAc,EAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAEzD,IAAA,UAAK,GAAE,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACxB,CAAC;AAED,SAAgB,eAAe;IAC7B,YAAY,GAAG,IAAI,CAAC;AACtB,CAAC","sourcesContent":["import { appendFileSync } from 'fs';\nimport { prepareMessage } from './logging';\nimport { getUI } from '../ui';\n\nlet debugEnabled = false;\nlet logFilePath = '/tmp/posthog-wizard.log';\nlet logEnabled = true;\n\nexport function getLogFilePath(): string {\n return logFilePath;\n}\n\n/**\n * Configure the log file path and enable/disable state.\n * Call before initLogFile() to override defaults.\n */\nexport function configureLogFile(opts: {\n path?: string;\n enabled?: boolean;\n}): void {\n if (opts.path !== undefined) logFilePath = opts.path;\n if (opts.enabled !== undefined) logEnabled = opts.enabled;\n}\n\n/**\n * Initialize the log file with a run header.\n * Call this at the start of each wizard run.\n * Fails silently to avoid crashing the wizard.\n */\nexport function initLogFile() {\n if (!logEnabled) return;\n try {\n const header = `\\n${'='.repeat(\n 60,\n )}\\nPostHog Wizard Run: ${new Date().toISOString()}\\n${'='.repeat(60)}\\n`;\n appendFileSync(logFilePath, header);\n } catch {\n // Silently ignore - logging is non-critical\n }\n}\n\n/**\n * Log a message to the log file.\n * Always writes regardless of debug flag (when logging is enabled).\n * Fails silently to avoid masking errors in catch blocks.\n */\nexport function logToFile(...args: unknown[]) {\n if (!logEnabled) return;\n try {\n const timestamp = new Date().toISOString();\n const msg = args.map((a) => prepareMessage(a)).join(' ');\n appendFileSync(logFilePath, `[${timestamp}] ${msg}\\n`);\n } catch {\n // Silently ignore logging failures to avoid masking original errors\n }\n}\n\nexport function debug(...args: unknown[]) {\n if (!debugEnabled) {\n return;\n }\n\n const msg = args.map((a) => prepareMessage(a)).join(' ');\n\n getUI().log.info(msg);\n}\n\nexport function enableDebugLogs() {\n debugEnabled = true;\n}\n"]}
1
+ {"version":3,"file":"debug.js","sourceRoot":"","sources":["../../../src/utils/debug.ts"],"names":[],"mappings":";;;;;AASA,wCAEC;AAMD,4CAMC;AAOD,0EAKC;AAOD,kCAUC;AAOD,8BASC;AAED,sBAQC;AAED,0CAEC;AAlFD,2BAAoC;AACpC,gDAAwB;AACxB,uCAA2C;AAC3C,8BAA8B;AAE9B,IAAI,YAAY,GAAG,KAAK,CAAC;AACzB,IAAI,WAAW,GAAG,yBAAyB,CAAC;AAC5C,IAAI,UAAU,GAAG,IAAI,CAAC;AAEtB,SAAgB,cAAc;IAC5B,OAAO,WAAW,CAAC;AACrB,CAAC;AAED;;;GAGG;AACH,SAAgB,gBAAgB,CAAC,IAGhC;IACC,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS;QAAE,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC;IACrD,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS;QAAE,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC;AAC5D,CAAC;AAED;;;;GAIG;AACH,SAAgB,+BAA+B;IAC7C,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC;IACrD,IAAI,SAAS,EAAE,CAAC;QACd,gBAAgB,CAAC,EAAE,IAAI,EAAE,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,oBAAoB,CAAC,EAAE,CAAC,CAAC;IACzE,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,SAAgB,WAAW;IACzB,IAAI,CAAC,UAAU;QAAE,OAAO;IACxB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,KAAK,GAAG,CAAC,MAAM,CAC5B,EAAE,CACH,yBAAyB,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,KAAK,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC;QAC1E,IAAA,mBAAc,EAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IACtC,CAAC;IAAC,MAAM,CAAC;QACP,4CAA4C;IAC9C,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,SAAgB,SAAS,CAAC,GAAG,IAAe;IAC1C,IAAI,CAAC,UAAU;QAAE,OAAO;IACxB,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC3C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAA,wBAAc,EAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACzD,IAAA,mBAAc,EAAC,WAAW,EAAE,IAAI,SAAS,KAAK,GAAG,IAAI,CAAC,CAAC;IACzD,CAAC;IAAC,MAAM,CAAC;QACP,oEAAoE;IACtE,CAAC;AACH,CAAC;AAED,SAAgB,KAAK,CAAC,GAAG,IAAe;IACtC,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO;IACT,CAAC;IAED,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAA,wBAAc,EAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAEzD,IAAA,UAAK,GAAE,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACxB,CAAC;AAED,SAAgB,eAAe;IAC7B,YAAY,GAAG,IAAI,CAAC;AACtB,CAAC","sourcesContent":["import { appendFileSync } from 'fs';\nimport path from 'path';\nimport { prepareMessage } from './logging';\nimport { getUI } from '../ui';\n\nlet debugEnabled = false;\nlet logFilePath = '/tmp/posthog-wizard.log';\nlet logEnabled = true;\n\nexport function getLogFilePath(): string {\n return logFilePath;\n}\n\n/**\n * Configure the log file path and enable/disable state.\n * Call before initLogFile() to override defaults.\n */\nexport function configureLogFile(opts: {\n path?: string;\n enabled?: boolean;\n}): void {\n if (opts.path !== undefined) logFilePath = opts.path;\n if (opts.enabled !== undefined) logEnabled = opts.enabled;\n}\n\n/**\n * Configure log path from environment variables.\n *\n * Uses POSTHOG_WIZARD_LOG_DIR when set, joined with posthog-wizard.log.\n */\nexport function configureLogFileFromEnvironment(): void {\n const envLogDir = process.env.POSTHOG_WIZARD_LOG_DIR;\n if (envLogDir) {\n configureLogFile({ path: path.join(envLogDir, 'posthog-wizard.log') });\n }\n}\n\n/**\n * Initialize the log file with a run header.\n * Call this at the start of each wizard run.\n * Fails silently to avoid crashing the wizard.\n */\nexport function initLogFile() {\n if (!logEnabled) return;\n try {\n const header = `\\n${'='.repeat(\n 60,\n )}\\nPostHog Wizard Run: ${new Date().toISOString()}\\n${'='.repeat(60)}\\n`;\n appendFileSync(logFilePath, header);\n } catch {\n // Silently ignore - logging is non-critical\n }\n}\n\n/**\n * Log a message to the log file.\n * Always writes regardless of debug flag (when logging is enabled).\n * Fails silently to avoid masking errors in catch blocks.\n */\nexport function logToFile(...args: unknown[]) {\n if (!logEnabled) return;\n try {\n const timestamp = new Date().toISOString();\n const msg = args.map((a) => prepareMessage(a)).join(' ');\n appendFileSync(logFilePath, `[${timestamp}] ${msg}\\n`);\n } catch {\n // Silently ignore logging failures to avoid masking original errors\n }\n}\n\nexport function debug(...args: unknown[]) {\n if (!debugEnabled) {\n return;\n }\n\n const msg = args.map((a) => prepareMessage(a)).join(' ');\n\n getUI().log.info(msg);\n}\n\nexport function enableDebugLogs() {\n debugEnabled = true;\n}\n"]}
@@ -257,7 +257,7 @@ async function performOAuthFlow(config) {
257
257
  try {
258
258
  const code = await Promise.race([
259
259
  waitForCallback(),
260
- new Promise((_, reject) => setTimeout(() => reject(new Error('Authorization timed out')), 60_000)),
260
+ new Promise((_, reject) => setTimeout(() => reject(new Error('Authorization timed out')), constants_1.OAUTH_TIMEOUT_MS)),
261
261
  ]);
262
262
  const token = await exchangeCodeForToken(code, codeVerifier);
263
263
  server.close();
@@ -1 +1 @@
1
- {"version":3,"file":"oauth.js","sourceRoot":"","sources":["../../../src/utils/oauth.ts"],"names":[],"mappings":"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","sourcesContent":["import * as crypto from 'node:crypto';\nimport * as http from 'node:http';\nimport { execSync } from 'node:child_process';\nimport axios from 'axios';\nimport { logToFile } from './debug';\nimport opn from 'opn';\nimport { z } from 'zod';\nimport { getUI } from '../ui';\nimport {\n IS_DEV,\n ISSUES_URL,\n OAUTH_PORT,\n POSTHOG_DEV_CLIENT_ID,\n POSTHOG_OAUTH_URL,\n POSTHOG_PROXY_CLIENT_ID,\n WIZARD_USER_AGENT,\n} from '../lib/constants';\nimport { abort } from './setup-utils';\nimport { analytics } from './analytics';\n\nconst OAUTH_CALLBACK_STYLES = `\n <style>\n * {\n font-family: monospace;\n background-color: #1b0a00;\n color: #F7A502;\n font-weight: medium;\n font-size: 24px;\n margin: .25rem;\n }\n\n .blink {\n animation: blink-animation 1s steps(2, start) infinite;\n }\n\n @keyframes blink-animation {\n to {\n opacity: 0;\n }\n }\n </style>\n`;\n\nconst OAuthTokenResponseSchema = z.object({\n access_token: z.string(),\n expires_in: z.number(),\n token_type: z.string(),\n scope: z.string(),\n refresh_token: z.string(),\n scoped_teams: z.array(z.number()).optional(),\n scoped_organizations: z.array(z.string()).optional(),\n});\n\nexport type OAuthTokenResponse = z.infer<typeof OAuthTokenResponseSchema>;\n\ninterface OAuthConfig {\n scopes: string[];\n signup?: boolean;\n}\n\nfunction generateCodeVerifier(): string {\n return crypto.randomBytes(32).toString('base64url');\n}\n\nfunction generateCodeChallenge(verifier: string): string {\n return crypto.createHash('sha256').update(verifier).digest('base64url');\n}\n\nasync function startCallbackServer(\n authUrl: string,\n signupUrl: string,\n): Promise<{\n server: http.Server;\n waitForCallback: () => Promise<string>;\n}> {\n return new Promise((resolve, reject) => {\n let callbackResolve: (code: string) => void;\n let callbackReject: (error: Error) => void;\n\n const waitForCallback = () =>\n new Promise<string>((res, rej) => {\n callbackResolve = res;\n callbackReject = rej;\n });\n\n const server = http.createServer((req, res) => {\n if (!req.url) {\n res.writeHead(400);\n res.end();\n return;\n }\n const url = new URL(req.url, `http://localhost:${OAUTH_PORT}`);\n\n if (url.pathname === '/authorize') {\n const isSignup = url.searchParams.get('signup') === 'true';\n const redirectUrl = isSignup ? signupUrl : authUrl;\n res.writeHead(302, { Location: redirectUrl });\n res.end();\n return;\n }\n\n const code = url.searchParams.get('code');\n const error = url.searchParams.get('error');\n\n if (error) {\n const isAccessDenied = error === 'access_denied';\n res.writeHead(isAccessDenied ? 200 : 400, {\n 'Content-Type': 'text/html; charset=utf-8',\n });\n res.end(`\n <html>\n <head>\n <meta charset=\"UTF-8\">\n <title>PostHog wizard - Authorization ${\n isAccessDenied ? 'cancelled' : 'failed'\n }</title>\n ${OAUTH_CALLBACK_STYLES}\n </head>\n <body>\n <p>${\n isAccessDenied\n ? 'Authorization cancelled.'\n : `Authorization failed.`\n }</p>\n <p>Return to your terminal. This window will close automatically.</p>\n <script>window.close();</script>\n </body>\n </html>\n `);\n callbackReject(new Error(`OAuth error: ${error}`));\n return;\n }\n\n if (code) {\n res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });\n res.end(`\n <html>\n <head>\n <meta charset=\"UTF-8\">\n <title>PostHog wizard is ready</title>\n ${OAUTH_CALLBACK_STYLES}\n </head>\n <body>\n <p>PostHog login complete!</p>\n <p>Return to your terminal: the wizard is hard at work on your project<span class=\"blink\">█</span></p>\n <script>window.close();</script>\n </body>\n </html>\n `);\n callbackResolve(code);\n } else {\n res.writeHead(400, { 'Content-Type': 'text/html; charset=utf-8' });\n res.end(`\n <html>\n <head>\n <meta charset=\"UTF-8\">\n <title>PostHog wizard - Invalid request</title>\n ${OAUTH_CALLBACK_STYLES}\n </head>\n <body>\n <p>Invalid request - no authorization code received.</p>\n <p>You can close this window.</p>\n </body>\n </html>\n `);\n }\n });\n\n server.listen(OAUTH_PORT, () => {\n resolve({ server, waitForCallback });\n });\n\n server.on('error', reject);\n });\n}\n\nfunction getPortProcessInfo(): { command: string; pid: string; user: string } {\n try {\n const output = execSync(`lsof -i :${OAUTH_PORT} -sTCP:LISTEN 2>/dev/null`, {\n encoding: 'utf-8',\n timeout: 3000,\n }).trim();\n const lines = output.split('\\n');\n // First line is header, second is the process\n if (lines.length < 2)\n return { command: 'unknown', pid: 'unknown', user: 'unknown' };\n const fields = lines[1].split(/\\s+/);\n // lsof columns: COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME\n const command = fields[0] ?? 'unknown';\n const pid = fields[1] ?? 'unknown';\n const user = fields[2] ?? 'unknown';\n return { command, pid, user };\n } catch {\n return { command: 'unknown', pid: 'unknown', user: 'unknown' };\n }\n}\n\nasync function startCallbackServerWithRetry(\n authUrl: string,\n signupUrl: string,\n): ReturnType<typeof startCallbackServer> {\n try {\n return await startCallbackServer(authUrl, signupUrl);\n } catch (e) {\n const isPortInUse =\n e instanceof Error &&\n 'code' in e &&\n (e as NodeJS.ErrnoException).code === 'EADDRINUSE';\n if (!isPortInUse) throw e;\n\n const processInfo = getPortProcessInfo();\n await getUI().showPortConflict(processInfo);\n\n // User killed the process — retry once\n return startCallbackServer(authUrl, signupUrl);\n }\n}\n\nasync function exchangeCodeForToken(\n code: string,\n codeVerifier: string,\n): Promise<OAuthTokenResponse> {\n const clientId = IS_DEV ? POSTHOG_DEV_CLIENT_ID : POSTHOG_PROXY_CLIENT_ID;\n\n const response = await axios.post(\n `${POSTHOG_OAUTH_URL}/oauth/token`,\n {\n grant_type: 'authorization_code',\n code,\n redirect_uri: `http://localhost:${OAUTH_PORT}/callback`,\n client_id: clientId,\n code_verifier: codeVerifier,\n },\n {\n headers: {\n 'Content-Type': 'application/json',\n 'User-Agent': WIZARD_USER_AGENT,\n },\n },\n );\n\n return OAuthTokenResponseSchema.parse(response.data);\n}\n\nexport async function performOAuthFlow(\n config: OAuthConfig,\n): Promise<OAuthTokenResponse> {\n const clientId = IS_DEV ? POSTHOG_DEV_CLIENT_ID : POSTHOG_PROXY_CLIENT_ID;\n const codeVerifier = generateCodeVerifier();\n const codeChallenge = generateCodeChallenge(codeVerifier);\n\n const authUrl = new URL(`${POSTHOG_OAUTH_URL}/oauth/authorize`);\n authUrl.searchParams.set('client_id', clientId);\n authUrl.searchParams.set(\n 'redirect_uri',\n `http://localhost:${OAUTH_PORT}/callback`,\n );\n authUrl.searchParams.set('response_type', 'code');\n authUrl.searchParams.set('code_challenge', codeChallenge);\n authUrl.searchParams.set('code_challenge_method', 'S256');\n authUrl.searchParams.set('scope', config.scopes.join(' '));\n authUrl.searchParams.set('required_access_level', 'project');\n\n const signupUrl = new URL(\n `${POSTHOG_OAUTH_URL}/signup?next=${encodeURIComponent(\n authUrl.toString(),\n )}`,\n );\n\n const localSignupUrl = `http://localhost:${OAUTH_PORT}/authorize?signup=true`;\n const localLoginUrl = `http://localhost:${OAUTH_PORT}/authorize`;\n\n const urlToOpen = config.signup ? localSignupUrl : localLoginUrl;\n\n logToFile('[oauth] starting callback server');\n const { server, waitForCallback } = await startCallbackServerWithRetry(\n authUrl.toString(),\n signupUrl.toString(),\n );\n logToFile('[oauth] callback server ready, showing login URL');\n\n getUI().setLoginUrl(urlToOpen);\n\n if (process.env.NODE_ENV !== 'test') {\n opn(urlToOpen, { wait: false }).catch(() => {\n // opn throws in environments without a browser\n });\n }\n\n const loginSpinner = getUI().spinner();\n loginSpinner.start('Waiting for authorization...');\n\n try {\n const code = await Promise.race([\n waitForCallback(),\n new Promise<never>((_, reject) =>\n setTimeout(() => reject(new Error('Authorization timed out')), 60_000),\n ),\n ]);\n\n const token = await exchangeCodeForToken(code, codeVerifier);\n\n server.close();\n getUI().setLoginUrl(null);\n loginSpinner.stop('Authorization complete!');\n\n return token;\n } catch (e) {\n loginSpinner.stop('Authorization failed.');\n server.close();\n\n const error = e instanceof Error ? e : new Error('Unknown error');\n\n if (error.message.includes('timeout')) {\n getUI().log.error('Authorization timed out. Please try again.');\n } else if (error.message.includes('access_denied')) {\n getUI().log.info(\n `Authorization was cancelled.\\n\\nYou denied access to PostHog. To use the wizard, you need to authorize access to your PostHog account.\\n\\nYou can try again by re-running the wizard.`,\n );\n } else {\n getUI().log.error(\n `Authorization failed:\\n\\n${error.message}\\n\\nIf you think this is a bug in the PostHog wizard, please create an issue:\\n${ISSUES_URL}`,\n );\n }\n\n analytics.captureException(error, {\n step: 'oauth_flow',\n });\n\n await abort();\n throw error;\n }\n}\n"]}
1
+ {"version":3,"file":"oauth.js","sourceRoot":"","sources":["../../../src/utils/oauth.ts"],"names":[],"mappings":"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","sourcesContent":["import * as crypto from 'node:crypto';\nimport * as http from 'node:http';\nimport { execSync } from 'node:child_process';\nimport axios from 'axios';\nimport { logToFile } from './debug';\nimport opn from 'opn';\nimport { z } from 'zod';\nimport { getUI } from '../ui';\nimport {\n IS_DEV,\n ISSUES_URL,\n OAUTH_PORT,\n OAUTH_TIMEOUT_MS,\n POSTHOG_DEV_CLIENT_ID,\n POSTHOG_OAUTH_URL,\n POSTHOG_PROXY_CLIENT_ID,\n WIZARD_USER_AGENT,\n} from '../lib/constants';\nimport { abort } from './setup-utils';\nimport { analytics } from './analytics';\n\nconst OAUTH_CALLBACK_STYLES = `\n <style>\n * {\n font-family: monospace;\n background-color: #1b0a00;\n color: #F7A502;\n font-weight: medium;\n font-size: 24px;\n margin: .25rem;\n }\n\n .blink {\n animation: blink-animation 1s steps(2, start) infinite;\n }\n\n @keyframes blink-animation {\n to {\n opacity: 0;\n }\n }\n </style>\n`;\n\nconst OAuthTokenResponseSchema = z.object({\n access_token: z.string(),\n expires_in: z.number(),\n token_type: z.string(),\n scope: z.string(),\n refresh_token: z.string(),\n scoped_teams: z.array(z.number()).optional(),\n scoped_organizations: z.array(z.string()).optional(),\n});\n\nexport type OAuthTokenResponse = z.infer<typeof OAuthTokenResponseSchema>;\n\ninterface OAuthConfig {\n scopes: string[];\n signup?: boolean;\n}\n\nfunction generateCodeVerifier(): string {\n return crypto.randomBytes(32).toString('base64url');\n}\n\nfunction generateCodeChallenge(verifier: string): string {\n return crypto.createHash('sha256').update(verifier).digest('base64url');\n}\n\nasync function startCallbackServer(\n authUrl: string,\n signupUrl: string,\n): Promise<{\n server: http.Server;\n waitForCallback: () => Promise<string>;\n}> {\n return new Promise((resolve, reject) => {\n let callbackResolve: (code: string) => void;\n let callbackReject: (error: Error) => void;\n\n const waitForCallback = () =>\n new Promise<string>((res, rej) => {\n callbackResolve = res;\n callbackReject = rej;\n });\n\n const server = http.createServer((req, res) => {\n if (!req.url) {\n res.writeHead(400);\n res.end();\n return;\n }\n const url = new URL(req.url, `http://localhost:${OAUTH_PORT}`);\n\n if (url.pathname === '/authorize') {\n const isSignup = url.searchParams.get('signup') === 'true';\n const redirectUrl = isSignup ? signupUrl : authUrl;\n res.writeHead(302, { Location: redirectUrl });\n res.end();\n return;\n }\n\n const code = url.searchParams.get('code');\n const error = url.searchParams.get('error');\n\n if (error) {\n const isAccessDenied = error === 'access_denied';\n res.writeHead(isAccessDenied ? 200 : 400, {\n 'Content-Type': 'text/html; charset=utf-8',\n });\n res.end(`\n <html>\n <head>\n <meta charset=\"UTF-8\">\n <title>PostHog wizard - Authorization ${\n isAccessDenied ? 'cancelled' : 'failed'\n }</title>\n ${OAUTH_CALLBACK_STYLES}\n </head>\n <body>\n <p>${\n isAccessDenied\n ? 'Authorization cancelled.'\n : `Authorization failed.`\n }</p>\n <p>Return to your terminal. This window will close automatically.</p>\n <script>window.close();</script>\n </body>\n </html>\n `);\n callbackReject(new Error(`OAuth error: ${error}`));\n return;\n }\n\n if (code) {\n res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });\n res.end(`\n <html>\n <head>\n <meta charset=\"UTF-8\">\n <title>PostHog wizard is ready</title>\n ${OAUTH_CALLBACK_STYLES}\n </head>\n <body>\n <p>PostHog login complete!</p>\n <p>Return to your terminal: the wizard is hard at work on your project<span class=\"blink\">█</span></p>\n <script>window.close();</script>\n </body>\n </html>\n `);\n callbackResolve(code);\n } else {\n res.writeHead(400, { 'Content-Type': 'text/html; charset=utf-8' });\n res.end(`\n <html>\n <head>\n <meta charset=\"UTF-8\">\n <title>PostHog wizard - Invalid request</title>\n ${OAUTH_CALLBACK_STYLES}\n </head>\n <body>\n <p>Invalid request - no authorization code received.</p>\n <p>You can close this window.</p>\n </body>\n </html>\n `);\n }\n });\n\n server.listen(OAUTH_PORT, () => {\n resolve({ server, waitForCallback });\n });\n\n server.on('error', reject);\n });\n}\n\nfunction getPortProcessInfo(): { command: string; pid: string; user: string } {\n try {\n const output = execSync(`lsof -i :${OAUTH_PORT} -sTCP:LISTEN 2>/dev/null`, {\n encoding: 'utf-8',\n timeout: 3000,\n }).trim();\n const lines = output.split('\\n');\n // First line is header, second is the process\n if (lines.length < 2)\n return { command: 'unknown', pid: 'unknown', user: 'unknown' };\n const fields = lines[1].split(/\\s+/);\n // lsof columns: COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME\n const command = fields[0] ?? 'unknown';\n const pid = fields[1] ?? 'unknown';\n const user = fields[2] ?? 'unknown';\n return { command, pid, user };\n } catch {\n return { command: 'unknown', pid: 'unknown', user: 'unknown' };\n }\n}\n\nasync function startCallbackServerWithRetry(\n authUrl: string,\n signupUrl: string,\n): ReturnType<typeof startCallbackServer> {\n try {\n return await startCallbackServer(authUrl, signupUrl);\n } catch (e) {\n const isPortInUse =\n e instanceof Error &&\n 'code' in e &&\n (e as NodeJS.ErrnoException).code === 'EADDRINUSE';\n if (!isPortInUse) throw e;\n\n const processInfo = getPortProcessInfo();\n await getUI().showPortConflict(processInfo);\n\n // User killed the process — retry once\n return startCallbackServer(authUrl, signupUrl);\n }\n}\n\nasync function exchangeCodeForToken(\n code: string,\n codeVerifier: string,\n): Promise<OAuthTokenResponse> {\n const clientId = IS_DEV ? POSTHOG_DEV_CLIENT_ID : POSTHOG_PROXY_CLIENT_ID;\n\n const response = await axios.post(\n `${POSTHOG_OAUTH_URL}/oauth/token`,\n {\n grant_type: 'authorization_code',\n code,\n redirect_uri: `http://localhost:${OAUTH_PORT}/callback`,\n client_id: clientId,\n code_verifier: codeVerifier,\n },\n {\n headers: {\n 'Content-Type': 'application/json',\n 'User-Agent': WIZARD_USER_AGENT,\n },\n },\n );\n\n return OAuthTokenResponseSchema.parse(response.data);\n}\n\nexport async function performOAuthFlow(\n config: OAuthConfig,\n): Promise<OAuthTokenResponse> {\n const clientId = IS_DEV ? POSTHOG_DEV_CLIENT_ID : POSTHOG_PROXY_CLIENT_ID;\n const codeVerifier = generateCodeVerifier();\n const codeChallenge = generateCodeChallenge(codeVerifier);\n\n const authUrl = new URL(`${POSTHOG_OAUTH_URL}/oauth/authorize`);\n authUrl.searchParams.set('client_id', clientId);\n authUrl.searchParams.set(\n 'redirect_uri',\n `http://localhost:${OAUTH_PORT}/callback`,\n );\n authUrl.searchParams.set('response_type', 'code');\n authUrl.searchParams.set('code_challenge', codeChallenge);\n authUrl.searchParams.set('code_challenge_method', 'S256');\n authUrl.searchParams.set('scope', config.scopes.join(' '));\n authUrl.searchParams.set('required_access_level', 'project');\n\n const signupUrl = new URL(\n `${POSTHOG_OAUTH_URL}/signup?next=${encodeURIComponent(\n authUrl.toString(),\n )}`,\n );\n\n const localSignupUrl = `http://localhost:${OAUTH_PORT}/authorize?signup=true`;\n const localLoginUrl = `http://localhost:${OAUTH_PORT}/authorize`;\n\n const urlToOpen = config.signup ? localSignupUrl : localLoginUrl;\n\n logToFile('[oauth] starting callback server');\n const { server, waitForCallback } = await startCallbackServerWithRetry(\n authUrl.toString(),\n signupUrl.toString(),\n );\n logToFile('[oauth] callback server ready, showing login URL');\n\n getUI().setLoginUrl(urlToOpen);\n\n if (process.env.NODE_ENV !== 'test') {\n opn(urlToOpen, { wait: false }).catch(() => {\n // opn throws in environments without a browser\n });\n }\n\n const loginSpinner = getUI().spinner();\n loginSpinner.start('Waiting for authorization...');\n\n try {\n const code = await Promise.race([\n waitForCallback(),\n new Promise<never>((_, reject) =>\n setTimeout(\n () => reject(new Error('Authorization timed out')),\n OAUTH_TIMEOUT_MS,\n ),\n ),\n ]);\n\n const token = await exchangeCodeForToken(code, codeVerifier);\n\n server.close();\n getUI().setLoginUrl(null);\n loginSpinner.stop('Authorization complete!');\n\n return token;\n } catch (e) {\n loginSpinner.stop('Authorization failed.');\n server.close();\n\n const error = e instanceof Error ? e : new Error('Unknown error');\n\n if (error.message.includes('timeout')) {\n getUI().log.error('Authorization timed out. Please try again.');\n } else if (error.message.includes('access_denied')) {\n getUI().log.info(\n `Authorization was cancelled.\\n\\nYou denied access to PostHog. To use the wizard, you need to authorize access to your PostHog account.\\n\\nYou can try again by re-running the wizard.`,\n );\n } else {\n getUI().log.error(\n `Authorization failed:\\n\\n${error.message}\\n\\nIf you think this is a bug in the PostHog wizard, please create an issue:\\n${ISSUES_URL}`,\n );\n }\n\n analytics.captureException(error, {\n step: 'oauth_flow',\n });\n\n await abort();\n throw error;\n }\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>;