# 2026-03-09 # notes_crud.py — CRUD роутер для таблицы notes. # # Назначение: единая функция, которая обрабатывает все операции с записями. # Роутинг осуществляется по sub-path URL (event._path), который runtime # берёт из входящего HTTP-запроса и добавляет в event автоматически. # # Доступные маршруты (все POST): # /fn/default/notes/add?title=...&body=... → создать запись # /fn/default/notes/update?id=1&title=...&body=... → обновить запись # /fn/default/notes/delete?id=1 → удалить запись # # Параметры берутся из query string (event._query) или из тела запроса (event). # event._path и event._query добавляет Python runtime (server.py) автоматически. import os import psycopg2 import psycopg2.extras def crud(event): dsn = os.environ['PG_DSN'] # sub-path без ведущего слэша: "add", "update", "delete" action = event.get('_path', '/').strip('/') q = event.get('_query', {}) conn = psycopg2.connect(dsn) try: cur = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor) if action == 'add': title = q.get('title') or event.get('title', '') body = q.get('body') or event.get('body', '') if not title: return {'error': 'title is required'} cur.execute( "INSERT INTO notes (title, body) VALUES (%s, %s)" " RETURNING id, title, body, created_at::text", (title, body) ) row = cur.fetchone() conn.commit() return dict(row) elif action == 'update': id_ = q.get('id') or event.get('id') if not id_: return {'error': 'id is required'} title = q.get('title') or event.get('title', '') body = q.get('body') or event.get('body', '') cur.execute( "UPDATE notes SET title=%s, body=%s WHERE id=%s" " RETURNING id, title, body, created_at::text", (title, body, int(id_)) ) row = cur.fetchone() conn.commit() return dict(row) if row else {'error': 'not found'} elif action == 'delete': id_ = q.get('id') or event.get('id') if not id_: return {'error': 'id is required'} cur.execute( "DELETE FROM notes WHERE id=%s RETURNING id", (int(id_),) ) row = cur.fetchone() conn.commit() return {'deleted': row['id']} if row else {'error': 'not found'} else: return { 'error': f'unknown action: /{action}', 'hint': 'use /add?title=...&body=..., /update?id=X&title=...&body=..., /delete?id=X' } except Exception as e: conn.rollback() return {'error': str(e)} finally: conn.close()