UNPKG

@posthog/wizard

Version:

The PostHog wizard helps you to configure your project

363 lines 12 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.FlaskProjectType = void 0; exports.getFlaskVersionBucket = getFlaskVersionBucket; exports.getFlaskVersion = getFlaskVersion; exports.getFlaskProjectType = getFlaskProjectType; exports.getFlaskProjectTypeName = getFlaskProjectTypeName; exports.findFlaskAppFile = findFlaskAppFile; const semver_1 = require("semver"); const fast_glob_1 = __importDefault(require("fast-glob")); const clack_1 = __importDefault(require("../utils/clack")); const fs = __importStar(require("node:fs")); const path = __importStar(require("node:path")); var FlaskProjectType; (function (FlaskProjectType) { FlaskProjectType["STANDARD"] = "standard"; FlaskProjectType["RESTFUL"] = "restful"; FlaskProjectType["RESTX"] = "restx"; FlaskProjectType["SMOREST"] = "smorest"; FlaskProjectType["BLUEPRINT"] = "blueprint"; })(FlaskProjectType || (exports.FlaskProjectType = FlaskProjectType = {})); const IGNORE_PATTERNS = [ '**/node_modules/**', '**/dist/**', '**/build/**', '**/venv/**', '**/.venv/**', '**/env/**', '**/.env/**', '**/__pycache__/**', '**/migrations/**', '**/instance/**', ]; /** * Get Flask version bucket for analytics */ function getFlaskVersionBucket(version) { if (!version) { return 'none'; } try { const minVer = (0, semver_1.minVersion)(version); if (!minVer) { return 'invalid'; } const majorVersion = (0, semver_1.major)(minVer); if (majorVersion >= 2) { return `${majorVersion}.x`; } return `<2.0.0`; } catch { return 'unknown'; } } /** * Extract Flask version from requirements files or pyproject.toml */ async function getFlaskVersion(options) { const { installDir } = options; // Check requirements files const requirementsFiles = await (0, fast_glob_1.default)(['**/requirements*.txt', '**/pyproject.toml', '**/setup.py', '**/Pipfile'], { cwd: installDir, ignore: IGNORE_PATTERNS, }); for (const reqFile of requirementsFiles) { try { const content = fs.readFileSync(path.join(installDir, reqFile), 'utf-8'); // Try to extract version from requirements.txt format (Flask==3.0.0 or flask>=2.0) const requirementsMatch = content.match(/[Ff]lask[=<>~!]+([0-9]+\.[0-9]+(?:\.[0-9]+)?)/); if (requirementsMatch) { return requirementsMatch[1]; } // Try to extract from pyproject.toml format const pyprojectMatch = content.match(/[Ff]lask["\s]*[=<>~!]+\s*["']?([0-9]+\.[0-9]+(?:\.[0-9]+)?)/); if (pyprojectMatch) { return pyprojectMatch[1]; } } catch { // Skip files that can't be read continue; } } return undefined; } /** * Check if Flask-RESTful is installed */ async function hasFlaskRESTful({ installDir, }) { const requirementsFiles = await (0, fast_glob_1.default)(['**/requirements*.txt', '**/pyproject.toml', '**/Pipfile'], { cwd: installDir, ignore: IGNORE_PATTERNS, }); for (const reqFile of requirementsFiles) { try { const content = fs.readFileSync(path.join(installDir, reqFile), 'utf-8'); if (content.includes('flask-restful') || content.includes('Flask-RESTful')) { return true; } } catch { continue; } } // Also check imports in Python files const pyFiles = await (0, fast_glob_1.default)(['**/*.py'], { cwd: installDir, ignore: IGNORE_PATTERNS, }); for (const pyFile of pyFiles) { try { const content = fs.readFileSync(path.join(installDir, pyFile), 'utf-8'); if (content.includes('from flask_restful import') || content.includes('import flask_restful')) { return true; } } catch { continue; } } return false; } /** * Check if Flask-RESTX is installed */ async function hasFlaskRESTX({ installDir, }) { const requirementsFiles = await (0, fast_glob_1.default)(['**/requirements*.txt', '**/pyproject.toml', '**/Pipfile'], { cwd: installDir, ignore: IGNORE_PATTERNS, }); for (const reqFile of requirementsFiles) { try { const content = fs.readFileSync(path.join(installDir, reqFile), 'utf-8'); if (content.includes('flask-restx') || content.includes('Flask-RESTX')) { return true; } } catch { continue; } } // Also check imports in Python files const pyFiles = await (0, fast_glob_1.default)(['**/*.py'], { cwd: installDir, ignore: IGNORE_PATTERNS, }); for (const pyFile of pyFiles) { try { const content = fs.readFileSync(path.join(installDir, pyFile), 'utf-8'); if (content.includes('from flask_restx import') || content.includes('import flask_restx')) { return true; } } catch { continue; } } return false; } /** * Check if flask-smorest is installed */ async function hasFlaskSmorest({ installDir, }) { const requirementsFiles = await (0, fast_glob_1.default)(['**/requirements*.txt', '**/pyproject.toml', '**/Pipfile'], { cwd: installDir, ignore: IGNORE_PATTERNS, }); for (const reqFile of requirementsFiles) { try { const content = fs.readFileSync(path.join(installDir, reqFile), 'utf-8'); if (content.includes('flask-smorest')) { return true; } } catch { continue; } } // Also check imports in Python files const pyFiles = await (0, fast_glob_1.default)(['**/*.py'], { cwd: installDir, ignore: IGNORE_PATTERNS, }); for (const pyFile of pyFiles) { try { const content = fs.readFileSync(path.join(installDir, pyFile), 'utf-8'); if (content.includes('from flask_smorest import') || content.includes('import flask_smorest')) { return true; } } catch { continue; } } return false; } /** * Check if app uses Flask Blueprints */ async function hasBlueprints({ installDir, }) { const pyFiles = await (0, fast_glob_1.default)(['**/*.py'], { cwd: installDir, ignore: IGNORE_PATTERNS, }); for (const pyFile of pyFiles) { try { const content = fs.readFileSync(path.join(installDir, pyFile), 'utf-8'); if (content.includes('Blueprint(') || content.includes('register_blueprint(') || content.includes('from flask import Blueprint')) { return true; } } catch { continue; } } return false; } /** * Detect Flask project type */ async function getFlaskProjectType(options) { const { installDir } = options; // Check for Flask-RESTX first (most specific - includes Swagger) if (await hasFlaskRESTX({ installDir })) { clack_1.default.log.info('Detected Flask-RESTX project'); return FlaskProjectType.RESTX; } // Check for flask-smorest (OpenAPI-first) if (await hasFlaskSmorest({ installDir })) { clack_1.default.log.info('Detected flask-smorest project'); return FlaskProjectType.SMOREST; } // Check for Flask-RESTful if (await hasFlaskRESTful({ installDir })) { clack_1.default.log.info('Detected Flask-RESTful project'); return FlaskProjectType.RESTFUL; } // Check for Blueprints (large app structure) if (await hasBlueprints({ installDir })) { clack_1.default.log.info('Detected Flask project with Blueprints'); return FlaskProjectType.BLUEPRINT; } // Default to standard Flask clack_1.default.log.info('Detected standard Flask project'); return FlaskProjectType.STANDARD; } /** * Get human-readable name for Flask project type */ function getFlaskProjectTypeName(projectType) { switch (projectType) { case FlaskProjectType.STANDARD: return 'Standard Flask'; case FlaskProjectType.RESTFUL: return 'Flask-RESTful'; case FlaskProjectType.RESTX: return 'Flask-RESTX'; case FlaskProjectType.SMOREST: return 'flask-smorest'; case FlaskProjectType.BLUEPRINT: return 'Flask with Blueprints'; } } /** * Find the main Flask app file */ async function findFlaskAppFile(options) { const { installDir } = options; // Common Flask app file patterns const commonPatterns = [ '**/app.py', '**/wsgi.py', '**/application.py', '**/run.py', '**/main.py', '**/__init__.py', ]; const appFiles = await (0, fast_glob_1.default)(commonPatterns, { cwd: installDir, ignore: IGNORE_PATTERNS, }); // Look for files with Flask() instantiation or create_app() factory for (const appFile of appFiles) { try { const content = fs.readFileSync(path.join(installDir, appFile), 'utf-8'); // Check for Flask app instantiation or application factory if (content.includes('Flask(__name__)') || content.includes('Flask(') || content.includes('def create_app(')) { return appFile; } } catch { continue; } } // If no file with Flask() found, check all Python files const allPyFiles = await (0, fast_glob_1.default)(['**/*.py'], { cwd: installDir, ignore: IGNORE_PATTERNS, }); for (const pyFile of allPyFiles) { try { const content = fs.readFileSync(path.join(installDir, pyFile), 'utf-8'); if (content.includes('Flask(__name__)') || content.includes('def create_app(')) { return pyFile; } } catch { continue; } } // Return first common pattern file if exists if (appFiles.length > 0) { return appFiles[0]; } return undefined; } //# sourceMappingURL=utils.js.map