mirror of
https://github.com/johndoe6345789/snippet-pastebin.git
synced 2026-04-24 13:34:55 +00:00
Generated by Spark: I think namespaces might of messed up the schema - It could detect this and wipe the slate clean. Update IndexedDB and Flask.
This commit is contained in:
259
backend/app.py
259
backend/app.py
@@ -30,26 +30,105 @@ def get_db():
|
||||
conn.row_factory = sqlite3.Row
|
||||
return conn
|
||||
|
||||
def check_and_migrate_schema():
|
||||
"""Check if schema needs migration and perform it if necessary"""
|
||||
conn = get_db()
|
||||
cursor = conn.cursor()
|
||||
|
||||
cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='namespaces'")
|
||||
namespaces_exists = cursor.fetchone() is not None
|
||||
|
||||
cursor.execute("PRAGMA table_info(snippets)")
|
||||
columns = [row[1] for row in cursor.fetchall()]
|
||||
has_namespace_id = 'namespaceId' in columns
|
||||
|
||||
if not namespaces_exists or not has_namespace_id:
|
||||
print("Schema migration needed - recreating tables with namespace support...")
|
||||
|
||||
cursor.execute("DROP TABLE IF EXISTS snippets")
|
||||
cursor.execute("DROP TABLE IF EXISTS namespaces")
|
||||
|
||||
cursor.execute('''
|
||||
CREATE TABLE namespaces (
|
||||
id TEXT PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
createdAt INTEGER NOT NULL,
|
||||
isDefault INTEGER DEFAULT 0
|
||||
)
|
||||
''')
|
||||
|
||||
cursor.execute('''
|
||||
CREATE TABLE snippets (
|
||||
id TEXT PRIMARY KEY,
|
||||
title TEXT NOT NULL,
|
||||
description TEXT,
|
||||
code TEXT NOT NULL,
|
||||
language TEXT NOT NULL,
|
||||
category TEXT NOT NULL,
|
||||
namespaceId TEXT,
|
||||
hasPreview INTEGER DEFAULT 0,
|
||||
functionName TEXT,
|
||||
inputParameters TEXT,
|
||||
createdAt INTEGER NOT NULL,
|
||||
updatedAt INTEGER NOT NULL,
|
||||
FOREIGN KEY (namespaceId) REFERENCES namespaces(id)
|
||||
)
|
||||
''')
|
||||
|
||||
cursor.execute('''
|
||||
INSERT INTO namespaces (id, name, createdAt, isDefault)
|
||||
VALUES ('default', 'Default', ?, 1)
|
||||
''', (int(datetime.utcnow().timestamp() * 1000),))
|
||||
|
||||
conn.commit()
|
||||
print("Schema migration completed")
|
||||
|
||||
conn.close()
|
||||
|
||||
def init_db():
|
||||
conn = get_db()
|
||||
cursor = conn.cursor()
|
||||
|
||||
cursor.execute('''
|
||||
CREATE TABLE IF NOT EXISTS namespaces (
|
||||
id TEXT PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
createdAt INTEGER NOT NULL,
|
||||
isDefault INTEGER DEFAULT 0
|
||||
)
|
||||
''')
|
||||
|
||||
cursor.execute('''
|
||||
CREATE TABLE IF NOT EXISTS snippets (
|
||||
id TEXT PRIMARY KEY,
|
||||
title TEXT NOT NULL,
|
||||
description TEXT,
|
||||
code TEXT NOT NULL,
|
||||
language TEXT NOT NULL,
|
||||
description TEXT,
|
||||
tags TEXT,
|
||||
category TEXT DEFAULT 'general',
|
||||
componentName TEXT,
|
||||
previewParams TEXT,
|
||||
createdAt TEXT NOT NULL,
|
||||
updatedAt TEXT NOT NULL
|
||||
category TEXT NOT NULL,
|
||||
namespaceId TEXT,
|
||||
hasPreview INTEGER DEFAULT 0,
|
||||
functionName TEXT,
|
||||
inputParameters TEXT,
|
||||
createdAt INTEGER NOT NULL,
|
||||
updatedAt INTEGER NOT NULL,
|
||||
FOREIGN KEY (namespaceId) REFERENCES namespaces(id)
|
||||
)
|
||||
''')
|
||||
|
||||
cursor.execute("SELECT COUNT(*) FROM namespaces WHERE isDefault = 1")
|
||||
default_count = cursor.fetchone()[0]
|
||||
|
||||
if default_count == 0:
|
||||
cursor.execute('''
|
||||
INSERT INTO namespaces (id, name, createdAt, isDefault)
|
||||
VALUES ('default', 'Default', ?, 1)
|
||||
''', (int(datetime.utcnow().timestamp() * 1000),))
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
check_and_migrate_schema()
|
||||
|
||||
@app.route('/health', methods=['GET'])
|
||||
def health():
|
||||
@@ -67,10 +146,12 @@ def get_snippets():
|
||||
snippets = []
|
||||
for row in rows:
|
||||
snippet = dict(row)
|
||||
if snippet.get('tags'):
|
||||
snippet['tags'] = json.loads(snippet['tags'])
|
||||
if snippet.get('previewParams'):
|
||||
snippet['previewParams'] = json.loads(snippet['previewParams'])
|
||||
if snippet.get('inputParameters'):
|
||||
try:
|
||||
snippet['inputParameters'] = json.loads(snippet['inputParameters'])
|
||||
except:
|
||||
snippet['inputParameters'] = None
|
||||
snippet['hasPreview'] = bool(snippet.get('hasPreview', 0))
|
||||
snippets.append(snippet)
|
||||
|
||||
return jsonify(snippets)
|
||||
@@ -90,10 +171,12 @@ def get_snippet(snippet_id):
|
||||
return jsonify({'error': 'Snippet not found'}), 404
|
||||
|
||||
snippet = dict(row)
|
||||
if snippet.get('tags'):
|
||||
snippet['tags'] = json.loads(snippet['tags'])
|
||||
if snippet.get('previewParams'):
|
||||
snippet['previewParams'] = json.loads(snippet['previewParams'])
|
||||
if snippet.get('inputParameters'):
|
||||
try:
|
||||
snippet['inputParameters'] = json.loads(snippet['inputParameters'])
|
||||
except:
|
||||
snippet['inputParameters'] = None
|
||||
snippet['hasPreview'] = bool(snippet.get('hasPreview', 0))
|
||||
|
||||
return jsonify(snippet)
|
||||
except Exception as e:
|
||||
@@ -106,24 +189,32 @@ def create_snippet():
|
||||
conn = get_db()
|
||||
cursor = conn.cursor()
|
||||
|
||||
tags_json = json.dumps(data.get('tags', []))
|
||||
preview_params_json = json.dumps(data.get('previewParams', {}))
|
||||
input_params_json = json.dumps(data.get('inputParameters')) if data.get('inputParameters') else None
|
||||
|
||||
created_at = data.get('createdAt')
|
||||
if isinstance(created_at, str):
|
||||
created_at = int(datetime.fromisoformat(created_at.replace('Z', '+00:00')).timestamp() * 1000)
|
||||
|
||||
updated_at = data.get('updatedAt')
|
||||
if isinstance(updated_at, str):
|
||||
updated_at = int(datetime.fromisoformat(updated_at.replace('Z', '+00:00')).timestamp() * 1000)
|
||||
|
||||
cursor.execute('''
|
||||
INSERT INTO snippets (id, title, code, language, description, tags, category, componentName, previewParams, createdAt, updatedAt)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
INSERT INTO snippets (id, title, description, code, language, category, namespaceId, hasPreview, functionName, inputParameters, createdAt, updatedAt)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
''', (
|
||||
data['id'],
|
||||
data['title'],
|
||||
data.get('description', ''),
|
||||
data['code'],
|
||||
data['language'],
|
||||
data.get('description', ''),
|
||||
tags_json,
|
||||
data.get('category', 'general'),
|
||||
data.get('componentName', ''),
|
||||
preview_params_json,
|
||||
data['createdAt'],
|
||||
data['updatedAt']
|
||||
data.get('namespaceId'),
|
||||
1 if data.get('hasPreview') else 0,
|
||||
data.get('functionName'),
|
||||
input_params_json,
|
||||
created_at,
|
||||
updated_at
|
||||
))
|
||||
|
||||
conn.commit()
|
||||
@@ -140,23 +231,27 @@ def update_snippet(snippet_id):
|
||||
conn = get_db()
|
||||
cursor = conn.cursor()
|
||||
|
||||
tags_json = json.dumps(data.get('tags', []))
|
||||
preview_params_json = json.dumps(data.get('previewParams', {}))
|
||||
input_params_json = json.dumps(data.get('inputParameters')) if data.get('inputParameters') else None
|
||||
|
||||
updated_at = data.get('updatedAt')
|
||||
if isinstance(updated_at, str):
|
||||
updated_at = int(datetime.fromisoformat(updated_at.replace('Z', '+00:00')).timestamp() * 1000)
|
||||
|
||||
cursor.execute('''
|
||||
UPDATE snippets
|
||||
SET title = ?, code = ?, language = ?, description = ?, tags = ?, category = ?, componentName = ?, previewParams = ?, updatedAt = ?
|
||||
SET title = ?, description = ?, code = ?, language = ?, category = ?, namespaceId = ?, hasPreview = ?, functionName = ?, inputParameters = ?, updatedAt = ?
|
||||
WHERE id = ?
|
||||
''', (
|
||||
data['title'],
|
||||
data.get('description', ''),
|
||||
data['code'],
|
||||
data['language'],
|
||||
data.get('description', ''),
|
||||
tags_json,
|
||||
data.get('category', 'general'),
|
||||
data.get('componentName', ''),
|
||||
preview_params_json,
|
||||
data['updatedAt'],
|
||||
data.get('namespaceId'),
|
||||
1 if data.get('hasPreview') else 0,
|
||||
data.get('functionName'),
|
||||
input_params_json,
|
||||
updated_at,
|
||||
snippet_id
|
||||
))
|
||||
|
||||
@@ -186,6 +281,104 @@ def delete_snippet(snippet_id):
|
||||
except Exception as e:
|
||||
return jsonify({'error': str(e)}), 500
|
||||
|
||||
@app.route('/api/namespaces', methods=['GET'])
|
||||
def get_namespaces():
|
||||
try:
|
||||
conn = get_db()
|
||||
cursor = conn.cursor()
|
||||
cursor.execute('SELECT * FROM namespaces ORDER BY isDefault DESC, name ASC')
|
||||
rows = cursor.fetchall()
|
||||
conn.close()
|
||||
|
||||
namespaces = []
|
||||
for row in rows:
|
||||
namespace = dict(row)
|
||||
namespace['isDefault'] = bool(namespace.get('isDefault', 0))
|
||||
namespaces.append(namespace)
|
||||
|
||||
return jsonify(namespaces)
|
||||
except Exception as e:
|
||||
return jsonify({'error': str(e)}), 500
|
||||
|
||||
@app.route('/api/namespaces', methods=['POST'])
|
||||
def create_namespace():
|
||||
try:
|
||||
data = request.json
|
||||
conn = get_db()
|
||||
cursor = conn.cursor()
|
||||
|
||||
created_at = data.get('createdAt')
|
||||
if isinstance(created_at, str):
|
||||
created_at = int(datetime.fromisoformat(created_at.replace('Z', '+00:00')).timestamp() * 1000)
|
||||
|
||||
cursor.execute('''
|
||||
INSERT INTO namespaces (id, name, createdAt, isDefault)
|
||||
VALUES (?, ?, ?, ?)
|
||||
''', (
|
||||
data['id'],
|
||||
data['name'],
|
||||
created_at,
|
||||
1 if data.get('isDefault') else 0
|
||||
))
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
return jsonify(data), 201
|
||||
except Exception as e:
|
||||
return jsonify({'error': str(e)}), 500
|
||||
|
||||
@app.route('/api/namespaces/<namespace_id>', methods=['DELETE'])
|
||||
def delete_namespace(namespace_id):
|
||||
try:
|
||||
conn = get_db()
|
||||
cursor = conn.cursor()
|
||||
|
||||
cursor.execute('SELECT isDefault FROM namespaces WHERE id = ?', (namespace_id,))
|
||||
row = cursor.fetchone()
|
||||
|
||||
if not row:
|
||||
conn.close()
|
||||
return jsonify({'error': 'Namespace not found'}), 404
|
||||
|
||||
if row['isDefault']:
|
||||
conn.close()
|
||||
return jsonify({'error': 'Cannot delete default namespace'}), 400
|
||||
|
||||
cursor.execute('SELECT id FROM namespaces WHERE isDefault = 1')
|
||||
default_row = cursor.fetchone()
|
||||
default_id = default_row['id'] if default_row else 'default'
|
||||
|
||||
cursor.execute('UPDATE snippets SET namespaceId = ? WHERE namespaceId = ?', (default_id, namespace_id))
|
||||
|
||||
cursor.execute('DELETE FROM namespaces WHERE id = ?', (namespace_id,))
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
return jsonify({'success': True})
|
||||
except Exception as e:
|
||||
return jsonify({'error': str(e)}), 500
|
||||
|
||||
@app.route('/api/wipe', methods=['POST'])
|
||||
def wipe_database():
|
||||
"""Emergency endpoint to wipe and recreate the database"""
|
||||
try:
|
||||
conn = get_db()
|
||||
cursor = conn.cursor()
|
||||
|
||||
cursor.execute("DROP TABLE IF EXISTS snippets")
|
||||
cursor.execute("DROP TABLE IF EXISTS namespaces")
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
init_db()
|
||||
|
||||
return jsonify({'success': True, 'message': 'Database wiped and recreated'})
|
||||
except Exception as e:
|
||||
return jsonify({'error': str(e)}), 500
|
||||
|
||||
if __name__ == '__main__':
|
||||
init_db()
|
||||
app.run(host='0.0.0.0', port=5000, debug=False)
|
||||
|
||||
Reference in New Issue
Block a user