postgres-memory-server 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +104 -79
- package/dist/cli.js +555 -61
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +50 -19
- package/dist/index.js +550 -55
- package/dist/index.js.map +1 -1
- package/package.json +5 -4
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts","../src/PostgresMemoryServer.ts","../src/errors.ts","../src/presets.ts"],"sourcesContent":["import process from \"node:process\";\n\nimport { PostgresMemoryServer } from \"./PostgresMemoryServer.js\";\nimport type {\n PostgresMemoryServerOptions,\n PostgresMemoryServerPreset,\n} from \"./types.js\";\n\nasync function main(): Promise<void> {\n const { options, initFiles, json } = parseArgs(process.argv.slice(2));\n\n const server = await PostgresMemoryServer.create(options);\n\n try {\n for (const file of initFiles) {\n await server.runSqlFile(file);\n }\n\n const payload = {\n uri: server.getUri(),\n host: server.getHost(),\n port: server.getPort(),\n database: server.getDatabase(),\n username: server.getUsername(),\n password: server.getPassword(),\n image: server.getImage(),\n };\n\n if (json) {\n process.stdout.write(`${JSON.stringify(payload, null, 2)}\\n`);\n } else {\n process.stdout.write(`POSTGRES_MEMORY_SERVER_URI=${payload.uri}\\n`);\n process.stdout.write(`POSTGRES_MEMORY_SERVER_HOST=${payload.host}\\n`);\n process.stdout.write(`POSTGRES_MEMORY_SERVER_PORT=${payload.port}\\n`);\n process.stdout.write(\n `POSTGRES_MEMORY_SERVER_DATABASE=${payload.database}\\n`,\n );\n process.stdout.write(\n `POSTGRES_MEMORY_SERVER_USERNAME=${payload.username}\\n`,\n );\n process.stdout.write(\n `POSTGRES_MEMORY_SERVER_PASSWORD=${payload.password}\\n`,\n );\n process.stdout.write(`POSTGRES_MEMORY_SERVER_IMAGE=${payload.image}\\n`);\n process.stdout.write(\"\\nPress Ctrl+C to stop the container.\\n\");\n }\n\n const stop = async () => {\n await server.stop();\n process.exit(0);\n };\n\n process.on(\"SIGINT\", () => {\n void stop();\n });\n process.on(\"SIGTERM\", () => {\n void stop();\n });\n\n await new Promise<void>(() => {\n // Intentionally never resolve. Signals will stop the process.\n });\n } catch (error) {\n await server.stop();\n throw error;\n }\n}\n\ntype ParsedArgs = {\n options: PostgresMemoryServerOptions;\n initFiles: string[];\n json: boolean;\n};\n\nfunction parseArgs(argv: string[]): ParsedArgs {\n const options: PostgresMemoryServerOptions = {};\n const initFiles: string[] = [];\n const extensions: string[] = [];\n let json = false;\n\n for (let index = 0; index < argv.length; index += 1) {\n const arg = argv[index];\n\n switch (arg) {\n case \"--preset\": {\n const value = readValue(\n argv,\n ++index,\n arg,\n ) as PostgresMemoryServerPreset;\n options.preset = value;\n break;\n }\n case \"--image\": {\n options.image = readValue(argv, ++index, arg);\n break;\n }\n case \"--version\": {\n options.version = readValue(argv, ++index, arg);\n break;\n }\n case \"--database\": {\n options.database = readValue(argv, ++index, arg);\n break;\n }\n case \"--username\": {\n options.username = readValue(argv, ++index, arg);\n break;\n }\n case \"--password\": {\n options.password = readValue(argv, ++index, arg);\n break;\n }\n case \"--extension\": {\n extensions.push(readValue(argv, ++index, arg));\n break;\n }\n case \"--init-file\": {\n initFiles.push(readValue(argv, ++index, arg));\n break;\n }\n case \"--json\": {\n json = true;\n break;\n }\n case \"--help\": {\n printHelp();\n process.exit(0);\n }\n default: {\n throw new Error(`Unknown argument: ${arg}`);\n }\n }\n }\n\n if (extensions.length > 0) {\n options.extensions = extensions;\n }\n\n return { options, initFiles, json };\n}\n\nfunction readValue(argv: string[], index: number, flag: string): string {\n const value = argv[index];\n if (!value) {\n throw new Error(`Missing value for ${flag}`);\n }\n return value;\n}\n\nfunction printHelp(): void {\n process.stdout.write(`postgres-memory-server\\n\\n`);\n process.stdout.write(`Options:\\n`);\n process.stdout.write(` --preset postgres|paradedb\\n`);\n process.stdout.write(` --version <tag>\\n`);\n process.stdout.write(` --image <image>\\n`);\n process.stdout.write(` --database <name>\\n`);\n process.stdout.write(` --username <name>\\n`);\n process.stdout.write(` --password <password>\\n`);\n process.stdout.write(` --extension <name> repeatable\\n`);\n process.stdout.write(` --init-file <path> repeatable\\n`);\n process.stdout.write(` --json\\n`);\n process.stdout.write(` --help\\n`);\n}\n\nvoid main().catch((error: unknown) => {\n const message =\n error instanceof Error ? (error.stack ?? error.message) : String(error);\n process.stderr.write(`${message}\\n`);\n process.exit(1);\n});\n","import { promises as fs } from \"node:fs\";\nimport path from \"node:path\";\n\nimport { PostgreSqlContainer } from \"@testcontainers/postgresql\";\nimport { Client, type QueryResultRow } from \"pg\";\n\nimport { ServerStoppedError, SnapshotUnsupportedError } from \"./errors.js\";\nimport { buildInitStatements, normalizeOptions } from \"./presets.js\";\nimport type {\n PostgresConnectionOptions,\n PostgresMemoryServerOptions,\n QueryParams,\n QueryResponse,\n QueryText,\n} from \"./types.js\";\n\nexport type StartedPostgreSqlContainer = Awaited<\n ReturnType<PostgreSqlContainer[\"start\"]>\n>;\n\nexport class PostgresMemoryServer {\n private stopped = false;\n private readonly snapshotSupported: boolean;\n\n private constructor(\n private readonly container: StartedPostgreSqlContainer,\n private readonly options: ReturnType<typeof normalizeOptions>,\n ) {\n this.snapshotSupported = options.database !== \"postgres\";\n }\n\n static async create(\n options: PostgresMemoryServerOptions = {},\n ): Promise<PostgresMemoryServer> {\n const normalized = normalizeOptions(options);\n\n const container = await new PostgreSqlContainer(normalized.image)\n .withDatabase(normalized.database)\n .withUsername(normalized.username)\n .withPassword(normalized.password)\n .start();\n\n const server = new PostgresMemoryServer(container, normalized);\n\n const initStatements = buildInitStatements(normalized);\n if (initStatements.length > 0) {\n await server.runSql(initStatements);\n }\n\n return server;\n }\n\n static createPostgres(\n options: Omit<PostgresMemoryServerOptions, \"preset\"> = {},\n ): Promise<PostgresMemoryServer> {\n return PostgresMemoryServer.create({ ...options, preset: \"postgres\" });\n }\n\n static createParadeDb(\n options: Omit<PostgresMemoryServerOptions, \"preset\"> = {},\n ): Promise<PostgresMemoryServer> {\n return PostgresMemoryServer.create({ ...options, preset: \"paradedb\" });\n }\n\n getUri(): string {\n this.ensureRunning();\n return this.container.getConnectionUri();\n }\n\n getHost(): string {\n this.ensureRunning();\n return this.container.getHost();\n }\n\n getPort(): number {\n this.ensureRunning();\n return this.container.getPort();\n }\n\n getDatabase(): string {\n return this.options.database;\n }\n\n getUsername(): string {\n return this.options.username;\n }\n\n getPassword(): string {\n return this.options.password;\n }\n\n getImage(): string {\n return this.options.image;\n }\n\n getConnectionOptions(): PostgresConnectionOptions {\n return {\n host: this.getHost(),\n port: this.getPort(),\n database: this.getDatabase(),\n user: this.getUsername(),\n password: this.getPassword(),\n };\n }\n\n async query<Row extends QueryResultRow = QueryResultRow>(\n text: QueryText<Row>,\n params?: QueryParams,\n ): Promise<QueryResponse<Row>> {\n return this.withClient((client) => {\n if (typeof text === \"string\") {\n if (params === undefined) {\n return client.query<Row>(text);\n }\n\n return client.query<Row>(text, params);\n }\n\n return client.query<Row>(text);\n });\n }\n\n async withClient<T>(callback: (client: Client) => Promise<T>): Promise<T> {\n this.ensureRunning();\n\n const client = new Client({\n connectionString: this.getUri(),\n });\n\n await client.connect();\n try {\n return await callback(client);\n } finally {\n await client.end();\n }\n }\n\n async runSql(sql: string | string[]): Promise<void> {\n const statements = Array.isArray(sql) ? sql : [sql];\n\n await this.withClient(async (client) => {\n for (const statement of statements) {\n await client.query(statement);\n }\n });\n }\n\n async runSqlFile(filePath: string): Promise<void> {\n const sql = await fs.readFile(filePath, \"utf8\");\n await this.runSql(sql);\n }\n\n async runMigrationsDir(dirPath: string): Promise<string[]> {\n const entries = await fs.readdir(dirPath, { withFileTypes: true });\n const files = entries\n .filter(\n (entry) => entry.isFile() && entry.name.toLowerCase().endsWith(\".sql\"),\n )\n .map((entry) => entry.name)\n .sort((left, right) => left.localeCompare(right));\n\n for (const file of files) {\n await this.runSqlFile(path.join(dirPath, file));\n }\n\n return files;\n }\n\n async snapshot(): Promise<void> {\n this.ensureRunning();\n this.ensureSnapshotSupported();\n await this.container.snapshot();\n }\n\n async restore(): Promise<void> {\n this.ensureRunning();\n this.ensureSnapshotSupported();\n await this.container.restoreSnapshot();\n }\n\n async stop(): Promise<void> {\n if (this.stopped) {\n return;\n }\n\n this.stopped = true;\n await this.container.stop();\n }\n\n private ensureRunning(): void {\n if (this.stopped) {\n throw new ServerStoppedError();\n }\n }\n\n private ensureSnapshotSupported(): void {\n if (!this.snapshotSupported) {\n throw new SnapshotUnsupportedError(this.options.database);\n }\n }\n}\n","export class PostgresMemoryServerError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = new.target.name;\n }\n}\n\nexport class SnapshotUnsupportedError extends PostgresMemoryServerError {\n constructor(database: string) {\n super(\n `Snapshots are not supported when the database name is \"${database}\". ` +\n `Use a non-system database name such as \"testdb\" before calling snapshot() or restore().`,\n );\n }\n}\n\nexport class ServerStoppedError extends PostgresMemoryServerError {\n constructor() {\n super(\"The PostgresMemoryServer has already been stopped.\");\n }\n}\n","import type {\n NormalizedPostgresMemoryServerOptions,\n PostgresMemoryServerOptions,\n PostgresMemoryServerPreset,\n} from \"./types.js\";\n\nexport const POSTGRES_IMAGE_REPOSITORY = \"postgres\";\nexport const PARADEDB_IMAGE_REPOSITORY = \"paradedb/paradedb\";\nexport const DEFAULT_POSTGRES_VERSION = \"17\";\nexport const DEFAULT_PARADEDB_VERSION = \"0.22.3-pg17\";\nexport const DEFAULT_POSTGRES_IMAGE = getImageForVersion(\n \"postgres\",\n DEFAULT_POSTGRES_VERSION,\n);\nexport const DEFAULT_PARADEDB_IMAGE = getImageForVersion(\n \"paradedb\",\n DEFAULT_PARADEDB_VERSION,\n);\n\nconst DEFAULT_DATABASE = \"testdb\";\nconst DEFAULT_USERNAME = \"testuser\";\nconst DEFAULT_PASSWORD = \"testpassword\";\n\nconst PARADEDB_DEFAULT_EXTENSIONS = [\"pg_search\", \"vector\"];\n\nexport function normalizeOptions(\n options: PostgresMemoryServerOptions = {},\n): NormalizedPostgresMemoryServerOptions {\n const preset = options.preset ?? \"postgres\";\n const version = options.version;\n const image = options.image ?? getImage(preset, version);\n const database = options.database ?? DEFAULT_DATABASE;\n const username = options.username ?? DEFAULT_USERNAME;\n const password = options.password ?? DEFAULT_PASSWORD;\n const extensions = options.extensions ?? getDefaultExtensions(preset);\n const initSql = options.initSql ?? [];\n\n return {\n preset,\n version,\n image,\n database,\n username,\n password,\n extensions,\n initSql,\n };\n}\n\nexport function getImageForVersion(\n preset: PostgresMemoryServerPreset,\n version: string,\n): string {\n const repository =\n preset === \"paradedb\"\n ? PARADEDB_IMAGE_REPOSITORY\n : POSTGRES_IMAGE_REPOSITORY;\n\n return `${repository}:${version}`;\n}\n\nexport function getDefaultImage(preset: PostgresMemoryServerPreset): string {\n return preset === \"paradedb\"\n ? DEFAULT_PARADEDB_IMAGE\n : DEFAULT_POSTGRES_IMAGE;\n}\n\nfunction getImage(\n preset: PostgresMemoryServerPreset,\n version?: string,\n): string {\n return version\n ? getImageForVersion(preset, version)\n : getDefaultImage(preset);\n}\n\nexport function getDefaultExtensions(\n preset: PostgresMemoryServerPreset,\n): string[] {\n return preset === \"paradedb\" ? [...PARADEDB_DEFAULT_EXTENSIONS] : [];\n}\n\nexport function buildInitStatements(\n options: NormalizedPostgresMemoryServerOptions,\n): string[] {\n const extensionStatements = options.extensions.map(\n (extension) =>\n `CREATE EXTENSION IF NOT EXISTS ${quoteIdentifier(extension)};`,\n );\n\n return [...extensionStatements, ...options.initSql];\n}\n\nfunction quoteIdentifier(name: string): string {\n if (/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name)) {\n return name;\n }\n\n return `\"${name.replaceAll('\"', '\"\"')}\"`;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/PostgresMemoryServer.ts","../src/errors.ts","../src/native.ts","../src/presets.ts"],"sourcesContent":["import process from \"node:process\";\n\nimport { PostgresMemoryServer } from \"./PostgresMemoryServer.js\";\nimport type {\n PostgresMemoryServerOptions,\n PostgresMemoryServerPreset,\n} from \"./types.js\";\n\nasync function main(): Promise<void> {\n const { options, initFiles, json } = parseArgs(process.argv.slice(2));\n\n const server = await PostgresMemoryServer.create(options);\n\n try {\n for (const file of initFiles) {\n await server.runSqlFile(file);\n }\n\n const payload = {\n uri: server.getUri(),\n host: server.getHost(),\n port: server.getPort(),\n database: server.getDatabase(),\n username: server.getUsername(),\n password: server.getPassword(),\n image: server.getImage(),\n };\n\n if (json) {\n process.stdout.write(`${JSON.stringify(payload, null, 2)}\\n`);\n } else {\n process.stdout.write(`POSTGRES_MEMORY_SERVER_URI=${payload.uri}\\n`);\n process.stdout.write(`POSTGRES_MEMORY_SERVER_HOST=${payload.host}\\n`);\n process.stdout.write(`POSTGRES_MEMORY_SERVER_PORT=${payload.port}\\n`);\n process.stdout.write(\n `POSTGRES_MEMORY_SERVER_DATABASE=${payload.database}\\n`,\n );\n process.stdout.write(\n `POSTGRES_MEMORY_SERVER_USERNAME=${payload.username}\\n`,\n );\n process.stdout.write(\n `POSTGRES_MEMORY_SERVER_PASSWORD=${payload.password}\\n`,\n );\n process.stdout.write(`POSTGRES_MEMORY_SERVER_IMAGE=${payload.image}\\n`);\n process.stdout.write(\"\\nPress Ctrl+C to stop the server.\\n\");\n }\n\n const stop = async () => {\n await server.stop();\n process.exit(0);\n };\n\n process.on(\"SIGINT\", () => {\n void stop();\n });\n process.on(\"SIGTERM\", () => {\n void stop();\n });\n\n await new Promise<void>(() => {\n // Intentionally never resolve. Signals will stop the process.\n });\n } catch (error) {\n await server.stop().catch(() => {});\n throw error;\n }\n}\n\ntype ParsedArgs = {\n options: PostgresMemoryServerOptions;\n initFiles: string[];\n json: boolean;\n};\n\nfunction parseArgs(argv: string[]): ParsedArgs {\n const options: PostgresMemoryServerOptions = {};\n const initFiles: string[] = [];\n const extensions: string[] = [];\n let json = false;\n\n for (let index = 0; index < argv.length; index += 1) {\n const arg = argv[index];\n\n switch (arg) {\n case \"--preset\": {\n const value = readValue(\n argv,\n ++index,\n arg,\n ) as PostgresMemoryServerPreset;\n options.preset = value;\n break;\n }\n case \"--image\": {\n // Deprecated: Docker images are no longer used. Ignore silently.\n readValue(argv, ++index, arg);\n break;\n }\n case \"--version\": {\n options.version = readValue(argv, ++index, arg);\n break;\n }\n case \"--database\": {\n options.database = readValue(argv, ++index, arg);\n break;\n }\n case \"--username\": {\n options.username = readValue(argv, ++index, arg);\n break;\n }\n case \"--password\": {\n options.password = readValue(argv, ++index, arg);\n break;\n }\n case \"--extension\": {\n extensions.push(readValue(argv, ++index, arg));\n break;\n }\n case \"--init-file\": {\n initFiles.push(readValue(argv, ++index, arg));\n break;\n }\n case \"--json\": {\n json = true;\n break;\n }\n case \"--help\": {\n printHelp();\n process.exit(0);\n }\n default: {\n throw new Error(`Unknown argument: ${arg}`);\n }\n }\n }\n\n if (extensions.length > 0) {\n options.extensions = extensions;\n }\n\n return { options, initFiles, json };\n}\n\nfunction readValue(argv: string[], index: number, flag: string): string {\n const value = argv[index];\n if (!value) {\n throw new Error(`Missing value for ${flag}`);\n }\n return value;\n}\n\nfunction printHelp(): void {\n process.stdout.write(`postgres-memory-server\\n\\n`);\n process.stdout.write(`Options:\\n`);\n process.stdout.write(` --preset postgres|paradedb\\n`);\n process.stdout.write(` --version <tag>\\n`);\n process.stdout.write(` --image <image> (deprecated, ignored)\\n`);\n process.stdout.write(` --database <name>\\n`);\n process.stdout.write(` --username <name>\\n`);\n process.stdout.write(` --password <password>\\n`);\n process.stdout.write(` --extension <name> repeatable\\n`);\n process.stdout.write(` --init-file <path> repeatable\\n`);\n process.stdout.write(` --json\\n`);\n process.stdout.write(` --help\\n`);\n}\n\nvoid main().catch((error: unknown) => {\n const message =\n error instanceof Error ? (error.stack ?? error.message) : String(error);\n process.stderr.write(`${message}\\n`);\n process.exit(1);\n});\n","import { promises as fs } from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\n\nimport EmbeddedPostgres from \"embedded-postgres\";\nimport { Client, type QueryResultRow } from \"pg\";\n\nimport {\n ExtensionInstallError,\n ServerStoppedError,\n SnapshotUnsupportedError,\n} from \"./errors.js\";\nimport {\n buildInitStatements,\n normalizeOptions,\n resolveParadeDBVersion,\n DEFAULT_POSTGRES_VERSION,\n} from \"./presets.js\";\nimport {\n getFreePort,\n getNativeDir,\n installParadeDBExtension,\n installPgVectorExtension,\n} from \"./native.js\";\nimport type {\n PostgresConnectionOptions,\n PostgresMemoryServerOptions,\n QueryParams,\n QueryResponse,\n QueryText,\n} from \"./types.js\";\n\nexport class PostgresMemoryServer {\n private stopped = false;\n private readonly snapshotSupported: boolean;\n private hasSnapshot = false;\n\n private constructor(\n private readonly pg: EmbeddedPostgres,\n private readonly port: number,\n private readonly dataDir: string,\n private readonly options: ReturnType<typeof normalizeOptions>,\n ) {\n this.snapshotSupported = options.database !== \"postgres\";\n }\n\n static async create(\n options: PostgresMemoryServerOptions = {},\n ): Promise<PostgresMemoryServer> {\n const normalized = normalizeOptions(options);\n const port = await getFreePort();\n const dataDir = await fs.mkdtemp(\n path.join(os.tmpdir(), \"postgres-memory-server-\"),\n );\n\n const postgresFlags: string[] = [];\n\n // Install ParadeDB extension if needed\n if (normalized.preset === \"paradedb\") {\n const nativeDir = getNativeDir();\n const extVersion = resolveParadeDBVersion(normalized.version);\n const pgMajor = DEFAULT_POSTGRES_VERSION;\n\n try {\n await installParadeDBExtension(nativeDir, extVersion, pgMajor);\n } catch (error) {\n throw new ExtensionInstallError(\n \"pg_search\",\n error instanceof Error ? error : new Error(String(error)),\n );\n }\n\n // Install pgvector if the vector extension is requested\n if (normalized.extensions.includes(\"vector\")) {\n try {\n await installPgVectorExtension(nativeDir, pgMajor);\n } catch (error) {\n throw new ExtensionInstallError(\n \"vector\",\n error instanceof Error ? error : new Error(String(error)),\n );\n }\n }\n\n // pg_search requires shared_preload_libraries for its background worker\n if (\n normalized.extensions.includes(\"pg_search\") ||\n normalized.extensions.length === 0\n ) {\n postgresFlags.push(\n \"-c\",\n \"shared_preload_libraries=pg_search\",\n );\n }\n }\n\n const pg = new EmbeddedPostgres({\n databaseDir: dataDir,\n port,\n user: normalized.username,\n password: normalized.password,\n persistent: false,\n postgresFlags,\n onLog: () => {},\n onError: () => {},\n });\n\n await pg.initialise();\n await pg.start();\n\n // Create the user database if it's not the system database\n if (normalized.database !== \"postgres\") {\n await pg.createDatabase(normalized.database);\n }\n\n const server = new PostgresMemoryServer(pg, port, dataDir, normalized);\n\n // Run init statements (CREATE EXTENSION, custom SQL)\n const initStatements = buildInitStatements(normalized);\n if (initStatements.length > 0) {\n await server.runSql(initStatements);\n }\n\n return server;\n }\n\n static createPostgres(\n options: Omit<PostgresMemoryServerOptions, \"preset\"> = {},\n ): Promise<PostgresMemoryServer> {\n return PostgresMemoryServer.create({ ...options, preset: \"postgres\" });\n }\n\n static createParadeDb(\n options: Omit<PostgresMemoryServerOptions, \"preset\"> = {},\n ): Promise<PostgresMemoryServer> {\n return PostgresMemoryServer.create({ ...options, preset: \"paradedb\" });\n }\n\n getUri(): string {\n this.ensureRunning();\n return `postgres://${this.options.username}:${this.options.password}@localhost:${this.port}/${this.options.database}`;\n }\n\n getHost(): string {\n this.ensureRunning();\n return \"localhost\";\n }\n\n getPort(): number {\n this.ensureRunning();\n return this.port;\n }\n\n getDatabase(): string {\n return this.options.database;\n }\n\n getUsername(): string {\n return this.options.username;\n }\n\n getPassword(): string {\n return this.options.password;\n }\n\n getImage(): string {\n return this.options.image;\n }\n\n getConnectionOptions(): PostgresConnectionOptions {\n return {\n host: this.getHost(),\n port: this.getPort(),\n database: this.getDatabase(),\n user: this.getUsername(),\n password: this.getPassword(),\n };\n }\n\n async query<Row extends QueryResultRow = QueryResultRow>(\n text: QueryText<Row>,\n params?: QueryParams,\n ): Promise<QueryResponse<Row>> {\n return this.withClient((client) => {\n if (typeof text === \"string\") {\n if (params === undefined) {\n return client.query<Row>(text);\n }\n\n return client.query<Row>(text, params);\n }\n\n return client.query<Row>(text);\n });\n }\n\n async withClient<T>(callback: (client: Client) => Promise<T>): Promise<T> {\n this.ensureRunning();\n\n const client = new Client({\n connectionString: this.getUri(),\n });\n\n await client.connect();\n try {\n return await callback(client);\n } finally {\n await client.end();\n }\n }\n\n async runSql(sql: string | string[]): Promise<void> {\n const statements = Array.isArray(sql) ? sql : [sql];\n\n await this.withClient(async (client) => {\n for (const statement of statements) {\n await client.query(statement);\n }\n });\n }\n\n async runSqlFile(filePath: string): Promise<void> {\n const sql = await fs.readFile(filePath, \"utf8\");\n await this.runSql(sql);\n }\n\n async runMigrationsDir(dirPath: string): Promise<string[]> {\n const entries = await fs.readdir(dirPath, { withFileTypes: true });\n const files = entries\n .filter(\n (entry) => entry.isFile() && entry.name.toLowerCase().endsWith(\".sql\"),\n )\n .map((entry) => entry.name)\n .sort((left, right) => left.localeCompare(right));\n\n for (const file of files) {\n await this.runSqlFile(path.join(dirPath, file));\n }\n\n return files;\n }\n\n /**\n * Create a snapshot of the current database state.\n * Uses PostgreSQL template databases for fast, native snapshots.\n */\n async snapshot(): Promise<void> {\n this.ensureRunning();\n this.ensureSnapshotSupported();\n\n const snapshotDb = `${this.options.database}_snapshot`;\n\n await this.withAdminClient(async (client) => {\n // Terminate other connections to the database\n await client.query(\n `SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = $1 AND pid != pg_backend_pid()`,\n [this.options.database],\n );\n\n // Drop existing snapshot if any\n if (this.hasSnapshot) {\n await client.query(`DROP DATABASE IF EXISTS \"${snapshotDb}\"`);\n }\n\n // Create snapshot as a template copy\n await client.query(\n `CREATE DATABASE \"${snapshotDb}\" TEMPLATE \"${this.options.database}\"`,\n );\n });\n\n this.hasSnapshot = true;\n }\n\n /**\n * Restore the database to the last snapshot.\n * Drops and recreates the database from the snapshot template.\n */\n async restore(): Promise<void> {\n this.ensureRunning();\n this.ensureSnapshotSupported();\n\n if (!this.hasSnapshot) {\n throw new Error(\n \"No snapshot exists. Call snapshot() before calling restore().\",\n );\n }\n\n const snapshotDb = `${this.options.database}_snapshot`;\n\n await this.withAdminClient(async (client) => {\n // Terminate all connections to the target database\n await client.query(\n `SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = $1 AND pid != pg_backend_pid()`,\n [this.options.database],\n );\n\n // Drop and recreate from snapshot\n await client.query(`DROP DATABASE \"${this.options.database}\"`);\n await client.query(\n `CREATE DATABASE \"${this.options.database}\" TEMPLATE \"${snapshotDb}\"`,\n );\n });\n }\n\n async stop(): Promise<void> {\n if (this.stopped) {\n return;\n }\n\n this.stopped = true;\n await this.pg.stop();\n }\n\n /**\n * Connect to the \"postgres\" system database for admin operations\n * (snapshot, restore, etc.).\n */\n private async withAdminClient<T>(\n callback: (client: Client) => Promise<T>,\n ): Promise<T> {\n const client = new Client({\n host: \"localhost\",\n port: this.port,\n database: \"postgres\",\n user: this.options.username,\n password: this.options.password,\n });\n\n await client.connect();\n try {\n return await callback(client);\n } finally {\n await client.end();\n }\n }\n\n private ensureRunning(): void {\n if (this.stopped) {\n throw new ServerStoppedError();\n }\n }\n\n private ensureSnapshotSupported(): void {\n if (!this.snapshotSupported) {\n throw new SnapshotUnsupportedError(this.options.database);\n }\n }\n}\n","export class PostgresMemoryServerError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = new.target.name;\n }\n}\n\nexport class SnapshotUnsupportedError extends PostgresMemoryServerError {\n constructor(database: string) {\n super(\n `Snapshots are not supported when the database name is \"${database}\". ` +\n `Use a non-system database name such as \"testdb\" before calling snapshot() or restore().`,\n );\n }\n}\n\nexport class ServerStoppedError extends PostgresMemoryServerError {\n constructor() {\n super(\"The PostgresMemoryServer has already been stopped.\");\n }\n}\n\nexport class ExtensionInstallError extends PostgresMemoryServerError {\n constructor(extensionName: string, cause?: Error) {\n super(\n `Failed to install the \"${extensionName}\" extension. ${cause?.message ?? \"\"}`.trim(),\n cause ? { cause } : undefined,\n );\n }\n}\n","import { promises as fs, readFileSync, existsSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { execFile as execFileCb } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport net from \"node:net\";\nimport os from \"node:os\";\nimport path from \"node:path\";\n\nconst execFile = promisify(execFileCb);\n\n/**\n * Get a free TCP port by binding to port 0 and reading the assigned port.\n */\nexport async function getFreePort(): Promise<number> {\n return new Promise((resolve, reject) => {\n const server = net.createServer();\n server.listen(0, () => {\n const { port } = server.address() as net.AddressInfo;\n server.close(() => resolve(port));\n });\n server.on(\"error\", reject);\n });\n}\n\n/**\n * Get the PG major version from the installed embedded-postgres package.\n * The npm package version mirrors the PG version (e.g., 18.3.0-beta.16 = PG 18).\n */\nexport function getPgMajorVersion(): string {\n // Resolve the main entry of embedded-postgres, then walk up to find package.json\n const req = createRequire(import.meta.url);\n const mainEntry = req.resolve(\"embedded-postgres\");\n let dir = path.dirname(mainEntry);\n\n // Walk up until we find a package.json with name \"embedded-postgres\"\n while (dir !== path.dirname(dir)) {\n const candidate = path.join(dir, \"package.json\");\n try {\n const content = readFileSync(candidate, \"utf8\");\n const pkg = JSON.parse(content) as { name?: string; version?: string };\n if (pkg.name === \"embedded-postgres\" && pkg.version) {\n return pkg.version.split(\".\")[0];\n }\n } catch {\n // continue walking up\n }\n dir = path.dirname(dir);\n }\n\n throw new Error(\n \"Could not determine embedded-postgres version. Ensure embedded-postgres is installed.\",\n );\n}\n\n/**\n * Get the native directory of the installed embedded-postgres platform package.\n * This directory contains bin/, lib/, and share/ subdirectories.\n */\nexport function getNativeDir(): string {\n const platform = os.platform();\n const arch = os.arch();\n\n const platformPkgNames: Record<string, Record<string, string>> = {\n darwin: {\n arm64: \"@embedded-postgres/darwin-arm64\",\n x64: \"@embedded-postgres/darwin-x64\",\n },\n linux: {\n x64: \"@embedded-postgres/linux-x64\",\n arm64: \"@embedded-postgres/linux-arm64\",\n },\n win32: {\n x64: \"@embedded-postgres/windows-x64\",\n },\n };\n\n const pkgName = platformPkgNames[platform]?.[arch];\n if (!pkgName) {\n throw new Error(`Unsupported platform: ${platform}-${arch}`);\n }\n\n const req = createRequire(import.meta.url);\n // Resolve the package's main entry, then find the native/ dir relative to it\n const mainEntry = req.resolve(pkgName);\n let dir = path.dirname(mainEntry);\n\n // Walk up to find the package root (containing native/)\n while (dir !== path.dirname(dir)) {\n const nativeDir = path.join(dir, \"native\");\n if (existsSync(nativeDir)) {\n return nativeDir;\n }\n dir = path.dirname(dir);\n }\n\n throw new Error(\n `Could not find native directory for ${pkgName}. Ensure embedded-postgres is installed correctly.`,\n );\n}\n\n/**\n * Get the cache directory for downloaded extension binaries.\n */\nexport function getCacheDir(): string {\n const xdgCache = process.env.XDG_CACHE_HOME;\n const base = xdgCache || path.join(os.homedir(), \".cache\");\n return path.join(base, \"postgres-memory-server\");\n}\n\n/**\n * Install the ParadeDB pg_search extension into the embedded-postgres native directory.\n * Downloads from GitHub releases if not already cached.\n */\nexport async function installParadeDBExtension(\n nativeDir: string,\n paradedbVersion: string,\n pgMajorVersion: string,\n): Promise<void> {\n // Check if already installed\n const libDir = path.join(nativeDir, \"lib\", \"postgresql\");\n const extDir = path.join(nativeDir, \"share\", \"postgresql\", \"extension\");\n\n const soName =\n os.platform() === \"darwin\" && parseInt(pgMajorVersion, 10) >= 16\n ? \"pg_search.dylib\"\n : \"pg_search.so\";\n\n try {\n await fs.access(path.join(libDir, soName));\n await fs.access(path.join(extDir, \"pg_search.control\"));\n return; // Already installed\n } catch {\n // Not installed, proceed\n }\n\n const cacheDir = getCacheDir();\n const platform = os.platform();\n const arch = os.arch();\n const cacheKey = `paradedb-${paradedbVersion}-pg${pgMajorVersion}-${platform}-${arch}`;\n const cachedDir = path.join(cacheDir, cacheKey);\n\n // Check cache\n let cached = false;\n try {\n await fs.access(path.join(cachedDir, \"lib\", soName));\n cached = true;\n } catch {\n // Not cached\n }\n\n if (!cached) {\n const url = buildDownloadUrl(\n paradedbVersion,\n pgMajorVersion,\n platform,\n arch,\n );\n const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), \"paradedb-\"));\n\n try {\n const filename = decodeURIComponent(url.split(\"/\").pop()!);\n const archivePath = path.join(tmpDir, filename);\n\n await downloadFile(url, archivePath);\n\n const extractedDir = path.join(tmpDir, \"extracted\");\n await fs.mkdir(extractedDir, { recursive: true });\n\n if (platform === \"darwin\") {\n await extractPkg(archivePath, extractedDir);\n } else {\n await extractDeb(archivePath, extractedDir);\n }\n\n // Cache the extracted extension files\n const cacheLibDir = path.join(cachedDir, \"lib\");\n const cacheExtDir = path.join(cachedDir, \"extension\");\n await fs.mkdir(cacheLibDir, { recursive: true });\n await fs.mkdir(cacheExtDir, { recursive: true });\n\n const soFiles = await findFiles(\n extractedDir,\n /pg_search\\.(so|dylib)$/,\n );\n for (const soFile of soFiles) {\n await copyFileWithPermissions(soFile, path.join(cacheLibDir, path.basename(soFile)));\n }\n\n const extFiles = await findFiles(\n extractedDir,\n /pg_search[^/]*(\\.control|\\.sql)$/,\n );\n for (const extFile of extFiles) {\n await copyFileWithPermissions(\n extFile,\n path.join(cacheExtDir, path.basename(extFile)),\n );\n }\n } finally {\n await fs.rm(tmpDir, { recursive: true, force: true });\n }\n }\n\n // Copy from cache to native dir\n await fs.mkdir(libDir, { recursive: true });\n await fs.mkdir(extDir, { recursive: true });\n\n const cacheLibDir = path.join(cachedDir, \"lib\");\n const cacheExtDir = path.join(cachedDir, \"extension\");\n\n for (const file of await fs.readdir(cacheLibDir)) {\n await copyFileWithPermissions(path.join(cacheLibDir, file), path.join(libDir, file));\n }\n\n for (const file of await fs.readdir(cacheExtDir)) {\n await copyFileWithPermissions(path.join(cacheExtDir, file), path.join(extDir, file));\n }\n}\n\nfunction buildDownloadUrl(\n version: string,\n pgMajorVersion: string,\n platform: string,\n arch: string,\n): string {\n const base = `https://github.com/paradedb/paradedb/releases/download/v${version}`;\n\n if (platform === \"darwin\") {\n if (arch !== \"arm64\") {\n throw new Error(\n \"ParadeDB only provides macOS binaries for arm64 (Apple Silicon). Intel Macs are not supported.\",\n );\n }\n const macosName = getMacOSCodename();\n return `${base}/pg_search%40${pgMajorVersion}--${version}.arm64_${macosName}.pkg`;\n }\n\n if (platform === \"linux\") {\n const debArch = arch === \"arm64\" ? \"arm64\" : \"amd64\";\n return `${base}/postgresql-${pgMajorVersion}-pg-search_${version}-1PARADEDB-bookworm_${debArch}.deb`;\n }\n\n throw new Error(\n `ParadeDB does not provide prebuilt binaries for ${platform}. Use the Docker-based preset instead.`,\n );\n}\n\nfunction getMacOSCodename(): string {\n const release = os.release();\n const majorVersion = parseInt(release.split(\".\")[0], 10);\n\n if (majorVersion >= 24) return \"sequoia\";\n if (majorVersion >= 23) return \"sonoma\";\n throw new Error(\n `ParadeDB requires macOS 14 (Sonoma) or later. Detected Darwin ${release}.`,\n );\n}\n\nasync function downloadFile(url: string, destPath: string): Promise<void> {\n const response = await fetch(url, { redirect: \"follow\" });\n\n if (!response.ok) {\n throw new Error(\n `Failed to download ParadeDB extension from ${url}: ${response.status} ${response.statusText}`,\n );\n }\n\n const buffer = Buffer.from(await response.arrayBuffer());\n await fs.writeFile(destPath, buffer);\n}\n\nasync function extractDeb(\n debPath: string,\n extractDir: string,\n): Promise<void> {\n await execFile(\"ar\", [\"x\", debPath], { cwd: extractDir });\n\n const files = await fs.readdir(extractDir);\n const dataTar = files.find((f) => f.startsWith(\"data.tar\"));\n\n if (!dataTar) {\n throw new Error(\n \"No data.tar.* found in .deb archive. The ParadeDB package format may have changed.\",\n );\n }\n\n const dataDir = path.join(extractDir, \"data\");\n await fs.mkdir(dataDir, { recursive: true });\n await execFile(\"tar\", [\n \"xf\",\n path.join(extractDir, dataTar),\n \"-C\",\n dataDir,\n ]);\n}\n\nasync function extractPkg(\n pkgPath: string,\n extractDir: string,\n): Promise<void> {\n const pkgDir = path.join(extractDir, \"pkg\");\n await execFile(\"pkgutil\", [\"--expand-full\", pkgPath, pkgDir]);\n}\n\n/**\n * Copy a file by reading and writing its contents, avoiding EACCES errors\n * when the source file is read-only (e.g., extracted from tar archives).\n */\nasync function copyFileWithPermissions(\n src: string,\n dest: string,\n): Promise<void> {\n const content = await fs.readFile(src);\n await fs.writeFile(dest, content, { mode: 0o755 });\n}\n\nasync function findFiles(dir: string, pattern: RegExp): Promise<string[]> {\n const results: string[] = [];\n\n async function walk(currentDir: string): Promise<void> {\n const entries = await fs.readdir(currentDir, { withFileTypes: true });\n for (const entry of entries) {\n const fullPath = path.join(currentDir, entry.name);\n if (entry.isDirectory()) {\n await walk(fullPath);\n } else if (pattern.test(entry.name)) {\n results.push(fullPath);\n }\n }\n }\n\n await walk(dir);\n return results;\n}\n\n/**\n * Install pgvector extension into the embedded-postgres native directory.\n * Downloads from Homebrew bottles (GHCR) which cover macOS + Linux.\n */\nexport async function installPgVectorExtension(\n nativeDir: string,\n pgMajorVersion: string,\n): Promise<void> {\n const libDir = path.join(nativeDir, \"lib\", \"postgresql\");\n const extDir = path.join(nativeDir, \"share\", \"postgresql\", \"extension\");\n\n const soName = os.platform() === \"darwin\" ? \"vector.dylib\" : \"vector.so\";\n\n // Check if already installed\n try {\n await fs.access(path.join(libDir, soName));\n await fs.access(path.join(extDir, \"vector.control\"));\n return;\n } catch {\n // Not installed\n }\n\n const platform = os.platform();\n const arch = os.arch();\n const cacheDir = getCacheDir();\n const cacheKey = `pgvector-pg${pgMajorVersion}-${platform}-${arch}`;\n const cachedDir = path.join(cacheDir, cacheKey);\n\n // Check cache\n let cached = false;\n try {\n await fs.access(path.join(cachedDir, \"lib\", soName));\n cached = true;\n } catch {\n // Not cached\n }\n\n if (!cached) {\n const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), \"pgvector-\"));\n\n try {\n // Fetch Homebrew formula metadata to get bottle URLs\n const formulaRes = await fetch(\n \"https://formulae.brew.sh/api/formula/pgvector.json\",\n );\n if (!formulaRes.ok) {\n throw new Error(\n `Failed to fetch pgvector formula: ${formulaRes.status}`,\n );\n }\n const formula = (await formulaRes.json()) as HomebrewFormula;\n\n const bottleTag = getHomebrewBottleTag(platform, arch);\n const fileInfo = formula.bottle.stable.files[bottleTag];\n if (!fileInfo) {\n throw new Error(\n `No pgvector Homebrew bottle for ${bottleTag}. ` +\n `Available: ${Object.keys(formula.bottle.stable.files).join(\", \")}`,\n );\n }\n\n // Get anonymous GHCR auth token\n const tokenRes = await fetch(\n \"https://ghcr.io/token?scope=repository:homebrew/core/pgvector:pull\",\n );\n if (!tokenRes.ok) {\n throw new Error(`Failed to get GHCR token: ${tokenRes.status}`);\n }\n const { token } = (await tokenRes.json()) as { token: string };\n\n // Download the bottle blob\n const blobUrl = `https://ghcr.io/v2/homebrew/core/pgvector/blobs/sha256:${fileInfo.sha256}`;\n const blobRes = await fetch(blobUrl, {\n headers: { Authorization: `Bearer ${token}` },\n redirect: \"follow\",\n });\n if (!blobRes.ok) {\n throw new Error(\n `Failed to download pgvector bottle: ${blobRes.status}`,\n );\n }\n\n const bottlePath = path.join(tmpDir, \"pgvector.tar.gz\");\n const buffer = Buffer.from(await blobRes.arrayBuffer());\n await fs.writeFile(bottlePath, buffer);\n\n // Extract the tarball\n const extractDir = path.join(tmpDir, \"extracted\");\n await fs.mkdir(extractDir, { recursive: true });\n await execFile(\"tar\", [\"xzf\", bottlePath, \"-C\", extractDir]);\n\n // Cache extracted extension files\n const cacheLibDir = path.join(cachedDir, \"lib\");\n const cacheExtDir = path.join(cachedDir, \"extension\");\n await fs.mkdir(cacheLibDir, { recursive: true });\n await fs.mkdir(cacheExtDir, { recursive: true });\n\n // Find vector.so/.dylib for the matching PG version\n const pgSubdir = `postgresql@${pgMajorVersion}`;\n let soFiles = await findFiles(\n extractDir,\n new RegExp(`${pgSubdir}.*vector\\\\.(so|dylib)$`),\n );\n if (soFiles.length === 0) {\n soFiles = await findFiles(extractDir, /vector\\.(so|dylib)$/);\n }\n for (const f of soFiles) {\n await copyFileWithPermissions(f, path.join(cacheLibDir, path.basename(f)));\n }\n\n // Find extension control and SQL files for matching PG version\n let extFiles = await findFiles(\n extractDir,\n new RegExp(`${pgSubdir}.*vector[^/]*(\\\\.control|\\\\.sql)$`),\n );\n if (extFiles.length === 0) {\n extFiles = await findFiles(extractDir, /vector[^/]*(\\.control|\\.sql)$/);\n }\n for (const f of extFiles) {\n await copyFileWithPermissions(f, path.join(cacheExtDir, path.basename(f)));\n }\n } finally {\n await fs.rm(tmpDir, { recursive: true, force: true });\n }\n }\n\n // Copy from cache to native dir\n await fs.mkdir(libDir, { recursive: true });\n await fs.mkdir(extDir, { recursive: true });\n\n const cacheLibDir = path.join(cachedDir, \"lib\");\n const cacheExtDir = path.join(cachedDir, \"extension\");\n\n for (const file of await fs.readdir(cacheLibDir)) {\n await copyFileWithPermissions(path.join(cacheLibDir, file), path.join(libDir, file));\n }\n\n for (const file of await fs.readdir(cacheExtDir)) {\n await copyFileWithPermissions(path.join(cacheExtDir, file), path.join(extDir, file));\n }\n}\n\nfunction getHomebrewBottleTag(platform: string, arch: string): string {\n if (platform === \"darwin\") {\n const release = os.release();\n const major = parseInt(release.split(\".\")[0], 10);\n const prefix = arch === \"arm64\" ? \"arm64_\" : \"\";\n if (major >= 25) return `${prefix}tahoe`;\n if (major >= 24) return `${prefix}sequoia`;\n if (major >= 23) return `${prefix}sonoma`;\n return `${prefix}ventura`;\n }\n if (platform === \"linux\") {\n return arch === \"arm64\" ? \"aarch64_linux\" : \"x86_64_linux\";\n }\n throw new Error(`No Homebrew bottles available for ${platform}-${arch}`);\n}\n\ninterface HomebrewFormula {\n bottle: {\n stable: {\n files: Record<string, { cellar: string; sha256: string }>;\n };\n };\n}\n\n/**\n * Parse a ParadeDB version string like \"0.22.5\" or \"0.22.5-pg17\".\n * Returns the extension version and optional PG version suffix.\n */\nexport function parseParadeDBVersion(version: string): {\n extVersion: string;\n pgVersion?: string;\n} {\n const match = version.match(/^(\\d+\\.\\d+\\.\\d+)(?:-pg(\\d+))?$/);\n if (!match) {\n return { extVersion: version };\n }\n return {\n extVersion: match[1],\n pgVersion: match[2],\n };\n}\n","import { getPgMajorVersion, parseParadeDBVersion } from \"./native.js\";\nimport type {\n NormalizedPostgresMemoryServerOptions,\n PostgresMemoryServerOptions,\n PostgresMemoryServerPreset,\n} from \"./types.js\";\n\nexport const DEFAULT_PARADEDB_EXT_VERSION = \"0.22.5\";\nexport const DEFAULT_POSTGRES_VERSION = getPgMajorVersion();\nexport const DEFAULT_PARADEDB_VERSION = `${DEFAULT_PARADEDB_EXT_VERSION}-pg${DEFAULT_POSTGRES_VERSION}`;\n\n/** Descriptive label for the postgres preset. */\nexport const DEFAULT_POSTGRES_IMAGE = `postgres:${DEFAULT_POSTGRES_VERSION}`;\n\n/** Descriptive label for the paradedb preset. */\nexport const DEFAULT_PARADEDB_IMAGE = `paradedb:${DEFAULT_PARADEDB_VERSION}`;\n\n// Keep old constants for backward compatibility\nexport const POSTGRES_IMAGE_REPOSITORY = \"postgres\";\nexport const PARADEDB_IMAGE_REPOSITORY = \"paradedb\";\n\nconst DEFAULT_DATABASE = \"testdb\";\nconst DEFAULT_USERNAME = \"testuser\";\nconst DEFAULT_PASSWORD = \"testpassword\";\n\nconst PARADEDB_DEFAULT_EXTENSIONS = [\"pg_search\", \"vector\"];\n\nexport function normalizeOptions(\n options: PostgresMemoryServerOptions = {},\n): NormalizedPostgresMemoryServerOptions {\n const preset = options.preset ?? \"postgres\";\n const version = options.version;\n const image = getImageLabel(preset, version);\n const database = options.database ?? DEFAULT_DATABASE;\n const username = options.username ?? DEFAULT_USERNAME;\n const password = options.password ?? DEFAULT_PASSWORD;\n const extensions = options.extensions ?? getDefaultExtensions(preset);\n const initSql = options.initSql ?? [];\n\n return {\n preset,\n version,\n image,\n database,\n username,\n password,\n extensions,\n initSql,\n };\n}\n\nexport function getImageForVersion(\n preset: PostgresMemoryServerPreset,\n version: string,\n): string {\n const repository =\n preset === \"paradedb\" ? PARADEDB_IMAGE_REPOSITORY : POSTGRES_IMAGE_REPOSITORY;\n\n return `${repository}:${version}`;\n}\n\nexport function getDefaultImage(preset: PostgresMemoryServerPreset): string {\n return preset === \"paradedb\" ? DEFAULT_PARADEDB_IMAGE : DEFAULT_POSTGRES_IMAGE;\n}\n\nfunction getImageLabel(\n preset: PostgresMemoryServerPreset,\n version?: string,\n): string {\n if (version) {\n return getImageForVersion(preset, version);\n }\n return getDefaultImage(preset);\n}\n\nexport function getDefaultExtensions(\n preset: PostgresMemoryServerPreset,\n): string[] {\n return preset === \"paradedb\" ? [...PARADEDB_DEFAULT_EXTENSIONS] : [];\n}\n\nexport function buildInitStatements(\n options: NormalizedPostgresMemoryServerOptions,\n): string[] {\n const extensionStatements = options.extensions.map(\n (extension) =>\n `CREATE EXTENSION IF NOT EXISTS ${quoteIdentifier(extension)};`,\n );\n\n return [...extensionStatements, ...options.initSql];\n}\n\n/**\n * Resolve the ParadeDB extension version from the user-provided version string.\n * Validates that any PG version suffix matches the installed embedded-postgres.\n */\nexport function resolveParadeDBVersion(version?: string): string {\n if (!version) {\n return DEFAULT_PARADEDB_EXT_VERSION;\n }\n\n const parsed = parseParadeDBVersion(version);\n\n if (parsed.pgVersion) {\n const installedPg = DEFAULT_POSTGRES_VERSION;\n if (parsed.pgVersion !== installedPg) {\n throw new Error(\n `ParadeDB version \"${version}\" targets PostgreSQL ${parsed.pgVersion}, ` +\n `but embedded-postgres provides PostgreSQL ${installedPg}. ` +\n `Install embedded-postgres@${parsed.pgVersion}.x to match, ` +\n `or use version \"${parsed.extVersion}\" without the -pg suffix.`,\n );\n }\n }\n\n return parsed.extVersion;\n}\n\nfunction quoteIdentifier(name: string): string {\n if (/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name)) {\n return name;\n }\n\n return `\"${name.replaceAll('\"', '\"\"')}\"`;\n}\n"],"mappings":"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","names":["process","fs","os","path","cacheLibDir","cacheExtDir","fs","path","os","process"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -3,40 +3,49 @@ import { QueryResultRow, QueryConfig, QueryResult, Client } from 'pg';
|
|
|
3
3
|
type PostgresMemoryServerPreset = "postgres" | "paradedb";
|
|
4
4
|
interface PostgresMemoryServerOptions {
|
|
5
5
|
/**
|
|
6
|
-
* Preset used to choose
|
|
6
|
+
* Preset used to choose default extensions and behavior.
|
|
7
7
|
* Defaults to "postgres".
|
|
8
8
|
*/
|
|
9
9
|
preset?: PostgresMemoryServerPreset;
|
|
10
10
|
/**
|
|
11
|
-
* Version
|
|
12
|
-
*
|
|
13
|
-
*
|
|
11
|
+
* Version string for the selected preset.
|
|
12
|
+
*
|
|
13
|
+
* For the "paradedb" preset, this specifies the ParadeDB extension version
|
|
14
|
+
* (e.g., "0.22.5" or "0.22.5-pg17"). The PG suffix, if present, is validated
|
|
15
|
+
* against the installed embedded-postgres version.
|
|
16
|
+
*
|
|
17
|
+
* For the "postgres" preset, this is ignored — the PostgreSQL version is
|
|
18
|
+
* determined by the installed `embedded-postgres` npm package version.
|
|
19
|
+
*
|
|
20
|
+
* Ignored when `image` is provided (Docker fallback).
|
|
14
21
|
*/
|
|
15
22
|
version?: string;
|
|
16
23
|
/**
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* and paradedb/paradedb:0.22.3-pg17 for the ParadeDB preset.
|
|
20
|
-
* Takes precedence over version when both are provided.
|
|
24
|
+
* @deprecated Docker images are no longer used. This option is ignored.
|
|
25
|
+
* The PostgreSQL version is determined by the `embedded-postgres` npm package.
|
|
21
26
|
*/
|
|
22
27
|
image?: string;
|
|
23
|
-
/** Database name created inside the
|
|
28
|
+
/** Database name created inside the instance. Defaults to "testdb". */
|
|
24
29
|
database?: string;
|
|
25
|
-
/** Username for the test database. Defaults to testuser. */
|
|
30
|
+
/** Username for the test database. Defaults to "testuser". */
|
|
26
31
|
username?: string;
|
|
27
|
-
/** Password for the test database. Defaults to testpassword. */
|
|
32
|
+
/** Password for the test database. Defaults to "testpassword". */
|
|
28
33
|
password?: string;
|
|
29
34
|
/**
|
|
30
|
-
* Extensions to create after the
|
|
35
|
+
* Extensions to create after the server starts.
|
|
31
36
|
* Each entry becomes CREATE EXTENSION IF NOT EXISTS <name>.
|
|
37
|
+
*
|
|
38
|
+
* For the "paradedb" preset, defaults to ["pg_search"].
|
|
39
|
+
* Note: pgvector ("vector") is not bundled — install it separately if needed.
|
|
32
40
|
*/
|
|
33
41
|
extensions?: string[];
|
|
34
|
-
/** Additional SQL statements to run after the
|
|
42
|
+
/** Additional SQL statements to run after the server starts. */
|
|
35
43
|
initSql?: string[];
|
|
36
44
|
}
|
|
37
45
|
interface NormalizedPostgresMemoryServerOptions {
|
|
38
46
|
preset: PostgresMemoryServerPreset;
|
|
39
47
|
version?: string;
|
|
48
|
+
/** Descriptive label (e.g., "postgres:18" or "paradedb:0.22.5-pg18"). */
|
|
40
49
|
image: string;
|
|
41
50
|
database: string;
|
|
42
51
|
username: string;
|
|
@@ -56,10 +65,13 @@ type QueryText<Row extends QueryResultRow = QueryResultRow> = string | QueryConf
|
|
|
56
65
|
type QueryResponse<Row extends QueryResultRow = QueryResultRow> = QueryResult<Row>;
|
|
57
66
|
|
|
58
67
|
declare class PostgresMemoryServer {
|
|
59
|
-
private readonly
|
|
68
|
+
private readonly pg;
|
|
69
|
+
private readonly port;
|
|
70
|
+
private readonly dataDir;
|
|
60
71
|
private readonly options;
|
|
61
72
|
private stopped;
|
|
62
73
|
private readonly snapshotSupported;
|
|
74
|
+
private hasSnapshot;
|
|
63
75
|
private constructor();
|
|
64
76
|
static create(options?: PostgresMemoryServerOptions): Promise<PostgresMemoryServer>;
|
|
65
77
|
static createPostgres(options?: Omit<PostgresMemoryServerOptions, "preset">): Promise<PostgresMemoryServer>;
|
|
@@ -77,9 +89,22 @@ declare class PostgresMemoryServer {
|
|
|
77
89
|
runSql(sql: string | string[]): Promise<void>;
|
|
78
90
|
runSqlFile(filePath: string): Promise<void>;
|
|
79
91
|
runMigrationsDir(dirPath: string): Promise<string[]>;
|
|
92
|
+
/**
|
|
93
|
+
* Create a snapshot of the current database state.
|
|
94
|
+
* Uses PostgreSQL template databases for fast, native snapshots.
|
|
95
|
+
*/
|
|
80
96
|
snapshot(): Promise<void>;
|
|
97
|
+
/**
|
|
98
|
+
* Restore the database to the last snapshot.
|
|
99
|
+
* Drops and recreates the database from the snapshot template.
|
|
100
|
+
*/
|
|
81
101
|
restore(): Promise<void>;
|
|
82
102
|
stop(): Promise<void>;
|
|
103
|
+
/**
|
|
104
|
+
* Connect to the "postgres" system database for admin operations
|
|
105
|
+
* (snapshot, restore, etc.).
|
|
106
|
+
*/
|
|
107
|
+
private withAdminClient;
|
|
83
108
|
private ensureRunning;
|
|
84
109
|
private ensureSnapshotSupported;
|
|
85
110
|
}
|
|
@@ -96,12 +121,15 @@ interface JestGlobalTeardownOptions {
|
|
|
96
121
|
declare function createJestGlobalSetup(options?: JestGlobalSetupOptions): () => Promise<void>;
|
|
97
122
|
declare function createJestGlobalTeardown(options?: JestGlobalTeardownOptions): () => Promise<void>;
|
|
98
123
|
|
|
99
|
-
declare const
|
|
100
|
-
declare const
|
|
101
|
-
declare const
|
|
102
|
-
|
|
124
|
+
declare const DEFAULT_PARADEDB_EXT_VERSION = "0.22.5";
|
|
125
|
+
declare const DEFAULT_POSTGRES_VERSION: string;
|
|
126
|
+
declare const DEFAULT_PARADEDB_VERSION: string;
|
|
127
|
+
/** Descriptive label for the postgres preset. */
|
|
103
128
|
declare const DEFAULT_POSTGRES_IMAGE: string;
|
|
129
|
+
/** Descriptive label for the paradedb preset. */
|
|
104
130
|
declare const DEFAULT_PARADEDB_IMAGE: string;
|
|
131
|
+
declare const POSTGRES_IMAGE_REPOSITORY = "postgres";
|
|
132
|
+
declare const PARADEDB_IMAGE_REPOSITORY = "paradedb";
|
|
105
133
|
declare function normalizeOptions(options?: PostgresMemoryServerOptions): NormalizedPostgresMemoryServerOptions;
|
|
106
134
|
declare function getImageForVersion(preset: PostgresMemoryServerPreset, version: string): string;
|
|
107
135
|
declare function getDefaultImage(preset: PostgresMemoryServerPreset): string;
|
|
@@ -117,5 +145,8 @@ declare class SnapshotUnsupportedError extends PostgresMemoryServerError {
|
|
|
117
145
|
declare class ServerStoppedError extends PostgresMemoryServerError {
|
|
118
146
|
constructor();
|
|
119
147
|
}
|
|
148
|
+
declare class ExtensionInstallError extends PostgresMemoryServerError {
|
|
149
|
+
constructor(extensionName: string, cause?: Error);
|
|
150
|
+
}
|
|
120
151
|
|
|
121
|
-
export { DEFAULT_JEST_ENV_VAR_NAME, DEFAULT_JEST_STATE_FILE, DEFAULT_PARADEDB_IMAGE, DEFAULT_PARADEDB_VERSION, DEFAULT_POSTGRES_IMAGE, DEFAULT_POSTGRES_VERSION, type JestGlobalSetupOptions, type JestGlobalTeardownOptions, type NormalizedPostgresMemoryServerOptions, PARADEDB_IMAGE_REPOSITORY, POSTGRES_IMAGE_REPOSITORY, type PostgresConnectionOptions, PostgresMemoryServer, PostgresMemoryServerError, type PostgresMemoryServerOptions, type PostgresMemoryServerPreset, type QueryResponse, type QueryText, ServerStoppedError, SnapshotUnsupportedError, buildInitStatements, createJestGlobalSetup, createJestGlobalTeardown, getDefaultExtensions, getDefaultImage, getImageForVersion, normalizeOptions };
|
|
152
|
+
export { DEFAULT_JEST_ENV_VAR_NAME, DEFAULT_JEST_STATE_FILE, DEFAULT_PARADEDB_EXT_VERSION, DEFAULT_PARADEDB_IMAGE, DEFAULT_PARADEDB_VERSION, DEFAULT_POSTGRES_IMAGE, DEFAULT_POSTGRES_VERSION, ExtensionInstallError, type JestGlobalSetupOptions, type JestGlobalTeardownOptions, type NormalizedPostgresMemoryServerOptions, PARADEDB_IMAGE_REPOSITORY, POSTGRES_IMAGE_REPOSITORY, type PostgresConnectionOptions, PostgresMemoryServer, PostgresMemoryServerError, type PostgresMemoryServerOptions, type PostgresMemoryServerPreset, type QueryResponse, type QueryText, ServerStoppedError, SnapshotUnsupportedError, buildInitStatements, createJestGlobalSetup, createJestGlobalTeardown, getDefaultExtensions, getDefaultImage, getImageForVersion, normalizeOptions };
|