From 2641793e0ff58c2817b3409324f8a13de66b0246 Mon Sep 17 00:00:00 2001 From: johndoe6345789 Date: Sun, 18 Jan 2026 17:58:01 +0000 Subject: [PATCH] Add identifier sanitization for Flask generators --- src/lib/generators/generateFlaskApp.ts | 7 +++--- src/lib/generators/generateFlaskBlueprint.ts | 12 +++++----- src/lib/generators/sanitizeIdentifier.ts | 23 ++++++++++++++++++++ 3 files changed, 34 insertions(+), 8 deletions(-) create mode 100644 src/lib/generators/sanitizeIdentifier.ts diff --git a/src/lib/generators/generateFlaskApp.ts b/src/lib/generators/generateFlaskApp.ts index 09858e1..a244d87 100644 --- a/src/lib/generators/generateFlaskApp.ts +++ b/src/lib/generators/generateFlaskApp.ts @@ -1,5 +1,6 @@ import { FlaskConfig } from '@/types/project' import { generateFlaskBlueprint } from './generateFlaskBlueprint' +import { sanitizeIdentifier } from './sanitizeIdentifier' export function generateFlaskApp(config: FlaskConfig): Record { const files: Record = {} @@ -11,7 +12,7 @@ export function generateFlaskApp(config: FlaskConfig): Record { appCode += `\n` config.blueprints.forEach(blueprint => { - const blueprintVarName = blueprint.name.toLowerCase().replace(/\s+/g, '_') + const blueprintVarName = sanitizeIdentifier(blueprint.name, { fallback: 'blueprint' }) appCode += `from blueprints.${blueprintVarName} import ${blueprintVarName}_bp\n` }) @@ -34,7 +35,7 @@ export function generateFlaskApp(config: FlaskConfig): Record { } config.blueprints.forEach(blueprint => { - const blueprintVarName = blueprint.name.toLowerCase().replace(/\s+/g, '_') + const blueprintVarName = sanitizeIdentifier(blueprint.name, { fallback: 'blueprint' }) appCode += ` app.register_blueprint(${blueprintVarName}_bp)\n` }) @@ -50,7 +51,7 @@ export function generateFlaskApp(config: FlaskConfig): Record { files['app.py'] = appCode config.blueprints.forEach(blueprint => { - const blueprintVarName = blueprint.name.toLowerCase().replace(/\s+/g, '_') + const blueprintVarName = sanitizeIdentifier(blueprint.name, { fallback: 'blueprint' }) files[`blueprints/${blueprintVarName}.py`] = generateFlaskBlueprint(blueprint) }) diff --git a/src/lib/generators/generateFlaskBlueprint.ts b/src/lib/generators/generateFlaskBlueprint.ts index 301efae..0279173 100644 --- a/src/lib/generators/generateFlaskBlueprint.ts +++ b/src/lib/generators/generateFlaskBlueprint.ts @@ -1,14 +1,15 @@ import { FlaskBlueprint } from '@/types/project' +import { sanitizeIdentifier } from './sanitizeIdentifier' export function generateFlaskBlueprint(blueprint: FlaskBlueprint): string { let code = `from flask import Blueprint, request, jsonify\n` code += `from typing import Dict, Any\n\n` - const blueprintVarName = blueprint.name.toLowerCase().replace(/\s+/g, '_') + const blueprintVarName = sanitizeIdentifier(blueprint.name, { fallback: 'blueprint' }) code += `${blueprintVarName}_bp = Blueprint('${blueprintVarName}', __name__, url_prefix='${blueprint.urlPrefix}')\n\n` blueprint.endpoints.forEach(endpoint => { - const functionName = endpoint.name.toLowerCase().replace(/\s+/g, '_') + const functionName = sanitizeIdentifier(endpoint.name, { fallback: 'endpoint' }) code += `@${blueprintVarName}_bp.route('${endpoint.path}', methods=['${endpoint.method}'])\n` code += `def ${functionName}():\n` code += ` """\n` @@ -31,13 +32,14 @@ export function generateFlaskBlueprint(blueprint: FlaskBlueprint): string { if (endpoint.queryParams && endpoint.queryParams.length > 0) { endpoint.queryParams.forEach(param => { + const paramVarName = sanitizeIdentifier(param.name, { fallback: 'param' }) if (param.required) { - code += ` ${param.name} = request.args.get('${param.name}')\n` - code += ` if ${param.name} is None:\n` + code += ` ${paramVarName} = request.args.get('${param.name}')\n` + code += ` if ${paramVarName} is None:\n` code += ` return jsonify({'error': '${param.name} is required'}), 400\n\n` } else { const defaultVal = param.defaultValue || (param.type === 'string' ? "''" : param.type === 'number' ? '0' : 'None') - code += ` ${param.name} = request.args.get('${param.name}', ${defaultVal})\n` + code += ` ${paramVarName} = request.args.get('${param.name}', ${defaultVal})\n` } }) code += `\n` diff --git a/src/lib/generators/sanitizeIdentifier.ts b/src/lib/generators/sanitizeIdentifier.ts new file mode 100644 index 0000000..bb94954 --- /dev/null +++ b/src/lib/generators/sanitizeIdentifier.ts @@ -0,0 +1,23 @@ +type SanitizeIdentifierOptions = { + fallback?: string +} + +export function sanitizeIdentifier(value: string, options: SanitizeIdentifierOptions = {}): string { + const fallback = options.fallback ?? 'identifier' + const trimmed = value.trim() + const normalized = trimmed + .toLowerCase() + .replace(/[^a-z0-9_]+/g, '_') + .replace(/^_+|_+$/g, '') + .replace(/_+/g, '_') + + if (!normalized) { + return fallback + } + + if (/^[0-9]/.test(normalized)) { + return `_${normalized}` + } + + return normalized +}