pg-here 0.1.3 → 0.1.5

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 CHANGED
@@ -31,7 +31,27 @@ If you have Bun installed, you can run the published package directly:
31
31
  bunx pg-here
32
32
  ```
33
33
 
34
- If this command currently fails with `could not determine executable to run for package`, you’re using a release that was published before the CLI binary was exposed. It will work after the next publish.
34
+ This is the single command you want from any directory.
35
+
36
+ If it still resolves an older release, the package `latest` dist-tag is behind:
37
+
38
+ To force that version and bypass a stale cache:
39
+
40
+ ```bash
41
+ bunx pg-here@0.1.5
42
+ ```
43
+
44
+ If maintainers want plain `bunx pg-here` to work for everyone, run once:
45
+
46
+ ```bash
47
+ npm dist-tag add pg-here@0.1.5 latest
48
+ ```
49
+
50
+ After that, this should work anywhere:
51
+
52
+ ```bash
53
+ bunx pg-here
54
+ ```
35
55
 
36
56
  This starts a local PostgreSQL instance in your current project directory and prints the connection string, then keeps the process alive until you stop it.
37
57
 
@@ -49,6 +69,27 @@ Pass CLI flags just like the local script when you want to override defaults:
49
69
  bunx pg-here --username postgres --password postgres --database my_app --port 55432
50
70
  ```
51
71
 
72
+ #### Linux note
73
+
74
+ If `bunx pg-here` fails with `error while loading shared libraries`:
75
+ - install missing system packages on the host (not in npm), then retry
76
+ - restart the command
77
+
78
+ Most commonly:
79
+
80
+ ```bash
81
+ # Ubuntu/Debian
82
+ sudo apt-get update && sudo apt-get install -y libxml2
83
+
84
+ # Fedora/RHEL
85
+ sudo dnf install -y libxml2
86
+
87
+ # Alpine
88
+ sudo apk add libxml2
89
+ ```
90
+
91
+ If that machine is intentionally minimal (or containerized), use an image with PostgreSQL runtime dependencies.
92
+
52
93
  ### Programmatic usage
53
94
 
54
95
  Use `pg-here` directly from your server startup code and auto-create the app database if missing.
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env node
2
+
3
+ import yargs from "yargs";
4
+ import { hideBin } from "yargs/helpers";
5
+ import { startPgHere } from "../dist/index.js";
6
+ import { maybePrintLinuxRuntimeHelp } from "../scripts/cli-error-help.mjs";
7
+
8
+ const argv = await yargs(hideBin(process.argv))
9
+ .version(false)
10
+ .option("username", {
11
+ alias: "u",
12
+ default: "postgres",
13
+ describe: "PostgreSQL username",
14
+ })
15
+ .option("password", {
16
+ alias: "p",
17
+ default: "postgres",
18
+ describe: "PostgreSQL password",
19
+ })
20
+ .option("port", {
21
+ default: 55432,
22
+ describe: "PostgreSQL port",
23
+ })
24
+ .option("database", {
25
+ alias: "d",
26
+ default: "postgres",
27
+ describe: "Database to use (created automatically if missing)",
28
+ })
29
+ .option("pg-version", {
30
+ default: process.env.PG_VERSION,
31
+ describe: "PostgreSQL version (e.g. 18.0.0 or >=17.0)",
32
+ })
33
+ .parse();
34
+
35
+ let pg;
36
+ try {
37
+ pg = await startPgHere({
38
+ projectDir: process.cwd(),
39
+ port: argv.port,
40
+ username: argv.username,
41
+ password: argv.password,
42
+ database: argv.database,
43
+ postgresVersion: argv["pg-version"],
44
+ });
45
+ } catch (error) {
46
+ if (process.platform === "linux") {
47
+ maybePrintLinuxRuntimeHelp(error);
48
+ }
49
+ throw error;
50
+ }
51
+
52
+ console.log(pg.databaseConnectionString);
53
+ setInterval(() => {}, 1 << 30);
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "pg-here",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "Per-project embedded PostgreSQL with programmatic startup and auto DB creation.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",
8
8
  "bin": {
9
- "pg-here": "scripts/pg-dev.mjs"
9
+ "pg-here": "bin/pg-here.mjs"
10
10
  },
11
11
  "exports": {
12
12
  ".": {
@@ -17,7 +17,9 @@
17
17
  "files": [
18
18
  "dist",
19
19
  "index.ts",
20
+ "bin/pg-here.mjs",
20
21
  "scripts/pg-dev.mjs",
22
+ "scripts/cli-error-help.mjs",
21
23
  "README.md"
22
24
  ],
23
25
  "private": false,
@@ -0,0 +1,57 @@
1
+ import { spawnSync } from "node:child_process";
2
+
3
+ const LIBXML_LIBRARY = /libxml2\.so\.2/;
4
+
5
+ export function maybePrintLinuxRuntimeHelp(error) {
6
+ const message = String(error?.message ?? error);
7
+ const missingLibsFromError = extractMissingLibrariesFromMessage(message);
8
+ const missingLibsFromBinary = extractMissingLibrariesFromBinaryPath(message);
9
+
10
+ const missingLibs = [...new Set([...missingLibsFromError, ...missingLibsFromBinary])];
11
+
12
+ if (missingLibs.length === 0) {
13
+ return;
14
+ }
15
+
16
+ console.error();
17
+ console.error("PostgreSQL startup failed due to missing Linux runtime dependencies.");
18
+ console.error(`Missing libraries: ${missingLibs.join(", ")}`);
19
+ console.error();
20
+ console.error("Install system packages for your distro and retry:");
21
+ console.error(" Ubuntu/Debian: sudo apt-get update && sudo apt-get install -y libxml2");
22
+ console.error(" Fedora/RHEL: sudo dnf install -y libxml2");
23
+ console.error(" Alpine: sudo apk add libxml2");
24
+ console.error(
25
+ `If your distro requires different package names, install packages that provide: ${missingLibs.join(
26
+ ", "
27
+ )}`
28
+ );
29
+
30
+ if (LIBXML_LIBRARY.test(message)) {
31
+ console.error("Hint: this project does not ship all optional shared objects in every Linux image.");
32
+ }
33
+ }
34
+
35
+ function extractMissingLibrariesFromMessage(message) {
36
+ const regex = /([A-Za-z0-9._-]+\.so(?:\.\d+)*)\b/g;
37
+ const matches = [...message.matchAll(regex)].map((match) => match[1]);
38
+ return matches.filter((value) => value.toLowerCase().includes("so"));
39
+ }
40
+
41
+ function extractMissingLibrariesFromBinaryPath(message) {
42
+ const pathMatch = message.match(/(\/[^\s"]*\/bin\/postgres)/);
43
+ if (!pathMatch) {
44
+ return [];
45
+ }
46
+
47
+ const binaryPath = pathMatch[1];
48
+ const result = spawnSync("ldd", [binaryPath], { encoding: "utf8" });
49
+ const output = `${result.stdout ?? ""} ${result.stderr ?? ""}`;
50
+ if (!output) {
51
+ return [];
52
+ }
53
+
54
+ return [...output.matchAll(/([^\s]+)\s+=>\s+not found/g)].map(
55
+ (match) => match[1]
56
+ );
57
+ }
@@ -1,6 +1,7 @@
1
1
  import yargs from "yargs";
2
2
  import { hideBin } from "yargs/helpers";
3
3
  import { startPgHere } from "../index.ts";
4
+ import { maybePrintLinuxRuntimeHelp } from "./cli-error-help.mjs";
4
5
 
5
6
  const argv = await yargs(hideBin(process.argv))
6
7
  .version(false)
@@ -29,14 +30,22 @@ const argv = await yargs(hideBin(process.argv))
29
30
  })
30
31
  .parse();
31
32
 
32
- const pg = await startPgHere({
33
- projectDir: process.cwd(),
34
- port: argv.port,
35
- username: argv.username,
36
- password: argv.password,
37
- database: argv.database,
38
- postgresVersion: argv["pg-version"],
39
- });
33
+ let pg;
34
+ try {
35
+ pg = await startPgHere({
36
+ projectDir: process.cwd(),
37
+ port: argv.port,
38
+ username: argv.username,
39
+ password: argv.password,
40
+ database: argv.database,
41
+ postgresVersion: argv["pg-version"],
42
+ });
43
+ } catch (error) {
44
+ if (process.platform === "linux") {
45
+ maybePrintLinuxRuntimeHelp(error);
46
+ }
47
+ throw error;
48
+ }
40
49
 
41
50
  // print connection string for tooling
42
51
  console.log(pg.databaseConnectionString);