#!/usr/bin/env node
#!/usr/bin/env node
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __esm = (fn, res) => function __init() {
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
};
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));

// src/adapters/postgres/PostgresDatabase.ts
var PostgresDatabase_exports = {};
__export(PostgresDatabase_exports, {
  PostgresDatabase: () => PostgresDatabase
});
function toPoolConfig(config) {
  const poolConfig = {};
  if (config.connectionString) {
    poolConfig.connectionString = config.connectionString;
  } else {
    poolConfig.host = config.host;
    poolConfig.port = config.port;
    poolConfig.database = config.database;
    poolConfig.user = config.user;
    poolConfig.password = config.password;
  }
  if (config.ssl !== void 0) {
    poolConfig.ssl = config.ssl;
  }
  poolConfig.max = config.max ?? 10;
  poolConfig.idleTimeoutMillis = config.idleTimeoutMillis ?? 3e4;
  poolConfig.connectionTimeoutMillis = config.connectionTimeoutMillis ?? 1e4;
  poolConfig.application_name = config.applicationName ?? "platform-core";
  if (config.statementTimeout) {
    poolConfig.statement_timeout = config.statementTimeout;
  }
  if (config.queryTimeout) {
    poolConfig.query_timeout = config.queryTimeout;
  }
  return poolConfig;
}
var import_crypto, PostgresDatabase, TransactionDatabase, PostgresQueryBuilder;
var init_PostgresDatabase = __esm({
  "src/adapters/postgres/PostgresDatabase.ts"() {
    "use strict";
    import_crypto = require("crypto");
    PostgresDatabase = class _PostgresDatabase {
      pool;
      config;
      constructor(pool, config = {}) {
        this.pool = pool;
        this.config = config;
      }
      /**
       * Create a PostgresDatabase from configuration
       */
      static async create(config) {
        const { Pool } = await import(
          /* webpackIgnore: true */
          /* turbopackIgnore: true */
          "pg"
        );
        const poolConfig = toPoolConfig(config);
        const pool = new Pool(poolConfig);
        const client = await pool.connect();
        client.release();
        return new _PostgresDatabase(pool, config);
      }
      /**
       * Create from environment variables
       */
      static async fromEnv() {
        const config = {
          connectionString: process.env.DATABASE_URL,
          host: process.env.POSTGRES_HOST ?? process.env.PGHOST,
          port: parseInt(
            process.env.POSTGRES_PORT ?? process.env.PGPORT ?? "5432",
            10
          ),
          database: process.env.POSTGRES_DATABASE ?? process.env.PGDATABASE,
          user: process.env.POSTGRES_USER ?? process.env.PGUSER,
          password: process.env.POSTGRES_PASSWORD ?? process.env.PGPASSWORD,
          max: parseInt(process.env.POSTGRES_POOL_MAX ?? "10", 10),
          ssl: process.env.POSTGRES_SSL === "true" ? {
            rejectUnauthorized: process.env.POSTGRES_SSL_REJECT_UNAUTHORIZED !== "false"
          } : void 0,
          applicationName: process.env.POSTGRES_APP_NAME ?? "platform-core"
        };
        return _PostgresDatabase.create(config);
      }
      from(table) {
        return new PostgresQueryBuilder(this.pool, table);
      }
      async raw(sql, params) {
        try {
          const result = await this.pool.query(sql, params);
          return {
            data: result.rows,
            count: result.rowCount ?? void 0
          };
        } catch (error) {
          return {
            data: [],
            error: error instanceof Error ? error : new Error(String(error))
          };
        }
      }
      /**
       * Execute a function within a database transaction.
       * Provides true ACID guarantees - either all operations succeed or all are rolled back.
       */
      async transaction(fn) {
        const client = await this.pool.connect();
        try {
          await client.query("BEGIN");
          const txDatabase = new TransactionDatabase(client);
          const result = await fn(txDatabase);
          await client.query("COMMIT");
          return result;
        } catch (error) {
          await client.query("ROLLBACK");
          throw error;
        } finally {
          client.release();
        }
      }
      async healthCheck() {
        try {
          const result = await this.pool.query("SELECT 1 as health");
          return result.rows.length > 0;
        } catch {
          return false;
        }
      }
      async close() {
        await this.pool.end();
      }
      /**
       * Get pool statistics for monitoring
       */
      getPoolStats() {
        return {
          totalCount: this.pool.totalCount,
          idleCount: this.pool.idleCount,
          waitingCount: this.pool.waitingCount
        };
      }
    };
    TransactionDatabase = class {
      constructor(client) {
        this.client = client;
      }
      from(table) {
        return new PostgresQueryBuilder(this.client, table);
      }
      async raw(sql, params) {
        try {
          const result = await this.client.query(sql, params);
          return {
            data: result.rows,
            count: result.rowCount ?? void 0
          };
        } catch (error) {
          return {
            data: [],
            error: error instanceof Error ? error : new Error(String(error))
          };
        }
      }
      async transaction(fn) {
        const savepointName = `sp_${Date.now()}_${(0, import_crypto.randomBytes)(4).toString("hex")}`;
        try {
          await this.client.query(`SAVEPOINT ${savepointName}`);
          const result = await fn(this);
          await this.client.query(`RELEASE SAVEPOINT ${savepointName}`);
          return result;
        } catch (error) {
          await this.client.query(`ROLLBACK TO SAVEPOINT ${savepointName}`);
          throw error;
        }
      }
      async healthCheck() {
        try {
          await this.client.query("SELECT 1");
          return true;
        } catch {
          return false;
        }
      }
      async close() {
      }
    };
    PostgresQueryBuilder = class {
      client;
      tableName;
      _select = ["*"];
      _where = [];
      _whereIn = [];
      _orderBy = null;
      _limit = null;
      _offset = 0;
      _insertData = null;
      _updateData = null;
      _deleteFlag = false;
      _returning = ["*"];
      constructor(client, tableName) {
        this.client = client;
        this.tableName = this.escapeIdentifier(tableName);
      }
      select(columns) {
        if (columns) {
          this._select = Array.isArray(columns) ? columns : [columns];
        }
        return this;
      }
      insert(data) {
        this._insertData = Array.isArray(data) ? data : [data];
        return this;
      }
      update(data) {
        this._updateData = data;
        return this;
      }
      delete() {
        this._deleteFlag = true;
        return this;
      }
      where(column, operator, value) {
        this._where.push({ column, operator, value });
        return this;
      }
      whereIn(column, values) {
        this._whereIn.push({ column, values });
        return this;
      }
      orderBy(column, direction = "asc") {
        this._orderBy = { column, direction };
        return this;
      }
      limit(count) {
        this._limit = count;
        return this;
      }
      offset(count) {
        this._offset = count;
        return this;
      }
      async single() {
        this._limit = 1;
        const result = await this.execute();
        if (result.error) {
          return { data: null, error: result.error };
        }
        return { data: result.data[0] ?? null };
      }
      async execute() {
        try {
          if (this._insertData) {
            return await this.executeInsert();
          }
          if (this._updateData) {
            return await this.executeUpdate();
          }
          if (this._deleteFlag) {
            return await this.executeDelete();
          }
          return await this.executeSelect();
        } catch (error) {
          return {
            data: [],
            error: error instanceof Error ? error : new Error(String(error))
          };
        }
      }
      async executeSelect() {
        const params = [];
        let paramIndex = 1;
        const selectClause = this._select.map((col) => this.escapeIdentifier(col)).join(", ");
        let sql = `SELECT ${selectClause} FROM ${this.tableName}`;
        const whereClauses = [];
        for (const { column, operator, value } of this._where) {
          whereClauses.push(
            `${this.escapeIdentifier(column)} ${this.mapOperator(operator)} $${paramIndex++}`
          );
          params.push(value);
        }
        for (const { column, values } of this._whereIn) {
          const placeholders = values.map(() => `$${paramIndex++}`).join(", ");
          whereClauses.push(
            `${this.escapeIdentifier(column)} IN (${placeholders})`
          );
          params.push(...values);
        }
        if (whereClauses.length > 0) {
          sql += ` WHERE ${whereClauses.join(" AND ")}`;
        }
        if (this._orderBy) {
          sql += ` ORDER BY ${this.escapeIdentifier(this._orderBy.column)} ${this._orderBy.direction.toUpperCase()}`;
        }
        if (this._limit !== null) {
          sql += ` LIMIT $${paramIndex++}`;
          params.push(this._limit);
        }
        if (this._offset > 0) {
          sql += ` OFFSET $${paramIndex++}`;
          params.push(this._offset);
        }
        const result = await this.client.query(sql, params);
        return {
          data: result.rows,
          count: result.rowCount ?? void 0
        };
      }
      async executeInsert() {
        if (!this._insertData || this._insertData.length === 0) {
          return { data: [] };
        }
        const params = [];
        let paramIndex = 1;
        const columns = /* @__PURE__ */ new Set();
        for (const row of this._insertData) {
          Object.keys(row).forEach((key) => columns.add(key));
        }
        const columnList = Array.from(columns);
        const columnClause = columnList.map((col) => this.escapeIdentifier(col)).join(", ");
        const valueRows = [];
        for (const row of this._insertData) {
          const rowValues = [];
          for (const col of columnList) {
            rowValues.push(`$${paramIndex++}`);
            params.push(row[col] ?? null);
          }
          valueRows.push(`(${rowValues.join(", ")})`);
        }
        const sql = `INSERT INTO ${this.tableName} (${columnClause}) VALUES ${valueRows.join(", ")} RETURNING ${this._returning.join(", ")}`;
        const result = await this.client.query(sql, params);
        return {
          data: result.rows,
          count: result.rowCount ?? void 0
        };
      }
      async executeUpdate() {
        if (!this._updateData) {
          return { data: [] };
        }
        const params = [];
        let paramIndex = 1;
        const setClauses = [];
        for (const [key, value] of Object.entries(this._updateData)) {
          setClauses.push(`${this.escapeIdentifier(key)} = $${paramIndex++}`);
          params.push(value);
        }
        let sql = `UPDATE ${this.tableName} SET ${setClauses.join(", ")}`;
        const whereClauses = [];
        for (const { column, operator, value } of this._where) {
          whereClauses.push(
            `${this.escapeIdentifier(column)} ${this.mapOperator(operator)} $${paramIndex++}`
          );
          params.push(value);
        }
        for (const { column, values } of this._whereIn) {
          const placeholders = values.map(() => `$${paramIndex++}`).join(", ");
          whereClauses.push(
            `${this.escapeIdentifier(column)} IN (${placeholders})`
          );
          params.push(...values);
        }
        if (whereClauses.length > 0) {
          sql += ` WHERE ${whereClauses.join(" AND ")}`;
        }
        sql += ` RETURNING ${this._returning.join(", ")}`;
        const result = await this.client.query(sql, params);
        return {
          data: result.rows,
          count: result.rowCount ?? void 0
        };
      }
      async executeDelete() {
        const params = [];
        let paramIndex = 1;
        let sql = `DELETE FROM ${this.tableName}`;
        const whereClauses = [];
        for (const { column, operator, value } of this._where) {
          whereClauses.push(
            `${this.escapeIdentifier(column)} ${this.mapOperator(operator)} $${paramIndex++}`
          );
          params.push(value);
        }
        for (const { column, values } of this._whereIn) {
          const placeholders = values.map(() => `$${paramIndex++}`).join(", ");
          whereClauses.push(
            `${this.escapeIdentifier(column)} IN (${placeholders})`
          );
          params.push(...values);
        }
        if (whereClauses.length > 0) {
          sql += ` WHERE ${whereClauses.join(" AND ")}`;
        }
        sql += ` RETURNING ${this._returning.join(", ")}`;
        const result = await this.client.query(sql, params);
        return {
          data: result.rows,
          count: result.rowCount ?? void 0
        };
      }
      escapeIdentifier(identifier) {
        if (identifier === "*") return "*";
        if (identifier.includes(".")) {
          return identifier.split(".").map((part) => `"${part.replace(/"/g, '""')}"`).join(".");
        }
        return `"${identifier.replace(/"/g, '""')}"`;
      }
      mapOperator(operator) {
        switch (operator.toLowerCase()) {
          case "=":
          case "==":
            return "=";
          case "!=":
          case "<>":
            return "<>";
          case "<":
            return "<";
          case "<=":
            return "<=";
          case ">":
            return ">";
          case ">=":
            return ">=";
          case "like":
            return "LIKE";
          case "ilike":
            return "ILIKE";
          case "is":
            return "IS";
          case "is not":
            return "IS NOT";
          default:
            return "=";
        }
      }
    };
  }
});

// src/migrations/Migrator.ts
var DEFAULT_CONFIG = {
  tableName: "_migrations",
  schema: "public",
  lockTimeout: 60,
  validateChecksums: true,
  migrationsDir: void 0
};
function generateChecksum(content) {
  let hash = 0;
  for (let i = 0; i < content.length; i++) {
    const char = content.charCodeAt(i);
    hash = (hash << 5) - hash + char;
    hash = hash & hash;
  }
  return Math.abs(hash).toString(16).padStart(8, "0");
}
function sortMigrations(migrations) {
  return [...migrations].sort((a, b) => a.version.localeCompare(b.version));
}
var Migrator = class {
  db;
  config;
  migrations = [];
  initialized = false;
  locked = false;
  constructor(db, config = {}) {
    this.db = db;
    this.config = { ...DEFAULT_CONFIG, ...config };
  }
  /**
   * Get the fully qualified migration table name
   */
  get tableName() {
    return `"${this.config.schema}"."${this.config.tableName}"`;
  }
  /**
   * Get the lock table name
   */
  get lockTableName() {
    return `"${this.config.schema}"."${this.config.tableName}_lock"`;
  }
  /**
   * Initialize migration tracking tables
   */
  async initialize() {
    if (this.initialized) return;
    await this.db.raw(`CREATE SCHEMA IF NOT EXISTS "${this.config.schema}"`);
    await this.db.raw(`
      CREATE TABLE IF NOT EXISTS ${this.tableName} (
        version VARCHAR(255) PRIMARY KEY,
        name VARCHAR(255) NOT NULL,
        applied_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
        execution_time INTEGER NOT NULL,
        checksum VARCHAR(64)
      )
    `);
    await this.db.raw(`
      CREATE TABLE IF NOT EXISTS ${this.lockTableName} (
        id INTEGER PRIMARY KEY DEFAULT 1,
        locked_at TIMESTAMP WITH TIME ZONE,
        locked_by VARCHAR(255),
        CONSTRAINT single_row CHECK (id = 1)
      )
    `);
    await this.db.raw(`
      INSERT INTO ${this.lockTableName} (id, locked_at, locked_by)
      VALUES (1, NULL, NULL)
      ON CONFLICT (id) DO NOTHING
    `);
    this.initialized = true;
  }
  /**
   * Acquire migration lock
   */
  async lock() {
    await this.initialize();
    const lockId = `${process.pid}-${Date.now()}`;
    const lockTimeout = new Date(Date.now() - this.config.lockTimeout * 1e3);
    const result = await this.db.raw(
      `
      UPDATE ${this.lockTableName}
      SET locked_at = CURRENT_TIMESTAMP, locked_by = $1
      WHERE id = 1 AND (locked_at IS NULL OR locked_at < $2)
      RETURNING locked_at
    `,
      [lockId, lockTimeout]
    );
    if (result.data.length > 0) {
      this.locked = true;
      return true;
    }
    return false;
  }
  /**
   * Release migration lock
   */
  async unlock() {
    if (!this.locked) return;
    await this.db.raw(
      `
      UPDATE ${this.lockTableName}
      SET locked_at = NULL, locked_by = NULL
      WHERE id = 1
    `
    );
    this.locked = false;
  }
  /**
   * Add migrations to the migrator
   */
  addMigrations(migrations) {
    for (const migration of migrations) {
      if (!migration.checksum) {
        const content = typeof migration.up === "string" ? migration.up : migration.up.toString();
        migration.checksum = generateChecksum(content);
      }
      if (!this.migrations.find((m) => m.version === migration.version)) {
        this.migrations.push(migration);
      }
    }
  }
  /**
   * Load migrations from directory
   * Expects files named: {version}_{name}.ts or {version}_{name}.sql
   */
  async loadMigrations(dir) {
    const { readdir, readFile } = await import("fs/promises");
    const { join } = await import("path");
    const files = await readdir(dir);
    const migrationFiles = files.filter(
      (f) => f.match(/^\d+_.*\.(ts|js|sql)$/)
    );
    for (const file of migrationFiles) {
      const filePath = join(dir, file);
      const [version, ...nameParts] = file.replace(/\.(ts|js|sql)$/, "").split("_");
      const name = nameParts.join("_");
      if (file.endsWith(".sql")) {
        const content = await readFile(filePath, "utf-8");
        const [up, down] = this.parseSqlMigration(content);
        this.addMigrations([
          {
            version,
            name,
            up,
            down
          }
        ]);
      } else {
        const module2 = await import(filePath);
        this.addMigrations([
          {
            version,
            name,
            up: module2.up,
            down: module2.down,
            transactional: module2.transactional
          }
        ]);
      }
    }
  }
  /**
   * Parse SQL migration file with -- UP and -- DOWN sections
   */
  parseSqlMigration(content) {
    const upMatch = content.match(/--\s*UP\s*\n([\s\S]*?)(?=--\s*DOWN|$)/i);
    const downMatch = content.match(/--\s*DOWN\s*\n([\s\S]*?)$/i);
    const up = upMatch?.[1]?.trim() ?? content.trim();
    const down = downMatch?.[1]?.trim() ?? "";
    return [up, down];
  }
  /**
   * Get current migration status
   */
  async status() {
    await this.initialize();
    const result = await this.db.raw(
      `SELECT version, name, applied_at, execution_time, checksum
       FROM ${this.tableName}
       ORDER BY version ASC`
    );
    const applied = result.data.map((row) => ({
      version: row.version,
      name: row.name,
      appliedAt: new Date(row.applied_at),
      executionTime: row.execution_time,
      checksum: row.checksum ?? void 0
    }));
    const appliedVersions = new Set(applied.map((m) => m.version));
    const sortedMigrations = sortMigrations(this.migrations);
    const pending = sortedMigrations.filter(
      (m) => !appliedVersions.has(m.version)
    );
    return {
      applied,
      pending,
      currentVersion: applied.length > 0 ? applied[applied.length - 1].version : null,
      latestVersion: sortedMigrations.length > 0 ? sortedMigrations[sortedMigrations.length - 1].version : null
    };
  }
  /**
   * Run all pending migrations (or up to a specific version)
   */
  async up(options = {}) {
    const { dryRun = false, to } = options;
    const results = [];
    if (!dryRun) {
      const acquired = await this.lock();
      if (!acquired) {
        throw new Error(
          "Could not acquire migration lock. Another migration may be in progress."
        );
      }
    }
    try {
      const status = await this.status();
      let pending = status.pending;
      if (to) {
        const targetIndex = pending.findIndex((m) => m.version === to);
        if (targetIndex === -1) {
          throw new Error(
            `Target version ${to} not found in pending migrations`
          );
        }
        pending = pending.slice(0, targetIndex + 1);
      }
      for (const migration of pending) {
        const result = await this.runMigration(migration, "up", dryRun);
        results.push(result);
        if (!result.success) {
          break;
        }
      }
    } finally {
      if (!dryRun) {
        await this.unlock();
      }
    }
    return results;
  }
  /**
   * Rollback migrations
   */
  async down(options = {}) {
    const { dryRun = false, steps = 1 } = options;
    const results = [];
    if (!dryRun) {
      const acquired = await this.lock();
      if (!acquired) {
        throw new Error(
          "Could not acquire migration lock. Another migration may be in progress."
        );
      }
    }
    try {
      const status = await this.status();
      const toRollback = status.applied.slice(-steps).reverse();
      for (const record of toRollback) {
        const migration = this.migrations.find(
          (m) => m.version === record.version
        );
        if (!migration) {
          throw new Error(
            `Migration ${record.version} was applied but is not registered. Cannot rollback.`
          );
        }
        const result = await this.runMigration(migration, "down", dryRun);
        results.push(result);
        if (!result.success) {
          break;
        }
      }
    } finally {
      if (!dryRun) {
        await this.unlock();
      }
    }
    return results;
  }
  /**
   * Rollback all migrations and re-run them
   */
  async reset(options = {}) {
    const status = await this.status();
    const downResults = await this.down({
      dryRun: options.dryRun,
      steps: status.applied.length
    });
    if (downResults.every((r) => r.success)) {
      const upResults = await this.up({ dryRun: options.dryRun });
      return [...downResults, ...upResults];
    }
    return downResults;
  }
  /**
   * Migrate to a specific version
   */
  async goto(version, options = {}) {
    const status = await this.status();
    const currentVersion = status.currentVersion;
    const results = [];
    if (currentVersion === version) {
      return results;
    }
    const isUp = !currentVersion || version > currentVersion;
    if (isUp) {
      return this.up({ ...options, to: version });
    } else {
      const currentIndex = status.applied.findIndex(
        (m) => m.version === currentVersion
      );
      const targetIndex = status.applied.findIndex(
        (m) => m.version === version
      );
      if (targetIndex === -1) {
        throw new Error(
          `Target version ${version} not found in applied migrations`
        );
      }
      const steps = currentIndex - targetIndex;
      return this.down({ ...options, steps });
    }
  }
  /**
   * Run a single migration
   */
  async runMigration(migration, direction, dryRun) {
    const startTime = Date.now();
    const action = direction === "up" ? migration.up : migration.down;
    try {
      if (dryRun) {
        return {
          migration,
          success: true,
          executionTime: 0,
          dryRun: true
        };
      }
      const transactional = migration.transactional !== false;
      const runAction = async (db) => {
        if (typeof action === "string") {
          const result = await db.raw(action);
          if (result.error) {
            throw result.error;
          }
        } else {
          await action(db);
        }
      };
      if (transactional) {
        await this.db.transaction(async (tx) => {
          await runAction(tx);
        });
      } else {
        await runAction(this.db);
      }
      const executionTime = Date.now() - startTime;
      if (direction === "up") {
        await this.db.raw(
          `INSERT INTO ${this.tableName} (version, name, execution_time, checksum)
           VALUES ($1, $2, $3, $4)`,
          [
            migration.version,
            migration.name,
            executionTime,
            migration.checksum
          ]
        );
      } else {
        await this.db.raw(`DELETE FROM ${this.tableName} WHERE version = $1`, [
          migration.version
        ]);
      }
      return {
        migration,
        success: true,
        executionTime,
        dryRun: false
      };
    } catch (error) {
      return {
        migration,
        success: false,
        executionTime: Date.now() - startTime,
        error: error instanceof Error ? error : new Error(String(error)),
        dryRun: false
      };
    }
  }
  /**
   * Create a new migration file
   */
  async create(name) {
    const { writeFile, mkdir } = await import("fs/promises");
    const { join } = await import("path");
    if (!this.config.migrationsDir) {
      throw new Error("migrationsDir must be configured to create migrations");
    }
    await mkdir(this.config.migrationsDir, { recursive: true });
    const now = /* @__PURE__ */ new Date();
    const version = [
      now.getFullYear(),
      String(now.getMonth() + 1).padStart(2, "0"),
      String(now.getDate()).padStart(2, "0"),
      String(now.getHours()).padStart(2, "0"),
      String(now.getMinutes()).padStart(2, "0"),
      String(now.getSeconds()).padStart(2, "0")
    ].join("");
    const safeName = name.replace(/[^a-zA-Z0-9_]/g, "_").toLowerCase();
    const fileName = `${version}_${safeName}.sql`;
    const filePath = join(this.config.migrationsDir, fileName);
    const template = `-- Migration: ${name}
-- Version: ${version}
-- Created: ${now.toISOString()}

-- UP
-- Add your forward migration SQL here


-- DOWN
-- Add your rollback migration SQL here

`;
    await writeFile(filePath, template, "utf-8");
    return filePath;
  }
  /**
   * Validate migration integrity
   */
  async validate() {
    const errors = [];
    const status = await this.status();
    if (!this.config.validateChecksums) {
      return { valid: true, errors };
    }
    for (const applied of status.applied) {
      const migration = this.migrations.find(
        (m) => m.version === applied.version
      );
      if (!migration) {
        errors.push(
          `Migration ${applied.version} (${applied.name}) was applied but is not registered`
        );
        continue;
      }
      if (applied.checksum && migration.checksum !== applied.checksum) {
        errors.push(
          `Migration ${applied.version} (${applied.name}) has been modified since it was applied`
        );
      }
    }
    return {
      valid: errors.length === 0,
      errors
    };
  }
};

// src/migrations/cli.ts
var HELP_TEXT = `
Database Migration CLI

USAGE:
  platform-migrate <command> [options]

COMMANDS:
  status        Show current migration status
  up            Run all pending migrations
  down          Rollback the last migration
  reset         Rollback all and re-run migrations
  goto <ver>    Migrate to a specific version
  create <name> Create a new migration file
  validate      Validate migration integrity

OPTIONS:
  --dry-run     Preview changes without applying
  --steps <n>   Number of migrations to rollback (for down command)
  --to <ver>    Target version (for up command)
  --dir <path>  Migrations directory (default: ./migrations)
  --help, -h    Show this help message

ENVIRONMENT:
  DATABASE_URL      PostgreSQL connection string (required)
  MIGRATIONS_DIR    Default migrations directory
  MIGRATIONS_TABLE  Migration tracking table name

EXAMPLES:
  platform-migrate status
  platform-migrate up
  platform-migrate up --dry-run
  platform-migrate down --steps 3
  platform-migrate create add_users_table
  platform-migrate goto 20240101000000
`;
function parseArgs(args) {
  const options = {
    command: "",
    dryRun: false,
    steps: 1,
    migrationsDir: process.env.MIGRATIONS_DIR ?? "./migrations",
    help: false
  };
  for (let i = 0; i < args.length; i++) {
    const arg = args[i];
    if (arg === "--dry-run") {
      options.dryRun = true;
    } else if (arg === "--steps" && args[i + 1]) {
      options.steps = parseInt(args[++i], 10);
    } else if (arg === "--to" && args[i + 1]) {
      options.to = args[++i];
    } else if ((arg === "--dir" || arg === "-d") && args[i + 1]) {
      options.migrationsDir = args[++i];
    } else if (arg === "--help" || arg === "-h") {
      options.help = true;
    } else if (!arg.startsWith("-") && !options.command) {
      options.command = arg;
    } else if (!arg.startsWith("-") && options.command && !options.name) {
      options.name = arg;
    }
  }
  return options;
}
function formatResults(results) {
  if (results.length === 0) {
    console.log("No migrations to run.");
    return;
  }
  for (const result of results) {
    const icon = result.success ? "\u2713" : "\u2717";
    const status = result.dryRun ? "[DRY RUN]" : "";
    const time = result.success ? `(${result.executionTime}ms)` : "";
    if (result.success) {
      console.log(
        `  ${icon} ${result.migration.version} - ${result.migration.name} ${time} ${status}`
      );
    } else {
      console.error(
        `  ${icon} ${result.migration.version} - ${result.migration.name}`
      );
      console.error(`    Error: ${result.error?.message}`);
    }
  }
  const successful = results.filter((r) => r.success).length;
  const failed = results.filter((r) => !r.success).length;
  console.log(`
${successful} successful, ${failed} failed`);
}
async function main() {
  const args = process.argv.slice(2);
  const options = parseArgs(args);
  if (options.help || !options.command) {
    console.log(HELP_TEXT);
    process.exit(options.help ? 0 : 1);
  }
  if (!process.env.DATABASE_URL) {
    console.error("Error: DATABASE_URL environment variable is required");
    process.exit(1);
  }
  try {
    const { PostgresDatabase: PostgresDatabase2 } = await Promise.resolve().then(() => (init_PostgresDatabase(), PostgresDatabase_exports));
    const db = await PostgresDatabase2.fromEnv();
    const migrator = new Migrator(db, {
      tableName: process.env.MIGRATIONS_TABLE ?? "_migrations",
      migrationsDir: options.migrationsDir
    });
    try {
      await migrator.loadMigrations(options.migrationsDir);
    } catch (e) {
      if (options.command !== "create") {
        console.warn(
          `Warning: Could not load migrations from ${options.migrationsDir}`
        );
      }
    }
    switch (options.command) {
      case "status": {
        const status = await migrator.status();
        console.log("\n=== Migration Status ===\n");
        console.log(`Current Version: ${status.currentVersion ?? "None"}`);
        console.log(`Latest Version:  ${status.latestVersion ?? "None"}`);
        console.log(`
Applied (${status.applied.length}):`);
        for (const m of status.applied) {
          console.log(
            `  \u2713 ${m.version} - ${m.name} (${m.appliedAt.toISOString()})`
          );
        }
        console.log(`
Pending (${status.pending.length}):`);
        for (const m of status.pending) {
          console.log(`  \u25CB ${m.version} - ${m.name}`);
        }
        break;
      }
      case "up": {
        console.log(
          options.dryRun ? "\n=== Dry Run: Migrate Up ===\n" : "\n=== Migrating Up ===\n"
        );
        const results = await migrator.up({
          dryRun: options.dryRun,
          to: options.to
        });
        formatResults(results);
        if (results.some((r) => !r.success)) {
          process.exit(1);
        }
        break;
      }
      case "down": {
        console.log(
          options.dryRun ? "\n=== Dry Run: Rollback ===\n" : "\n=== Rolling Back ===\n"
        );
        const results = await migrator.down({
          dryRun: options.dryRun,
          steps: options.steps
        });
        formatResults(results);
        if (results.some((r) => !r.success)) {
          process.exit(1);
        }
        break;
      }
      case "reset": {
        console.log(
          options.dryRun ? "\n=== Dry Run: Reset ===\n" : "\n=== Resetting Database ===\n"
        );
        const results = await migrator.reset({ dryRun: options.dryRun });
        formatResults(results);
        if (results.some((r) => !r.success)) {
          process.exit(1);
        }
        break;
      }
      case "goto": {
        if (!options.name) {
          console.error(
            "Error: Version required. Usage: platform-migrate goto <version>"
          );
          process.exit(1);
        }
        console.log(`
=== Migrating to Version ${options.name} ===
`);
        const results = await migrator.goto(options.name, {
          dryRun: options.dryRun
        });
        formatResults(results);
        if (results.some((r) => !r.success)) {
          process.exit(1);
        }
        break;
      }
      case "create": {
        if (!options.name) {
          console.error(
            "Error: Migration name required. Usage: platform-migrate create <name>"
          );
          process.exit(1);
        }
        const filePath = await migrator.create(options.name);
        console.log(`
Created migration: ${filePath}
`);
        break;
      }
      case "validate": {
        console.log("\n=== Validating Migrations ===\n");
        const { valid, errors } = await migrator.validate();
        if (valid) {
          console.log("\u2713 All migrations are valid");
        } else {
          console.error("\u2717 Validation failed:");
          for (const error of errors) {
            console.error(`  - ${error}`);
          }
          process.exit(1);
        }
        break;
      }
      default:
        console.error(`Unknown command: ${options.command}`);
        console.log(HELP_TEXT);
        process.exit(1);
    }
    await db.close();
  } catch (error) {
    console.error("Error:", error instanceof Error ? error.message : error);
    process.exit(1);
  }
}
main().catch((error) => {
  console.error("Fatal error:", error);
  process.exit(1);
});
//# sourceMappingURL=migrate.js.map