@posthog/wizard
Version:
The PostHog wizard helps you to configure your project
363 lines • 12 kB
JavaScript
"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