68 lines
2.1 KiB
TypeScript
68 lines
2.1 KiB
TypeScript
import 'dotenv/config';
|
|
import { query, close } from './index.js';
|
|
|
|
const up = `
|
|
CREATE TABLE IF NOT EXISTS notes (
|
|
id VARCHAR(64) PRIMARY KEY,
|
|
text TEXT NOT NULL,
|
|
x INTEGER DEFAULT 0,
|
|
y INTEGER DEFAULT 0,
|
|
author VARCHAR(128),
|
|
color VARCHAR(32) DEFAULT 'yellow',
|
|
source_meta JSONB DEFAULT '{}',
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS integrations (
|
|
id SERIAL PRIMARY KEY,
|
|
provider VARCHAR(32) NOT NULL,
|
|
external_workspace_id VARCHAR(128),
|
|
display_name VARCHAR(255),
|
|
api_key_hash CHAR(64),
|
|
access_token_ciphertext TEXT,
|
|
refresh_token_ciphertext TEXT,
|
|
signing_secret_ciphertext TEXT,
|
|
token_expires_at TIMESTAMPTZ,
|
|
scopes TEXT[] DEFAULT '{}',
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ DEFAULT NOW(),
|
|
UNIQUE (provider, external_workspace_id)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS integrations_api_key_hash_idx
|
|
ON integrations (api_key_hash);
|
|
|
|
-- The unique constraint is the deduplication mechanism: providers deliver
|
|
-- at least once, so a redelivery must collide rather than insert.
|
|
CREATE TABLE IF NOT EXISTS ingest_events (
|
|
id SERIAL PRIMARY KEY,
|
|
provider VARCHAR(32) NOT NULL,
|
|
external_id VARCHAR(255) NOT NULL,
|
|
integration_id INTEGER REFERENCES integrations(id) ON DELETE SET NULL,
|
|
status VARCHAR(16) NOT NULL DEFAULT 'pending',
|
|
attempts INTEGER NOT NULL DEFAULT 0,
|
|
last_error TEXT,
|
|
received_at TIMESTAMPTZ DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ DEFAULT NOW(),
|
|
UNIQUE (provider, external_id)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS ingest_events_status_idx
|
|
ON ingest_events (status, updated_at);
|
|
`;
|
|
|
|
const run = async (): Promise<void> => {
|
|
try {
|
|
await query(up);
|
|
console.log('Migration complete — notes, integrations, ingest_events ready.');
|
|
} catch (err) {
|
|
console.error('Migration failed:', err instanceof Error ? err.message : err);
|
|
process.exit(1);
|
|
} finally {
|
|
await close();
|
|
}
|
|
};
|
|
|
|
run();
|