@nostr-dev-kit/ndk-mobile
Version:
NDK Mobile
317 lines (290 loc) • 10.8 kB
text/typescript
import type * as SQLite from "expo-sqlite";
export const migrations = [
{
version: 0,
up: (db: SQLite.SQLiteDatabase) => {
db.execSync(
`CREATE TABLE IF NOT EXISTS unpublished_events (
id TEXT PRIMARY KEY,
event TEXT,
relays TEXT,
last_try_at INTEGER
);`,
);
db.execSync(
`CREATE TABLE IF NOT EXISTS events (
id TEXT PRIMARY KEY,
created_at INTEGER,
pubkey TEXT,
event TEXT,
kind INTEGER,
relay TEXT
);`,
);
db.execSync(
`CREATE TABLE IF NOT EXISTS profiles (
pubkey TEXT PRIMARY KEY,
profile TEXT,
catched_at INTEGER
);`,
);
db.execSync(
`CREATE TABLE IF NOT EXISTS relay_status (
url TEXT PRIMARY KEY,
lastConnectedAt INTEGER,
dontConnectBefore INTEGER
);`,
);
// New table for event tags
db.execSync(
`CREATE TABLE IF NOT EXISTS event_tags (
event_id TEXT,
tag TEXT,
value TEXT,
PRIMARY KEY (event_id, tag)
);`,
);
db.execSync("CREATE INDEX IF NOT EXISTS idx_events_pubkey ON events (pubkey);");
db.execSync("CREATE INDEX IF NOT EXISTS idx_events_kind ON events (kind);");
db.execSync("CREATE INDEX IF NOT EXISTS idx_event_tags_tag ON event_tags (tag);");
},
},
{
version: 1,
up: (db: SQLite.SQLiteDatabase) => {
db.execSync("ALTER TABLE profiles ADD COLUMN created_at INTEGER;");
},
},
{
version: 2,
up: (db: SQLite.SQLiteDatabase) => {
db.execSync("CREATE INDEX IF NOT EXISTS idx_profiles_pubkey ON profiles (pubkey);");
db.execSync("DROP INDEX IF EXISTS idx_event_tags_tag;");
db.execSync("CREATE INDEX IF NOT EXISTS idx_event_tags_tag ON event_tags (tag, value);");
},
},
{
version: 3,
up: (db: SQLite.SQLiteDatabase) => {
db.execSync(`CREATE TABLE IF NOT EXISTS wot (
pubkey TEXT PRIMARY KEY,
wot INTEGER
);`);
},
},
{
version: 4,
// the format we use to reference to event ids has changed, so we need to truncate the tables
up: (db: SQLite.SQLiteDatabase) => {
db.execSync("DELETE FROM events;");
db.execSync("DELETE FROM event_tags;");
},
},
{
version: 5, // Increment the version number
up: (db: SQLite.SQLiteDatabase) => {
// Temporarily disable foreign key constraints
db.execSync("PRAGMA foreign_keys=off;");
// Rename the existing table
db.execSync("ALTER TABLE event_tags RENAME TO event_tags_old;");
// Create the new table without a primary key
db.execSync(`
CREATE TABLE event_tags (
event_id TEXT,
tag TEXT,
value TEXT
);
`);
// Copy data back into the new table
db.execSync(`
INSERT INTO event_tags (event_id, tag, value)
SELECT event_id, tag, value FROM event_tags_old;
`);
// Drop the old table
db.execSync("DROP TABLE event_tags_old;");
// Add a non-unique index on event_id and tag
db.execSync(`
CREATE INDEX IF NOT EXISTS idx_event_tags_event_id_tag ON event_tags (event_id, tag);
`);
// Re-enable foreign key constraints
db.execSync("PRAGMA foreign_keys=on;");
},
},
{
version: 6,
up: (db: SQLite.SQLiteDatabase) => {
db.execSync("DROP TABLE IF EXISTS wallet_nutzaps;"); // XXX
db.execSync(`CREATE TABLE IF NOT EXISTS wallet_nutzaps (
event_id TEXT PRIMARY KEY UNIQUE,
status TEXT,
claimed_at INTEGER,
tx_event_id TEXT
);`);
},
},
{
version: 7,
up: (db: SQLite.SQLiteDatabase) => {
const profiles = db.getAllSync("SELECT * FROM profiles;") as {
pubkey: string;
profile: string;
}[];
db.execSync(`
ALTER TABLE profiles ADD COLUMN name TEXT;
ALTER TABLE profiles ADD COLUMN about TEXT;
ALTER TABLE profiles ADD COLUMN picture TEXT;
ALTER TABLE profiles ADD COLUMN banner TEXT;
ALTER TABLE profiles ADD COLUMN nip05 TEXT;
ALTER TABLE profiles ADD COLUMN lud16 TEXT;
ALTER TABLE profiles ADD COLUMN lud06 TEXT;
ALTER TABLE profiles ADD COLUMN display_name TEXT;
ALTER TABLE profiles ADD COLUMN website TEXT;
`);
for (const profile of profiles) {
try {
const profileJson = JSON.parse(profile.profile);
db.runSync(
"UPDATE profiles SET name = ?, about = ?, picture = ?, banner = ?, nip05 = ?, lud16 = ?, lud06 = ?, display_name = ?, website = ? WHERE pubkey = ?;",
[
profileJson.name,
profileJson.about,
profileJson.image ?? profileJson.picture,
profileJson.banner,
profileJson.nip05,
profileJson.lud16,
profileJson.lud06,
profileJson.displayName,
profileJson.website,
profile.pubkey,
],
);
} catch (_e) {
db.runSync("DELETE FROM profiles WHERE pubkey = ?;", [profile.pubkey]);
}
}
},
},
{
version: 8,
up: (db: SQLite.SQLiteDatabase) => {
db.execSync(`
-- Create the new table with NOCASE collation
CREATE TABLE event_tags_new (
event_id TEXT NOT NULL,
tag TEXT NOT NULL,
value TEXT COLLATE NOCASE,
PRIMARY KEY (event_id, tag, value)
);
-- Insert deduplicated data (group by case-insensitive value)
INSERT INTO event_tags_new (event_id, tag, value)
SELECT event_id, tag, value
FROM event_tags
GROUP BY event_id, tag, LOWER(value); -- Deduplicate by lowercase value
-- Drop the old table
DROP TABLE event_tags;
-- Rename the new table
ALTER TABLE event_tags_new RENAME TO event_tags;
`);
},
},
{
version: 9,
up: (db: SQLite.SQLiteDatabase) => {
// Log current indexes to verify
const _indexes = db.getAllSync(`PRAGMA index_list('event_tags');`);
// Proceed with dropping and recreating
db.execSync(`
ALTER TABLE event_tags RENAME TO event_tags_old;
CREATE TABLE event_tags (
event_id TEXT NOT NULL,
tag TEXT NOT NULL,
value TEXT COLLATE NOCASE
);
INSERT INTO event_tags (event_id, tag, value) SELECT event_id, tag, value FROM event_tags_old;
DROP TABLE event_tags_old;
CREATE INDEX IF NOT EXISTS idx_event_tags_event_id_tag ON event_tags (event_id, tag);
CREATE INDEX IF NOT EXISTS idx_event_tags_tag_value ON event_tags (tag, value);
`);
},
},
{
version: 10,
up: (db: SQLite.SQLiteDatabase) => {
db.execSync(`
CREATE TABLE IF NOT EXISTS nutzap_monitor_state (
event_id TEXT PRIMARY KEY,
status TEXT NOT NULL,
nutzap TEXT,
redeemed_by_id TEXT,
error_message TEXT,
redeemed_amount INTEGER,
updated_at INTEGER
);
`);
},
},
{
version: 11,
up: (db: SQLite.SQLiteDatabase) => {
// Drop the old nutzaps table as it's no longer needed
db.execSync("DROP TABLE IF EXISTS wallet_nutzaps;");
},
},
{
version: 12,
up: (db: SQLite.SQLiteDatabase) => {
db.execSync(`
CREATE TABLE IF NOT EXISTS mint_info (
url TEXT PRIMARY KEY,
payload TEXT,
created_at INTEGER,
updated_at INTEGER
)
`);
},
},
// New migration for Cashu mint_keys table
{
version: 13,
up: (db: SQLite.SQLiteDatabase) => {
db.execSync(`
CREATE TABLE IF NOT EXISTS mint_keys (
url TEXT,
keyset_id TEXT,
payload TEXT,
created_at INTEGER,
updated_at INTEGER,
PRIMARY KEY (url, keyset_id)
)
`);
},
},
{
version: 14,
up: (db: SQLite.SQLiteDatabase) => {
db.execSync(`
CREATE TABLE IF NOT EXISTS relays (
url TEXT PRIMARY KEY,
connect BOOLEAN DEFAULT 1,
read BOOLEAN DEFAULT 1,
write BOOLEAN DEFAULT 1
);
`);
},
},
{
version: 15,
up: (db: SQLite.SQLiteDatabase) => {
// Create a new table for storing decrypted events
db.execSync(`
CREATE TABLE IF NOT EXISTS decrypted_events (
event_id TEXT PRIMARY KEY,
event TEXT NOT NULL,
decrypted_at INTEGER NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_decrypted_events_event_id
ON decrypted_events (event_id);
`);
},
},
];