Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 11 additions & 3 deletions src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down Expand Up @@ -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()
2 changes: 1 addition & 1 deletion src/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export const generate = async ({
schemas,
defaultDatabase,
dbDir,
pglite = false,
pglite = true,
migrationsDir,
}: Pick<Context, "schemas" | "defaultDatabase" | "dbDir"> & {
pglite?: boolean
Expand Down
57 changes: 57 additions & 0 deletions tests/cli.test.ts
Original file line number Diff line number Diff line change
@@ -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)
37 changes: 36 additions & 1 deletion tests/generate.pglite.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
2 changes: 1 addition & 1 deletion tests/pglite.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,4 @@ test("migration of a pglite db works", async () => {

// Clean up
fs.rmSync(migrationsDir, { recursive: true, force: true })
})
}, 30000)