import os from flask import Flask, send_from_directory from sqlalchemy import text from .extensions import db, migrate, cors from config import config def create_app(config_name=None): if config_name is None: config_name = os.environ.get('FLASK_ENV', 'production') app = Flask(__name__, static_folder='static', static_url_path='') app.config.from_object(config.get(config_name, config['default'])) db.init_app(app) migrate.init_app(app, db) cors.init_app(app, resources={r'/api/*': {'origins': '*'}}) from .routes.projects import projects_bp from .routes.deliverables import deliverables_bp app.register_blueprint(projects_bp, url_prefix='/api') app.register_blueprint(deliverables_bp, url_prefix='/api') with app.app_context(): db.create_all() _run_migrations() @app.route('/', defaults={'path': ''}) @app.route('/') def serve_react(path): static_folder = app.static_folder if path and os.path.exists(os.path.join(static_folder, path)): return send_from_directory(static_folder, path) return send_from_directory(static_folder, 'index.html') return app def _run_migrations(): """ Safe idempotent migrations for existing databases. ALTER TABLE is a no-op if the column already exists (exception silently caught). Add new columns here as the schema evolves. """ migrations = [ 'ALTER TABLE projects ADD COLUMN drive_url VARCHAR(500)', 'ALTER TABLE projects ADD COLUMN archived_at DATETIME', ] with db.engine.connect() as conn: for stmt in migrations: try: conn.execute(text(stmt)) conn.commit() except Exception: # Column already exists — safe to ignore pass