@posthog/wizard 1.31.1 → 1.32.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (183) hide show
  1. package/README.md +2 -1
  2. package/dist/bin.js +14 -1
  3. package/dist/bin.js.map +1 -1
  4. package/dist/src/__tests__/run.test.js +5 -5
  5. package/dist/src/__tests__/run.test.js.map +1 -1
  6. package/dist/src/android/android-wizard-agent.d.ts +6 -0
  7. package/dist/src/android/android-wizard-agent.js +140 -0
  8. package/dist/src/android/android-wizard-agent.js.map +1 -0
  9. package/dist/src/android/utils.d.ts +11 -0
  10. package/dist/src/android/utils.js +97 -0
  11. package/dist/src/android/utils.js.map +1 -0
  12. package/dist/src/angular/angular-wizard-agent.d.ts +4 -0
  13. package/dist/src/angular/angular-wizard-agent.js +67 -0
  14. package/dist/src/angular/angular-wizard-agent.js.map +1 -0
  15. package/dist/src/angular/utils.d.ts +4 -0
  16. package/dist/src/angular/utils.js +9 -0
  17. package/dist/src/angular/utils.js.map +1 -0
  18. package/dist/src/astro/astro-wizard-agent.d.ts +7 -0
  19. package/dist/src/astro/astro-wizard-agent.js +102 -0
  20. package/dist/src/astro/astro-wizard-agent.js.map +1 -0
  21. package/dist/src/astro/utils.d.ts +17 -0
  22. package/dist/src/astro/utils.js +163 -0
  23. package/dist/src/astro/utils.js.map +1 -0
  24. package/dist/src/django/django-wizard-agent.d.ts +8 -5
  25. package/dist/src/django/django-wizard-agent.js +62 -51
  26. package/dist/src/django/django-wizard-agent.js.map +1 -1
  27. package/dist/src/django/utils.d.ts +1 -1
  28. package/dist/src/django/utils.js +3 -22
  29. package/dist/src/django/utils.js.map +1 -1
  30. package/dist/src/fastapi/fastapi-wizard-agent.d.ts +7 -0
  31. package/dist/src/fastapi/fastapi-wizard-agent.js +217 -0
  32. package/dist/src/fastapi/fastapi-wizard-agent.js.map +1 -0
  33. package/dist/src/fastapi/utils.d.ts +26 -0
  34. package/dist/src/fastapi/utils.js +258 -0
  35. package/dist/src/fastapi/utils.js.map +1 -0
  36. package/dist/src/flask/flask-wizard-agent.d.ts +8 -5
  37. package/dist/src/flask/flask-wizard-agent.js +67 -51
  38. package/dist/src/flask/flask-wizard-agent.js.map +1 -1
  39. package/dist/src/flask/utils.d.ts +1 -1
  40. package/dist/src/flask/utils.js +3 -22
  41. package/dist/src/flask/utils.js.map +1 -1
  42. package/dist/src/laravel/laravel-wizard-agent.d.ts +10 -5
  43. package/dist/src/laravel/laravel-wizard-agent.js +50 -53
  44. package/dist/src/laravel/laravel-wizard-agent.js.map +1 -1
  45. package/dist/src/laravel/utils.d.ts +1 -1
  46. package/dist/src/laravel/utils.js +3 -22
  47. package/dist/src/laravel/utils.js.map +1 -1
  48. package/dist/src/lib/__tests__/agent-interface.test.js +1 -0
  49. package/dist/src/lib/__tests__/agent-interface.test.js.map +1 -1
  50. package/dist/src/lib/agent-interface.d.ts +4 -1
  51. package/dist/src/lib/agent-interface.js +36 -3
  52. package/dist/src/lib/agent-interface.js.map +1 -1
  53. package/dist/src/lib/agent-runner.js +69 -6
  54. package/dist/src/lib/agent-runner.js.map +1 -1
  55. package/dist/src/lib/api.d.ts +4 -4
  56. package/dist/src/lib/constants.d.ts +15 -14
  57. package/dist/src/lib/constants.js +17 -40
  58. package/dist/src/lib/constants.js.map +1 -1
  59. package/dist/src/lib/env-file-tools.d.ts +11 -0
  60. package/dist/src/lib/env-file-tools.js +154 -0
  61. package/dist/src/lib/env-file-tools.js.map +1 -0
  62. package/dist/src/lib/framework-config.d.ts +34 -16
  63. package/dist/src/lib/framework-config.js.map +1 -1
  64. package/dist/src/lib/registry.d.ts +3 -0
  65. package/dist/src/lib/registry.js +41 -0
  66. package/dist/src/lib/registry.js.map +1 -0
  67. package/dist/src/nextjs/nextjs-wizard-agent.d.ts +7 -5
  68. package/dist/src/nextjs/nextjs-wizard-agent.js +16 -79
  69. package/dist/src/nextjs/nextjs-wizard-agent.js.map +1 -1
  70. package/dist/src/nextjs/utils.d.ts +1 -1
  71. package/dist/src/nextjs/utils.js +3 -22
  72. package/dist/src/nextjs/utils.js.map +1 -1
  73. package/dist/src/nuxt/nuxt-wizard-agent.d.ts +6 -0
  74. package/dist/src/nuxt/nuxt-wizard-agent.js +77 -0
  75. package/dist/src/nuxt/nuxt-wizard-agent.js.map +1 -0
  76. package/dist/src/python/python-wizard-agent.d.ts +7 -0
  77. package/dist/src/python/python-wizard-agent.js +269 -0
  78. package/dist/src/python/python-wizard-agent.js.map +1 -0
  79. package/dist/src/python/utils.d.ts +28 -0
  80. package/dist/src/python/utils.js +147 -0
  81. package/dist/src/python/utils.js.map +1 -0
  82. package/dist/src/react-native/react-native-wizard-agent.d.ts +7 -0
  83. package/dist/src/react-native/react-native-wizard-agent.js +91 -0
  84. package/dist/src/react-native/react-native-wizard-agent.js.map +1 -0
  85. package/dist/src/react-native/utils.d.ts +8 -0
  86. package/dist/src/react-native/utils.js +31 -0
  87. package/dist/src/react-native/utils.js.map +1 -0
  88. package/dist/src/react-router/react-router-wizard-agent.d.ts +7 -5
  89. package/dist/src/react-router/react-router-wizard-agent.js +18 -80
  90. package/dist/src/react-router/react-router-wizard-agent.js.map +1 -1
  91. package/dist/src/react-router/utils.d.ts +1 -1
  92. package/dist/src/react-router/utils.js +3 -21
  93. package/dist/src/react-router/utils.js.map +1 -1
  94. package/dist/src/run.d.ts +1 -0
  95. package/dist/src/run.js +28 -76
  96. package/dist/src/run.js.map +1 -1
  97. package/dist/src/steps/add-mcp-server-to-clients/clients/claude-code.d.ts +6 -6
  98. package/dist/src/steps/add-mcp-server-to-clients/clients/claude.d.ts +6 -6
  99. package/dist/src/steps/add-mcp-server-to-clients/clients/codex.d.ts +6 -6
  100. package/dist/src/steps/add-mcp-server-to-clients/clients/cursor.d.ts +6 -6
  101. package/dist/src/steps/add-mcp-server-to-clients/clients/visual-studio-code.d.ts +6 -6
  102. package/dist/src/steps/add-mcp-server-to-clients/clients/zed.d.ts +6 -6
  103. package/dist/src/steps/add-mcp-server-to-clients/defaults.d.ts +6 -6
  104. package/dist/src/svelte/svelte-wizard-agent.d.ts +4 -0
  105. package/dist/src/svelte/svelte-wizard-agent.js +60 -0
  106. package/dist/src/svelte/svelte-wizard-agent.js.map +1 -0
  107. package/dist/src/swift/swift-wizard-agent.d.ts +7 -0
  108. package/dist/src/swift/swift-wizard-agent.js +141 -0
  109. package/dist/src/swift/swift-wizard-agent.js.map +1 -0
  110. package/dist/src/swift/utils.d.ts +8 -0
  111. package/dist/src/swift/utils.js +105 -0
  112. package/dist/src/swift/utils.js.map +1 -0
  113. package/dist/src/tanstack-router/tanstack-router-wizard-agent.d.ts +7 -0
  114. package/dist/src/tanstack-router/tanstack-router-wizard-agent.js +93 -0
  115. package/dist/src/tanstack-router/tanstack-router-wizard-agent.js.map +1 -0
  116. package/dist/src/tanstack-router/utils.d.ts +17 -0
  117. package/dist/src/tanstack-router/utils.js +192 -0
  118. package/dist/src/tanstack-router/utils.js.map +1 -0
  119. package/dist/src/tanstack-start/tanstack-start-wizard-agent.d.ts +4 -0
  120. package/dist/src/tanstack-start/tanstack-start-wizard-agent.js +66 -0
  121. package/dist/src/tanstack-start/tanstack-start-wizard-agent.js.map +1 -0
  122. package/dist/src/tanstack-start/utils.d.ts +4 -0
  123. package/dist/src/tanstack-start/utils.js +9 -0
  124. package/dist/src/tanstack-start/utils.js.map +1 -0
  125. package/dist/src/utils/__tests__/semver.test.d.ts +1 -0
  126. package/dist/src/utils/__tests__/semver.test.js +117 -0
  127. package/dist/src/utils/__tests__/semver.test.js.map +1 -0
  128. package/dist/src/utils/clack-utils.js +3 -5
  129. package/dist/src/utils/clack-utils.js.map +1 -1
  130. package/dist/src/utils/debug.d.ts +2 -0
  131. package/dist/src/utils/debug.js +17 -5
  132. package/dist/src/utils/debug.js.map +1 -1
  133. package/dist/src/utils/file-utils.d.ts +1 -31
  134. package/dist/src/utils/file-utils.js +0 -163
  135. package/dist/src/utils/file-utils.js.map +1 -1
  136. package/dist/src/utils/semver.d.ts +16 -0
  137. package/dist/src/utils/semver.js +37 -0
  138. package/dist/src/utils/semver.js.map +1 -1
  139. package/dist/src/utils/types.d.ts +4 -0
  140. package/dist/src/utils/types.js.map +1 -1
  141. package/dist/src/vue/vue-wizard-agent.d.ts +4 -0
  142. package/dist/src/vue/vue-wizard-agent.js +64 -0
  143. package/dist/src/vue/vue-wizard-agent.js.map +1 -0
  144. package/package.json +1 -1
  145. package/dist/src/astro/astro-wizard.d.ts +0 -2
  146. package/dist/src/astro/astro-wizard.js +0 -89
  147. package/dist/src/astro/astro-wizard.js.map +0 -1
  148. package/dist/src/astro/docs.d.ts +0 -4
  149. package/dist/src/astro/docs.js +0 -101
  150. package/dist/src/astro/docs.js.map +0 -1
  151. package/dist/src/lib/config.d.ts +0 -104
  152. package/dist/src/lib/config.js +0 -368
  153. package/dist/src/lib/config.js.map +0 -1
  154. package/dist/src/lib/messages.d.ts +0 -16
  155. package/dist/src/lib/messages.js +0 -66
  156. package/dist/src/lib/messages.js.map +0 -1
  157. package/dist/src/lib/prompts.d.ts +0 -16
  158. package/dist/src/lib/prompts.js +0 -83
  159. package/dist/src/lib/prompts.js.map +0 -1
  160. package/dist/src/react/docs.d.ts +0 -4
  161. package/dist/src/react/docs.js +0 -49
  162. package/dist/src/react/docs.js.map +0 -1
  163. package/dist/src/react/react-wizard.d.ts +0 -2
  164. package/dist/src/react/react-wizard.js +0 -121
  165. package/dist/src/react/react-wizard.js.map +0 -1
  166. package/dist/src/react-native/docs.d.ts +0 -5
  167. package/dist/src/react-native/docs.js +0 -31
  168. package/dist/src/react-native/docs.js.map +0 -1
  169. package/dist/src/react-native/react-native-wizard.d.ts +0 -2
  170. package/dist/src/react-native/react-native-wizard.js +0 -128
  171. package/dist/src/react-native/react-native-wizard.js.map +0 -1
  172. package/dist/src/svelte/docs.d.ts +0 -3
  173. package/dist/src/svelte/docs.js +0 -111
  174. package/dist/src/svelte/docs.js.map +0 -1
  175. package/dist/src/svelte/svelte-wizard.d.ts +0 -2
  176. package/dist/src/svelte/svelte-wizard.js +0 -121
  177. package/dist/src/svelte/svelte-wizard.js.map +0 -1
  178. package/dist/src/utils/errors.d.ts +0 -3
  179. package/dist/src/utils/errors.js +0 -11
  180. package/dist/src/utils/errors.js.map +0 -1
  181. package/dist/src/utils/query.d.ts +0 -11
  182. package/dist/src/utils/query.js +0 -115
  183. package/dist/src/utils/query.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/django/utils.ts"],"names":[],"mappings":"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","sourcesContent":["import { major, minVersion } from 'semver';\nimport fg from 'fast-glob';\nimport clack from '../utils/clack';\nimport type { WizardOptions } from '../utils/types';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\n\nexport enum DjangoProjectType {\n STANDARD = 'standard', // Traditional Django project (django-admin startproject)\n DRF = 'drf', // Django REST Framework API\n WAGTAIL = 'wagtail', // Wagtail CMS\n CHANNELS = 'channels', // Django Channels (async/websockets)\n}\n\nconst IGNORE_PATTERNS = [\n '**/node_modules/**',\n '**/dist/**',\n '**/build/**',\n '**/venv/**',\n '**/.venv/**',\n '**/env/**',\n '**/.env/**',\n '**/__pycache__/**',\n '**/migrations/**',\n];\n\n/**\n * Get Django version bucket for analytics\n */\nexport function getDjangoVersionBucket(version: string | undefined): string {\n if (!version) {\n return 'none';\n }\n\n try {\n const minVer = minVersion(version);\n if (!minVer) {\n return 'invalid';\n }\n const majorVersion = major(minVer);\n if (majorVersion >= 3) {\n return `${majorVersion}.x`;\n }\n return `<3.0.0`;\n } catch {\n return 'unknown';\n }\n}\n\n/**\n * Extract Django version from requirements files or pyproject.toml\n */\nexport async function getDjangoVersion(\n options: Pick<WizardOptions, 'installDir'>,\n): Promise<string | undefined> {\n const { installDir } = options;\n\n // Check requirements files\n const requirementsFiles = await fg(\n ['**/requirements*.txt', '**/pyproject.toml', '**/setup.py', '**/Pipfile'],\n {\n cwd: installDir,\n ignore: IGNORE_PATTERNS,\n },\n );\n\n for (const reqFile of requirementsFiles) {\n try {\n const content = fs.readFileSync(path.join(installDir, reqFile), 'utf-8');\n\n // Try to extract version from requirements.txt format (Django==4.2.0 or Django>=4.0)\n const requirementsMatch = content.match(\n /[Dd]jango[=<>~!]+([0-9]+\\.[0-9]+(?:\\.[0-9]+)?)/,\n );\n if (requirementsMatch) {\n return requirementsMatch[1];\n }\n\n // Try to extract from pyproject.toml format\n const pyprojectMatch = content.match(\n /[Dd]jango[\"\\s]*[=<>~!]+\\s*[\"']?([0-9]+\\.[0-9]+(?:\\.[0-9]+)?)/,\n );\n if (pyprojectMatch) {\n return pyprojectMatch[1];\n }\n } catch {\n // Skip files that can't be read\n continue;\n }\n }\n\n return undefined;\n}\n\n/**\n * Check if Django REST Framework is installed\n */\nasync function hasDRF({\n installDir,\n}: Pick<WizardOptions, 'installDir'>): Promise<boolean> {\n const requirementsFiles = await fg(\n ['**/requirements*.txt', '**/pyproject.toml', '**/Pipfile'],\n {\n cwd: installDir,\n ignore: IGNORE_PATTERNS,\n },\n );\n\n for (const reqFile of requirementsFiles) {\n try {\n const content = fs.readFileSync(path.join(installDir, reqFile), 'utf-8');\n if (content.includes('djangorestframework')) {\n return true;\n }\n } catch {\n continue;\n }\n }\n\n // Also check INSTALLED_APPS in settings\n const settingsFiles = await fg('**/settings.py', {\n cwd: installDir,\n ignore: IGNORE_PATTERNS,\n });\n\n for (const settingsFile of settingsFiles) {\n try {\n const content = fs.readFileSync(\n path.join(installDir, settingsFile),\n 'utf-8',\n );\n if (content.includes('rest_framework')) {\n return true;\n }\n } catch {\n continue;\n }\n }\n\n return false;\n}\n\n/**\n * Check if Wagtail is installed\n */\nasync function hasWagtail({\n installDir,\n}: Pick<WizardOptions, 'installDir'>): Promise<boolean> {\n const requirementsFiles = await fg(\n ['**/requirements*.txt', '**/pyproject.toml', '**/Pipfile'],\n {\n cwd: installDir,\n ignore: IGNORE_PATTERNS,\n },\n );\n\n for (const reqFile of requirementsFiles) {\n try {\n const content = fs.readFileSync(path.join(installDir, reqFile), 'utf-8');\n if (content.includes('wagtail')) {\n return true;\n }\n } catch {\n continue;\n }\n }\n\n return false;\n}\n\n/**\n * Check if Django Channels is installed\n */\nasync function hasChannels({\n installDir,\n}: Pick<WizardOptions, 'installDir'>): Promise<boolean> {\n const requirementsFiles = await fg(\n ['**/requirements*.txt', '**/pyproject.toml', '**/Pipfile'],\n {\n cwd: installDir,\n ignore: IGNORE_PATTERNS,\n },\n );\n\n for (const reqFile of requirementsFiles) {\n try {\n const content = fs.readFileSync(path.join(installDir, reqFile), 'utf-8');\n if (content.includes('channels')) {\n return true;\n }\n } catch {\n continue;\n }\n }\n\n return false;\n}\n\n/**\n * Detect Django project type\n */\nexport async function getDjangoProjectType(\n options: WizardOptions,\n): Promise<DjangoProjectType> {\n const { installDir } = options;\n\n // Check for Wagtail first (CMS)\n if (await hasWagtail({ installDir })) {\n clack.log.info('Detected Django with Wagtail CMS');\n return DjangoProjectType.WAGTAIL;\n }\n\n // Check for Django REST Framework\n if (await hasDRF({ installDir })) {\n clack.log.info('Detected Django REST Framework project');\n return DjangoProjectType.DRF;\n }\n\n // Check for Django Channels\n if (await hasChannels({ installDir })) {\n clack.log.info('Detected Django Channels project');\n return DjangoProjectType.CHANNELS;\n }\n\n // Default to standard Django\n clack.log.info('Detected standard Django project');\n return DjangoProjectType.STANDARD;\n}\n\n/**\n * Get human-readable name for Django project type\n */\nexport function getDjangoProjectTypeName(\n projectType: DjangoProjectType,\n): string {\n switch (projectType) {\n case DjangoProjectType.STANDARD:\n return 'Standard Django';\n case DjangoProjectType.DRF:\n return 'Django REST Framework';\n case DjangoProjectType.WAGTAIL:\n return 'Wagtail CMS';\n case DjangoProjectType.CHANNELS:\n return 'Django Channels';\n }\n}\n\n/**\n * Find the main Django settings file\n */\nexport async function findDjangoSettingsFile(\n options: Pick<WizardOptions, 'installDir'>,\n): Promise<string | undefined> {\n const { installDir } = options;\n\n // Look for settings.py files\n const settingsFiles = await fg('**/settings.py', {\n cwd: installDir,\n ignore: IGNORE_PATTERNS,\n });\n\n if (settingsFiles.length === 0) {\n // Try settings/__init__.py for split settings\n const splitSettingsFiles = await fg('**/settings/__init__.py', {\n cwd: installDir,\n ignore: IGNORE_PATTERNS,\n });\n\n if (splitSettingsFiles.length > 0) {\n return splitSettingsFiles[0];\n }\n\n return undefined;\n }\n\n // If multiple settings files, prefer the one next to manage.py or in root\n if (settingsFiles.length === 1) {\n return settingsFiles[0];\n }\n\n // Try to find the main settings file by looking for ROOT_URLCONF\n for (const settingsFile of settingsFiles) {\n try {\n const content = fs.readFileSync(\n path.join(installDir, settingsFile),\n 'utf-8',\n );\n if (content.includes('ROOT_URLCONF')) {\n return settingsFile;\n }\n } catch {\n continue;\n }\n }\n\n // Default to first found\n return settingsFiles[0];\n}\n\n/**\n * Find the main Django urls.py file\n */\nexport async function findDjangoUrlsFile(\n options: Pick<WizardOptions, 'installDir'>,\n): Promise<string | undefined> {\n const { installDir } = options;\n\n // First, try to find the root urls.py referenced in settings\n const settingsFile = await findDjangoSettingsFile(options);\n if (settingsFile) {\n try {\n const settingsContent = fs.readFileSync(\n path.join(installDir, settingsFile),\n 'utf-8',\n );\n const urlconfMatch = settingsContent.match(\n /ROOT_URLCONF\\s*=\\s*['\"]([^'\"]+)['\"]/,\n );\n if (urlconfMatch) {\n const urlconfPath = urlconfMatch[1].replace(/\\./g, '/') + '.py';\n const fullPath = path.join(installDir, urlconfPath);\n if (fs.existsSync(fullPath)) {\n return urlconfPath;\n }\n }\n } catch {\n // Fall through to glob search\n }\n }\n\n // Fallback to glob search\n const urlsFiles = await fg('**/urls.py', {\n cwd: installDir,\n ignore: [...IGNORE_PATTERNS, '**/admin/**'],\n });\n\n if (urlsFiles.length === 0) {\n return undefined;\n }\n\n // Prefer urls.py files that contain urlpatterns\n for (const urlsFile of urlsFiles) {\n try {\n const content = fs.readFileSync(path.join(installDir, urlsFile), 'utf-8');\n if (content.includes('urlpatterns')) {\n return urlsFile;\n }\n } catch {\n continue;\n }\n }\n\n return urlsFiles[0];\n}\n"]}
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/django/utils.ts"],"names":[],"mappings":"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","sourcesContent":["import fg from 'fast-glob';\nimport clack from '../utils/clack';\nimport type { WizardOptions } from '../utils/types';\nimport { createVersionBucket } from '../utils/semver';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\n\nexport enum DjangoProjectType {\n STANDARD = 'standard', // Traditional Django project (django-admin startproject)\n DRF = 'drf', // Django REST Framework API\n WAGTAIL = 'wagtail', // Wagtail CMS\n CHANNELS = 'channels', // Django Channels (async/websockets)\n}\n\nconst IGNORE_PATTERNS = [\n '**/node_modules/**',\n '**/dist/**',\n '**/build/**',\n '**/venv/**',\n '**/.venv/**',\n '**/env/**',\n '**/.env/**',\n '**/__pycache__/**',\n '**/migrations/**',\n];\n\n/**\n * Get Django version bucket for analytics\n */\nexport const getDjangoVersionBucket = createVersionBucket();\n\n/**\n * Extract Django version from requirements files or pyproject.toml\n */\nexport async function getDjangoVersion(\n options: Pick<WizardOptions, 'installDir'>,\n): Promise<string | undefined> {\n const { installDir } = options;\n\n // Check requirements files\n const requirementsFiles = await fg(\n ['**/requirements*.txt', '**/pyproject.toml', '**/setup.py', '**/Pipfile'],\n {\n cwd: installDir,\n ignore: IGNORE_PATTERNS,\n },\n );\n\n for (const reqFile of requirementsFiles) {\n try {\n const content = fs.readFileSync(path.join(installDir, reqFile), 'utf-8');\n\n // Try to extract version from requirements.txt format (Django==4.2.0 or Django>=4.0)\n const requirementsMatch = content.match(\n /[Dd]jango[=<>~!]+([0-9]+\\.[0-9]+(?:\\.[0-9]+)?)/,\n );\n if (requirementsMatch) {\n return requirementsMatch[1];\n }\n\n // Try to extract from pyproject.toml format\n const pyprojectMatch = content.match(\n /[Dd]jango[\"\\s]*[=<>~!]+\\s*[\"']?([0-9]+\\.[0-9]+(?:\\.[0-9]+)?)/,\n );\n if (pyprojectMatch) {\n return pyprojectMatch[1];\n }\n } catch {\n // Skip files that can't be read\n continue;\n }\n }\n\n return undefined;\n}\n\n/**\n * Check if Django REST Framework is installed\n */\nasync function hasDRF({\n installDir,\n}: Pick<WizardOptions, 'installDir'>): Promise<boolean> {\n const requirementsFiles = await fg(\n ['**/requirements*.txt', '**/pyproject.toml', '**/Pipfile'],\n {\n cwd: installDir,\n ignore: IGNORE_PATTERNS,\n },\n );\n\n for (const reqFile of requirementsFiles) {\n try {\n const content = fs.readFileSync(path.join(installDir, reqFile), 'utf-8');\n if (content.includes('djangorestframework')) {\n return true;\n }\n } catch {\n continue;\n }\n }\n\n // Also check INSTALLED_APPS in settings\n const settingsFiles = await fg('**/settings.py', {\n cwd: installDir,\n ignore: IGNORE_PATTERNS,\n });\n\n for (const settingsFile of settingsFiles) {\n try {\n const content = fs.readFileSync(\n path.join(installDir, settingsFile),\n 'utf-8',\n );\n if (content.includes('rest_framework')) {\n return true;\n }\n } catch {\n continue;\n }\n }\n\n return false;\n}\n\n/**\n * Check if Wagtail is installed\n */\nasync function hasWagtail({\n installDir,\n}: Pick<WizardOptions, 'installDir'>): Promise<boolean> {\n const requirementsFiles = await fg(\n ['**/requirements*.txt', '**/pyproject.toml', '**/Pipfile'],\n {\n cwd: installDir,\n ignore: IGNORE_PATTERNS,\n },\n );\n\n for (const reqFile of requirementsFiles) {\n try {\n const content = fs.readFileSync(path.join(installDir, reqFile), 'utf-8');\n if (content.includes('wagtail')) {\n return true;\n }\n } catch {\n continue;\n }\n }\n\n return false;\n}\n\n/**\n * Check if Django Channels is installed\n */\nasync function hasChannels({\n installDir,\n}: Pick<WizardOptions, 'installDir'>): Promise<boolean> {\n const requirementsFiles = await fg(\n ['**/requirements*.txt', '**/pyproject.toml', '**/Pipfile'],\n {\n cwd: installDir,\n ignore: IGNORE_PATTERNS,\n },\n );\n\n for (const reqFile of requirementsFiles) {\n try {\n const content = fs.readFileSync(path.join(installDir, reqFile), 'utf-8');\n if (content.includes('channels')) {\n return true;\n }\n } catch {\n continue;\n }\n }\n\n return false;\n}\n\n/**\n * Detect Django project type\n */\nexport async function getDjangoProjectType(\n options: WizardOptions,\n): Promise<DjangoProjectType> {\n const { installDir } = options;\n\n // Check for Wagtail first (CMS)\n if (await hasWagtail({ installDir })) {\n clack.log.info('Detected Django with Wagtail CMS');\n return DjangoProjectType.WAGTAIL;\n }\n\n // Check for Django REST Framework\n if (await hasDRF({ installDir })) {\n clack.log.info('Detected Django REST Framework project');\n return DjangoProjectType.DRF;\n }\n\n // Check for Django Channels\n if (await hasChannels({ installDir })) {\n clack.log.info('Detected Django Channels project');\n return DjangoProjectType.CHANNELS;\n }\n\n // Default to standard Django\n clack.log.info('Detected standard Django project');\n return DjangoProjectType.STANDARD;\n}\n\n/**\n * Get human-readable name for Django project type\n */\nexport function getDjangoProjectTypeName(\n projectType: DjangoProjectType,\n): string {\n switch (projectType) {\n case DjangoProjectType.STANDARD:\n return 'Standard Django';\n case DjangoProjectType.DRF:\n return 'Django REST Framework';\n case DjangoProjectType.WAGTAIL:\n return 'Wagtail CMS';\n case DjangoProjectType.CHANNELS:\n return 'Django Channels';\n }\n}\n\n/**\n * Find the main Django settings file\n */\nexport async function findDjangoSettingsFile(\n options: Pick<WizardOptions, 'installDir'>,\n): Promise<string | undefined> {\n const { installDir } = options;\n\n // Look for settings.py files\n const settingsFiles = await fg('**/settings.py', {\n cwd: installDir,\n ignore: IGNORE_PATTERNS,\n });\n\n if (settingsFiles.length === 0) {\n // Try settings/__init__.py for split settings\n const splitSettingsFiles = await fg('**/settings/__init__.py', {\n cwd: installDir,\n ignore: IGNORE_PATTERNS,\n });\n\n if (splitSettingsFiles.length > 0) {\n return splitSettingsFiles[0];\n }\n\n return undefined;\n }\n\n // If multiple settings files, prefer the one next to manage.py or in root\n if (settingsFiles.length === 1) {\n return settingsFiles[0];\n }\n\n // Try to find the main settings file by looking for ROOT_URLCONF\n for (const settingsFile of settingsFiles) {\n try {\n const content = fs.readFileSync(\n path.join(installDir, settingsFile),\n 'utf-8',\n );\n if (content.includes('ROOT_URLCONF')) {\n return settingsFile;\n }\n } catch {\n continue;\n }\n }\n\n // Default to first found\n return settingsFiles[0];\n}\n\n/**\n * Find the main Django urls.py file\n */\nexport async function findDjangoUrlsFile(\n options: Pick<WizardOptions, 'installDir'>,\n): Promise<string | undefined> {\n const { installDir } = options;\n\n // First, try to find the root urls.py referenced in settings\n const settingsFile = await findDjangoSettingsFile(options);\n if (settingsFile) {\n try {\n const settingsContent = fs.readFileSync(\n path.join(installDir, settingsFile),\n 'utf-8',\n );\n const urlconfMatch = settingsContent.match(\n /ROOT_URLCONF\\s*=\\s*['\"]([^'\"]+)['\"]/,\n );\n if (urlconfMatch) {\n const urlconfPath = urlconfMatch[1].replace(/\\./g, '/') + '.py';\n const fullPath = path.join(installDir, urlconfPath);\n if (fs.existsSync(fullPath)) {\n return urlconfPath;\n }\n }\n } catch {\n // Fall through to glob search\n }\n }\n\n // Fallback to glob search\n const urlsFiles = await fg('**/urls.py', {\n cwd: installDir,\n ignore: [...IGNORE_PATTERNS, '**/admin/**'],\n });\n\n if (urlsFiles.length === 0) {\n return undefined;\n }\n\n // Prefer urls.py files that contain urlpatterns\n for (const urlsFile of urlsFiles) {\n try {\n const content = fs.readFileSync(path.join(installDir, urlsFile), 'utf-8');\n if (content.includes('urlpatterns')) {\n return urlsFile;\n }\n } catch {\n continue;\n }\n }\n\n return urlsFiles[0];\n}\n"]}
@@ -0,0 +1,7 @@
1
+ import type { WizardOptions } from '../utils/types';
2
+ import type { FrameworkConfig } from '../lib/framework-config';
3
+ export declare const FASTAPI_AGENT_CONFIG: FrameworkConfig;
4
+ /**
5
+ * FastAPI wizard powered by the universal agent runner.
6
+ */
7
+ export declare function runFastAPIWizardAgent(options: WizardOptions): Promise<void>;
@@ -0,0 +1,217 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.FASTAPI_AGENT_CONFIG = void 0;
40
+ exports.runFastAPIWizardAgent = runFastAPIWizardAgent;
41
+ const debug_1 = require("../utils/debug");
42
+ const agent_runner_1 = require("../lib/agent-runner");
43
+ const constants_1 = require("../lib/constants");
44
+ const clack_1 = __importDefault(require("../utils/clack"));
45
+ const chalk_1 = __importDefault(require("chalk"));
46
+ const semver = __importStar(require("semver"));
47
+ const utils_1 = require("./utils");
48
+ const fast_glob_1 = __importDefault(require("fast-glob"));
49
+ const fs = __importStar(require("node:fs"));
50
+ const path = __importStar(require("node:path"));
51
+ /**
52
+ * FastAPI framework configuration for the universal agent runner
53
+ */
54
+ const MINIMUM_FASTAPI_VERSION = '0.100.0';
55
+ exports.FASTAPI_AGENT_CONFIG = {
56
+ metadata: {
57
+ name: 'FastAPI',
58
+ integration: constants_1.Integration.fastapi,
59
+ docsUrl: 'https://posthog.com/docs/libraries/python',
60
+ unsupportedVersionDocsUrl: 'https://posthog.com/docs/libraries/python',
61
+ gatherContext: async (options) => {
62
+ const projectType = await (0, utils_1.getFastAPIProjectType)(options);
63
+ const appFile = await (0, utils_1.findFastAPIAppFile)(options);
64
+ return { projectType, appFile };
65
+ },
66
+ },
67
+ detection: {
68
+ packageName: 'fastapi',
69
+ packageDisplayName: 'FastAPI',
70
+ usesPackageJson: false,
71
+ getVersion: (_packageJson) => {
72
+ // For FastAPI, we don't use package.json. Version is extracted separately
73
+ // from requirements.txt or pyproject.toml in the wizard entry point
74
+ return undefined;
75
+ },
76
+ getVersionBucket: utils_1.getFastAPIVersionBucket,
77
+ getInstalledVersion: utils_1.getFastAPIVersion,
78
+ detect: async (options) => {
79
+ const { installDir } = options;
80
+ // Note: Django and Flask are checked before FastAPI in INTEGRATION_ORDER,
81
+ // so if we get here, the project is not a Django or Flask project.
82
+ // Check for FastAPI in requirements files
83
+ const requirementsFiles = await (0, fast_glob_1.default)([
84
+ '**/requirements*.txt',
85
+ '**/pyproject.toml',
86
+ '**/setup.py',
87
+ '**/Pipfile',
88
+ ], {
89
+ cwd: installDir,
90
+ ignore: ['**/venv/**', '**/.venv/**', '**/env/**', '**/.env/**'],
91
+ });
92
+ for (const reqFile of requirementsFiles) {
93
+ try {
94
+ const content = fs.readFileSync(path.join(installDir, reqFile), 'utf-8');
95
+ // Check for fastapi package (case-insensitive)
96
+ // Match "fastapi" as a standalone package
97
+ if (/^fastapi([<>=~!]|$|\s)/im.test(content) ||
98
+ /["']fastapi["']/i.test(content)) {
99
+ return true;
100
+ }
101
+ }
102
+ catch {
103
+ continue;
104
+ }
105
+ }
106
+ // Check for FastAPI app patterns in Python files
107
+ const pyFiles = await (0, fast_glob_1.default)(['**/main.py', '**/app.py', '**/application.py', '**/__init__.py'], {
108
+ cwd: installDir,
109
+ ignore: [
110
+ '**/venv/**',
111
+ '**/.venv/**',
112
+ '**/env/**',
113
+ '**/.env/**',
114
+ '**/__pycache__/**',
115
+ ],
116
+ });
117
+ for (const pyFile of pyFiles) {
118
+ try {
119
+ const content = fs.readFileSync(path.join(installDir, pyFile), 'utf-8');
120
+ if (content.includes('from fastapi import') ||
121
+ content.includes('import fastapi') ||
122
+ /FastAPI\s*\(/.test(content)) {
123
+ return true;
124
+ }
125
+ }
126
+ catch {
127
+ continue;
128
+ }
129
+ }
130
+ return false;
131
+ },
132
+ },
133
+ environment: {
134
+ uploadToHosting: false,
135
+ getEnvVars: (apiKey, host) => ({
136
+ POSTHOG_API_KEY: apiKey,
137
+ POSTHOG_HOST: host,
138
+ }),
139
+ },
140
+ analytics: {
141
+ getTags: (context) => {
142
+ const projectType = context.projectType;
143
+ return {
144
+ projectType: projectType || 'unknown',
145
+ };
146
+ },
147
+ },
148
+ prompts: {
149
+ projectTypeDetection: 'This is a Python/FastAPI project. Look for requirements.txt, pyproject.toml, setup.py, Pipfile, or main.py/app.py to confirm.',
150
+ packageInstallation: 'Use pip, poetry, or pipenv based on existing config files (requirements.txt, pyproject.toml, Pipfile). Do not pin the posthog version - just add "posthog" without version constraints.',
151
+ getAdditionalContextLines: (context) => {
152
+ const projectType = context.projectType;
153
+ const projectTypeName = projectType
154
+ ? (0, utils_1.getFastAPIProjectTypeName)(projectType)
155
+ : 'unknown';
156
+ // Map project type to framework ID for MCP docs resource
157
+ const frameworkIdMap = {
158
+ [utils_1.FastAPIProjectType.STANDARD]: 'fastapi',
159
+ [utils_1.FastAPIProjectType.ROUTER]: 'fastapi',
160
+ [utils_1.FastAPIProjectType.FULLSTACK]: 'fastapi',
161
+ };
162
+ const frameworkId = projectType ? frameworkIdMap[projectType] : 'fastapi';
163
+ const lines = [
164
+ `Project type: ${projectTypeName}`,
165
+ `Framework docs ID: ${frameworkId} (use posthog://docs/frameworks/${frameworkId} for documentation)`,
166
+ ];
167
+ if (context.appFile) {
168
+ lines.push(`App file: ${context.appFile}`);
169
+ }
170
+ return lines;
171
+ },
172
+ },
173
+ ui: {
174
+ successMessage: 'PostHog integration complete',
175
+ estimatedDurationMinutes: 5,
176
+ getOutroChanges: (context) => {
177
+ const projectType = context.projectType;
178
+ const projectTypeName = projectType
179
+ ? (0, utils_1.getFastAPIProjectTypeName)(projectType)
180
+ : 'FastAPI';
181
+ return [
182
+ `Analyzed your ${projectTypeName} project structure`,
183
+ `Installed the PostHog Python package`,
184
+ `Configured PostHog in your FastAPI application`,
185
+ `Added PostHog initialization with lifespan event handling`,
186
+ ];
187
+ },
188
+ getOutroNextSteps: () => [
189
+ 'Start your FastAPI development server to see PostHog in action',
190
+ 'Visit your PostHog dashboard to see incoming events',
191
+ 'Use posthog.identify() to associate events with users',
192
+ ],
193
+ },
194
+ };
195
+ /**
196
+ * FastAPI wizard powered by the universal agent runner.
197
+ */
198
+ async function runFastAPIWizardAgent(options) {
199
+ if (options.debug) {
200
+ (0, debug_1.enableDebugLogs)();
201
+ }
202
+ // Check FastAPI version - agent wizard requires >= 0.100.0
203
+ const fastapiVersion = await (0, utils_1.getFastAPIVersion)(options);
204
+ if (fastapiVersion) {
205
+ const coercedVersion = semver.coerce(fastapiVersion);
206
+ if (coercedVersion && semver.lt(coercedVersion, MINIMUM_FASTAPI_VERSION)) {
207
+ const docsUrl = exports.FASTAPI_AGENT_CONFIG.metadata.unsupportedVersionDocsUrl ??
208
+ exports.FASTAPI_AGENT_CONFIG.metadata.docsUrl;
209
+ clack_1.default.log.warn(`Sorry: the wizard can't help you with FastAPI ${fastapiVersion}. Upgrade to FastAPI ${MINIMUM_FASTAPI_VERSION} or later, or check out the manual setup guide.`);
210
+ clack_1.default.log.info(`Setup FastAPI manually: ${chalk_1.default.cyan(docsUrl)}`);
211
+ clack_1.default.outro('PostHog wizard will see you next time!');
212
+ return;
213
+ }
214
+ }
215
+ await (0, agent_runner_1.runAgentWizard)(exports.FASTAPI_AGENT_CONFIG, options);
216
+ }
217
+ //# sourceMappingURL=fastapi-wizard-agent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fastapi-wizard-agent.js","sourceRoot":"","sources":["../../../src/fastapi/fastapi-wizard-agent.ts"],"names":[],"mappings":"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","sourcesContent":["/* FastAPI wizard using posthog-agent with PostHog MCP */\nimport type { WizardOptions } from '../utils/types';\nimport type { FrameworkConfig } from '../lib/framework-config';\nimport { enableDebugLogs } from '../utils/debug';\nimport { runAgentWizard } from '../lib/agent-runner';\nimport { Integration } from '../lib/constants';\nimport clack from '../utils/clack';\nimport chalk from 'chalk';\nimport * as semver from 'semver';\nimport {\n getFastAPIVersion,\n getFastAPIProjectType,\n getFastAPIProjectTypeName,\n getFastAPIVersionBucket,\n FastAPIProjectType,\n findFastAPIAppFile,\n} from './utils';\nimport fg from 'fast-glob';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\n\n/**\n * FastAPI framework configuration for the universal agent runner\n */\nconst MINIMUM_FASTAPI_VERSION = '0.100.0';\n\nexport const FASTAPI_AGENT_CONFIG: FrameworkConfig = {\n metadata: {\n name: 'FastAPI',\n integration: Integration.fastapi,\n docsUrl: 'https://posthog.com/docs/libraries/python',\n unsupportedVersionDocsUrl: 'https://posthog.com/docs/libraries/python',\n gatherContext: async (options: WizardOptions) => {\n const projectType = await getFastAPIProjectType(options);\n const appFile = await findFastAPIAppFile(options);\n return { projectType, appFile };\n },\n },\n\n detection: {\n packageName: 'fastapi',\n packageDisplayName: 'FastAPI',\n usesPackageJson: false,\n getVersion: (_packageJson: any) => {\n // For FastAPI, we don't use package.json. Version is extracted separately\n // from requirements.txt or pyproject.toml in the wizard entry point\n return undefined;\n },\n getVersionBucket: getFastAPIVersionBucket,\n getInstalledVersion: getFastAPIVersion,\n detect: async (options) => {\n const { installDir } = options;\n\n // Note: Django and Flask are checked before FastAPI in INTEGRATION_ORDER,\n // so if we get here, the project is not a Django or Flask project.\n\n // Check for FastAPI in requirements files\n const requirementsFiles = await fg(\n [\n '**/requirements*.txt',\n '**/pyproject.toml',\n '**/setup.py',\n '**/Pipfile',\n ],\n {\n cwd: installDir,\n ignore: ['**/venv/**', '**/.venv/**', '**/env/**', '**/.env/**'],\n },\n );\n\n for (const reqFile of requirementsFiles) {\n try {\n const content = fs.readFileSync(\n path.join(installDir, reqFile),\n 'utf-8',\n );\n // Check for fastapi package (case-insensitive)\n // Match \"fastapi\" as a standalone package\n if (\n /^fastapi([<>=~!]|$|\\s)/im.test(content) ||\n /[\"']fastapi[\"']/i.test(content)\n ) {\n return true;\n }\n } catch {\n continue;\n }\n }\n\n // Check for FastAPI app patterns in Python files\n const pyFiles = await fg(\n ['**/main.py', '**/app.py', '**/application.py', '**/__init__.py'],\n {\n cwd: installDir,\n ignore: [\n '**/venv/**',\n '**/.venv/**',\n '**/env/**',\n '**/.env/**',\n '**/__pycache__/**',\n ],\n },\n );\n\n for (const pyFile of pyFiles) {\n try {\n const content = fs.readFileSync(\n path.join(installDir, pyFile),\n 'utf-8',\n );\n if (\n content.includes('from fastapi import') ||\n content.includes('import fastapi') ||\n /FastAPI\\s*\\(/.test(content)\n ) {\n return true;\n }\n } catch {\n continue;\n }\n }\n\n return false;\n },\n },\n\n environment: {\n uploadToHosting: false,\n getEnvVars: (apiKey: string, host: string) => ({\n POSTHOG_API_KEY: apiKey,\n POSTHOG_HOST: host,\n }),\n },\n\n analytics: {\n getTags: (context: any) => {\n const projectType = context.projectType as FastAPIProjectType;\n return {\n projectType: projectType || 'unknown',\n };\n },\n },\n\n prompts: {\n projectTypeDetection:\n 'This is a Python/FastAPI project. Look for requirements.txt, pyproject.toml, setup.py, Pipfile, or main.py/app.py to confirm.',\n packageInstallation:\n 'Use pip, poetry, or pipenv based on existing config files (requirements.txt, pyproject.toml, Pipfile). Do not pin the posthog version - just add \"posthog\" without version constraints.',\n getAdditionalContextLines: (context: any) => {\n const projectType = context.projectType as FastAPIProjectType;\n const projectTypeName = projectType\n ? getFastAPIProjectTypeName(projectType)\n : 'unknown';\n\n // Map project type to framework ID for MCP docs resource\n const frameworkIdMap: Record<FastAPIProjectType, string> = {\n [FastAPIProjectType.STANDARD]: 'fastapi',\n [FastAPIProjectType.ROUTER]: 'fastapi',\n [FastAPIProjectType.FULLSTACK]: 'fastapi',\n };\n\n const frameworkId = projectType ? frameworkIdMap[projectType] : 'fastapi';\n\n const lines = [\n `Project type: ${projectTypeName}`,\n `Framework docs ID: ${frameworkId} (use posthog://docs/frameworks/${frameworkId} for documentation)`,\n ];\n\n if (context.appFile) {\n lines.push(`App file: ${context.appFile}`);\n }\n\n return lines;\n },\n },\n\n ui: {\n successMessage: 'PostHog integration complete',\n estimatedDurationMinutes: 5,\n getOutroChanges: (context: any) => {\n const projectType = context.projectType as FastAPIProjectType;\n const projectTypeName = projectType\n ? getFastAPIProjectTypeName(projectType)\n : 'FastAPI';\n return [\n `Analyzed your ${projectTypeName} project structure`,\n `Installed the PostHog Python package`,\n `Configured PostHog in your FastAPI application`,\n `Added PostHog initialization with lifespan event handling`,\n ];\n },\n getOutroNextSteps: () => [\n 'Start your FastAPI development server to see PostHog in action',\n 'Visit your PostHog dashboard to see incoming events',\n 'Use posthog.identify() to associate events with users',\n ],\n },\n};\n\n/**\n * FastAPI wizard powered by the universal agent runner.\n */\nexport async function runFastAPIWizardAgent(\n options: WizardOptions,\n): Promise<void> {\n if (options.debug) {\n enableDebugLogs();\n }\n\n // Check FastAPI version - agent wizard requires >= 0.100.0\n const fastapiVersion = await getFastAPIVersion(options);\n\n if (fastapiVersion) {\n const coercedVersion = semver.coerce(fastapiVersion);\n if (coercedVersion && semver.lt(coercedVersion, MINIMUM_FASTAPI_VERSION)) {\n const docsUrl =\n FASTAPI_AGENT_CONFIG.metadata.unsupportedVersionDocsUrl ??\n FASTAPI_AGENT_CONFIG.metadata.docsUrl;\n\n clack.log.warn(\n `Sorry: the wizard can't help you with FastAPI ${fastapiVersion}. Upgrade to FastAPI ${MINIMUM_FASTAPI_VERSION} or later, or check out the manual setup guide.`,\n );\n clack.log.info(`Setup FastAPI manually: ${chalk.cyan(docsUrl)}`);\n clack.outro('PostHog wizard will see you next time!');\n return;\n }\n }\n\n await runAgentWizard(FASTAPI_AGENT_CONFIG, options);\n}\n"]}
@@ -0,0 +1,26 @@
1
+ import type { WizardOptions } from '../utils/types';
2
+ export declare enum FastAPIProjectType {
3
+ STANDARD = "standard",// Basic FastAPI app
4
+ ROUTER = "router",// FastAPI with APIRouter
5
+ FULLSTACK = "fullstack"
6
+ }
7
+ /**
8
+ * Get FastAPI version bucket for analytics
9
+ */
10
+ export declare function getFastAPIVersionBucket(version: string | undefined): string;
11
+ /**
12
+ * Extract FastAPI version from requirements files or pyproject.toml
13
+ */
14
+ export declare function getFastAPIVersion(options: Pick<WizardOptions, 'installDir'>): Promise<string | undefined>;
15
+ /**
16
+ * Detect FastAPI project type
17
+ */
18
+ export declare function getFastAPIProjectType(options: WizardOptions): Promise<FastAPIProjectType>;
19
+ /**
20
+ * Get human-readable name for FastAPI project type
21
+ */
22
+ export declare function getFastAPIProjectTypeName(projectType: FastAPIProjectType): string;
23
+ /**
24
+ * Find the main FastAPI app file
25
+ */
26
+ export declare function findFastAPIAppFile(options: Pick<WizardOptions, 'installDir'>): Promise<string | undefined>;
@@ -0,0 +1,258 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.FastAPIProjectType = void 0;
40
+ exports.getFastAPIVersionBucket = getFastAPIVersionBucket;
41
+ exports.getFastAPIVersion = getFastAPIVersion;
42
+ exports.getFastAPIProjectType = getFastAPIProjectType;
43
+ exports.getFastAPIProjectTypeName = getFastAPIProjectTypeName;
44
+ exports.findFastAPIAppFile = findFastAPIAppFile;
45
+ const semver_1 = require("semver");
46
+ const fast_glob_1 = __importDefault(require("fast-glob"));
47
+ const clack_1 = __importDefault(require("../utils/clack"));
48
+ const fs = __importStar(require("node:fs"));
49
+ const path = __importStar(require("node:path"));
50
+ var FastAPIProjectType;
51
+ (function (FastAPIProjectType) {
52
+ FastAPIProjectType["STANDARD"] = "standard";
53
+ FastAPIProjectType["ROUTER"] = "router";
54
+ FastAPIProjectType["FULLSTACK"] = "fullstack";
55
+ })(FastAPIProjectType || (exports.FastAPIProjectType = FastAPIProjectType = {}));
56
+ const IGNORE_PATTERNS = [
57
+ '**/node_modules/**',
58
+ '**/dist/**',
59
+ '**/build/**',
60
+ '**/venv/**',
61
+ '**/.venv/**',
62
+ '**/env/**',
63
+ '**/.env/**',
64
+ '**/__pycache__/**',
65
+ '**/migrations/**',
66
+ ];
67
+ /**
68
+ * Get FastAPI version bucket for analytics
69
+ */
70
+ function getFastAPIVersionBucket(version) {
71
+ if (!version) {
72
+ return 'none';
73
+ }
74
+ try {
75
+ const minVer = (0, semver_1.minVersion)(version);
76
+ if (!minVer) {
77
+ return 'invalid';
78
+ }
79
+ const majorVersion = (0, semver_1.major)(minVer);
80
+ // FastAPI 0.x is still the common version range
81
+ if (majorVersion === 0) {
82
+ return '0.x';
83
+ }
84
+ return `${majorVersion}.x`;
85
+ }
86
+ catch {
87
+ return 'unknown';
88
+ }
89
+ }
90
+ /**
91
+ * Extract FastAPI version from requirements files or pyproject.toml
92
+ */
93
+ async function getFastAPIVersion(options) {
94
+ const { installDir } = options;
95
+ // Check requirements files
96
+ const requirementsFiles = await (0, fast_glob_1.default)(['**/requirements*.txt', '**/pyproject.toml', '**/setup.py', '**/Pipfile'], {
97
+ cwd: installDir,
98
+ ignore: IGNORE_PATTERNS,
99
+ });
100
+ for (const reqFile of requirementsFiles) {
101
+ try {
102
+ const content = fs.readFileSync(path.join(installDir, reqFile), 'utf-8');
103
+ // Try to extract version from requirements.txt format (fastapi==0.109.0 or fastapi>=0.100)
104
+ const requirementsMatch = content.match(/[Ff]ast[Aa][Pp][Ii][=<>~!]+([0-9]+\.[0-9]+(?:\.[0-9]+)?)/);
105
+ if (requirementsMatch) {
106
+ return requirementsMatch[1];
107
+ }
108
+ // Try to extract from pyproject.toml format
109
+ const pyprojectMatch = content.match(/[Ff]ast[Aa][Pp][Ii]["\s]*[=<>~!]+\s*["']?([0-9]+\.[0-9]+(?:\.[0-9]+)?)/);
110
+ if (pyprojectMatch) {
111
+ return pyprojectMatch[1];
112
+ }
113
+ }
114
+ catch {
115
+ // Skip files that can't be read
116
+ continue;
117
+ }
118
+ }
119
+ return undefined;
120
+ }
121
+ /**
122
+ * Check if app uses FastAPI APIRouter
123
+ */
124
+ async function hasAPIRouter({ installDir, }) {
125
+ const pyFiles = await (0, fast_glob_1.default)(['**/*.py'], {
126
+ cwd: installDir,
127
+ ignore: IGNORE_PATTERNS,
128
+ });
129
+ for (const pyFile of pyFiles) {
130
+ try {
131
+ const content = fs.readFileSync(path.join(installDir, pyFile), 'utf-8');
132
+ if (content.includes('APIRouter(') ||
133
+ content.includes('include_router(') ||
134
+ content.includes('from fastapi import APIRouter')) {
135
+ return true;
136
+ }
137
+ }
138
+ catch {
139
+ continue;
140
+ }
141
+ }
142
+ return false;
143
+ }
144
+ /**
145
+ * Check if app uses Jinja2 templates (fullstack pattern)
146
+ */
147
+ async function hasTemplates({ installDir, }) {
148
+ // Check for Jinja2Templates usage in Python files
149
+ const pyFiles = await (0, fast_glob_1.default)(['**/*.py'], {
150
+ cwd: installDir,
151
+ ignore: IGNORE_PATTERNS,
152
+ });
153
+ for (const pyFile of pyFiles) {
154
+ try {
155
+ const content = fs.readFileSync(path.join(installDir, pyFile), 'utf-8');
156
+ if (content.includes('Jinja2Templates') ||
157
+ content.includes('from fastapi.templating import')) {
158
+ return true;
159
+ }
160
+ }
161
+ catch {
162
+ continue;
163
+ }
164
+ }
165
+ // Check for templates directory
166
+ const templateDirs = await (0, fast_glob_1.default)(['**/templates'], {
167
+ cwd: installDir,
168
+ ignore: IGNORE_PATTERNS,
169
+ onlyDirectories: true,
170
+ });
171
+ return templateDirs.length > 0;
172
+ }
173
+ /**
174
+ * Detect FastAPI project type
175
+ */
176
+ async function getFastAPIProjectType(options) {
177
+ const { installDir } = options;
178
+ // Check for fullstack pattern (templates)
179
+ if (await hasTemplates({ installDir })) {
180
+ clack_1.default.log.info('Detected FastAPI fullstack project with templates');
181
+ return FastAPIProjectType.FULLSTACK;
182
+ }
183
+ // Check for APIRouter (modular structure)
184
+ if (await hasAPIRouter({ installDir })) {
185
+ clack_1.default.log.info('Detected FastAPI project with APIRouter');
186
+ return FastAPIProjectType.ROUTER;
187
+ }
188
+ // Default to standard FastAPI
189
+ clack_1.default.log.info('Detected standard FastAPI project');
190
+ return FastAPIProjectType.STANDARD;
191
+ }
192
+ /**
193
+ * Get human-readable name for FastAPI project type
194
+ */
195
+ function getFastAPIProjectTypeName(projectType) {
196
+ switch (projectType) {
197
+ case FastAPIProjectType.STANDARD:
198
+ return 'Standard FastAPI';
199
+ case FastAPIProjectType.ROUTER:
200
+ return 'FastAPI with APIRouter';
201
+ case FastAPIProjectType.FULLSTACK:
202
+ return 'FastAPI Fullstack';
203
+ }
204
+ }
205
+ /**
206
+ * Find the main FastAPI app file
207
+ */
208
+ async function findFastAPIAppFile(options) {
209
+ const { installDir } = options;
210
+ // Common FastAPI app file patterns
211
+ const commonPatterns = [
212
+ '**/main.py',
213
+ '**/app.py',
214
+ '**/application.py',
215
+ '**/api.py',
216
+ '**/__init__.py',
217
+ ];
218
+ const appFiles = await (0, fast_glob_1.default)(commonPatterns, {
219
+ cwd: installDir,
220
+ ignore: IGNORE_PATTERNS,
221
+ });
222
+ // Look for files with FastAPI() instantiation
223
+ for (const appFile of appFiles) {
224
+ try {
225
+ const content = fs.readFileSync(path.join(installDir, appFile), 'utf-8');
226
+ // Check for FastAPI app instantiation
227
+ if (content.includes('FastAPI(') ||
228
+ content.includes('from fastapi import FastAPI')) {
229
+ return appFile;
230
+ }
231
+ }
232
+ catch {
233
+ continue;
234
+ }
235
+ }
236
+ // If no file with FastAPI() found, check all Python files
237
+ const allPyFiles = await (0, fast_glob_1.default)(['**/*.py'], {
238
+ cwd: installDir,
239
+ ignore: IGNORE_PATTERNS,
240
+ });
241
+ for (const pyFile of allPyFiles) {
242
+ try {
243
+ const content = fs.readFileSync(path.join(installDir, pyFile), 'utf-8');
244
+ if (content.includes('FastAPI(')) {
245
+ return pyFile;
246
+ }
247
+ }
248
+ catch {
249
+ continue;
250
+ }
251
+ }
252
+ // Return first common pattern file if exists
253
+ if (appFiles.length > 0) {
254
+ return appFiles[0];
255
+ }
256
+ return undefined;
257
+ }
258
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/fastapi/utils.ts"],"names":[],"mappings":"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","sourcesContent":["import { major, minVersion } from 'semver';\nimport fg from 'fast-glob';\nimport clack from '../utils/clack';\nimport type { WizardOptions } from '../utils/types';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\n\nexport enum FastAPIProjectType {\n STANDARD = 'standard', // Basic FastAPI app\n ROUTER = 'router', // FastAPI with APIRouter\n FULLSTACK = 'fullstack', // FastAPI with templates (Jinja2)\n}\n\nconst IGNORE_PATTERNS = [\n '**/node_modules/**',\n '**/dist/**',\n '**/build/**',\n '**/venv/**',\n '**/.venv/**',\n '**/env/**',\n '**/.env/**',\n '**/__pycache__/**',\n '**/migrations/**',\n];\n\n/**\n * Get FastAPI version bucket for analytics\n */\nexport function getFastAPIVersionBucket(version: string | undefined): string {\n if (!version) {\n return 'none';\n }\n\n try {\n const minVer = minVersion(version);\n if (!minVer) {\n return 'invalid';\n }\n const majorVersion = major(minVer);\n // FastAPI 0.x is still the common version range\n if (majorVersion === 0) {\n return '0.x';\n }\n return `${majorVersion}.x`;\n } catch {\n return 'unknown';\n }\n}\n\n/**\n * Extract FastAPI version from requirements files or pyproject.toml\n */\nexport async function getFastAPIVersion(\n options: Pick<WizardOptions, 'installDir'>,\n): Promise<string | undefined> {\n const { installDir } = options;\n\n // Check requirements files\n const requirementsFiles = await fg(\n ['**/requirements*.txt', '**/pyproject.toml', '**/setup.py', '**/Pipfile'],\n {\n cwd: installDir,\n ignore: IGNORE_PATTERNS,\n },\n );\n\n for (const reqFile of requirementsFiles) {\n try {\n const content = fs.readFileSync(path.join(installDir, reqFile), 'utf-8');\n\n // Try to extract version from requirements.txt format (fastapi==0.109.0 or fastapi>=0.100)\n const requirementsMatch = content.match(\n /[Ff]ast[Aa][Pp][Ii][=<>~!]+([0-9]+\\.[0-9]+(?:\\.[0-9]+)?)/,\n );\n if (requirementsMatch) {\n return requirementsMatch[1];\n }\n\n // Try to extract from pyproject.toml format\n const pyprojectMatch = content.match(\n /[Ff]ast[Aa][Pp][Ii][\"\\s]*[=<>~!]+\\s*[\"']?([0-9]+\\.[0-9]+(?:\\.[0-9]+)?)/,\n );\n if (pyprojectMatch) {\n return pyprojectMatch[1];\n }\n } catch {\n // Skip files that can't be read\n continue;\n }\n }\n\n return undefined;\n}\n\n/**\n * Check if app uses FastAPI APIRouter\n */\nasync function hasAPIRouter({\n installDir,\n}: Pick<WizardOptions, 'installDir'>): Promise<boolean> {\n const pyFiles = await fg(['**/*.py'], {\n cwd: installDir,\n ignore: IGNORE_PATTERNS,\n });\n\n for (const pyFile of pyFiles) {\n try {\n const content = fs.readFileSync(path.join(installDir, pyFile), 'utf-8');\n if (\n content.includes('APIRouter(') ||\n content.includes('include_router(') ||\n content.includes('from fastapi import APIRouter')\n ) {\n return true;\n }\n } catch {\n continue;\n }\n }\n\n return false;\n}\n\n/**\n * Check if app uses Jinja2 templates (fullstack pattern)\n */\nasync function hasTemplates({\n installDir,\n}: Pick<WizardOptions, 'installDir'>): Promise<boolean> {\n // Check for Jinja2Templates usage in Python files\n const pyFiles = await fg(['**/*.py'], {\n cwd: installDir,\n ignore: IGNORE_PATTERNS,\n });\n\n for (const pyFile of pyFiles) {\n try {\n const content = fs.readFileSync(path.join(installDir, pyFile), 'utf-8');\n if (\n content.includes('Jinja2Templates') ||\n content.includes('from fastapi.templating import')\n ) {\n return true;\n }\n } catch {\n continue;\n }\n }\n\n // Check for templates directory\n const templateDirs = await fg(['**/templates'], {\n cwd: installDir,\n ignore: IGNORE_PATTERNS,\n onlyDirectories: true,\n });\n\n return templateDirs.length > 0;\n}\n\n/**\n * Detect FastAPI project type\n */\nexport async function getFastAPIProjectType(\n options: WizardOptions,\n): Promise<FastAPIProjectType> {\n const { installDir } = options;\n\n // Check for fullstack pattern (templates)\n if (await hasTemplates({ installDir })) {\n clack.log.info('Detected FastAPI fullstack project with templates');\n return FastAPIProjectType.FULLSTACK;\n }\n\n // Check for APIRouter (modular structure)\n if (await hasAPIRouter({ installDir })) {\n clack.log.info('Detected FastAPI project with APIRouter');\n return FastAPIProjectType.ROUTER;\n }\n\n // Default to standard FastAPI\n clack.log.info('Detected standard FastAPI project');\n return FastAPIProjectType.STANDARD;\n}\n\n/**\n * Get human-readable name for FastAPI project type\n */\nexport function getFastAPIProjectTypeName(\n projectType: FastAPIProjectType,\n): string {\n switch (projectType) {\n case FastAPIProjectType.STANDARD:\n return 'Standard FastAPI';\n case FastAPIProjectType.ROUTER:\n return 'FastAPI with APIRouter';\n case FastAPIProjectType.FULLSTACK:\n return 'FastAPI Fullstack';\n }\n}\n\n/**\n * Find the main FastAPI app file\n */\nexport async function findFastAPIAppFile(\n options: Pick<WizardOptions, 'installDir'>,\n): Promise<string | undefined> {\n const { installDir } = options;\n\n // Common FastAPI app file patterns\n const commonPatterns = [\n '**/main.py',\n '**/app.py',\n '**/application.py',\n '**/api.py',\n '**/__init__.py',\n ];\n\n const appFiles = await fg(commonPatterns, {\n cwd: installDir,\n ignore: IGNORE_PATTERNS,\n });\n\n // Look for files with FastAPI() instantiation\n for (const appFile of appFiles) {\n try {\n const content = fs.readFileSync(path.join(installDir, appFile), 'utf-8');\n // Check for FastAPI app instantiation\n if (\n content.includes('FastAPI(') ||\n content.includes('from fastapi import FastAPI')\n ) {\n return appFile;\n }\n } catch {\n continue;\n }\n }\n\n // If no file with FastAPI() found, check all Python files\n const allPyFiles = await fg(['**/*.py'], {\n cwd: installDir,\n ignore: IGNORE_PATTERNS,\n });\n\n for (const pyFile of allPyFiles) {\n try {\n const content = fs.readFileSync(path.join(installDir, pyFile), 'utf-8');\n if (content.includes('FastAPI(')) {\n return pyFile;\n }\n } catch {\n continue;\n }\n }\n\n // Return first common pattern file if exists\n if (appFiles.length > 0) {\n return appFiles[0];\n }\n\n return undefined;\n}\n"]}