diff --git a/README.md b/README.md index 20e3127..67ec42d 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ npm install pgstrap --save-dev - `npm run db:migrate` - Run pending migrations - `npm run db:reset` - Drop and recreate the database, then run all migrations -- `npm run db:generate` - Generate types and structure dumps. Use `pgstrap generate --pglite` to run migrations against an in-memory PGlite instance. +- `npm run db:generate` - Generate types and structure dumps using an in-memory PGlite instance (no background Postgres required). Use `pgstrap generate --no-pglite` to run against an external Postgres database. - `npm run db:create-migration` - Create a new migration file ### Configuration diff --git a/bun.lock b/bun.lock index 83407d9..e43bb07 100644 --- a/bun.lock +++ b/bun.lock @@ -1,5 +1,6 @@ { "lockfileVersion": 1, + "configVersion": 0, "workspaces": { "": { "name": "pgstrap", diff --git a/src/cli.ts b/src/cli.ts index 9a9bdec..d713776 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -2,7 +2,12 @@ import yargs from "yargs" import { migrate, reset, generate, createMigration, initPgstrap } from "./" import { getProjectContext } from "./get-project-context" -;(yargs as any) +const cli = + typeof (yargs as any) === "function" + ? (yargs as any)(process.argv.slice(2)) + : yargs + +cli .command("init", "initialize pgstrap", {}, async () => { await initPgstrap({ cwd: process.cwd(), @@ -35,10 +40,13 @@ import { getProjectContext } from "./get-project-context" "generate", "generate types and sql documentation from database", (yargs) => { - yargs.option("pglite", { type: "boolean", default: false }) + yargs.option("pglite", { type: "boolean", default: true }) }, async (argv) => { - generate({ ...(await getProjectContext()), pglite: !!argv.pglite }) + generate({ + ...(await getProjectContext()), + pglite: argv.pglite !== false, + }) }, ) .parse() diff --git a/src/generate.ts b/src/generate.ts index f337094..09294e8 100644 --- a/src/generate.ts +++ b/src/generate.ts @@ -12,7 +12,7 @@ export const generate = async ({ schemas, defaultDatabase, dbDir, - pglite = false, + pglite = true, migrationsDir, }: Pick & { pglite?: boolean diff --git a/tests/cli.test.ts b/tests/cli.test.ts new file mode 100644 index 0000000..909a76c --- /dev/null +++ b/tests/cli.test.ts @@ -0,0 +1,57 @@ +import { test, expect } from "bun:test" +import fs from "fs" +import os from "os" +import path from "path" +import { execSync } from "child_process" + +const migrationFile = ` +exports.up = async (pgm) => { + pgm.createTable('cli_test_table', { id: 'id' }) +} +exports.down = async (pgm) => { + pgm.dropTable('cli_test_table') +} +` + +test("cli generate runs with pglite by default without postgres", async () => { + const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "pgstrap-cli-test-")) + const dbDir = path.join(tmp, "src", "db") + const migrationsDir = path.join(dbDir, "migrations") + fs.mkdirSync(migrationsDir, { recursive: true }) + fs.writeFileSync(path.join(migrationsDir, "001_cli_table.js"), migrationFile) + fs.writeFileSync( + path.join(tmp, "package.json"), + JSON.stringify({ name: "cli-test-pkg" }), + ) + fs.writeFileSync( + path.join(tmp, "pgstrap.config.js"), + `module.exports = { defaultDatabase: "test_db", schemas: ["public"] }`, + ) + + const cliPath = path.resolve(__dirname, "../src/cli.ts") + + // Run cli generate using bun without --pglite argument (relying on default: true) + execSync(`bun ${cliPath} generate`, { + cwd: tmp, + env: { + ...process.env, + // Ensure no DATABASE_URL is pointing to a live DB + DATABASE_URL: "", + }, + stdio: "pipe", + }) + + const zapatosFile = path.join(dbDir, "zapatos", "schema.d.ts") + const structureDir = path.join( + dbDir, + "structure", + "public", + "tables", + "cli_test_table", + ) + + expect(fs.existsSync(zapatosFile)).toBe(true) + expect(fs.existsSync(path.join(structureDir, "table.sql"))).toBe(true) + + fs.rmSync(tmp, { recursive: true, force: true }) +}, 30000) diff --git a/tests/generate.pglite.test.ts b/tests/generate.pglite.test.ts index 56dcd53..9b30f90 100644 --- a/tests/generate.pglite.test.ts +++ b/tests/generate.pglite.test.ts @@ -44,4 +44,39 @@ test("generate with pglite runs migrations and dumps structure", async () => { expect(fs.existsSync(path.join(structureDir, "table.sql"))).toBe(true) fs.rmSync(tmp, { recursive: true, force: true }) -}) +}, 30000) + +test("generate defaults to pglite without requiring external postgres", async () => { + const tmp = fs.mkdtempSync( + path.join(os.tmpdir(), "pgstrap-generate-default-"), + ) + const migrationsDir = path.join(tmp, "migrations") + fs.mkdirSync(migrationsDir, { recursive: true }) + fs.writeFileSync( + path.join(migrationsDir, "001_create_table.js"), + migrationFile, + ) + + // Call generate without passing `pglite` option - should default to true + await generate({ + schemas: ["public"], + defaultDatabase: "postgres", + dbDir: path.join(tmp, "db"), + migrationsDir, + }) + + const zapatosFile = path.join(tmp, "db", "zapatos", "schema.d.ts") + const structureDir = path.join( + tmp, + "db", + "structure", + "public", + "tables", + "foo", + ) + + expect(fs.existsSync(zapatosFile)).toBe(true) + expect(fs.existsSync(path.join(structureDir, "table.sql"))).toBe(true) + + fs.rmSync(tmp, { recursive: true, force: true }) +}, 30000) diff --git a/tests/pglite.test.ts b/tests/pglite.test.ts index 2fbc8bc..a1b0966 100644 --- a/tests/pglite.test.ts +++ b/tests/pglite.test.ts @@ -48,4 +48,4 @@ test("migration of a pglite db works", async () => { // Clean up fs.rmSync(migrationsDir, { recursive: true, force: true }) -}) +}, 30000)