Files
fabdash/backend/app/__init__.py
2026-03-12 10:36:02 -05:00

75 lines
2.4 KiB
Python

import os
from flask import Flask, send_from_directory, jsonify
from werkzeug.exceptions import HTTPException, NotFound, BadRequest
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('/')
def index():
return send_from_directory(app.static_folder, 'index.html')
@app.errorhandler(404)
def handle_404(e):
if request.path.startswith('/api/'):
return jsonify({'error': 'Resource not found', 'message': str(e)}), 404
return send_from_directory(app.static_folder, 'index.html')
@app.errorhandler(400)
def bad_request(e):
return jsonify({'error': 'Bad request', 'message': str(e)}), 400
@app.errorhandler(Exception)
def handle_exception(e):
if isinstance(e, HTTPException):
return jsonify({'error': e.name, 'message': e.description}), e.code
app.logger.error(f"Unhandled exception: {str(e)}", exc_info=True)
return jsonify({'error': 'Internal server error', 'message': 'An unexpected error occurred'}), 500
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