💾 Archived View for iich.space › src › db › migrate.ts captured on 2022-03-01 at 15:59:49.

View Raw

More Information

⬅️ Previous capture (2021-12-03)

-=-=-=-=-=-=-

import { readdirSync, writeFileSync } from 'fs';
import { join } from 'path/posix';

import { Database } from 'better-sqlite3';

import dotenv from '@/dotenv';

if (require.main === module) {
  dotenv();
}

import db from '.';

const [, , arg] = process.argv;

const currentVersion = db.pragma('user_version', { simple: true });
const setVersion = (version: number) =>
  db.pragma(`user_version = ${version};`, { simple: true });

const migrationTemplate = (
  version: number,
) => `import { Migration } from "../migrate";

export const migration: Migration = {
  version: ${version},
  up: (db) => {},
  down: (db) => {},
};`;

export interface Migration {
  version: number;
  up: (db: Database) => void;
  down: (db: Database) => void;
}

const migrationsPath = join(__dirname, 'migrations');
const migrationFiles = readdirSync(migrationsPath);
const migrations = migrationFiles.map<Migration>(
  // eslint-disable-next-line @typescript-eslint/no-var-requires
  (filename) => require(join(migrationsPath, filename)).migration,
);

const runMigration = (fn: (db: Database) => void, version: number) => {
  try {
    fn(db);
    setVersion(version);
  } catch (error: unknown) {
    console.error(error);
  }
};

switch (arg) {
  case 'create': {
    const version = Math.floor(Date.now() / 1000);
    const filepath = join(migrationsPath, `${version}.ts`);
    console.log(`created ${filepath}`);
    writeFileSync(filepath, migrationTemplate(version));
    break;
  }
  case 'version': {
    console.log(currentVersion);
    break;
  }
  case 'down': {
    const before = migrations
      .filter(({ version }) => version <= currentVersion)
      .sort((a, b) => b.version - a.version);

    if (before.length === 0) {
      console.log('nothing to migrate down');
    } else {
      const [migration] = before;
      db.transaction(() => {
        runMigration(migration.down, migration.version - 1);
      })();
    }

    break;
  }
  default: {
    const after = migrations
      .filter(({ version }) => version > currentVersion)
      .sort((a, b) => a.version - b.version);

    if (after.length === 0) {
      console.log('nothing to migrate up');
    } else {
      after.forEach((migration) =>
        db.transaction(() => {
          runMigration(migration.up, migration.version);
        })(),
      );
    }

    break;
  }
}