@posthog/wizard 2.10.3 → 2.11.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/dist/{McpScreen-23GY1pWz.js → McpScreen-DvUncZBi.js} +153 -23
- package/dist/McpScreen-DvUncZBi.js.map +1 -0
- package/dist/{add-mcp-server-to-clients-B6baHy_h.js → add-mcp-server-to-clients-Br1hDRiB.js} +157 -125
- package/dist/add-mcp-server-to-clients-Br1hDRiB.js.map +1 -0
- package/dist/{agent-runner-CBPBefLt.js → agent-runner-fWYFO4H0.js} +11 -9
- package/dist/agent-runner-fWYFO4H0.js.map +1 -0
- package/dist/{agent-skill-BVjJqol6.js → agent-skill-DJOzDaQV.js} +1 -1
- package/dist/{agent-skill-BVjJqol6.js.map → agent-skill-DJOzDaQV.js.map} +1 -1
- package/dist/analytics-CfAUlt6-.js +2 -0
- package/dist/{analytics-xANpxdVL.js → analytics-D3rY3TaN.js} +7 -4
- package/dist/analytics-D3rY3TaN.js.map +1 -0
- package/dist/bin.js +234 -41
- package/dist/bin.js.map +1 -1
- package/dist/{debug-CIyf0ZGx.js → debug-D-0xueVl.js} +1 -1
- package/dist/{debug-CyJ_3dTP.js → debug-gWEjmYVV.js} +4 -2
- package/dist/{debug-CyJ_3dTP.js.map → debug-gWEjmYVV.js.map} +1 -1
- package/dist/{defaults-DoVkE0gW.js → defaults-CPH6eWhN.js} +8 -8
- package/dist/defaults-CPH6eWhN.js.map +1 -0
- package/dist/{detection-Drfq0l8n.js → detection-B7GNzve-.js} +103 -19
- package/dist/detection-B7GNzve-.js.map +1 -0
- package/dist/{env-api-key-K8TdTDII.js → env-api-key-DU8uIEvo.js} +1 -1
- package/dist/{env-api-key-K8TdTDII.js.map → env-api-key-DU8uIEvo.js.map} +1 -1
- package/dist/file-DhSBlq-x.js +16 -0
- package/dist/file-DhSBlq-x.js.map +1 -0
- package/dist/{file-utils-BWneZy6p.js → file-utils-Dy9JncCo.js} +1 -1
- package/dist/{file-utils-BWneZy6p.js.map → file-utils-Dy9JncCo.js.map} +1 -1
- package/dist/package-json-BzVey4Bd.js +2 -0
- package/dist/{package-json-Ctq6LSl8.js → package-json-F_7oktsp.js} +1 -1
- package/dist/{package-json-Ctq6LSl8.js.map → package-json-F_7oktsp.js.map} +1 -1
- package/dist/{package-manager-Ls_8r9Ot.js → package-manager-D3Lo6nXf.js} +2 -2
- package/dist/{package-manager-Ls_8r9Ot.js.map → package-manager-D3Lo6nXf.js.map} +1 -1
- package/dist/paths-BL-x2rFy.js +16 -0
- package/dist/paths-BL-x2rFy.js.map +1 -0
- package/dist/posthog-ByrpqEjN.js +11 -0
- package/dist/posthog-ByrpqEjN.js.map +1 -0
- package/dist/{posthog-integration-DUZpiyxg.js → posthog-integration-D4SRhJIQ.js} +10 -9
- package/dist/posthog-integration-D4SRhJIQ.js.map +1 -0
- package/dist/{readiness-BAgN8xAg.js → readiness-gQvQNCeL.js} +10 -10
- package/dist/readiness-gQvQNCeL.js.map +1 -0
- package/dist/{registry-qfhSxTjo.js → registry-DaPKstG3.js} +6 -6
- package/dist/{registry-qfhSxTjo.js.map → registry-DaPKstG3.js.map} +1 -1
- package/dist/{router-D5A1Sb4p.js → router-SgzmfLGi.js} +11 -18
- package/dist/router-SgzmfLGi.js.map +1 -0
- package/dist/setup-utils-_ONxN-TT.js +2 -0
- package/dist/{setup-utils-C1h1QDiG.js → setup-utils-y4s-3uKT.js} +13 -7
- package/dist/setup-utils-y4s-3uKT.js.map +1 -0
- package/dist/{start-playground-xOLMYzst.js → start-playground-g1TxpCZ5.js} +84 -7
- package/dist/start-playground-g1TxpCZ5.js.map +1 -0
- package/dist/{start-tui-Ddo4TI9T.js → start-tui-CQef69NR.js} +305 -23
- package/dist/start-tui-CQef69NR.js.map +1 -0
- package/dist/{steps-BjvFG--8.js → steps-D1zKDqAo.js} +6 -6
- package/dist/{steps-BjvFG--8.js.map → steps-D1zKDqAo.js.map} +1 -1
- package/dist/task-stream-DX_jKDQu.js +61 -0
- package/dist/task-stream-DX_jKDQu.js.map +1 -0
- package/dist/{telemetry-CC6zPKJg.js → telemetry-CyUUSAYy.js} +2 -2
- package/dist/{telemetry-CC6zPKJg.js.map → telemetry-CyUUSAYy.js.map} +1 -1
- package/dist/{wizard-abort-XhapT0Ly.js → wizard-abort-Buodno3f.js} +3 -3
- package/dist/{wizard-abort-XhapT0Ly.js.map → wizard-abort-Buodno3f.js.map} +1 -1
- package/dist/{wizard-abort-Bc3lWNLb.js → wizard-abort-DZmO_sIZ.js} +1 -1
- package/dist/wizard-session-COhklXAF.js +2 -0
- package/dist/{wizard-session-Db6R023m.js → wizard-session-D5bggSsu.js} +1 -1
- package/dist/{wizard-session-Db6R023m.js.map → wizard-session-D5bggSsu.js.map} +1 -1
- package/dist/wizard-ui-BExOjdjA.js +14 -0
- package/dist/wizard-ui-BExOjdjA.js.map +1 -0
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/dist/McpScreen-23GY1pWz.js.map +0 -1
- package/dist/add-mcp-server-to-clients-B6baHy_h.js.map +0 -1
- package/dist/agent-runner-CBPBefLt.js.map +0 -1
- package/dist/analytics-DdTDVjqs.js +0 -2
- package/dist/analytics-xANpxdVL.js.map +0 -1
- package/dist/defaults-DoVkE0gW.js.map +0 -1
- package/dist/detection-Drfq0l8n.js.map +0 -1
- package/dist/package-json-BQgl5C3Z.js +0 -2
- package/dist/posthog-integration-DUZpiyxg.js.map +0 -1
- package/dist/readiness-BAgN8xAg.js.map +0 -1
- package/dist/router-D5A1Sb4p.js.map +0 -1
- package/dist/setup-utils-C1h1QDiG.js.map +0 -1
- package/dist/start-playground-xOLMYzst.js.map +0 -1
- package/dist/start-tui-Ddo4TI9T.js.map +0 -1
- package/dist/wizard-session-y7nf6aKH.js +0 -2
package/dist/bin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bin.js","names":[],"sources":["../src/utils/environment.ts","../src/lib/workflows/revenue-analytics/detect.ts","../src/lib/workflows/revenue-analytics/steps.ts","../src/lib/workflows/revenue-analytics/index.ts","../src/lib/workflows/workflow-registry.ts","../bin.ts"],"sourcesContent":["import readEnvModule from 'read-env';\n\nconst readEnv =\n typeof readEnvModule === 'function'\n ? readEnvModule\n : (readEnvModule as any).default;\nimport { tryGetPackageJson } from './setup-utils';\nimport type { WizardOptions } from './types';\nimport fg from 'fast-glob';\nimport { IS_DEV } from '../lib/constants';\n\nexport function isNonInteractiveEnvironment(): boolean {\n if (IS_DEV) {\n return false;\n }\n\n if (!process.stdout.isTTY || !process.stderr.isTTY) {\n return true;\n }\n\n return false;\n}\n\nexport function readEnvironment(): Record<string, unknown> {\n const result = readEnv('POSTHOG_WIZARD');\n\n return result;\n}\n\nexport async function detectEnvVarPrefix(\n options: WizardOptions,\n): Promise<string> {\n const packageJson = await tryGetPackageJson(options);\n if (!packageJson) return 'VITE_PUBLIC_';\n\n const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };\n const has = (name: string) => name in deps;\n const hasAnyFile = async (patterns: string[]) => {\n const matches = await fg(patterns, {\n cwd: options.installDir,\n absolute: false,\n onlyFiles: true,\n ignore: ['**/node_modules/**'],\n });\n return matches.length > 0;\n };\n\n // --- Next.js\n if (has('next') || (await hasAnyFile(['**/next.config.{js,ts,mjs,cjs}']))) {\n return 'NEXT_PUBLIC_';\n }\n\n // --- Create React App\n if (\n has('react-scripts') ||\n has('create-react-app') ||\n (await hasAnyFile(['**/config-overrides.js']))\n ) {\n return 'REACT_APP_';\n }\n\n // --- Vite (vanilla, TanStack, Solid, etc.)\n // Note: Vite does not need PUBLIC_ but we use it to follow the docs, to improve the chances of an LLM getting it right.\n if (has('vite') || (await hasAnyFile(['**/vite.config.{js,ts,mjs,cjs}']))) {\n return 'VITE_PUBLIC_';\n }\n\n // --- SvelteKit\n if (\n has('@sveltejs/kit') ||\n (await hasAnyFile(['**/svelte.config.{js,ts}']))\n ) {\n return 'PUBLIC_';\n }\n\n // --- TanStack Start (uses Vite)\n if (\n has('@tanstack/start') ||\n (await hasAnyFile(['**/tanstack.config.{js,ts}']))\n ) {\n return 'VITE_PUBLIC_';\n }\n\n // --- SolidStart (uses Vite)\n if (has('solid-start') || (await hasAnyFile(['**/solid.config.{js,ts}']))) {\n return 'VITE_PUBLIC_';\n }\n\n // --- Astro\n if (has('astro') || (await hasAnyFile(['**/astro.config.{js,ts,mjs}']))) {\n return 'PUBLIC_';\n }\n\n // We default to Vite if we can't detect a specific framework, since it's the most commonly used.\n return 'VITE_PUBLIC_';\n}\n","/**\n * Revenue analytics prerequisite detection.\n *\n * Scans the project for PostHog + Stripe SDKs and writes results\n * into frameworkContext for the intro screen to render.\n */\n\nimport type { Dirent } from 'fs';\nimport { readFileSync, readdirSync, existsSync, statSync } from 'fs';\nimport { join, relative } from 'path';\nimport { IGNORED_DIRS } from '../../../utils/file-utils.js';\nimport type { WizardSession } from '../../wizard-session.js';\nimport type { AbortCase } from '../../agent/agent-runner.js';\n\nexport const POSTHOG_SDKS = [\n 'posthog-js',\n 'posthog-node',\n 'posthog-react-native',\n 'posthog-android',\n 'posthog-ios',\n];\n\nexport const STRIPE_SDKS = [\n 'stripe',\n '@stripe/stripe-js',\n '@stripe/react-stripe-js',\n];\n\ninterface PackageMatch {\n /** Path to the package.json relative to installDir */\n path: string;\n posthogSdks: string[];\n stripeSdks: string[];\n}\n\n/**\n * Structured detection errors. The screen renders each kind into JSX\n * with proper formatting — keeps error data separate from presentation.\n */\nexport type RevenueDetectError =\n | {\n kind: 'bad-directory';\n path: string;\n reason: 'missing' | 'not-dir' | 'unreadable';\n }\n | { kind: 'no-package-json' }\n | { kind: 'no-sdks'; scannedCount: number }\n | { kind: 'missing-posthog'; foundStripe: string[] }\n | { kind: 'missing-stripe'; foundPosthog: string[] };\n\n/** `[ABORT] <reason>` cases the revenue analytics skill can emit. */\nexport const REVENUE_ABORT_CASES: AbortCase[] = [\n {\n // Skill emits: [ABORT] Could not find a PostHog distinct_id\n match: /^could not find a posthog distinct_id$/i,\n message: 'Could not find a PostHog distinct_id',\n body:\n 'The agent could not find PostHog distinct_id usage in your codebase. ' +\n 'Your users must be identified in PostHog before they can be tagged in Stripe. ' +\n 'Please identify your users and try again.',\n docsUrl: 'https://posthog.com/docs/product-analytics/identify',\n },\n {\n // Skill emits: [ABORT] Could not find a Stripe integration\n match: /^could not find a stripe integration$/i,\n message: 'Could not find a Stripe integration',\n body:\n 'The Wizard could not find an existing Stripe customer, charge, ' +\n 'subscription, or other Stripe operations. Please run the Revenue ' +\n 'Analytics Wizard on a project with an existing Stripe integration.',\n docsUrl: 'https://posthog.com/docs/revenue-analytics',\n },\n];\n\n/**\n * Recursively find all package.json files under installDir (max depth 3),\n * skipping common ignored directories. Returns matches with detected SDKs.\n */\nfunction findPackageJsons(installDir: string, maxDepth = 3): PackageMatch[] {\n const matches: PackageMatch[] = [];\n\n function scan(dir: string, depth: number): void {\n if (depth > maxDepth) return;\n\n let entries: Dirent[];\n try {\n entries = readdirSync(dir, { withFileTypes: true });\n } catch {\n return;\n }\n\n for (const entry of entries) {\n if (entry.name.startsWith('.') && entry.name !== '.') continue;\n if (IGNORED_DIRS.has(entry.name)) continue;\n\n const fullPath = join(dir, entry.name);\n\n if (entry.isFile() && entry.name === 'package.json') {\n try {\n const pkg = JSON.parse(readFileSync(fullPath, 'utf-8')) as {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n };\n const depNames = [\n ...Object.keys(pkg.dependencies ?? {}),\n ...Object.keys(pkg.devDependencies ?? {}),\n ];\n const posthogSdks = depNames.filter((d) => POSTHOG_SDKS.includes(d));\n const stripeSdks = depNames.filter((d) => STRIPE_SDKS.includes(d));\n matches.push({\n path: relative(installDir, fullPath) || 'package.json',\n posthogSdks,\n stripeSdks,\n });\n } catch {\n // Skip malformed package.json\n }\n } else if (entry.isDirectory()) {\n scan(fullPath, depth + 1);\n }\n }\n }\n\n scan(installDir, 0);\n return matches;\n}\n\n/**\n * Scan `session.installDir` for PostHog + Stripe SDKs. Writes detection\n * results into frameworkContext via the callback — either the detected\n * SDK lists (for the intro screen) or a `RevenueDetectError` on failure.\n *\n * The skill install happens later in the bootstrap runner, not here.\n */\nexport function detectRevenuePrerequisites(\n session: WizardSession,\n setFrameworkContext: (key: string, value: unknown) => void,\n): void {\n const fail = (error: RevenueDetectError) =>\n setFrameworkContext('detectError', error);\n\n const installDir = session.installDir;\n\n // Verify the install directory exists and is readable\n if (!existsSync(installDir)) {\n fail({ kind: 'bad-directory', path: installDir, reason: 'missing' });\n return;\n }\n try {\n if (!statSync(installDir).isDirectory()) {\n fail({ kind: 'bad-directory', path: installDir, reason: 'not-dir' });\n return;\n }\n } catch {\n fail({ kind: 'bad-directory', path: installDir, reason: 'unreadable' });\n return;\n }\n\n // Find all package.json files (root + monorepo subpackages)\n const matches = findPackageJsons(installDir);\n\n if (matches.length === 0) {\n fail({ kind: 'no-package-json' });\n return;\n }\n\n // Aggregate detected SDKs across all package.json files\n const allPosthogSdks = new Set<string>();\n const allStripeSdks = new Set<string>();\n for (const match of matches) {\n for (const sdk of match.posthogSdks) allPosthogSdks.add(sdk);\n for (const sdk of match.stripeSdks) allStripeSdks.add(sdk);\n }\n\n const detectedPosthogSdks = [...allPosthogSdks];\n const detectedStripeSdks = [...allStripeSdks];\n\n if (detectedPosthogSdks.length === 0 && detectedStripeSdks.length === 0) {\n fail({ kind: 'no-sdks', scannedCount: matches.length });\n return;\n }\n\n if (detectedPosthogSdks.length === 0) {\n fail({ kind: 'missing-posthog', foundStripe: detectedStripeSdks });\n return;\n }\n\n if (detectedStripeSdks.length === 0) {\n fail({ kind: 'missing-stripe', foundPosthog: detectedPosthogSdks });\n return;\n }\n\n setFrameworkContext('detectedPosthogSdks', detectedPosthogSdks);\n setFrameworkContext('detectedStripeSdks', detectedStripeSdks);\n setFrameworkContext(\n 'detectedPackagePaths',\n matches\n .filter((m) => m.posthogSdks.length > 0 || m.stripeSdks.length > 0)\n .map((m) => m.path),\n );\n}\n","/**\n * Revenue analytics workflow step list.\n *\n * The detect step checks for PostHog + Stripe SDKs. The skill install\n * and agent run live in the workflow runner (see agent-runner.ts).\n */\n\nimport type { Workflow } from '../workflow-step.js';\nimport { RunPhase } from '../../wizard-session.js';\nimport { detectRevenuePrerequisites } from './detect.js';\n\nexport const REVENUE_ANALYTICS_WORKFLOW: Workflow = [\n {\n id: 'detect',\n label: 'Detecting prerequisites',\n // Headless step: no screen, no gate. onReady fires after bin.ts\n // assigns the session — the hook scans for PostHog + Stripe SDKs\n // and writes the results (or a detectError) to frameworkContext\n // for the intro screen to render.\n onReady: (ctx) =>\n detectRevenuePrerequisites(ctx.session, ctx.setFrameworkContext),\n },\n {\n id: 'intro',\n label: 'Welcome',\n screen: 'revenue-intro',\n gate: (session) => session.setupConfirmed,\n },\n {\n id: 'auth',\n label: 'Authentication',\n screen: 'auth',\n isComplete: (session) => session.credentials !== null,\n },\n {\n id: 'run',\n label: 'Revenue analytics',\n screen: 'run',\n isComplete: (session) =>\n session.runPhase === RunPhase.Completed ||\n session.runPhase === RunPhase.Error,\n },\n {\n id: 'outro',\n label: 'Done',\n screen: 'outro',\n isComplete: (session) => session.outroDismissed,\n },\n {\n id: 'skills',\n label: 'Skills',\n screen: 'keep-skills',\n },\n];\n","import type { WorkflowConfig } from '../workflow-step.js';\nimport { REVENUE_ANALYTICS_WORKFLOW } from './steps.js';\nimport { REVENUE_ABORT_CASES } from './detect.js';\n\nexport const revenueAnalyticsConfig: WorkflowConfig = {\n command: 'revenue',\n description: 'Set up PostHog revenue analytics (e.g. Stripe integration)',\n flowKey: 'revenue-analytics-setup',\n steps: REVENUE_ANALYTICS_WORKFLOW,\n run: {\n skillId: 'revenue-analytics-setup',\n integrationLabel: 'revenue-analytics-setup',\n customPrompt: () => 'Set up revenue analytics for this project.',\n successMessage: 'Revenue analytics configured!',\n reportFile: 'posthog-revenue-report.md',\n docsUrl: 'https://posthog.com/docs/revenue-analytics',\n spinnerMessage: 'Setting up revenue analytics...',\n estimatedDurationMinutes: 5,\n abortCases: REVENUE_ABORT_CASES,\n },\n requires: ['posthog-integration'],\n};\n\nexport { REVENUE_ANALYTICS_WORKFLOW } from './steps.js';\nexport {\n detectRevenuePrerequisites,\n POSTHOG_SDKS,\n STRIPE_SDKS,\n type RevenueDetectError,\n} from './detect.js';\n","/**\n * Central registry of all wizard workflows.\n *\n * Adding a new workflow:\n * 1. Create src/lib/workflows/<name>/ with index.ts exporting a WorkflowConfig\n * 2. Import and add it to WORKFLOW_REGISTRY below\n * 3. Add a matching Flow enum entry in src/ui/tui/flows.ts\n * 4. (If custom intro screen) add to src/ui/tui/screen-registry.tsx\n *\n * flows.ts, store.ts, and bin.ts all derive their wiring from this array —\n * no need to touch those files when adding a workflow.\n */\n\nimport type { WorkflowConfig } from './workflow-step.js';\nimport { posthogIntegrationConfig } from './posthog-integration/index.js';\nimport { revenueAnalyticsConfig } from './revenue-analytics/index.js';\n\nexport const WORKFLOW_REGISTRY: WorkflowConfig[] = [\n posthogIntegrationConfig,\n revenueAnalyticsConfig,\n];\n\n/** Look up a workflow config by its flowKey. */\nexport function getWorkflowConfig(flowKey: string): WorkflowConfig | undefined {\n return WORKFLOW_REGISTRY.find((c) => c.flowKey === flowKey);\n}\n\n/** All workflow configs that are exposed as CLI subcommands. */\nexport function getSubcommandWorkflows(): WorkflowConfig[] {\n return WORKFLOW_REGISTRY.filter((c) => c.command != null);\n}\n","#!/usr/bin/env node\nimport { satisfies } from 'semver';\nimport { red } from './src/utils/logging';\n\nimport yargs from 'yargs';\nimport { hideBin } from 'yargs/helpers';\nimport { VERSION } from './src/lib/version.js';\n\nconst WIZARD_VERSION = VERSION;\n\nconst NODE_VERSION_RANGE = '>=18.17.0';\n\n// Have to run this above the other imports because they are importing clack that\n// has the problematic imports.\nif (!satisfies(process.version, NODE_VERSION_RANGE)) {\n red(\n `PostHog wizard requires Node.js ${NODE_VERSION_RANGE}. You are using Node.js ${process.version}. Please upgrade your Node.js version.`,\n );\n process.exit(1);\n}\n\nimport { isNonInteractiveEnvironment } from './src/utils/environment';\nimport { getUI, setUI } from './src/ui';\nimport { LoggingUI } from './src/ui/logging-ui';\nimport { getSubcommandWorkflows } from './src/lib/workflows/workflow-registry';\nimport type { WorkflowConfig } from './src/lib/workflows/workflow-step';\nimport type { WizardSession } from './src/lib/wizard-session';\nimport { runtimeEnv } from '@env';\n\n// Test mock server — only loaded when NODE_ENV is 'test'.\n// In production builds, tsdown replaces process.env.NODE_ENV with 'production',\n// making this block dead code.\nif (process.env.NODE_ENV === 'test') {\n void (async () => {\n try {\n const { server } = await import('./e2e-tests/mocks/server.js');\n server.listen({\n onUnhandledRequest: 'bypass',\n });\n } catch (error) {\n // Mock server import failed - this can happen during non-E2E tests\n }\n })();\n}\n\n/** Shared yargs options for skill-based workflow subcommands. */\nconst skillSubcommandOptions = {\n debug: {\n default: false,\n describe: 'Enable verbose logging',\n type: 'boolean' as const,\n },\n 'install-dir': {\n describe: 'Directory to install in',\n type: 'string' as const,\n },\n 'local-mcp': {\n default: false,\n describe: 'Use local MCP server',\n type: 'boolean' as const,\n },\n benchmark: {\n default: false,\n describe: 'Run in benchmark mode',\n type: 'boolean' as const,\n },\n 'yara-report': {\n default: false,\n describe: 'Print YARA scanner summary',\n type: 'boolean' as const,\n hidden: true,\n },\n};\n\nconst cli = yargs(hideBin(process.argv))\n .env('POSTHOG_WIZARD')\n // global options\n .options({\n debug: {\n default: false,\n describe: 'Enable verbose logging\\nenv: POSTHOG_WIZARD_DEBUG',\n type: 'boolean',\n },\n region: {\n describe: 'PostHog cloud region\\nenv: POSTHOG_WIZARD_REGION',\n choices: ['us', 'eu'],\n type: 'string',\n },\n default: {\n default: true,\n describe:\n 'Use default options for all prompts\\nenv: POSTHOG_WIZARD_DEFAULT',\n type: 'boolean',\n },\n signup: {\n default: false,\n describe:\n 'Create a new PostHog account during setup\\nenv: POSTHOG_WIZARD_SIGNUP',\n type: 'boolean',\n },\n 'local-mcp': {\n default: false,\n describe:\n 'Use local MCP server at http://localhost:8787/mcp\\nenv: POSTHOG_WIZARD_LOCAL_MCP',\n type: 'boolean',\n },\n ci: {\n default: false,\n describe:\n 'Enable CI mode for non-interactive execution\\nenv: POSTHOG_WIZARD_CI',\n type: 'boolean',\n },\n 'api-key': {\n describe:\n 'PostHog personal API key (phx_xxx) for authentication\\nenv: POSTHOG_WIZARD_API_KEY',\n type: 'string',\n },\n 'project-id': {\n describe:\n 'PostHog project ID to use (optional; when not set, uses default from API key or OAuth)\\nenv: POSTHOG_WIZARD_PROJECT_ID',\n type: 'string',\n },\n email: {\n describe:\n 'Email address for signup (used with --signup)\\nenv: POSTHOG_WIZARD_EMAIL',\n type: 'string',\n },\n })\n .command(\n ['$0'],\n 'Run the PostHog setup wizard',\n (yargs) => {\n return yargs.options({\n 'force-install': {\n default: false,\n describe:\n 'Force install packages even if peer dependency checks fail\\nenv: POSTHOG_WIZARD_FORCE_INSTALL',\n type: 'boolean',\n },\n 'install-dir': {\n describe:\n 'Directory to install PostHog in\\nenv: POSTHOG_WIZARD_INSTALL_DIR',\n type: 'string',\n },\n playground: {\n default: false,\n describe: 'Launch the TUI primitives playground',\n type: 'boolean',\n },\n integration: {\n describe: 'Integration to set up',\n choices: [\n 'nextjs',\n 'astro',\n 'react',\n 'svelte',\n 'react-native',\n 'tanstack-router',\n 'tanstack-start',\n ],\n type: 'string',\n },\n menu: {\n default: false,\n describe:\n 'Show menu for manual integration selection instead of auto-detecting\\nenv: POSTHOG_WIZARD_MENU',\n type: 'boolean',\n },\n benchmark: {\n default: false,\n describe:\n 'Run in benchmark mode with per-phase token tracking\\nenv: POSTHOG_WIZARD_BENCHMARK',\n type: 'boolean',\n },\n 'yara-report': {\n default: false,\n describe:\n 'Print YARA scanner summary after the agent run\\nenv: POSTHOG_WIZARD_YARA_REPORT',\n type: 'boolean',\n hidden: true,\n },\n skill: {\n describe:\n 'Run a specific context-mill skill by ID\\nenv: POSTHOG_WIZARD_SKILL',\n type: 'string',\n },\n });\n },\n (argv) => {\n const options = { ...argv };\n\n // CI mode validation and TTY check\n if (options.ci) {\n if (!options.region) options.region = 'us';\n if (!options.apiKey) {\n setUI(new LoggingUI());\n getUI().intro('PostHog Wizard');\n getUI().log.error(\n 'CI mode requires --api-key (personal API key phx_xxx)',\n );\n process.exit(1);\n return;\n }\n if (!options.installDir) {\n setUI(new LoggingUI());\n getUI().intro('PostHog Wizard');\n getUI().log.error(\n 'CI mode requires --install-dir (directory to install in)',\n );\n process.exit(1);\n return;\n }\n void (async () => {\n const { posthogIntegrationConfig } = await import(\n './src/lib/workflows/posthog-integration/index.js'\n );\n const { FRAMEWORK_REGISTRY } = await import('./src/lib/registry.js');\n const { detectFramework, gatherFrameworkContext } = await import(\n './src/lib/detection/index.js'\n );\n const { analytics } = await import('./src/utils/analytics.js');\n const { wizardAbort } = await import('./src/utils/wizard-abort.js');\n\n // preRun: honor --integration, else auto-detect, then gather\n // framework context. Bypasses onReady hooks by design.\n runWizardCI(posthogIntegrationConfig, options, async (session) => {\n const integration =\n session.integration ??\n (await detectFramework(session.installDir));\n if (!integration) {\n await wizardAbort({\n message:\n 'Could not auto-detect your framework. Please specify --integration on the command line.',\n });\n return;\n }\n session.integration = integration;\n analytics.setTag('integration', integration);\n\n const frameworkConfig = FRAMEWORK_REGISTRY[integration];\n session.frameworkConfig = frameworkConfig;\n\n const context = await gatherFrameworkContext(frameworkConfig, {\n installDir: session.installDir,\n debug: session.debug,\n forceInstall: session.forceInstall,\n default: false,\n signup: session.signup,\n localMcp: session.localMcp,\n ci: true,\n menu: session.menu,\n benchmark: session.benchmark,\n yaraReport: session.yaraReport,\n });\n for (const [key, value] of Object.entries(context)) {\n if (!(key in session.frameworkContext)) {\n session.frameworkContext[key] = value;\n }\n }\n });\n })().catch(() => {\n process.exit(1);\n });\n } else if (isNonInteractiveEnvironment()) {\n // Non-interactive non-CI: error out\n getUI().intro(`PostHog Wizard`);\n getUI().log.error(\n 'This installer requires an interactive terminal (TTY) to run.\\n' +\n 'It appears you are running in a non-interactive environment.\\n' +\n 'Please run the wizard in an interactive terminal.\\n\\n' +\n 'For CI/CD environments, use --ci mode:\\n' +\n ' npx @posthog/wizard --ci --region us --api-key phx_xxx',\n );\n process.exit(1);\n } else if (options.playground) {\n // Playground mode: launch the TUI primitives playground\n void (async () => {\n const { startPlayground } = await import(\n './src/ui/tui/playground/start-playground.js'\n );\n (startPlayground as (version: string) => void)(WIZARD_VERSION);\n })();\n } else if (options.skill) {\n // Run a specific skill by ID\n void (async () => {\n const { createSkillWorkflow } = await import(\n './src/lib/workflows/agent-skill/index.js'\n );\n const skillId = options.skill as string;\n const config = createSkillWorkflow({\n skillId,\n command: 'skill',\n flowKey: 'agent-skill',\n description: `Run skill: ${skillId}`,\n integrationLabel: skillId,\n successMessage: `${skillId} completed!`,\n reportFile: `posthog-${skillId}-report.md`,\n docsUrl: 'https://posthog.com/docs',\n spinnerMessage: `Running ${skillId}...`,\n estimatedDurationMinutes: 5,\n });\n runWizard(config, options);\n })();\n } else {\n // Interactive TTY: run core-integration through the unified workflow path.\n // Same codepath as `npx @posthog/wizard integrate`.\n void (async () => {\n const { posthogIntegrationConfig } = await import(\n './src/lib/workflows/posthog-integration/index.js'\n );\n runWizard(posthogIntegrationConfig, options);\n })();\n }\n },\n )\n .command('mcp <command>', 'MCP server management commands', (yargs) => {\n return yargs\n .command(\n 'add',\n 'Install PostHog MCP server to supported clients',\n (yargs) => {\n return yargs.options({\n local: {\n default: false,\n describe:\n 'Add local development MCP server (http://localhost:8787)',\n type: 'boolean',\n },\n features: {\n describe:\n 'Comma-separated list of features to enable (default: all)',\n type: 'string',\n },\n 'api-key': {\n describe:\n 'PostHog personal API key (phx_xxx) for MCP authentication',\n type: 'string',\n },\n });\n },\n (argv) => {\n const options = { ...argv };\n const mcpFeatures = options.features\n ?.split(',')\n .map((s) => s.trim())\n .filter(Boolean);\n void (async () => {\n const { readApiKeyFromEnv } = await import(\n './src/utils/env-api-key.js'\n );\n const apiKey =\n (options.apiKey as string | undefined) || readApiKeyFromEnv();\n\n try {\n const { startTUI } = await import('./src/ui/tui/start-tui.js');\n const { buildSession } = await import(\n './src/lib/wizard-session.js'\n );\n\n const { Flow } = await import('./src/ui/tui/router.js');\n const tui = startTUI(WIZARD_VERSION, Flow.McpAdd);\n const session = buildSession({\n debug: options.debug,\n localMcp: options.local,\n mcpFeatures,\n apiKey,\n });\n tui.store.session = session;\n } catch {\n // TUI unavailable — fallback to logging\n setUI(new LoggingUI());\n const { addMCPServerToClientsStep } = await import(\n './src/steps/add-mcp-server-to-clients/index.js'\n );\n await addMCPServerToClientsStep({\n local: options.local,\n features: mcpFeatures,\n apiKey,\n });\n }\n })();\n },\n )\n .command(\n 'remove',\n 'Remove PostHog MCP server from supported clients',\n (yargs) => {\n return yargs.options({\n local: {\n default: false,\n describe:\n 'Remove local development MCP server (http://localhost:8787)',\n type: 'boolean',\n },\n });\n },\n (argv) => {\n const options = { ...argv };\n void (async () => {\n try {\n const { startTUI } = await import('./src/ui/tui/start-tui.js');\n const { buildSession } = await import(\n './src/lib/wizard-session.js'\n );\n\n const { Flow } = await import('./src/ui/tui/router.js');\n const tui = startTUI(WIZARD_VERSION, Flow.McpRemove);\n const session = buildSession({\n debug: options.debug,\n localMcp: options.local,\n });\n tui.store.session = session;\n } catch {\n // TUI unavailable — fallback to logging\n setUI(new LoggingUI());\n const { removeMCPServerFromClientsStep } = await import(\n './src/steps/add-mcp-server-to-clients/index.js'\n );\n await removeMCPServerFromClientsStep({\n local: options.local,\n });\n }\n })();\n },\n )\n .demandCommand(1, 'You must specify a subcommand (add or remove)')\n .help();\n });\n\n// ── Skill-based workflow subcommands (derived from registry) ─────────\nfor (const wfConfig of getSubcommandWorkflows()) {\n cli.command(\n wfConfig.command!,\n wfConfig.description,\n (y) => y.options(skillSubcommandOptions),\n (argv) => {\n const options = { ...argv };\n if (options.ci) {\n runWizardCI(wfConfig, options);\n } else {\n runWizard(wfConfig, options);\n }\n },\n );\n}\n\ncli\n .help()\n .alias('help', 'h')\n .version()\n .alias('version', 'v')\n .wrap(process.stdout.isTTY ? cli.terminalWidth() : 80).argv;\n\n/**\n * Run a full wizard workflow in the TUI. Handles the full lifecycle: start TUI,\n * build session, run detection, wait for intro gate, execute the\n * agent pipeline, wait for outro dismissal, then exit.\n */\nfunction runWizard(\n config: WorkflowConfig,\n options: Record<string, unknown>,\n): void {\n void (async () => {\n try {\n const installDir = (options.installDir as string) || process.cwd();\n\n const { startTUI } = await import('./src/ui/tui/start-tui.js');\n const { buildSession } = await import('./src/lib/wizard-session.js');\n\n // flowKey values match Flow enum values by convention\n const tui = startTUI(WIZARD_VERSION, config.flowKey as any);\n\n const session = buildSession({\n debug: options.debug as boolean | undefined,\n forceInstall: options.forceInstall as boolean | undefined,\n localMcp: options.localMcp as boolean | undefined,\n installDir,\n ci: false,\n signup: options.signup as boolean | undefined,\n apiKey: options.apiKey as string | undefined,\n projectId: options.projectId as string | undefined,\n email: options.email as string | undefined,\n menu: options.menu as boolean | undefined,\n integration: options.integration as any,\n benchmark: options.benchmark as boolean | undefined,\n yaraReport: options.yaraReport as boolean | undefined,\n });\n // Set workflow metadata for TUI display\n session.workflowLabel = config.flowKey;\n const runDef = typeof config.run === 'object' ? config.run : null;\n session.skillId = runDef?.skillId ?? null;\n\n tui.store.session = session;\n\n await tui.store.runReadyHooks();\n await tui.store.getGate('intro');\n\n const { runAgent } = await import('./src/lib/agent/agent-runner.js');\n await runAgent(config, tui.store.session);\n\n await new Promise<void>((resolve) => {\n const unsub = tui.store.subscribe(() => {\n if (tui.store.session.skillsComplete) {\n unsub();\n resolve();\n }\n });\n if (tui.store.session.skillsComplete) {\n unsub();\n resolve();\n }\n });\n process.exit(0);\n } catch (err) {\n if (runtimeEnv('DEBUG') || runtimeEnv('POSTHOG_WIZARD_DEBUG')) {\n console.error('TUI init failed:', err); // eslint-disable-line no-console\n }\n }\n })();\n}\n\n/**\n * CI-mode pipeline shared by every non-interactive entry point.\n *\n * Validates flags, builds a `ci:true` session, runs `preRun` (or the\n * workflow's `onReady` hooks by default), executes `runAgent`, and\n * routes any failure through `wizardAbort`. `wizardAbort` owns all\n * exits — never add a raw `process.exit` here.\n */\nfunction runWizardCI(\n config: WorkflowConfig,\n options: Record<string, unknown>,\n preRun?: (session: WizardSession) => Promise<void>,\n): void {\n setUI(new LoggingUI());\n if (!options.region) options.region = 'us';\n if (!options.apiKey) {\n getUI().intro('PostHog Wizard');\n getUI().log.error('CI mode requires --api-key (personal API key phx_xxx)');\n process.exit(1);\n }\n if (!options.installDir) {\n getUI().intro('PostHog Wizard');\n getUI().log.error(\n 'CI mode requires --install-dir (directory to install in)',\n );\n process.exit(1);\n }\n\n void (async () => {\n const path = await import('path');\n const { buildSession } = await import('./src/lib/wizard-session.js');\n const { readEnvironment } = await import('./src/utils/environment.js');\n const { readApiKeyFromEnv } = await import('./src/utils/env-api-key.js');\n const { configureLogFileFromEnvironment, logToFile } = await import(\n './src/utils/debug.js'\n );\n const { wizardAbort, WizardError } = await import(\n './src/utils/wizard-abort.js'\n );\n\n configureLogFileFromEnvironment();\n\n const env = readEnvironment();\n const apiKey =\n (options.apiKey as string) ?? readApiKeyFromEnv() ?? undefined;\n const installDir = path.isAbsolute(options.installDir as string)\n ? (options.installDir as string)\n : path.join(process.cwd(), options.installDir as string);\n\n const session = buildSession({\n debug: options.debug as boolean | undefined,\n forceInstall: options.forceInstall as boolean | undefined,\n installDir,\n ci: true,\n signup: options.signup as boolean | undefined,\n localMcp: options.localMcp as boolean | undefined,\n apiKey,\n email: options.email as string | undefined,\n menu: options.menu as boolean | undefined,\n integration: options.integration as any, // eslint-disable-line @typescript-eslint/no-explicit-any\n projectId: options.projectId as string | undefined,\n benchmark: options.benchmark as boolean | undefined,\n yaraReport: options.yaraReport as boolean | undefined,\n ...env,\n });\n session.workflowLabel = config.flowKey;\n const runDef = typeof config.run === 'object' ? config.run : null;\n session.skillId = runDef?.skillId ?? null;\n\n getUI().intro('Welcome to the PostHog setup wizard');\n getUI().log.info(`Running ${config.flowKey} in CI mode`);\n\n try {\n if (preRun) {\n await preRun(session);\n } else {\n // Run onReady hooks against a minimal store-less context.\n const readyCtx = {\n session,\n setFrameworkContext: (key: string, value: unknown) => {\n session.frameworkContext[key] = value;\n },\n setFrameworkConfig: () => undefined,\n setDetectedFramework: () => undefined,\n setUnsupportedVersion: () => undefined,\n addDiscoveredFeature: () => undefined,\n setDetectionComplete: () => undefined,\n };\n for (const step of config.steps) {\n if (step.onReady) {\n await step.onReady(readyCtx);\n }\n }\n\n // Surface detectError written by the workflow's detect hook.\n const detectError = session.frameworkContext.detectError as\n | { kind: string; [k: string]: unknown }\n | undefined;\n if (detectError) {\n await wizardAbort({\n message: `Prerequisites not met: ${detectError.kind}\\n\\nSee ${\n runDef?.docsUrl ?? 'https://posthog.com/docs'\n }`,\n error: new WizardError(`${config.flowKey} prerequisites failed`, {\n integration: config.flowKey,\n detect_error_kind: detectError.kind,\n }),\n });\n }\n }\n\n const { runAgent } = await import('./src/lib/agent/agent-runner.js');\n await runAgent(config, session);\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n const errorStack =\n error instanceof Error && error.stack ? error.stack : undefined;\n\n logToFile(`[bin.ts CI] ERROR: ${errorMessage}`);\n if (errorStack) logToFile(`[bin.ts CI] STACK: ${errorStack}`);\n\n const debugInfo = session.debug && errorStack ? `\\n\\n${errorStack}` : '';\n const docsUrl =\n session.frameworkConfig?.metadata.docsUrl ??\n runDef?.docsUrl ??\n 'https://posthog.com/docs';\n await wizardAbort({\n message: `Something went wrong: ${errorMessage}\\n\\nYou can read the documentation at ${docsUrl} to set up manually.${debugInfo}`,\n error: error as Error,\n });\n }\n })().catch(() => {\n process.exit(1);\n });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"bin.js","names":[],"sources":["../src/utils/environment.ts","../src/lib/workflows/revenue-analytics/detect.ts","../src/lib/workflows/revenue-analytics/steps.ts","../src/lib/workflows/revenue-analytics/index.ts","../src/lib/workflows/posthog-doctor/steps.ts","../src/lib/workflows/posthog-doctor/types.ts","../src/lib/workflows/posthog-doctor/fetch.ts","../src/lib/workflows/posthog-doctor/kind-metadata.ts","../src/lib/workflows/posthog-doctor/index.ts","../src/lib/workflows/workflow-registry.ts","../bin.ts"],"sourcesContent":["import readEnvModule from 'read-env';\n\nconst readEnv =\n typeof readEnvModule === 'function'\n ? readEnvModule\n : (readEnvModule as any).default;\nimport { tryGetPackageJson } from './setup-utils';\nimport type { WizardOptions } from './types';\nimport fg from 'fast-glob';\nimport { IS_DEV } from '../lib/constants';\n\nexport function isNonInteractiveEnvironment(): boolean {\n if (IS_DEV) {\n return false;\n }\n\n if (!process.stdout.isTTY || !process.stderr.isTTY) {\n return true;\n }\n\n return false;\n}\n\nexport function readEnvironment(): Record<string, unknown> {\n const result = readEnv('POSTHOG_WIZARD');\n\n return result;\n}\n\nexport async function detectEnvVarPrefix(\n options: WizardOptions,\n): Promise<string> {\n const packageJson = await tryGetPackageJson(options);\n if (!packageJson) return 'VITE_PUBLIC_';\n\n const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };\n const has = (name: string) => name in deps;\n const hasAnyFile = async (patterns: string[]) => {\n const matches = await fg(patterns, {\n cwd: options.installDir,\n absolute: false,\n onlyFiles: true,\n ignore: ['**/node_modules/**'],\n });\n return matches.length > 0;\n };\n\n // --- Next.js\n if (has('next') || (await hasAnyFile(['**/next.config.{js,ts,mjs,cjs}']))) {\n return 'NEXT_PUBLIC_';\n }\n\n // --- Create React App\n if (\n has('react-scripts') ||\n has('create-react-app') ||\n (await hasAnyFile(['**/config-overrides.js']))\n ) {\n return 'REACT_APP_';\n }\n\n // --- Vite (vanilla, TanStack, Solid, etc.)\n // Note: Vite does not need PUBLIC_ but we use it to follow the docs, to improve the chances of an LLM getting it right.\n if (has('vite') || (await hasAnyFile(['**/vite.config.{js,ts,mjs,cjs}']))) {\n return 'VITE_PUBLIC_';\n }\n\n // --- SvelteKit\n if (\n has('@sveltejs/kit') ||\n (await hasAnyFile(['**/svelte.config.{js,ts}']))\n ) {\n return 'PUBLIC_';\n }\n\n // --- TanStack Start (uses Vite)\n if (\n has('@tanstack/start') ||\n (await hasAnyFile(['**/tanstack.config.{js,ts}']))\n ) {\n return 'VITE_PUBLIC_';\n }\n\n // --- SolidStart (uses Vite)\n if (has('solid-start') || (await hasAnyFile(['**/solid.config.{js,ts}']))) {\n return 'VITE_PUBLIC_';\n }\n\n // --- Astro\n if (has('astro') || (await hasAnyFile(['**/astro.config.{js,ts,mjs}']))) {\n return 'PUBLIC_';\n }\n\n // We default to Vite if we can't detect a specific framework, since it's the most commonly used.\n return 'VITE_PUBLIC_';\n}\n","/**\n * Revenue analytics prerequisite detection.\n *\n * Scans the project for PostHog + Stripe SDKs and writes results\n * into frameworkContext for the intro screen to render.\n */\n\nimport type { Dirent } from 'fs';\nimport { readFileSync, readdirSync, existsSync, statSync } from 'fs';\nimport { join, relative } from 'path';\nimport { IGNORED_DIRS } from '../../../utils/file-utils.js';\nimport type { WizardSession } from '../../wizard-session.js';\nimport type { AbortCase } from '../../agent/agent-runner.js';\n\nexport const POSTHOG_SDKS = [\n 'posthog-js',\n 'posthog-node',\n 'posthog-react-native',\n 'posthog-android',\n 'posthog-ios',\n];\n\nexport const STRIPE_SDKS = [\n 'stripe',\n '@stripe/stripe-js',\n '@stripe/react-stripe-js',\n];\n\ninterface PackageMatch {\n /** Path to the package.json relative to installDir */\n path: string;\n posthogSdks: string[];\n stripeSdks: string[];\n}\n\n/**\n * Structured detection errors. The screen renders each kind into JSX\n * with proper formatting — keeps error data separate from presentation.\n */\nexport type RevenueDetectError =\n | {\n kind: 'bad-directory';\n path: string;\n reason: 'missing' | 'not-dir' | 'unreadable';\n }\n | { kind: 'no-package-json' }\n | { kind: 'no-sdks'; scannedCount: number }\n | { kind: 'missing-posthog'; foundStripe: string[] }\n | { kind: 'missing-stripe'; foundPosthog: string[] };\n\n/** `[ABORT] <reason>` cases the revenue analytics skill can emit. */\nexport const REVENUE_ABORT_CASES: AbortCase[] = [\n {\n // Skill emits: [ABORT] Could not find a PostHog distinct_id\n match: /^could not find a posthog distinct_id$/i,\n message: 'Could not find a PostHog distinct_id',\n body:\n 'The agent could not find PostHog distinct_id usage in your codebase. ' +\n 'Your users must be identified in PostHog before they can be tagged in Stripe. ' +\n 'Please identify your users and try again.',\n docsUrl: 'https://posthog.com/docs/product-analytics/identify',\n },\n {\n // Skill emits: [ABORT] Could not find a Stripe integration\n match: /^could not find a stripe integration$/i,\n message: 'Could not find a Stripe integration',\n body:\n 'The Wizard could not find an existing Stripe customer, charge, ' +\n 'subscription, or other Stripe operations. Please run the Revenue ' +\n 'Analytics Wizard on a project with an existing Stripe integration.',\n docsUrl: 'https://posthog.com/docs/revenue-analytics',\n },\n];\n\n/**\n * Recursively find all package.json files under installDir (max depth 3),\n * skipping common ignored directories. Returns matches with detected SDKs.\n */\nfunction findPackageJsons(installDir: string, maxDepth = 3): PackageMatch[] {\n const matches: PackageMatch[] = [];\n\n function scan(dir: string, depth: number): void {\n if (depth > maxDepth) return;\n\n let entries: Dirent[];\n try {\n entries = readdirSync(dir, { withFileTypes: true });\n } catch {\n return;\n }\n\n for (const entry of entries) {\n if (entry.name.startsWith('.') && entry.name !== '.') continue;\n if (IGNORED_DIRS.has(entry.name)) continue;\n\n const fullPath = join(dir, entry.name);\n\n if (entry.isFile() && entry.name === 'package.json') {\n try {\n const pkg = JSON.parse(readFileSync(fullPath, 'utf-8')) as {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n };\n const depNames = [\n ...Object.keys(pkg.dependencies ?? {}),\n ...Object.keys(pkg.devDependencies ?? {}),\n ];\n const posthogSdks = depNames.filter((d) => POSTHOG_SDKS.includes(d));\n const stripeSdks = depNames.filter((d) => STRIPE_SDKS.includes(d));\n matches.push({\n path: relative(installDir, fullPath) || 'package.json',\n posthogSdks,\n stripeSdks,\n });\n } catch {\n // Skip malformed package.json\n }\n } else if (entry.isDirectory()) {\n scan(fullPath, depth + 1);\n }\n }\n }\n\n scan(installDir, 0);\n return matches;\n}\n\n/**\n * Scan `session.installDir` for PostHog + Stripe SDKs. Writes detection\n * results into frameworkContext via the callback — either the detected\n * SDK lists (for the intro screen) or a `RevenueDetectError` on failure.\n *\n * The skill install happens later in the bootstrap runner, not here.\n */\nexport function detectRevenuePrerequisites(\n session: WizardSession,\n setFrameworkContext: (key: string, value: unknown) => void,\n): void {\n const fail = (error: RevenueDetectError) =>\n setFrameworkContext('detectError', error);\n\n const installDir = session.installDir;\n\n // Verify the install directory exists and is readable\n if (!existsSync(installDir)) {\n fail({ kind: 'bad-directory', path: installDir, reason: 'missing' });\n return;\n }\n try {\n if (!statSync(installDir).isDirectory()) {\n fail({ kind: 'bad-directory', path: installDir, reason: 'not-dir' });\n return;\n }\n } catch {\n fail({ kind: 'bad-directory', path: installDir, reason: 'unreadable' });\n return;\n }\n\n // Find all package.json files (root + monorepo subpackages)\n const matches = findPackageJsons(installDir);\n\n if (matches.length === 0) {\n fail({ kind: 'no-package-json' });\n return;\n }\n\n // Aggregate detected SDKs across all package.json files\n const allPosthogSdks = new Set<string>();\n const allStripeSdks = new Set<string>();\n for (const match of matches) {\n for (const sdk of match.posthogSdks) allPosthogSdks.add(sdk);\n for (const sdk of match.stripeSdks) allStripeSdks.add(sdk);\n }\n\n const detectedPosthogSdks = [...allPosthogSdks];\n const detectedStripeSdks = [...allStripeSdks];\n\n if (detectedPosthogSdks.length === 0 && detectedStripeSdks.length === 0) {\n fail({ kind: 'no-sdks', scannedCount: matches.length });\n return;\n }\n\n if (detectedPosthogSdks.length === 0) {\n fail({ kind: 'missing-posthog', foundStripe: detectedStripeSdks });\n return;\n }\n\n if (detectedStripeSdks.length === 0) {\n fail({ kind: 'missing-stripe', foundPosthog: detectedPosthogSdks });\n return;\n }\n\n setFrameworkContext('detectedPosthogSdks', detectedPosthogSdks);\n setFrameworkContext('detectedStripeSdks', detectedStripeSdks);\n setFrameworkContext(\n 'detectedPackagePaths',\n matches\n .filter((m) => m.posthogSdks.length > 0 || m.stripeSdks.length > 0)\n .map((m) => m.path),\n );\n}\n","/**\n * Revenue analytics workflow step list.\n *\n * The detect step checks for PostHog + Stripe SDKs. The skill install\n * and agent run live in the workflow runner (see agent-runner.ts).\n */\n\nimport type { Workflow } from '../workflow-step.js';\nimport { RunPhase } from '../../wizard-session.js';\nimport { detectRevenuePrerequisites } from './detect.js';\n\nexport const REVENUE_ANALYTICS_WORKFLOW: Workflow = [\n {\n id: 'detect',\n label: 'Detecting prerequisites',\n // Headless step: no screen, no gate. onReady fires after bin.ts\n // assigns the session — the hook scans for PostHog + Stripe SDKs\n // and writes the results (or a detectError) to frameworkContext\n // for the intro screen to render.\n onReady: (ctx) =>\n detectRevenuePrerequisites(ctx.session, ctx.setFrameworkContext),\n },\n {\n id: 'intro',\n label: 'Welcome',\n screen: 'revenue-intro',\n gate: (session) => session.setupConfirmed,\n },\n {\n id: 'auth',\n label: 'Authentication',\n screen: 'auth',\n isComplete: (session) => session.credentials !== null,\n },\n {\n id: 'run',\n label: 'Revenue analytics',\n screen: 'run',\n isComplete: (session) =>\n session.runPhase === RunPhase.Completed ||\n session.runPhase === RunPhase.Error,\n },\n {\n id: 'outro',\n label: 'Done',\n screen: 'outro',\n isComplete: (session) => session.outroDismissed,\n },\n {\n id: 'skills',\n label: 'Skills',\n screen: 'keep-skills',\n },\n];\n","import type { WorkflowConfig } from '../workflow-step.js';\nimport { REVENUE_ANALYTICS_WORKFLOW } from './steps.js';\nimport { REVENUE_ABORT_CASES } from './detect.js';\n\nexport const revenueAnalyticsConfig: WorkflowConfig = {\n command: 'revenue',\n description: 'Set up PostHog revenue analytics (e.g. Stripe integration)',\n flowKey: 'revenue-analytics-setup',\n steps: REVENUE_ANALYTICS_WORKFLOW,\n run: {\n skillId: 'revenue-analytics-setup',\n integrationLabel: 'revenue-analytics-setup',\n customPrompt: () => 'Set up revenue analytics for this project.',\n successMessage: 'Revenue analytics configured!',\n reportFile: 'posthog-revenue-report.md',\n docsUrl: 'https://posthog.com/docs/revenue-analytics',\n spinnerMessage: 'Setting up revenue analytics...',\n estimatedDurationMinutes: 5,\n abortCases: REVENUE_ABORT_CASES,\n },\n requires: ['posthog-integration'],\n};\n\nexport { REVENUE_ANALYTICS_WORKFLOW } from './steps.js';\nexport {\n detectRevenuePrerequisites,\n POSTHOG_SDKS,\n STRIPE_SDKS,\n type RevenueDetectError,\n} from './detect.js';\n","import type { Workflow } from '../workflow-step.js';\n\nexport const POSTHOG_DOCTOR_WORKFLOW: Workflow = [\n {\n id: 'intro',\n label: 'Welcome',\n screen: 'doctor-intro',\n gate: (session) => session.setupConfirmed,\n },\n {\n id: 'auth',\n label: 'Authentication',\n screen: 'auth',\n isComplete: (session) => session.credentials !== null,\n },\n {\n id: 'report',\n label: 'Doctor report',\n screen: 'doctor-report',\n isComplete: (session) => session.outroData !== null,\n },\n {\n id: 'outro',\n label: 'Done',\n screen: 'outro',\n isComplete: (session) => session.outroDismissed,\n },\n];\n","import { z } from 'zod';\n\nexport const HealthIssueSeveritySchema = z.enum([\n 'critical',\n 'warning',\n 'info',\n]);\nexport type HealthIssueSeverity = z.infer<typeof HealthIssueSeveritySchema>;\n\nexport const HealthIssueStatusSchema = z.enum(['active', 'resolved']);\n\nexport const HealthIssueSchema = z.object({\n id: z.string(),\n kind: z.string(),\n severity: HealthIssueSeveritySchema,\n status: HealthIssueStatusSchema,\n dismissed: z.boolean(),\n created_at: z.string(),\n updated_at: z.string(),\n resolved_at: z.string().nullable().optional(),\n});\nexport type HealthIssue = z.infer<typeof HealthIssueSchema>;\n\nexport const HealthIssueListResponseSchema = z.object({\n results: z.array(HealthIssueSchema),\n count: z.number().optional(),\n next: z.string().nullable().optional(),\n previous: z.string().nullable().optional(),\n});\nexport type HealthIssueListResponse = z.infer<\n typeof HealthIssueListResponseSchema\n>;\n\nexport interface HealthIssueSummary {\n total: number;\n by_severity: Record<HealthIssueSeverity, number>;\n}\n","import axios from 'axios';\nimport { analytics } from '../../../utils/analytics';\nimport { handleApiError } from '../../api';\nimport { WIZARD_USER_AGENT } from '../../constants';\nimport { HealthIssueListResponseSchema, type HealthIssue } from './types';\n\nexport async function fetchHealthIssues(\n accessToken: string,\n baseUrl: string,\n projectId: number,\n): Promise<HealthIssue[]> {\n const endpoint = `/api/environments/${projectId}/health_issues/`;\n const url = `${baseUrl}${endpoint}?status=active&dismissed=false&limit=250`;\n try {\n const response = await axios.get(url, {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n 'User-Agent': WIZARD_USER_AGENT,\n },\n });\n return HealthIssueListResponseSchema.parse(response.data).results;\n } catch (error) {\n const apiError = handleApiError(error, 'fetch health issues');\n analytics.captureException(apiError, { endpoint, baseUrl, projectId });\n throw apiError;\n }\n}\n","import { POSTHOG_DOCS_URL } from '../../constants';\n\nexport interface KindMeta {\n title: string;\n description: string;\n docsUrl: string;\n}\n\nexport const KIND_METADATA: Record<string, KindMeta> = {\n ingestion_lag: {\n title: 'Ingestion is delayed',\n description:\n 'Events are being received but are taking longer than usual to appear.',\n docsUrl: `${POSTHOG_DOCS_URL}/support/troubleshooting`,\n },\n ingestion_warning: {\n title: 'Ingestion warnings on recent events',\n description:\n 'Some recent events were rejected or flagged by the ingestion pipeline.',\n docsUrl: `${POSTHOG_DOCS_URL}/support/troubleshooting`,\n },\n sdk_outdated: {\n title: 'SDK version is out of date',\n description:\n 'One or more SDKs are running an old version. Upgrade to get the latest fixes.',\n docsUrl: `${POSTHOG_DOCS_URL}/libraries`,\n },\n no_live_events: {\n title: 'No $pageview or $screen events in the last 30 days',\n description:\n 'PostHog is not receiving page or screen events from this project.',\n docsUrl: `${POSTHOG_DOCS_URL}/getting-started/install`,\n },\n no_pageleave_events: {\n title: '$pageleave events not being sent',\n description:\n 'Enable pageleave tracking to power bounce rate and session duration.',\n docsUrl: `${POSTHOG_DOCS_URL}/libraries/js#config`,\n },\n scroll_depth: {\n title: 'Scroll depth tracking disabled',\n description:\n 'Turn on scroll depth to capture how far users read each page.',\n docsUrl: `${POSTHOG_DOCS_URL}/libraries/js#config`,\n },\n authorized_urls: {\n title: 'No authorized URLs configured',\n description:\n 'Some web analytics filters require at least one authorized URL to work.',\n docsUrl: `${POSTHOG_DOCS_URL}/web-analytics/faq`,\n },\n reverse_proxy: {\n title: 'No reverse proxy detected',\n description: 'A reverse proxy reduces data loss from ad blockers.',\n docsUrl: `${POSTHOG_DOCS_URL}/advanced/proxy`,\n },\n web_vitals: {\n title: 'Web Vitals tracking disabled',\n description:\n 'Enable Web Vitals to capture LCP, CLS and other performance metrics.',\n docsUrl: `${POSTHOG_DOCS_URL}/web-analytics/web-vitals`,\n },\n materialized_view_failure: {\n title: 'A materialized view is failing',\n description: 'A data modeling pipeline failed its most recent run.',\n docsUrl: `${POSTHOG_DOCS_URL}/data-warehouse`,\n },\n external_data_failure: {\n title: 'External data source is failing',\n description: 'An external data source sync failed and data may be stale.',\n docsUrl: `${POSTHOG_DOCS_URL}/data-warehouse/sources`,\n },\n};\n\nexport const UNKNOWN_KIND_META: KindMeta = {\n title: 'Unknown issue',\n description:\n 'PostHog reported an issue kind the wizard does not yet recognize.',\n docsUrl: POSTHOG_DOCS_URL,\n};\n\nexport function getKindMeta(kind: string): KindMeta {\n return KIND_METADATA[kind] ?? { ...UNKNOWN_KIND_META, title: kind };\n}\n","import type { WorkflowConfig } from '../workflow-step.js';\nimport { POSTHOG_DOCTOR_WORKFLOW } from './steps.js';\n\nexport const posthogDoctorConfig: WorkflowConfig = {\n command: 'doctor',\n description:\n 'Diagnose your PostHog project for configuration issues and setup warnings',\n flowKey: 'posthog-doctor',\n steps: POSTHOG_DOCTOR_WORKFLOW,\n};\n\nexport { POSTHOG_DOCTOR_WORKFLOW } from './steps.js';\nexport { fetchHealthIssues } from './fetch.js';\nexport { getKindMeta, KIND_METADATA } from './kind-metadata.js';\nexport type { KindMeta } from './kind-metadata.js';\nexport type {\n HealthIssue,\n HealthIssueSeverity,\n HealthIssueSummary,\n} from './types.js';\n","/**\n * Central registry of all wizard workflows.\n *\n * Adding a new workflow:\n * 1. Create src/lib/workflows/<name>/ with index.ts exporting a WorkflowConfig\n * 2. Import and add it to WORKFLOW_REGISTRY below\n * 3. Add a matching Flow enum entry in src/ui/tui/flows.ts\n * 4. (If custom intro screen) add to src/ui/tui/screen-registry.tsx\n *\n * flows.ts, store.ts, and bin.ts all derive their wiring from this array —\n * no need to touch those files when adding a workflow.\n */\n\nimport type { WorkflowConfig } from './workflow-step.js';\nimport { posthogIntegrationConfig } from './posthog-integration/index.js';\nimport { revenueAnalyticsConfig } from './revenue-analytics/index.js';\nimport { posthogDoctorConfig } from './posthog-doctor/index.js';\n\nexport const WORKFLOW_REGISTRY: WorkflowConfig[] = [\n posthogIntegrationConfig,\n revenueAnalyticsConfig,\n posthogDoctorConfig,\n];\n\n/** Look up a workflow config by its flowKey. */\nexport function getWorkflowConfig(flowKey: string): WorkflowConfig | undefined {\n return WORKFLOW_REGISTRY.find((c) => c.flowKey === flowKey);\n}\n\n/** All workflow configs that are exposed as CLI subcommands. */\nexport function getSubcommandWorkflows(): WorkflowConfig[] {\n return WORKFLOW_REGISTRY.filter((c) => c.command != null);\n}\n","#!/usr/bin/env node\nimport { satisfies } from 'semver';\nimport { red } from './src/utils/logging';\n\nimport yargs from 'yargs';\nimport { hideBin } from 'yargs/helpers';\nimport { VERSION } from './src/lib/version.js';\n\nconst WIZARD_VERSION = VERSION;\n\nconst NODE_VERSION_RANGE = '>=18.17.0';\n\n// Have to run this above the other imports because they are importing clack that\n// has the problematic imports.\nif (!satisfies(process.version, NODE_VERSION_RANGE)) {\n red(\n `PostHog wizard requires Node.js ${NODE_VERSION_RANGE}. You are using Node.js ${process.version}. Please upgrade your Node.js version.`,\n );\n process.exit(1);\n}\n\nimport { isNonInteractiveEnvironment } from './src/utils/environment';\nimport { getUI, setUI } from './src/ui';\nimport { LoggingUI } from './src/ui/logging-ui';\nimport { getSubcommandWorkflows } from './src/lib/workflows/workflow-registry';\nimport type { WorkflowConfig } from './src/lib/workflows/workflow-step';\nimport type { WizardSession } from './src/lib/wizard-session';\nimport { POSTHOG_DOCS_URL } from './src/lib/constants';\nimport { runtimeEnv } from '@env';\n\n// Test mock server — only loaded when NODE_ENV is 'test'.\n// In production builds, tsdown replaces process.env.NODE_ENV with 'production',\n// making this block dead code.\nif (process.env.NODE_ENV === 'test') {\n void (async () => {\n try {\n const { server } = await import('./e2e-tests/mocks/server.js');\n server.listen({\n onUnhandledRequest: 'bypass',\n });\n } catch (error) {\n // Mock server import failed - this can happen during non-E2E tests\n }\n })();\n}\n\n/** Shared yargs options for skill-based workflow subcommands. */\nconst skillSubcommandOptions = {\n debug: {\n default: false,\n describe: 'Enable verbose logging',\n type: 'boolean' as const,\n },\n 'install-dir': {\n describe: 'Directory to install in',\n type: 'string' as const,\n },\n 'local-mcp': {\n default: false,\n describe: 'Use local MCP server',\n type: 'boolean' as const,\n },\n benchmark: {\n default: false,\n describe: 'Run in benchmark mode',\n type: 'boolean' as const,\n },\n 'yara-report': {\n default: false,\n describe: 'Print YARA scanner summary',\n type: 'boolean' as const,\n hidden: true,\n },\n};\n\nconst cli = yargs(hideBin(process.argv))\n .env('POSTHOG_WIZARD')\n // global options\n .options({\n debug: {\n default: false,\n describe: 'Enable verbose logging\\nenv: POSTHOG_WIZARD_DEBUG',\n type: 'boolean',\n },\n region: {\n describe: 'PostHog cloud region\\nenv: POSTHOG_WIZARD_REGION',\n choices: ['us', 'eu'],\n type: 'string',\n },\n default: {\n default: true,\n describe:\n 'Use default options for all prompts\\nenv: POSTHOG_WIZARD_DEFAULT',\n type: 'boolean',\n },\n signup: {\n default: false,\n describe:\n 'Create a new PostHog account during setup\\nenv: POSTHOG_WIZARD_SIGNUP',\n type: 'boolean',\n },\n 'local-mcp': {\n default: false,\n describe:\n 'Use local MCP server at http://localhost:8787/mcp\\nenv: POSTHOG_WIZARD_LOCAL_MCP',\n type: 'boolean',\n },\n ci: {\n default: false,\n describe:\n 'Enable CI mode for non-interactive execution\\nenv: POSTHOG_WIZARD_CI',\n type: 'boolean',\n },\n 'api-key': {\n describe:\n 'PostHog personal API key (phx_xxx) for authentication\\nenv: POSTHOG_WIZARD_API_KEY',\n type: 'string',\n },\n 'project-id': {\n describe:\n 'PostHog project ID to use (optional; when not set, uses default from API key or OAuth)\\nenv: POSTHOG_WIZARD_PROJECT_ID',\n type: 'string',\n },\n email: {\n describe:\n 'Email address for signup (used with --signup)\\nenv: POSTHOG_WIZARD_EMAIL',\n type: 'string',\n },\n })\n .command(\n ['$0'],\n 'Run the PostHog setup wizard',\n (yargs) => {\n return yargs.options({\n 'force-install': {\n default: false,\n describe:\n 'Force install packages even if peer dependency checks fail\\nenv: POSTHOG_WIZARD_FORCE_INSTALL',\n type: 'boolean',\n },\n 'install-dir': {\n describe:\n 'Directory to install PostHog in\\nenv: POSTHOG_WIZARD_INSTALL_DIR',\n type: 'string',\n },\n playground: {\n default: false,\n describe: 'Launch the TUI primitives playground',\n type: 'boolean',\n },\n integration: {\n describe: 'Integration to set up',\n choices: [\n 'nextjs',\n 'astro',\n 'react',\n 'svelte',\n 'react-native',\n 'tanstack-router',\n 'tanstack-start',\n ],\n type: 'string',\n },\n menu: {\n default: false,\n describe:\n 'Show menu for manual integration selection instead of auto-detecting\\nenv: POSTHOG_WIZARD_MENU',\n type: 'boolean',\n },\n benchmark: {\n default: false,\n describe:\n 'Run in benchmark mode with per-phase token tracking\\nenv: POSTHOG_WIZARD_BENCHMARK',\n type: 'boolean',\n },\n 'yara-report': {\n default: false,\n describe:\n 'Print YARA scanner summary after the agent run\\nenv: POSTHOG_WIZARD_YARA_REPORT',\n type: 'boolean',\n hidden: true,\n },\n skill: {\n describe:\n 'Run a specific context-mill skill by ID\\nenv: POSTHOG_WIZARD_SKILL',\n type: 'string',\n },\n });\n },\n (argv) => {\n const options = { ...argv };\n\n // CI mode validation and TTY check\n if (options.ci) {\n if (!options.region) options.region = 'us';\n if (!options.apiKey) {\n setUI(new LoggingUI());\n getUI().intro('PostHog Wizard');\n getUI().log.error(\n 'CI mode requires --api-key (personal API key phx_xxx)',\n );\n process.exit(1);\n return;\n }\n if (!options.installDir) {\n setUI(new LoggingUI());\n getUI().intro('PostHog Wizard');\n getUI().log.error(\n 'CI mode requires --install-dir (directory to install in)',\n );\n process.exit(1);\n return;\n }\n void (async () => {\n const { posthogIntegrationConfig } = await import(\n './src/lib/workflows/posthog-integration/index.js'\n );\n const { FRAMEWORK_REGISTRY } = await import('./src/lib/registry.js');\n const { detectFramework, gatherFrameworkContext } = await import(\n './src/lib/detection/index.js'\n );\n const { analytics } = await import('./src/utils/analytics.js');\n const { wizardAbort } = await import('./src/utils/wizard-abort.js');\n\n // preRun: honor --integration, else auto-detect, then gather\n // framework context. Bypasses onReady hooks by design.\n runWizardCI(posthogIntegrationConfig, options, async (session) => {\n const integration =\n session.integration ??\n (await detectFramework(session.installDir));\n if (!integration) {\n await wizardAbort({\n message:\n 'Could not auto-detect your framework. Please specify --integration on the command line.',\n });\n return;\n }\n session.integration = integration;\n analytics.setTag('integration', integration);\n\n const frameworkConfig = FRAMEWORK_REGISTRY[integration];\n session.frameworkConfig = frameworkConfig;\n\n const context = await gatherFrameworkContext(frameworkConfig, {\n installDir: session.installDir,\n debug: session.debug,\n forceInstall: session.forceInstall,\n default: false,\n signup: session.signup,\n localMcp: session.localMcp,\n ci: true,\n menu: session.menu,\n benchmark: session.benchmark,\n yaraReport: session.yaraReport,\n });\n for (const [key, value] of Object.entries(context)) {\n if (!(key in session.frameworkContext)) {\n session.frameworkContext[key] = value;\n }\n }\n });\n })().catch(() => {\n process.exit(1);\n });\n } else if (isNonInteractiveEnvironment()) {\n // Non-interactive non-CI: error out\n getUI().intro(`PostHog Wizard`);\n getUI().log.error(\n 'This installer requires an interactive terminal (TTY) to run.\\n' +\n 'It appears you are running in a non-interactive environment.\\n' +\n 'Please run the wizard in an interactive terminal.\\n\\n' +\n 'For CI/CD environments, use --ci mode:\\n' +\n ' npx @posthog/wizard --ci --region us --api-key phx_xxx',\n );\n process.exit(1);\n } else if (options.playground) {\n // Playground mode: launch the TUI primitives playground\n void (async () => {\n const { startPlayground } = await import(\n './src/ui/tui/playground/start-playground.js'\n );\n (startPlayground as (version: string) => void)(WIZARD_VERSION);\n })();\n } else if (options.skill) {\n // Run a specific skill by ID\n void (async () => {\n const { createSkillWorkflow } = await import(\n './src/lib/workflows/agent-skill/index.js'\n );\n const skillId = options.skill as string;\n const config = createSkillWorkflow({\n skillId,\n command: 'skill',\n flowKey: 'agent-skill',\n description: `Run skill: ${skillId}`,\n integrationLabel: skillId,\n successMessage: `${skillId} completed!`,\n reportFile: `posthog-${skillId}-report.md`,\n docsUrl: POSTHOG_DOCS_URL,\n spinnerMessage: `Running ${skillId}...`,\n estimatedDurationMinutes: 5,\n });\n runWizard(config, { ...options, skillId });\n })();\n } else {\n // Interactive TTY: run core-integration through the unified workflow path.\n // Same codepath as `npx @posthog/wizard integrate`.\n void (async () => {\n const { posthogIntegrationConfig } = await import(\n './src/lib/workflows/posthog-integration/index.js'\n );\n runWizard(posthogIntegrationConfig, options);\n })();\n }\n },\n )\n .command('mcp <command>', 'MCP server management commands', (yargs) => {\n return yargs\n .command(\n 'add',\n 'Install PostHog MCP server to supported clients',\n (yargs) => {\n return yargs.options({\n local: {\n default: false,\n describe:\n 'Add local development MCP server (http://localhost:8787)',\n type: 'boolean',\n },\n features: {\n describe:\n 'Comma-separated list of features to enable (default: all)',\n type: 'string',\n },\n 'api-key': {\n describe:\n 'PostHog personal API key (phx_xxx) for MCP authentication',\n type: 'string',\n },\n });\n },\n (argv) => {\n const options = { ...argv };\n const mcpFeatures = options.features\n ?.split(',')\n .map((s) => s.trim())\n .filter(Boolean);\n void (async () => {\n const { readApiKeyFromEnv } = await import(\n './src/utils/env-api-key.js'\n );\n const apiKey =\n (options.apiKey as string | undefined) || readApiKeyFromEnv();\n\n try {\n const { startTUI } = await import('./src/ui/tui/start-tui.js');\n const { buildSession } = await import(\n './src/lib/wizard-session.js'\n );\n\n const { Flow } = await import('./src/ui/tui/router.js');\n const tui = startTUI(WIZARD_VERSION, Flow.McpAdd);\n const session = buildSession({\n debug: options.debug,\n localMcp: options.local,\n mcpFeatures,\n apiKey,\n });\n tui.store.session = session;\n } catch {\n // TUI unavailable — fallback to logging\n setUI(new LoggingUI());\n const { addMCPServerToClientsStep } = await import(\n './src/steps/add-mcp-server-to-clients/index.js'\n );\n await addMCPServerToClientsStep({\n local: options.local,\n features: mcpFeatures,\n apiKey,\n });\n }\n })();\n },\n )\n .command(\n 'remove',\n 'Remove PostHog MCP server from supported clients',\n (yargs) => {\n return yargs.options({\n local: {\n default: false,\n describe:\n 'Remove local development MCP server (http://localhost:8787)',\n type: 'boolean',\n },\n });\n },\n (argv) => {\n const options = { ...argv };\n void (async () => {\n try {\n const { startTUI } = await import('./src/ui/tui/start-tui.js');\n const { buildSession } = await import(\n './src/lib/wizard-session.js'\n );\n\n const { Flow } = await import('./src/ui/tui/router.js');\n const tui = startTUI(WIZARD_VERSION, Flow.McpRemove);\n const session = buildSession({\n debug: options.debug,\n localMcp: options.local,\n });\n tui.store.session = session;\n } catch {\n // TUI unavailable — fallback to logging\n setUI(new LoggingUI());\n const { removeMCPServerFromClientsStep } = await import(\n './src/steps/add-mcp-server-to-clients/index.js'\n );\n await removeMCPServerFromClientsStep({\n local: options.local,\n });\n }\n })();\n },\n )\n .demandCommand(1, 'You must specify a subcommand (add or remove)')\n .help();\n });\n\n// ── Skill-based workflow subcommands (derived from registry) ─────────\nfor (const wfConfig of getSubcommandWorkflows()) {\n cli.command(\n wfConfig.command!,\n wfConfig.description,\n (y) => y.options(skillSubcommandOptions),\n (argv) => {\n const options = { ...argv };\n if (options.ci) {\n runWizardCI(wfConfig, options);\n } else {\n runWizard(wfConfig, options);\n }\n },\n );\n}\n\ncli\n .help()\n .alias('help', 'h')\n .version()\n .alias('version', 'v')\n .wrap(process.stdout.isTTY ? cli.terminalWidth() : 80).argv;\n\n/**\n * Run a full wizard workflow in the TUI. Handles the full lifecycle: start TUI,\n * build session, run detection, wait for intro gate, execute the\n * agent pipeline, wait for outro dismissal, then exit.\n */\nfunction runWizard(\n config: WorkflowConfig,\n options: Record<string, unknown>,\n): void {\n void (async () => {\n try {\n const installDir = (options.installDir as string) || process.cwd();\n\n const { startTUI } = await import('./src/ui/tui/start-tui.js');\n const { buildSession } = await import('./src/lib/wizard-session.js');\n const { TaskStreamPush } = await import('./src/lib/task-stream/index.js');\n const { FileDestination } = await import(\n './src/lib/task-stream/destinations/file.js'\n );\n const { PostHogDestination } = await import(\n './src/lib/task-stream/destinations/posthog.js'\n );\n const { analytics } = await import('./src/utils/analytics.js');\n\n const tui = startTUI(WIZARD_VERSION, config.flowKey as any);\n\n const session = buildSession({\n debug: options.debug as boolean | undefined,\n forceInstall: options.forceInstall as boolean | undefined,\n localMcp: options.localMcp as boolean | undefined,\n installDir,\n ci: false,\n signup: options.signup as boolean | undefined,\n apiKey: options.apiKey as string | undefined,\n projectId: options.projectId as string | undefined,\n email: options.email as string | undefined,\n menu: options.menu as boolean | undefined,\n integration: options.integration as any,\n benchmark: options.benchmark as boolean | undefined,\n yaraReport: options.yaraReport as boolean | undefined,\n });\n session.workflowLabel = config.flowKey;\n if (options.skillId) {\n session.skillId = options.skillId as string;\n }\n\n tui.store.session = session;\n\n // Task stream — pushes state to external consumers on task changes\n const taskStream = new TaskStreamPush({\n store: tui.store,\n workflowId: config.flowKey,\n destinations: [new FileDestination(), new PostHogDestination()],\n });\n tui.store.onTasksChanged = () => void taskStream.push();\n\n await tui.store.runReadyHooks();\n await tui.store.getGate('intro');\n\n const skipAgent = config.run == null;\n\n if (skipAgent) {\n const { getOrAskForProjectData } = await import(\n './src/utils/setup-utils.js'\n );\n const { projectApiKey, host, accessToken, projectId } =\n await getOrAskForProjectData({\n signup: session.signup,\n ci: session.ci,\n apiKey: session.apiKey,\n projectId: session.projectId,\n });\n tui.store.setCredentials({\n accessToken,\n projectApiKey,\n host,\n projectId,\n });\n } else {\n const { runAgent } = await import('./src/lib/agent/agent-runner.js');\n await runAgent(config, tui.store.session);\n }\n\n const isDone = (): boolean =>\n skipAgent\n ? tui.store.session.outroDismissed\n : tui.store.session.skillsComplete;\n\n await new Promise<void>((resolve) => {\n const unsub = tui.store.subscribe(() => {\n if (isDone()) {\n unsub();\n resolve();\n }\n });\n if (isDone()) {\n unsub();\n resolve();\n }\n });\n\n try {\n await taskStream.dispose();\n } catch (error) {\n analytics.captureException(error as Error);\n }\n tui.unmount();\n process.exit(0);\n } catch (err) {\n if (runtimeEnv('DEBUG') || runtimeEnv('POSTHOG_WIZARD_DEBUG')) {\n console.error('TUI init failed:', err); // eslint-disable-line no-console\n }\n }\n })();\n}\n\n/**\n * CI-mode pipeline shared by every non-interactive entry point.\n *\n * Validates flags, builds a `ci:true` session, runs `preRun` (or the\n * workflow's `onReady` hooks by default), executes `runAgent`, and\n * routes any failure through `wizardAbort`. `wizardAbort` owns all\n * exits — never add a raw `process.exit` here.\n */\nfunction runWizardCI(\n config: WorkflowConfig,\n options: Record<string, unknown>,\n preRun?: (session: WizardSession) => Promise<void>,\n): void {\n setUI(new LoggingUI());\n if (!options.region) options.region = 'us';\n if (!options.apiKey) {\n getUI().intro('PostHog Wizard');\n getUI().log.error('CI mode requires --api-key (personal API key phx_xxx)');\n process.exit(1);\n }\n if (!options.installDir) {\n getUI().intro('PostHog Wizard');\n getUI().log.error(\n 'CI mode requires --install-dir (directory to install in)',\n );\n process.exit(1);\n }\n\n void (async () => {\n const path = await import('path');\n const { buildSession } = await import('./src/lib/wizard-session.js');\n const { readEnvironment } = await import('./src/utils/environment.js');\n const { readApiKeyFromEnv } = await import('./src/utils/env-api-key.js');\n const { configureLogFileFromEnvironment, logToFile } = await import(\n './src/utils/debug.js'\n );\n const { wizardAbort, WizardError } = await import(\n './src/utils/wizard-abort.js'\n );\n\n configureLogFileFromEnvironment();\n\n const env = readEnvironment();\n const apiKey =\n (options.apiKey as string) ?? readApiKeyFromEnv() ?? undefined;\n const installDir = path.isAbsolute(options.installDir as string)\n ? (options.installDir as string)\n : path.join(process.cwd(), options.installDir as string);\n\n const session = buildSession({\n debug: options.debug as boolean | undefined,\n forceInstall: options.forceInstall as boolean | undefined,\n installDir,\n ci: true,\n signup: options.signup as boolean | undefined,\n localMcp: options.localMcp as boolean | undefined,\n apiKey,\n email: options.email as string | undefined,\n menu: options.menu as boolean | undefined,\n integration: options.integration as any, // eslint-disable-line @typescript-eslint/no-explicit-any\n projectId: options.projectId as string | undefined,\n benchmark: options.benchmark as boolean | undefined,\n yaraReport: options.yaraReport as boolean | undefined,\n ...env,\n });\n session.workflowLabel = config.flowKey;\n const runDef = typeof config.run === 'object' ? config.run : null;\n\n getUI().intro('Welcome to the PostHog setup wizard');\n getUI().log.info(`Running ${config.flowKey} in CI mode`);\n\n try {\n if (preRun) {\n await preRun(session);\n } else {\n // Run onReady hooks against a minimal store-less context.\n const readyCtx = {\n session,\n setFrameworkContext: (key: string, value: unknown) => {\n session.frameworkContext[key] = value;\n },\n setFrameworkConfig: () => undefined,\n setDetectedFramework: () => undefined,\n setUnsupportedVersion: () => undefined,\n addDiscoveredFeature: () => undefined,\n setDetectionComplete: () => undefined,\n };\n for (const step of config.steps) {\n if (step.onReady) {\n await step.onReady(readyCtx);\n }\n }\n\n // Surface detectError written by the workflow's detect hook.\n const detectError = session.frameworkContext.detectError as\n | { kind: string; [k: string]: unknown }\n | undefined;\n if (detectError) {\n await wizardAbort({\n message: `Prerequisites not met: ${detectError.kind}\\n\\nSee ${\n runDef?.docsUrl ?? POSTHOG_DOCS_URL\n }`,\n error: new WizardError(`${config.flowKey} prerequisites failed`, {\n integration: config.flowKey,\n detect_error_kind: detectError.kind,\n }),\n });\n }\n }\n\n const { runAgent } = await import('./src/lib/agent/agent-runner.js');\n await runAgent(config, session);\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n const errorStack =\n error instanceof Error && error.stack ? error.stack : undefined;\n\n logToFile(`[bin.ts CI] ERROR: ${errorMessage}`);\n if (errorStack) logToFile(`[bin.ts CI] STACK: ${errorStack}`);\n\n const debugInfo = session.debug && errorStack ? `\\n\\n${errorStack}` : '';\n const docsUrl =\n session.frameworkConfig?.metadata.docsUrl ??\n runDef?.docsUrl ??\n POSTHOG_DOCS_URL;\n await wizardAbort({\n message: `Something went wrong: ${errorMessage}\\n\\nYou can read the documentation at ${docsUrl} to set up manually.${debugInfo}`,\n error: error as Error,\n });\n }\n })().catch(() => {\n process.exit(1);\n });\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as configureLogFileFromEnvironment, s as logToFile } from "./debug-
|
|
1
|
+
import { n as configureLogFileFromEnvironment, s as logToFile } from "./debug-gWEjmYVV.js";
|
|
2
2
|
export { configureLogFileFromEnvironment, logToFile };
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import "./wizard-ui-BExOjdjA.js";
|
|
2
|
+
import { n as WIZARD_LOG_FILE } from "./paths-BL-x2rFy.js";
|
|
1
3
|
import { appendFileSync } from "fs";
|
|
2
4
|
import path from "path";
|
|
3
5
|
//#region src/utils/logging.ts
|
|
@@ -140,7 +142,7 @@ function setUI(ui) {
|
|
|
140
142
|
//#endregion
|
|
141
143
|
//#region src/utils/debug.ts
|
|
142
144
|
let debugEnabled = false;
|
|
143
|
-
let logFilePath =
|
|
145
|
+
let logFilePath = WIZARD_LOG_FILE;
|
|
144
146
|
let logEnabled = true;
|
|
145
147
|
function getLogFilePath() {
|
|
146
148
|
return logFilePath;
|
|
@@ -198,4 +200,4 @@ function enableDebugLogs() {
|
|
|
198
200
|
//#endregion
|
|
199
201
|
export { getLogFilePath as a, getUI as c, NODE_ENV as d, runtimeEnv as f, enableDebugLogs as i, setUI as l, configureLogFileFromEnvironment as n, initLogFile as o, red as p, debug as r, logToFile as s, configureLogFile as t, LoggingUI as u };
|
|
200
202
|
|
|
201
|
-
//# sourceMappingURL=debug-
|
|
203
|
+
//# sourceMappingURL=debug-gWEjmYVV.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"debug-CyJ_3dTP.js","names":[],"sources":["../src/utils/logging.ts","../src/env.ts","../src/ui/logging-ui.ts","../src/ui/index.ts","../src/utils/debug.ts"],"sourcesContent":["export function prepareMessage(msg: unknown): string {\n if (typeof msg === 'string') {\n return msg;\n }\n if (msg instanceof Error) {\n return `${msg.stack || ''}`;\n }\n return JSON.stringify(msg, null, '\\t');\n}\n\nexport function l(msg: string): void {\n // eslint-disable-next-line no-console\n console.log(msg);\n}\n\nexport function nl(): void {\n return l('');\n}\n\nexport function green(msg: string): void {\n return l(prepareMessage(msg));\n}\n\nexport function red(msg: string): void {\n return l(prepareMessage(msg));\n}\n\nexport function dim(msg: string): void {\n return l(prepareMessage(msg));\n}\n\nexport function yellow(msg: string): void {\n return l(prepareMessage(msg));\n}\n\nexport function cyan(msg: string): void {\n return l(prepareMessage(msg));\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function debug(msg: any): void {\n return l(prepareMessage(msg));\n}\n","/**\n * Central environment variable access for the PostHog wizard.\n *\n * ── Build-time constants ────────────────────────────────────────────\n * Inlined by tsdown's `env` option at compile time. After build, the\n * runtime value of these env vars has zero effect on the wizard.\n *\n * ── Runtime variables ───────────────────────────────────────────────\n * Read through `runtimeEnv()` with a typed allowlist. This makes every\n * runtime dependency on the environment explicit and grep-able.\n *\n * ── Direct process.env access ───────────────────────────────────────\n * Reserved for subprocess environment configuration (writes) and\n * vendored code. Production source outside those cases should use\n * this module instead.\n */\n\n// ── Build-time constants ─────────────────────────────────────────────\n// tsdown replaces `process.env.NODE_ENV` with a string literal.\n// After build these are just `\"production\"`, `false`, etc.\n\nexport const NODE_ENV = process.env.NODE_ENV as string;\nexport const IS_DEV =\n process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test';\n\n// ── Runtime environment ──────────────────────────────────────────────\n\n/**\n * Exhaustive allowlist of env vars the wizard reads at runtime.\n * Add new keys here when a new runtime dependency is needed.\n */\ntype RuntimeEnvKey =\n // Wizard CLI configuration (yargs POSTHOG_WIZARD_ prefix)\n | 'POSTHOG_WIZARD_BENCHMARK_CONFIG'\n | 'POSTHOG_WIZARD_BENCHMARK_FILE'\n | 'POSTHOG_WIZARD_LOG_DIR'\n | 'POSTHOG_WIZARD_DEBUG'\n | 'DEBUG'\n // Agent / MCP\n | 'MCP_URL'\n | 'POSTHOG_API_KEY'\n // Platform: terminal detection\n | 'TERM'\n | 'TERM_PROGRAM'\n | 'TERMINAL_EMULATOR'\n | 'CI'\n | 'WT_SESSION'\n | 'TERMINUS_SUBLIME'\n | 'ConEmuTask'\n // Platform: paths\n | 'APPDATA'\n | 'XDG_CONFIG_HOME';\n\n/** Read a runtime environment variable. Only allowlisted keys compile. */\nexport function runtimeEnv(key: RuntimeEnvKey): string | undefined {\n return process.env[key];\n}\n","/* eslint-disable no-console */\n/**\n * LoggingUI — Logging-only implementation for CI mode.\n * No prompts, no TUI, no interactivity. Just console output.\n */\n\nimport { TaskStatus, type WizardUI, type SpinnerHandle } from './wizard-ui';\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 class LoggingUI implements WizardUI {\n intro(message: string): void {\n console.log(`┌ ${message}`);\n }\n\n outro(message: string): void {\n console.log(`└ ${message}`);\n }\n\n outroError(data: OutroData): void {\n console.log(`✖ ${data.message ?? 'Wizard aborted'}`);\n if (data.body) console.log(`│ ${data.body}`);\n if (data.docsUrl) console.log(`│ Docs: ${data.docsUrl}`);\n }\n\n cancel(message: string): void {\n console.log(`■ ${message}`);\n }\n\n log = {\n info(message: string): void {\n console.log(`│ ${message}`);\n },\n warn(message: string): void {\n console.log(`▲ ${message}`);\n },\n error(message: string): void {\n console.log(`✖ ${message}`);\n },\n success(message: string): void {\n console.log(`✔ ${message}`);\n },\n step(message: string): void {\n console.log(`◇ ${message}`);\n },\n };\n\n note(message: string): void {\n console.log(`│ ${message}`);\n }\n\n spinner(): SpinnerHandle {\n return {\n start(message?: string) {\n if (message) console.log(`◌ ${message}`);\n },\n stop(message?: string) {\n if (message) console.log(`● ${message}`);\n },\n message(msg?: string) {\n if (msg) console.log(`◌ ${msg}`);\n },\n };\n }\n\n pushStatus(message: string): void {\n console.log(`◇ ${message}`);\n }\n\n setDetectedFramework(label: string): void {\n console.log(`✔ Framework: ${label}`);\n }\n\n onEnterScreen(_screen: string, _fn: () => void): void {\n // No screen transitions in CI\n }\n\n setLoginUrl(url: string | null): void {\n if (url) {\n console.log(\n `│ If the browser didn't open automatically, use this link:`,\n );\n console.log(`│ ${url}`);\n }\n }\n\n showBlockingOutage(result: WizardReadinessResult): Promise<void> {\n console.log(`▲ Service health issues detected — blocking outage.`);\n for (const reason of result.reasons) {\n console.log(`│ ${reason}`);\n }\n console.log(\n `│ The wizard may not work reliably while services are affected.`,\n );\n return Promise.resolve();\n }\n\n setReadinessWarnings(result: WizardReadinessResult): void {\n console.log(`▲ Service health warnings detected.`);\n for (const reason of result.reasons) {\n console.log(`│ ${reason}`);\n }\n }\n\n showPortConflict(_processInfo: {\n command: string;\n pid: string;\n port: number;\n user: string;\n }): Promise<void> {\n return Promise.resolve();\n }\n\n showSettingsOverride(\n _conflicts: SettingsConflict[],\n _backupAndFix: () => boolean,\n ): Promise<void> {\n return Promise.resolve();\n }\n\n showAuthError(): void {\n console.log(`✖ Authentication failed (401)`);\n console.log(\n `│ Claude Code auth is conflicting with the wizard. Please try again after logging out:`,\n );\n console.log(`│ claude auth logout`);\n }\n\n startRun(): void {\n // No-op in CI mode\n }\n\n setCredentials(_credentials: {\n accessToken: string;\n projectApiKey: string;\n host: string;\n projectId: number;\n }): void {\n // No-op in CI mode — credentials are handled directly\n }\n\n syncTodos(\n todos: Array<{ content: string; status: string; activeForm?: string }>,\n ): void {\n const completed = todos.filter(\n (t) => t.status === TaskStatus.Completed,\n ).length;\n const inProgress = todos.find((t) => t.status === TaskStatus.InProgress);\n if (inProgress) {\n console.log(\n `◌ [${completed}/${todos.length}] ${\n inProgress.activeForm || inProgress.content\n }`,\n );\n }\n }\n\n setEventPlan(_events: Array<{ name: string; description: string }>): void {\n // No-op in CI mode\n }\n}\n","/**\n * UI singleton — provides getUI() and setUI() for the wizard.\n * Default: LoggingUI. Swap to InkUI at startup for TUI mode.\n */\n\nimport type { WizardUI } from './wizard-ui';\nimport { LoggingUI } from './logging-ui';\n\nlet currentUI: WizardUI = new LoggingUI();\n\nexport function getUI(): WizardUI {\n return currentUI;\n}\n\nexport function setUI(ui: WizardUI): void {\n currentUI = ui;\n}\n\nexport type { WizardUI, SpinnerHandle } from './wizard-ui';\n","import { appendFileSync } from 'fs';\nimport path from 'path';\nimport { prepareMessage } from './logging';\nimport { getUI } from '../ui';\nimport { runtimeEnv } from '@env';\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 = runtimeEnv('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"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"debug-gWEjmYVV.js","names":[],"sources":["../src/utils/logging.ts","../src/env.ts","../src/ui/logging-ui.ts","../src/ui/index.ts","../src/utils/debug.ts"],"sourcesContent":["export function prepareMessage(msg: unknown): string {\n if (typeof msg === 'string') {\n return msg;\n }\n if (msg instanceof Error) {\n return `${msg.stack || ''}`;\n }\n return JSON.stringify(msg, null, '\\t');\n}\n\nexport function l(msg: string): void {\n // eslint-disable-next-line no-console\n console.log(msg);\n}\n\nexport function nl(): void {\n return l('');\n}\n\nexport function green(msg: string): void {\n return l(prepareMessage(msg));\n}\n\nexport function red(msg: string): void {\n return l(prepareMessage(msg));\n}\n\nexport function dim(msg: string): void {\n return l(prepareMessage(msg));\n}\n\nexport function yellow(msg: string): void {\n return l(prepareMessage(msg));\n}\n\nexport function cyan(msg: string): void {\n return l(prepareMessage(msg));\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function debug(msg: any): void {\n return l(prepareMessage(msg));\n}\n","/**\n * Central environment variable access for the PostHog wizard.\n *\n * ── Build-time constants ────────────────────────────────────────────\n * Inlined by tsdown's `env` option at compile time. After build, the\n * runtime value of these env vars has zero effect on the wizard.\n *\n * ── Runtime variables ───────────────────────────────────────────────\n * Read through `runtimeEnv()` with a typed allowlist. This makes every\n * runtime dependency on the environment explicit and grep-able.\n *\n * ── Direct process.env access ───────────────────────────────────────\n * Reserved for subprocess environment configuration (writes) and\n * vendored code. Production source outside those cases should use\n * this module instead.\n */\n\n// ── Build-time constants ─────────────────────────────────────────────\n// tsdown replaces `process.env.NODE_ENV` with a string literal.\n// After build these are just `\"production\"`, `false`, etc.\n\nexport const NODE_ENV = process.env.NODE_ENV as string;\nexport const IS_DEV =\n process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test';\n\n// ── Runtime environment ──────────────────────────────────────────────\n\n/**\n * Exhaustive allowlist of env vars the wizard reads at runtime.\n * Add new keys here when a new runtime dependency is needed.\n */\ntype RuntimeEnvKey =\n // Wizard CLI configuration (yargs POSTHOG_WIZARD_ prefix)\n | 'POSTHOG_WIZARD_BENCHMARK_CONFIG'\n | 'POSTHOG_WIZARD_BENCHMARK_FILE'\n | 'POSTHOG_WIZARD_LOG_DIR'\n | 'POSTHOG_WIZARD_DEBUG'\n | 'DEBUG'\n // Agent / MCP\n | 'MCP_URL'\n | 'POSTHOG_API_KEY'\n // Platform: terminal detection\n | 'TERM'\n | 'TERM_PROGRAM'\n | 'TERMINAL_EMULATOR'\n | 'CI'\n | 'WT_SESSION'\n | 'TERMINUS_SUBLIME'\n | 'ConEmuTask'\n // Platform: paths\n | 'APPDATA'\n | 'XDG_CONFIG_HOME';\n\n/** Read a runtime environment variable. Only allowlisted keys compile. */\nexport function runtimeEnv(key: RuntimeEnvKey): string | undefined {\n return process.env[key];\n}\n","/* eslint-disable no-console */\n/**\n * LoggingUI — Logging-only implementation for CI mode.\n * No prompts, no TUI, no interactivity. Just console output.\n */\n\nimport { TaskStatus, type WizardUI, type SpinnerHandle } from './wizard-ui';\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 class LoggingUI implements WizardUI {\n intro(message: string): void {\n console.log(`┌ ${message}`);\n }\n\n outro(message: string): void {\n console.log(`└ ${message}`);\n }\n\n outroError(data: OutroData): void {\n console.log(`✖ ${data.message ?? 'Wizard aborted'}`);\n if (data.body) console.log(`│ ${data.body}`);\n if (data.docsUrl) console.log(`│ Docs: ${data.docsUrl}`);\n }\n\n cancel(message: string): void {\n console.log(`■ ${message}`);\n }\n\n log = {\n info(message: string): void {\n console.log(`│ ${message}`);\n },\n warn(message: string): void {\n console.log(`▲ ${message}`);\n },\n error(message: string): void {\n console.log(`✖ ${message}`);\n },\n success(message: string): void {\n console.log(`✔ ${message}`);\n },\n step(message: string): void {\n console.log(`◇ ${message}`);\n },\n };\n\n note(message: string): void {\n console.log(`│ ${message}`);\n }\n\n spinner(): SpinnerHandle {\n return {\n start(message?: string) {\n if (message) console.log(`◌ ${message}`);\n },\n stop(message?: string) {\n if (message) console.log(`● ${message}`);\n },\n message(msg?: string) {\n if (msg) console.log(`◌ ${msg}`);\n },\n };\n }\n\n pushStatus(message: string): void {\n console.log(`◇ ${message}`);\n }\n\n setDetectedFramework(label: string): void {\n console.log(`✔ Framework: ${label}`);\n }\n\n onEnterScreen(_screen: string, _fn: () => void): void {\n // No screen transitions in CI\n }\n\n setLoginUrl(url: string | null): void {\n if (url) {\n console.log(\n `│ If the browser didn't open automatically, use this link:`,\n );\n console.log(`│ ${url}`);\n }\n }\n\n showBlockingOutage(result: WizardReadinessResult): Promise<void> {\n console.log(`▲ Service health issues detected — blocking outage.`);\n for (const reason of result.reasons) {\n console.log(`│ ${reason}`);\n }\n console.log(\n `│ The wizard may not work reliably while services are affected.`,\n );\n return Promise.resolve();\n }\n\n setReadinessWarnings(result: WizardReadinessResult): void {\n console.log(`▲ Service health warnings detected.`);\n for (const reason of result.reasons) {\n console.log(`│ ${reason}`);\n }\n }\n\n showPortConflict(_processInfo: {\n command: string;\n pid: string;\n port: number;\n user: string;\n }): Promise<void> {\n return Promise.resolve();\n }\n\n showSettingsOverride(\n _conflicts: SettingsConflict[],\n _backupAndFix: () => boolean,\n ): Promise<void> {\n return Promise.resolve();\n }\n\n showAuthError(): void {\n console.log(`✖ Authentication failed (401)`);\n console.log(\n `│ Claude Code auth is conflicting with the wizard. Please try again after logging out:`,\n );\n console.log(`│ claude auth logout`);\n }\n\n startRun(): void {\n // No-op in CI mode\n }\n\n setCredentials(_credentials: {\n accessToken: string;\n projectApiKey: string;\n host: string;\n projectId: number;\n }): void {\n // No-op in CI mode — credentials are handled directly\n }\n\n syncTodos(\n todos: Array<{ content: string; status: string; activeForm?: string }>,\n ): void {\n const completed = todos.filter(\n (t) => t.status === TaskStatus.Completed,\n ).length;\n const inProgress = todos.find((t) => t.status === TaskStatus.InProgress);\n if (inProgress) {\n console.log(\n `◌ [${completed}/${todos.length}] ${\n inProgress.activeForm || inProgress.content\n }`,\n );\n }\n }\n\n setEventPlan(_events: Array<{ name: string; description: string }>): void {\n // No-op in CI mode\n }\n}\n","/**\n * UI singleton — provides getUI() and setUI() for the wizard.\n * Default: LoggingUI. Swap to InkUI at startup for TUI mode.\n */\n\nimport type { WizardUI } from './wizard-ui';\nimport { LoggingUI } from './logging-ui';\n\nlet currentUI: WizardUI = new LoggingUI();\n\nexport function getUI(): WizardUI {\n return currentUI;\n}\n\nexport function setUI(ui: WizardUI): void {\n currentUI = ui;\n}\n\nexport type { WizardUI, SpinnerHandle } from './wizard-ui';\n","import { appendFileSync } from 'fs';\nimport path from 'path';\nimport { prepareMessage } from './logging';\nimport { getUI } from '../ui';\nimport { runtimeEnv } from '@env';\nimport { WIZARD_LOG_FILE } from './paths';\n\nlet debugEnabled = false;\nlet logFilePath = WIZARD_LOG_FILE;\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 = runtimeEnv('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"],"mappings":"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"}
|
|
@@ -194,20 +194,20 @@ const AVAILABLE_FEATURES = {
|
|
|
194
194
|
]
|
|
195
195
|
};
|
|
196
196
|
const ALL_FEATURE_VALUES = Object.values(AVAILABLE_FEATURES).flat().map((feature) => feature.value);
|
|
197
|
-
const buildMCPUrl = (
|
|
198
|
-
const baseUrl = `${local ? "http://localhost:8787" : "https://mcp.posthog.com"}
|
|
197
|
+
const buildMCPUrl = (selectedFeatures, local) => {
|
|
198
|
+
const baseUrl = `${local ? "http://localhost:8787" : "https://mcp.posthog.com"}/mcp`;
|
|
199
199
|
const isAllFeaturesSelected = selectedFeatures && selectedFeatures.length === ALL_FEATURE_VALUES.length && ALL_FEATURE_VALUES.every((feature) => selectedFeatures.includes(feature));
|
|
200
200
|
const params = [];
|
|
201
201
|
if (selectedFeatures && selectedFeatures.length > 0 && !isAllFeaturesSelected) params.push(`features=${selectedFeatures.join(",")}`);
|
|
202
202
|
return params.length > 0 ? `${baseUrl}?${params.join("&")}` : baseUrl;
|
|
203
203
|
};
|
|
204
|
-
const getNativeHTTPServerConfig = (apiKey,
|
|
205
|
-
const config = { url: buildMCPUrl(
|
|
204
|
+
const getNativeHTTPServerConfig = (apiKey, selectedFeatures, local) => {
|
|
205
|
+
const config = { url: buildMCPUrl(selectedFeatures, local) };
|
|
206
206
|
if (apiKey) config.headers = { Authorization: `Bearer ${apiKey}` };
|
|
207
207
|
return config;
|
|
208
208
|
};
|
|
209
|
-
const getDefaultServerConfig = (apiKey,
|
|
210
|
-
const urlWithFeatures = buildMCPUrl(
|
|
209
|
+
const getDefaultServerConfig = (apiKey, selectedFeatures, local) => {
|
|
210
|
+
const urlWithFeatures = buildMCPUrl(selectedFeatures, local);
|
|
211
211
|
if (!apiKey) return {
|
|
212
212
|
command: "npx",
|
|
213
213
|
args: [
|
|
@@ -229,6 +229,6 @@ const getDefaultServerConfig = (apiKey, type, selectedFeatures, local) => {
|
|
|
229
229
|
};
|
|
230
230
|
};
|
|
231
231
|
//#endregion
|
|
232
|
-
export { getNativeHTTPServerConfig as
|
|
232
|
+
export { getNativeHTTPServerConfig as i, AVAILABLE_FEATURES as n, getDefaultServerConfig as r, ALL_FEATURE_VALUES as t };
|
|
233
233
|
|
|
234
|
-
//# sourceMappingURL=defaults-
|
|
234
|
+
//# sourceMappingURL=defaults-CPH6eWhN.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaults-CPH6eWhN.js","names":["z"],"sources":["../src/steps/add-mcp-server-to-clients/defaults.ts"],"sourcesContent":["import z from 'zod';\n\nexport const DefaultMCPClientConfig = z\n .object({\n mcpServers: z.record(\n z.string(),\n z.union([\n z.object({\n command: z.string().optional(),\n args: z.array(z.string()).optional(),\n env: z.record(z.string(), z.string()).optional(),\n }),\n z.object({\n url: z.string(),\n headers: z.record(z.string(), z.string()).optional(),\n }),\n ]),\n ),\n })\n .passthrough();\n\nexport const AVAILABLE_FEATURES = {\n 'Data & Analytics': [\n {\n value: 'dashboards',\n label: 'Dashboards',\n hint: 'Dashboard creation and management',\n },\n {\n value: 'insights',\n label: 'Insights',\n hint: 'Analytics insights',\n },\n {\n value: 'product_analytics',\n label: 'Product Analytics',\n hint: 'Insight CRUD management',\n },\n {\n value: 'experiments',\n label: 'Experiments',\n hint: 'A/B testing experiments',\n },\n {\n value: 'surveys',\n label: 'Surveys',\n hint: 'Survey management',\n },\n {\n value: 'annotations',\n label: 'Annotations',\n hint: 'Annotation management',\n },\n {\n value: 'replay',\n label: 'Session Replay',\n hint: 'Session recording management',\n },\n {\n value: 'sql',\n label: 'SQL',\n hint: 'SQL query execution',\n },\n ],\n 'AI Engineering': [\n {\n value: 'llm_analytics',\n label: 'LLM Analytics',\n hint: 'LLM usage and cost tracking',\n },\n {\n value: 'prompts',\n label: 'Prompts',\n hint: 'LLM prompt management',\n },\n ],\n 'Development Tools': [\n {\n value: 'error_tracking',\n label: 'Error Tracking',\n hint: 'Error monitoring and debugging',\n },\n {\n value: 'logs',\n label: 'Logs',\n hint: 'Log querying',\n },\n {\n value: 'flags',\n label: 'Feature Flags',\n hint: 'Feature flag management',\n },\n {\n value: 'early_access_features',\n label: 'Early Access Features',\n hint: 'Early access feature management',\n },\n {\n value: 'cohorts',\n label: 'Cohorts',\n hint: 'Cohort management',\n },\n ],\n 'Data Management': [\n {\n value: 'events',\n label: 'Events',\n hint: 'Event and property definitions',\n },\n {\n value: 'persons',\n label: 'Persons',\n hint: 'Person and group management',\n },\n {\n value: 'actions',\n label: 'Actions',\n hint: 'Action definitions',\n },\n {\n value: 'data_warehouse',\n label: 'Data Warehouse',\n hint: 'Data warehouse management',\n },\n {\n value: 'endpoints',\n label: 'Endpoints',\n hint: 'Data warehouse endpoint management',\n },\n {\n value: 'data_schema',\n label: 'Data Schema',\n hint: 'Data schema exploration',\n },\n ],\n 'CDP & Automation': [\n {\n value: 'hog_functions',\n label: 'Hog Functions',\n hint: 'CDP function management',\n },\n {\n value: 'hog_function_templates',\n label: 'Hog Function Templates',\n hint: 'CDP function template browsing',\n },\n {\n value: 'workflows',\n label: 'Workflows',\n hint: 'Workflow management',\n },\n ],\n 'Platform & Management': [\n {\n value: 'workspace',\n label: 'Workspace',\n hint: 'Organization and project management',\n },\n {\n value: 'docs',\n label: 'Documentation',\n hint: 'PostHog documentation search',\n },\n {\n value: 'notebooks',\n label: 'Notebooks',\n hint: 'Notebook management',\n },\n {\n value: 'alerts',\n label: 'Alerts',\n hint: 'Alert management',\n },\n {\n value: 'platform_features',\n label: 'Platform Features',\n hint: 'Activity logs, approvals, comments, and roles',\n },\n {\n value: 'integrations',\n label: 'Integrations',\n hint: 'Connected integration management',\n },\n {\n value: 'conversations',\n label: 'Conversations',\n hint: 'Support ticket management',\n },\n {\n value: 'core',\n label: 'Subscriptions',\n hint: 'Scheduled insight and dashboard deliveries',\n },\n {\n value: 'search',\n label: 'Search',\n hint: 'Entity search across the project',\n },\n {\n value: 'reverse_proxy',\n label: 'Reverse Proxy',\n hint: 'Reverse proxy record management',\n },\n {\n value: 'debug',\n label: 'Debug',\n hint: 'Debug and diagnostic tools',\n },\n ],\n};\n\nexport const ALL_FEATURE_VALUES = Object.values(AVAILABLE_FEATURES)\n .flat()\n .map((feature) => feature.value);\n\nexport const buildMCPUrl = (selectedFeatures?: string[], local?: boolean) => {\n const host = local ? 'http://localhost:8787' : 'https://mcp.posthog.com';\n const baseUrl = `${host}/mcp`;\n\n const isAllFeaturesSelected =\n selectedFeatures &&\n selectedFeatures.length === ALL_FEATURE_VALUES.length &&\n ALL_FEATURE_VALUES.every((feature) => selectedFeatures.includes(feature));\n\n const params: string[] = [];\n\n // Add features param if not all features selected\n if (\n selectedFeatures &&\n selectedFeatures.length > 0 &&\n !isAllFeaturesSelected\n ) {\n params.push(`features=${selectedFeatures.join(',')}`);\n }\n\n return params.length > 0 ? `${baseUrl}?${params.join('&')}` : baseUrl;\n};\n\nexport const getNativeHTTPServerConfig = (\n apiKey: string | undefined,\n selectedFeatures?: string[],\n local?: boolean,\n) => {\n const config: Record<string, unknown> = {\n url: buildMCPUrl(selectedFeatures, local),\n };\n\n // Only add auth header if API key is provided (not OAuth mode)\n if (apiKey) {\n config.headers = {\n Authorization: `Bearer ${apiKey}`,\n };\n }\n\n return config;\n};\n\nexport const getDefaultServerConfig = (\n apiKey: string | undefined,\n selectedFeatures?: string[],\n local?: boolean,\n) => {\n const urlWithFeatures = buildMCPUrl(selectedFeatures, local);\n\n // OAuth mode: no auth header, let MCP handle OAuth\n if (!apiKey) {\n return {\n command: 'npx',\n args: ['-y', 'mcp-remote@latest', urlWithFeatures],\n };\n }\n\n // API key mode: include auth header\n return {\n command: 'npx',\n args: [\n '-y',\n 'mcp-remote@latest',\n urlWithFeatures,\n '--header',\n `Authorization:\\${POSTHOG_AUTH_HEADER}`,\n ],\n env: {\n POSTHOG_AUTH_HEADER: `Bearer ${apiKey}`,\n },\n };\n};\n"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-B_-DWIq7.js";
|
|
2
|
-
import { l as Integration, o as DETECTION_TIMEOUT_MS } from "./analytics-
|
|
3
|
-
import { t as FRAMEWORK_REGISTRY } from "./registry-
|
|
2
|
+
import { l as Integration, o as DETECTION_TIMEOUT_MS } from "./analytics-D3rY3TaN.js";
|
|
3
|
+
import { t as FRAMEWORK_REGISTRY } from "./registry-DaPKstG3.js";
|
|
4
4
|
import * as semver from "semver";
|
|
5
5
|
import { readFileSync } from "fs";
|
|
6
6
|
import { join } from "path";
|
|
@@ -49,26 +49,110 @@ const LLM_PACKAGES = [
|
|
|
49
49
|
"@mastra/core",
|
|
50
50
|
"portkey-ai"
|
|
51
51
|
];
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
52
|
+
const PYTHON_LLM_PACKAGES = [
|
|
53
|
+
"openai",
|
|
54
|
+
"anthropic",
|
|
55
|
+
"langchain",
|
|
56
|
+
"langchain-openai",
|
|
57
|
+
"langchain-anthropic",
|
|
58
|
+
"langchain-google-genai",
|
|
59
|
+
"langgraph",
|
|
60
|
+
"litellm",
|
|
61
|
+
"llama-index",
|
|
62
|
+
"pydantic-ai",
|
|
63
|
+
"crewai",
|
|
64
|
+
"instructor",
|
|
65
|
+
"dspy-ai",
|
|
66
|
+
"mistralai",
|
|
67
|
+
"cohere",
|
|
68
|
+
"google-generativeai",
|
|
69
|
+
"google-genai",
|
|
70
|
+
"portkey-ai"
|
|
71
|
+
];
|
|
59
72
|
function discoverFeatures(installDir) {
|
|
60
73
|
const features = [];
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
const depNames = Object.keys({
|
|
64
|
-
...pkg.dependencies,
|
|
65
|
-
...pkg.devDependencies
|
|
66
|
-
});
|
|
67
|
-
if (depNames.some((d) => STRIPE_PACKAGES.includes(d))) features.push("stripe");
|
|
68
|
-
if (depNames.some((d) => LLM_PACKAGES.includes(d))) features.push("llm");
|
|
69
|
-
} catch {}
|
|
74
|
+
discoverNodeFeatures(installDir, features);
|
|
75
|
+
discoverPythonFeatures(installDir, features);
|
|
70
76
|
return features;
|
|
71
77
|
}
|
|
78
|
+
function discoverNodeFeatures(installDir, features) {
|
|
79
|
+
const packageJsonText = safeRead(installDir, "package.json");
|
|
80
|
+
if (!packageJsonText) return;
|
|
81
|
+
let packageJson;
|
|
82
|
+
try {
|
|
83
|
+
packageJson = JSON.parse(packageJsonText);
|
|
84
|
+
} catch {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
const depNames = Object.keys({
|
|
88
|
+
...packageJson.dependencies,
|
|
89
|
+
...packageJson.devDependencies
|
|
90
|
+
});
|
|
91
|
+
if (depNames.some((depName) => STRIPE_PACKAGES.includes(depName))) features.push("stripe");
|
|
92
|
+
if (depNames.some((depName) => LLM_PACKAGES.includes(depName))) features.push("llm");
|
|
93
|
+
}
|
|
94
|
+
function discoverPythonFeatures(installDir, features) {
|
|
95
|
+
if (features.includes("llm")) return;
|
|
96
|
+
const depNames = [];
|
|
97
|
+
const requirementsTxt = safeRead(installDir, "requirements.txt");
|
|
98
|
+
if (requirementsTxt) depNames.push(...parseRequirementsTxt(requirementsTxt));
|
|
99
|
+
const pyprojectToml = safeRead(installDir, "pyproject.toml");
|
|
100
|
+
if (pyprojectToml) depNames.push(...parsePyprojectToml(pyprojectToml));
|
|
101
|
+
const pipfile = safeRead(installDir, "Pipfile");
|
|
102
|
+
if (pipfile) depNames.push(...parsePipfile(pipfile));
|
|
103
|
+
if (depNames.some((depName) => PYTHON_LLM_PACKAGES.includes(depName))) features.push("llm");
|
|
104
|
+
}
|
|
105
|
+
function safeRead(installDir, file) {
|
|
106
|
+
try {
|
|
107
|
+
return readFileSync(join(installDir, file), "utf-8");
|
|
108
|
+
} catch {
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
function normalizePyName(name) {
|
|
113
|
+
return name.toLowerCase().replace(/_/g, "-");
|
|
114
|
+
}
|
|
115
|
+
function parseRequirementsTxt(content) {
|
|
116
|
+
return content.split("\n").map((line) => line.trim()).filter((line) => line && !line.startsWith("#") && !line.startsWith("-")).map((line) => line.replace(/\[[^\]]*\]/, "")).map((line) => line.split(/[<>=!~;\s]/)[0]).filter(Boolean).map(normalizePyName);
|
|
117
|
+
}
|
|
118
|
+
function parsePyprojectToml(content) {
|
|
119
|
+
const depNames = [];
|
|
120
|
+
for (const arrayMatch of content.matchAll(/dependencies\s*=\s*\[([^\]]*)\]/g)) {
|
|
121
|
+
const arrayBody = arrayMatch[1];
|
|
122
|
+
for (const quotedMatch of arrayBody.matchAll(/["']([^"']+)["']/g)) {
|
|
123
|
+
const name = quotedMatch[1].replace(/\[[^\]]*\]/, "").split(/[<>=!~;\s]/)[0];
|
|
124
|
+
if (name) depNames.push(normalizePyName(name));
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
for (const sectionMatch of content.matchAll(/\[tool\.poetry\.(?:dev-dependencies|dependencies|group\.[^.\]]+\.dependencies)\]([\s\S]*?)(?=\n\[|$)/g)) {
|
|
128
|
+
const sectionBody = sectionMatch[1];
|
|
129
|
+
depNames.push(...extractTomlSectionKeys(sectionBody, { skip: ["python"] }));
|
|
130
|
+
}
|
|
131
|
+
return depNames;
|
|
132
|
+
}
|
|
133
|
+
function parsePipfile(content) {
|
|
134
|
+
const depNames = [];
|
|
135
|
+
for (const sectionMatch of content.matchAll(/\[(packages|dev-packages)\]([\s\S]*?)(?=\n\[|$)/g)) {
|
|
136
|
+
const sectionBody = sectionMatch[2];
|
|
137
|
+
depNames.push(...extractTomlSectionKeys(sectionBody));
|
|
138
|
+
}
|
|
139
|
+
return depNames;
|
|
140
|
+
}
|
|
141
|
+
function extractTomlSectionKeys(sectionBody, opts = {}) {
|
|
142
|
+
const skipNames = new Set(opts.skip ?? []);
|
|
143
|
+
const depNames = [];
|
|
144
|
+
for (const line of sectionBody.split("\n")) {
|
|
145
|
+
const trimmed = line.trim();
|
|
146
|
+
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
147
|
+
const equalsIndex = trimmed.indexOf("=");
|
|
148
|
+
if (equalsIndex <= 0) continue;
|
|
149
|
+
const name = trimmed.slice(0, equalsIndex).trim();
|
|
150
|
+
if (!/^[a-zA-Z0-9._-]+$/.test(name)) continue;
|
|
151
|
+
if (skipNames.has(name.toLowerCase())) continue;
|
|
152
|
+
depNames.push(normalizePyName(name));
|
|
153
|
+
}
|
|
154
|
+
return depNames;
|
|
155
|
+
}
|
|
72
156
|
//#endregion
|
|
73
157
|
//#region src/lib/detection/context.ts
|
|
74
158
|
/**
|
|
@@ -119,4 +203,4 @@ var detection_exports = /* @__PURE__ */ __exportAll({
|
|
|
119
203
|
//#endregion
|
|
120
204
|
export { detectFramework as a, discoverFeatures as i, checkFrameworkVersion as n, gatherFrameworkContext as r, detection_exports as t };
|
|
121
205
|
|
|
122
|
-
//# sourceMappingURL=detection-
|
|
206
|
+
//# sourceMappingURL=detection-B7GNzve-.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detection-B7GNzve-.js","names":[],"sources":["../src/lib/detection/framework.ts","../src/lib/detection/features.ts","../src/lib/detection/context.ts","../src/lib/detection/index.ts"],"sourcesContent":["/**\n * Framework detection — identify which PostHog-supported framework\n * is present in the project directory.\n *\n * Pure function: takes an install dir, returns the detected integration\n * (or undefined). No store mutations, no UI calls.\n */\n\nimport { Integration, DETECTION_TIMEOUT_MS } from '../constants.js';\nimport { FRAMEWORK_REGISTRY } from '../registry.js';\n\n/**\n * Loop through all registered frameworks and return the first one\n * whose `detect()` predicate matches the given directory.\n * Returns undefined if no framework is detected or detection times out.\n */\nexport async function detectFramework(\n installDir: string,\n): Promise<Integration | undefined> {\n for (const integration of Object.values(Integration)) {\n const config = FRAMEWORK_REGISTRY[integration];\n try {\n const detected = await Promise.race([\n config.detection.detect({ installDir }),\n new Promise<false>((resolve) =>\n setTimeout(() => resolve(false), DETECTION_TIMEOUT_MS),\n ),\n ]);\n if (detected) {\n return integration;\n }\n } catch {\n // Skip frameworks whose detection throws\n }\n }\n}\n","/**\n * Feature discovery — scan project dependencies for known SDK patterns\n * that indicate additional PostHog workflows are relevant.\n *\n * Pure function: takes an install dir, returns a set of discovered features.\n * No store mutations, no UI calls.\n */\n\nimport { readFileSync } from 'fs';\nimport { join } from 'path';\nimport { DiscoveredFeature } from '../wizard-session.js';\n\nconst STRIPE_PACKAGES = ['stripe', '@stripe/stripe-js'];\n\nconst LLM_PACKAGES = [\n 'openai',\n '@anthropic-ai/sdk',\n 'ai',\n '@ai-sdk/openai',\n 'langchain',\n '@langchain/openai',\n '@langchain/langgraph',\n '@google/generative-ai',\n '@google/genai',\n '@instructor-ai/instructor',\n '@mastra/core',\n 'portkey-ai',\n];\n\n// PyPI normalizes `_` to `-` and is case-insensitive; compare via normalizePyName.\nconst PYTHON_LLM_PACKAGES = [\n 'openai',\n 'anthropic',\n 'langchain',\n 'langchain-openai',\n 'langchain-anthropic',\n 'langchain-google-genai',\n 'langgraph',\n 'litellm',\n 'llama-index',\n 'pydantic-ai',\n 'crewai',\n 'instructor',\n 'dspy-ai',\n 'mistralai',\n 'cohere',\n 'google-generativeai',\n 'google-genai',\n 'portkey-ai',\n];\n\nexport function discoverFeatures(installDir: string): DiscoveredFeature[] {\n const features: DiscoveredFeature[] = [];\n discoverNodeFeatures(installDir, features);\n discoverPythonFeatures(installDir, features);\n return features;\n}\n\nfunction discoverNodeFeatures(\n installDir: string,\n features: DiscoveredFeature[],\n): void {\n const packageJsonText = safeRead(installDir, 'package.json');\n if (!packageJsonText) return;\n\n let packageJson: {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n };\n try {\n packageJson = JSON.parse(packageJsonText);\n } catch {\n return;\n }\n\n const depNames = Object.keys({\n ...packageJson.dependencies,\n ...packageJson.devDependencies,\n });\n\n if (depNames.some((depName) => STRIPE_PACKAGES.includes(depName))) {\n features.push(DiscoveredFeature.Stripe);\n }\n if (depNames.some((depName) => LLM_PACKAGES.includes(depName))) {\n features.push(DiscoveredFeature.LLM);\n }\n}\n\nfunction discoverPythonFeatures(\n installDir: string,\n features: DiscoveredFeature[],\n): void {\n if (features.includes(DiscoveredFeature.LLM)) return;\n\n const depNames: string[] = [];\n\n const requirementsTxt = safeRead(installDir, 'requirements.txt');\n if (requirementsTxt) depNames.push(...parseRequirementsTxt(requirementsTxt));\n\n const pyprojectToml = safeRead(installDir, 'pyproject.toml');\n if (pyprojectToml) depNames.push(...parsePyprojectToml(pyprojectToml));\n\n const pipfile = safeRead(installDir, 'Pipfile');\n if (pipfile) depNames.push(...parsePipfile(pipfile));\n\n if (depNames.some((depName) => PYTHON_LLM_PACKAGES.includes(depName))) {\n features.push(DiscoveredFeature.LLM);\n }\n}\n\nfunction safeRead(installDir: string, file: string): string | null {\n try {\n return readFileSync(join(installDir, file), 'utf-8');\n } catch {\n return null;\n }\n}\n\nfunction normalizePyName(name: string): string {\n return name.toLowerCase().replace(/_/g, '-');\n}\n\nexport function parseRequirementsTxt(content: string): string[] {\n return content\n .split('\\n')\n .map((line) => line.trim())\n .filter((line) => line && !line.startsWith('#') && !line.startsWith('-'))\n .map((line) => line.replace(/\\[[^\\]]*\\]/, ''))\n .map((line) => line.split(/[<>=!~;\\s]/)[0])\n .filter(Boolean)\n .map(normalizePyName);\n}\n\n// Pragmatic, not a full TOML parser — only the dep shapes we care about.\nexport function parsePyprojectToml(content: string): string[] {\n const depNames: string[] = [];\n\n for (const arrayMatch of content.matchAll(\n /dependencies\\s*=\\s*\\[([^\\]]*)\\]/g,\n )) {\n const arrayBody = arrayMatch[1];\n for (const quotedMatch of arrayBody.matchAll(/[\"']([^\"']+)[\"']/g)) {\n const depSpec = quotedMatch[1];\n const name = depSpec.replace(/\\[[^\\]]*\\]/, '').split(/[<>=!~;\\s]/)[0];\n if (name) depNames.push(normalizePyName(name));\n }\n }\n\n const poetrySectionRe =\n /\\[tool\\.poetry\\.(?:dev-dependencies|dependencies|group\\.[^.\\]]+\\.dependencies)\\]([\\s\\S]*?)(?=\\n\\[|$)/g;\n for (const sectionMatch of content.matchAll(poetrySectionRe)) {\n const sectionBody = sectionMatch[1];\n depNames.push(...extractTomlSectionKeys(sectionBody, { skip: ['python'] }));\n }\n\n return depNames;\n}\n\nexport function parsePipfile(content: string): string[] {\n const depNames: string[] = [];\n const sectionRe = /\\[(packages|dev-packages)\\]([\\s\\S]*?)(?=\\n\\[|$)/g;\n for (const sectionMatch of content.matchAll(sectionRe)) {\n const sectionBody = sectionMatch[2];\n depNames.push(...extractTomlSectionKeys(sectionBody));\n }\n return depNames;\n}\n\nfunction extractTomlSectionKeys(\n sectionBody: string,\n opts: { skip?: string[] } = {},\n): string[] {\n const skipNames = new Set(opts.skip ?? []);\n const depNames: string[] = [];\n for (const line of sectionBody.split('\\n')) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#')) continue;\n const equalsIndex = trimmed.indexOf('=');\n if (equalsIndex <= 0) continue;\n const name = trimmed.slice(0, equalsIndex).trim();\n if (!/^[a-zA-Z0-9._-]+$/.test(name)) continue;\n if (skipNames.has(name.toLowerCase())) continue;\n depNames.push(normalizePyName(name));\n }\n return depNames;\n}\n","/**\n * Framework context gathering — run gatherContext and version checks\n * for a detected framework.\n *\n * Pure functions: take a framework config and options, return results.\n * No store mutations, no UI calls.\n */\n\nimport * as semver from 'semver';\nimport { DETECTION_TIMEOUT_MS } from '../constants.js';\nimport type { FrameworkConfig } from '../framework-config.js';\nimport type { WizardOptions } from '../../utils/types.js';\n\n/**\n * Run a framework's `gatherContext()` to collect variant-specific\n * metadata (e.g., router type for Next.js, Expo vs bare for React Native).\n *\n * Returns the gathered context, or an empty object on failure/timeout.\n */\nexport async function gatherFrameworkContext(\n config: FrameworkConfig,\n options: WizardOptions,\n): Promise<Record<string, unknown>> {\n if (!config.metadata.gatherContext) return {};\n\n try {\n return await Promise.race([\n config.metadata.gatherContext(options),\n new Promise<Record<string, never>>((resolve) =>\n setTimeout(() => resolve({}), DETECTION_TIMEOUT_MS),\n ),\n ]);\n } catch {\n return {};\n }\n}\n\nexport interface VersionCheckResult {\n /** Whether the installed version is supported */\n supported:\n | true\n | {\n current: string;\n minimum: string;\n docsUrl: string;\n };\n}\n\n/**\n * Check whether the installed framework version meets the minimum requirement.\n *\n * Returns `{ supported: true }` if the version is fine (or no check is needed).\n * Returns the version details if unsupported.\n */\nexport async function checkFrameworkVersion(\n config: FrameworkConfig,\n options: WizardOptions,\n): Promise<VersionCheckResult> {\n if (\n !config.detection.minimumVersion ||\n !config.detection.getInstalledVersion\n ) {\n return { supported: true };\n }\n\n const version = await config.detection.getInstalledVersion(options);\n if (!version) return { supported: true };\n\n const coerced = semver.coerce(version);\n if (coerced && semver.lt(coerced, config.detection.minimumVersion)) {\n return {\n supported: {\n current: version,\n minimum: config.detection.minimumVersion,\n docsUrl:\n config.metadata.unsupportedVersionDocsUrl ?? config.metadata.docsUrl,\n },\n };\n }\n\n return { supported: true };\n}\n","export { detectFramework } from './framework.js';\nexport { discoverFeatures } from './features.js';\nexport {\n gatherFrameworkContext,\n checkFrameworkVersion,\n type VersionCheckResult,\n} from './context.js';\n"],"mappings":"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"}
|