{"version":3,"file":"test-utils.d.ts","sourceRoot":"","sources":["../src/test-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AAQpB,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,UAAU,EAAE,KAAK,GAAG,mBAAmB,CAAC,CAAC;IAC9D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1D;AAID,UAAU,qBAAqB;IAC7B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAChD;AAED,UAAU,mBAAmB;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAmHD,MAAM,WAAW,iBAAiB;IAChC,cAAc,EAAE,CAAC,OAAO,CAAC,EAAE,qBAAqB,KAAK,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC;IAC5E,aAAa,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,YAAY,EAAE,CAAC,OAAO,CAAC,EAAE,mBAAmB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/D,mCAAmC,EAAE,MAAM,MAAM,CAAC;IAClD,aAAa,EAAE,MAAM,EAAE,CAAC,UAAU,CAAC;CACpC;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,wBAAwB,GAAG,iBAAiB,CAU1F","sourcesContent":["import pg from 'pg';\n\nimport * as defaultPool from './default-pool.js';\n\nconst POSTGRES_USER = 'postgres';\nconst POSTGRES_HOST = 'localhost';\nconst POSTGRES_DATABASE = 'postgres';\n\nexport interface PostgresTestUtilsOptions {\n  database: string;\n  user?: string;\n  host?: string;\n  poolConfig?: Pick<pg.PoolConfig, 'max' | 'idleTimeoutMillis'>;\n  defaultDatabase?: string;\n  prepareAfterReset?: (client: pg.Client) => Promise<void>;\n}\n\ntype PostgresTestPoolConfig = Required<Pick<pg.PoolConfig, 'user' | 'host' | 'database'>>;\n\ninterface CreateDatabaseOptions {\n  dropExistingDatabase?: boolean;\n  database?: string;\n  templateDatabase?: string;\n  configurePool?: boolean;\n  prepare?: (client: pg.Client) => Promise<void>;\n}\n\ninterface DropDatabaseOptions {\n  database?: string;\n  force?: boolean;\n  closePool?: boolean;\n}\n\nasync function createDatabase(\n  options: PostgresTestUtilsOptions,\n  {\n    dropExistingDatabase = true,\n    configurePool = true,\n    database,\n    templateDatabase,\n    prepare,\n  }: CreateDatabaseOptions = {},\n): Promise<PostgresTestPoolConfig> {\n  const client = new pg.Client({\n    ...getPoolConfig(options),\n    database: options.defaultDatabase ?? POSTGRES_DATABASE,\n  });\n  await client.connect();\n\n  const escapedDatabase = client.escapeIdentifier(\n    database ?? getDatabaseNameForCurrentTestWorker(options.database),\n  );\n  if (dropExistingDatabase ?? true) {\n    await client.query(`DROP DATABASE IF EXISTS ${escapedDatabase}`);\n  }\n\n  if (templateDatabase) {\n    const escapedTemplateDatabase = client.escapeIdentifier(templateDatabase);\n    await client.query(`CREATE DATABASE ${escapedDatabase} TEMPLATE ${escapedTemplateDatabase}`);\n  } else {\n    await client.query(`CREATE DATABASE ${escapedDatabase}`);\n  }\n\n  await client.end();\n\n  await prepare?.(client);\n\n  const poolConfig = getPoolConfig(options);\n\n  if (configurePool) {\n    await defaultPool.initAsync(\n      {\n        ...poolConfig,\n        // Offer sensible default, but these can be overridden by `options.poolConfig`.\n        max: 10,\n        idleTimeoutMillis: 30000,\n        errorOnUnusedParameters: true,\n        ...options.poolConfig,\n      },\n      (err) => {\n        throw err;\n      },\n    );\n  }\n\n  return poolConfig;\n}\n\nasync function resetDatabase(options: PostgresTestUtilsOptions): Promise<void> {\n  const client = new pg.Client(getPoolConfig(options));\n  await client.connect();\n  await client.query(`\n    DO\n    $func$\n    BEGIN\n      EXECUTE (\n        SELECT 'TRUNCATE TABLE ' || string_agg(oid::regclass::text, ', ') || ' RESTART IDENTITY CASCADE'\n          FROM pg_class\n          WHERE relkind = 'r'\n          AND relnamespace = 'public'::regnamespace\n      );\n    END\n    $func$;\n  `);\n  await options.prepareAfterReset?.(client);\n  await client.end();\n}\n\nasync function dropDatabase(\n  options: PostgresTestUtilsOptions,\n  { closePool = true, force = false, database }: DropDatabaseOptions = {},\n): Promise<void> {\n  if (closePool) {\n    await defaultPool.closeAsync();\n  }\n\n  const databaseName = database ?? getDatabaseNameForCurrentTestWorker(options.database);\n  if ('PL_KEEP_TEST_DB' in process.env && !force) {\n    // eslint-disable-next-line no-console\n    console.log(`PL_KEEP_TEST_DB environment variable set, not dropping database ${databaseName}`);\n    return;\n  }\n\n  const client = new pg.Client({\n    ...getPoolConfig(options),\n    database: options.defaultDatabase ?? POSTGRES_DATABASE,\n  });\n  await client.connect();\n  await client.query(`DROP DATABASE IF EXISTS ${client.escapeIdentifier(databaseName)}`);\n  await client.end();\n}\n\nfunction getDatabaseNameForCurrentTestWorker(namespace: string): string {\n  // https://playwright.dev/docs/test-parallel#isolate-test-data-between-parallel-workers\n  const workerId = process.env.TEST_WORKER_INDEX ?? process.env.VITEST_POOL_ID ?? '1';\n  return `${namespace}_${workerId}`;\n}\n\nfunction getPoolConfig(options: PostgresTestUtilsOptions): PostgresTestPoolConfig {\n  return {\n    user: options.user ?? POSTGRES_USER,\n    host: options.host ?? POSTGRES_HOST,\n    database: getDatabaseNameForCurrentTestWorker(options.database),\n  };\n}\n\nexport interface PostgresTestUtils {\n  createDatabase: (options?: CreateDatabaseOptions) => Promise<pg.PoolConfig>;\n  resetDatabase: () => Promise<void>;\n  dropDatabase: (options?: DropDatabaseOptions) => Promise<void>;\n  getDatabaseNameForCurrentTestWorker: () => string;\n  getPoolConfig: () => pg.PoolConfig;\n}\n\nexport function makePostgresTestUtils(options: PostgresTestUtilsOptions): PostgresTestUtils {\n  return {\n    createDatabase: (createOptions?: CreateDatabaseOptions) =>\n      createDatabase(options, createOptions),\n    resetDatabase: () => resetDatabase(options),\n    dropDatabase: (dropOptions?: DropDatabaseOptions) => dropDatabase(options, dropOptions),\n    getDatabaseNameForCurrentTestWorker: () =>\n      getDatabaseNameForCurrentTestWorker(options.database),\n    getPoolConfig: () => getPoolConfig(options),\n  };\n}\n"]}