@shivaedev/local-postgres 0.1.0 → 0.1.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.1 - 2026-10-04
4
+
5
+ ### Changed
6
+
7
+ - Imports that leave their folder go through `#` aliases declared in the `imports` field of `package.json`: `#*.ts` resolves to `src` under the `source` condition and to `dist` otherwise, and `#test/*` names a test file. The published modules and declarations name the package's own files through these aliases.
8
+
9
+ - Build with the `@shivaedev/quality` tsconfig presets, which target ESNext and allow only erasable TypeScript syntax.
10
+
11
+ - Type-check with TypeScript 7 only. TypeScript 6 still builds the package.
12
+
13
+ - Lint and format with the `@shivaedev/quality` Biome preset through `quality lint` at the repository root, which replaces the package's `check` script.
14
+
15
+ - Run tests through the `@shivaedev/quality` Vitest projects, which take a test's environment from its file name. Type tests are named `*.typecheck.test.ts`.
16
+
17
+ - Keep `package.json` in sort-package-json key order, checked by `quality lint`.
18
+
3
19
  ## 0.1.0
4
20
 
5
21
  - Prepare one persistent local PostgreSQL 18.6 service and create missing databases without resetting existing data.
package/dist/index.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  import { type DockerEnvironment } from "./local-docker.ts";
2
2
  export declare const localServer = "postgresql://postgres:postgres@127.0.0.1:55432";
3
- export declare function assertLocalDatabase(value: string, names: readonly string[]): URL;
3
+ export declare function assertLocalDatabase(value: string, names: readonly string[]): import("url").URL;
4
4
  export declare function localPostgres(environment: DockerEnvironment): {
5
+ prepareDatabases: (values: readonly string[]) => void;
5
6
  sql: (value: string | URL, query: string) => string;
6
7
  startPostgres: (connection?: string) => void;
7
- prepareDatabases: (values: readonly string[]) => void;
8
8
  };
9
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,iBAAiB,EAAU,MAAM,mBAAmB,CAAC;AAEnE,eAAO,MAAM,WAAW,mDAAmD,CAAC;AAE5E,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,OAY1E;AAED,wBAAgB,aAAa,CAAC,WAAW,EAAE,iBAAiB;iBAGvC,MAAM,GAAG,GAAG,SAAS,MAAM;;+BAsCb,SAAS,MAAM,EAAE;EAgBnD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,iBAAiB,EAAU,MAAM,mBAAmB,CAAC;AAEnE,eAAO,MAAM,WAAW,mDAAmD,CAAC;AAE5E,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,qBAY1E;AAED,wBAAgB,aAAa,CAAC,WAAW,EAAE,iBAAiB;+BAgDzB,SAAS,MAAM,EAAE;iBA7C/B,MAAM,GAAG,GAAG,SAAS,MAAM;;EAiE/C"}
package/dist/index.js CHANGED
@@ -5,12 +5,12 @@ export const localServer = "postgresql://postgres:postgres@127.0.0.1:55432";
5
5
  export function assertLocalDatabase(value, names) {
6
6
  const url = new URL(value);
7
7
  const name = url.pathname.slice(1);
8
- if (!["postgres:", "postgresql:"].includes(url.protocol) ||
9
- !["localhost", "127.0.0.1"].includes(url.hostname) ||
10
- url.port !== "55432" ||
11
- ["host", "hostaddr", "port", "dbname", "service"].some((key) => url.searchParams.has(key)) ||
12
- !names.includes(name))
8
+ if (!(["postgres:", "postgresql:"].includes(url.protocol) && ["localhost", "127.0.0.1"].includes(url.hostname))
9
+ || url.port !== "55432"
10
+ || ["host", "hostaddr", "port", "dbname", "service"].some((key) => url.searchParams.has(key))
11
+ || !names.includes(name)) {
13
12
  throw new Error(`Use a local database on 127.0.0.1:55432 named ${names.join(" or ")}.`);
13
+ }
14
14
  return url;
15
15
  }
16
16
  export function localPostgres(environment) {
@@ -18,18 +18,21 @@ export function localPostgres(environment) {
18
18
  function sql(value, query) {
19
19
  const url = new URL(value);
20
20
  assertLocalDatabase(url.toString(), [url.pathname.slice(1)]);
21
- for (const key of ["schema", "connection_limit", "pool_timeout", "pgbouncer"])
21
+ for (const key of ["schema", "connection_limit", "pool_timeout", "pgbouncer"]) {
22
22
  url.searchParams.delete(key);
23
+ }
23
24
  const args = ["-X", "--set", "ON_ERROR_STOP=1", "-At", "-c", query];
24
- if (!url.searchParams.has("connect_timeout"))
25
+ if (!url.searchParams.has("connect_timeout")) {
25
26
  url.searchParams.set("connect_timeout", "3");
27
+ }
26
28
  const options = { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] };
27
29
  try {
28
30
  return execFileSync("psql", [...args, "--dbname", String(url)], options).trim();
29
31
  }
30
32
  catch (error) {
31
- if (!(error instanceof Error && "code" in error && error.code === "ENOENT"))
33
+ if (!(error instanceof Error && "code" in error && error.code === "ENOENT")) {
32
34
  throw new Error(error instanceof Error && "stderr" in error ? String(error.stderr) : "PostgreSQL query failed.");
35
+ }
33
36
  return sqlInContainer(localDocker, url, args, options);
34
37
  }
35
38
  }
@@ -53,15 +56,17 @@ export function localPostgres(environment) {
53
56
  }
54
57
  }
55
58
  }
56
- if (version !== "18.6")
59
+ if (version !== "18.6") {
57
60
  throw new Error("Expected local PostgreSQL 18.6. Check the existing service; setup never removes containers or data.");
61
+ }
58
62
  }
59
63
  function prepareDatabases(values) {
60
64
  for (const value of values) {
61
65
  const name = new URL(value).pathname.slice(1);
62
66
  assertLocalDatabase(value, [name]);
63
- if (!/^[a-z][a-z0-9_]{0,62}$/.test(name))
67
+ if (!/^[a-z][a-z0-9_]{0,62}$/u.test(name)) {
64
68
  throw new Error("Invalid local database name.");
69
+ }
65
70
  }
66
71
  startPostgres(values[0]);
67
72
  for (const value of values) {
@@ -69,10 +74,11 @@ export function localPostgres(environment) {
69
74
  const name = url.pathname.slice(1);
70
75
  const server = new URL(url);
71
76
  server.pathname = "/postgres";
72
- if (!sql(server, `SELECT 1 FROM pg_database WHERE datname = '${name}'`))
77
+ if (!sql(server, `SELECT 1 FROM pg_database WHERE datname = '${name}'`)) {
73
78
  sql(server, `CREATE DATABASE "${name}"`);
79
+ }
74
80
  }
75
81
  }
76
- return { sql, startPostgres, prepareDatabases };
82
+ return { prepareDatabases, sql, startPostgres };
77
83
  }
78
84
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"local-container.d.ts","sourceRoot":"","sources":["../src/local-container.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qCAAqC,EAAE,MAAM,oBAAoB,CAAC;AAIhF,KAAK,MAAM,GAAG,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,qCAAqC,KAAK,MAAM,CAAC;AAEnG,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,OAAO,EAAE,qCAAqC,UAS/H;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,QA4B5C"}
1
+ {"version":3,"file":"local-container.d.ts","sourceRoot":"","sources":["../src/local-container.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qCAAqC,EAAE,MAAM,oBAAoB,CAAC;AAIhF,KAAK,MAAM,GAAG,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,qCAAqC,KAAK,MAAM,CAAC;AAEnG,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,OAAO,EAAE,qCAAqC,UAY/H;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,QA6B5C"}
@@ -2,10 +2,12 @@ const image = "postgres:18.6-alpine@sha256:77f585114c32fbca283dc835b0596f4e52b51
2
2
  const container = "development-postgres";
3
3
  export function sqlInContainer(docker, url, args, options) {
4
4
  const id = docker(["ps", "--filter", "publish=55432", "--format", "{{.ID}}"], options).trim();
5
- if (!id || id.includes("\n"))
5
+ if (!id || id.includes("\n")) {
6
6
  throw new Error("Install psql or start the shared PostgreSQL service with Docker.");
7
- if (docker(["inspect", "--format", "{{.Config.Image}}", id], options).trim() !== image)
7
+ }
8
+ if (docker(["inspect", "--format", "{{.Config.Image}}", id], options).trim() !== image) {
8
9
  throw new Error("The shared PostgreSQL image differs from the pinned baseline. Upgrade explicitly, preserving data.");
10
+ }
9
11
  const inside = new URL(url);
10
12
  inside.hostname = "127.0.0.1";
11
13
  inside.port = "5432";
@@ -20,8 +22,9 @@ export function startContainer(docker) {
20
22
  }
21
23
  catch { }
22
24
  if (existing) {
23
- if (docker(["inspect", "--format", "{{.Config.Image}}", container]).trim() !== image)
25
+ if (docker(["inspect", "--format", "{{.Config.Image}}", container]).trim() !== image) {
24
26
  throw new Error("The shared PostgreSQL container uses a different image. Preserve its volume and upgrade it explicitly.");
27
+ }
25
28
  docker(["start", container]);
26
29
  }
27
30
  else {
@@ -1 +1 @@
1
- {"version":3,"file":"local-container.js","sourceRoot":"","sources":["../src/local-container.ts"],"names":[],"mappings":"AAEA,MAAM,KAAK,GAAG,8FAA8F,CAAC;AAC7G,MAAM,SAAS,GAAG,sBAAsB,CAAC;AAGzC,MAAM,UAAU,cAAc,CAAC,MAAc,EAAE,GAAQ,EAAE,IAAuB,EAAE,OAA8C;IAC/H,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,IAAI,EAAE,UAAU,EAAE,eAAe,EAAE,UAAU,EAAE,SAAS,CAAC,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;IAC9F,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,kEAAkE,CAAC,CAAC;IAClH,IAAI,MAAM,CAAC,CAAC,SAAS,EAAE,UAAU,EAAE,mBAAmB,EAAE,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,KAAK;QACrF,MAAM,IAAI,KAAK,CAAC,oGAAoG,CAAC,CAAC;IACvH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IAC5B,MAAM,CAAC,QAAQ,GAAG,WAAW,CAAC;IAC9B,MAAM,CAAC,IAAI,GAAG,MAAM,CAAC;IACrB,OAAO,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,UAAU,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;AAC7F,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAc;IAC5C,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;IACjB,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,IAAI,CAAC;QACJ,MAAM,CAAC,CAAC,WAAW,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC;QAC5C,QAAQ,GAAG,IAAI,CAAC;IACjB,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;IACV,IAAI,QAAQ,EAAE,CAAC;QACd,IAAI,MAAM,CAAC,CAAC,SAAS,EAAE,UAAU,EAAE,mBAAmB,EAAE,SAAS,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,KAAK;YACnF,MAAM,IAAI,KAAK,CAAC,wGAAwG,CAAC,CAAC;QAC3H,MAAM,CAAC,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC;IAC9B,CAAC;SAAM,CAAC;QACP,MAAM,CAAC;YACN,KAAK;YACL,UAAU;YACV,QAAQ;YACR,SAAS;YACT,WAAW;YACX,sBAAsB;YACtB,OAAO;YACP,wBAAwB;YACxB,OAAO;YACP,4BAA4B;YAC5B,SAAS;YACT,8DAA8D;YAC9D,KAAK;SACL,CAAC,CAAC;IACJ,CAAC;AACF,CAAC"}
1
+ {"version":3,"file":"local-container.js","sourceRoot":"","sources":["../src/local-container.ts"],"names":[],"mappings":"AAEA,MAAM,KAAK,GAAG,8FAA8F,CAAC;AAC7G,MAAM,SAAS,GAAG,sBAAsB,CAAC;AAGzC,MAAM,UAAU,cAAc,CAAC,MAAc,EAAE,GAAQ,EAAE,IAAuB,EAAE,OAA8C;IAC/H,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,IAAI,EAAE,UAAU,EAAE,eAAe,EAAE,UAAU,EAAE,SAAS,CAAC,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;IAC9F,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,kEAAkE,CAAC,CAAC;IACrF,CAAC;IACD,IAAI,MAAM,CAAC,CAAC,SAAS,EAAE,UAAU,EAAE,mBAAmB,EAAE,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,KAAK,EAAE,CAAC;QACxF,MAAM,IAAI,KAAK,CAAC,oGAAoG,CAAC,CAAC;IACvH,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IAC5B,MAAM,CAAC,QAAQ,GAAG,WAAW,CAAC;IAC9B,MAAM,CAAC,IAAI,GAAG,MAAM,CAAC;IACrB,OAAO,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,UAAU,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;AAC7F,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAc;IAC5C,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;IACjB,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,IAAI,CAAC;QACJ,MAAM,CAAC,CAAC,WAAW,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC;QAC5C,QAAQ,GAAG,IAAI,CAAC;IACjB,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;IACV,IAAI,QAAQ,EAAE,CAAC;QACd,IAAI,MAAM,CAAC,CAAC,SAAS,EAAE,UAAU,EAAE,mBAAmB,EAAE,SAAS,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,KAAK,EAAE,CAAC;YACtF,MAAM,IAAI,KAAK,CAAC,wGAAwG,CAAC,CAAC;QAC3H,CAAC;QACD,MAAM,CAAC,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC;IAC9B,CAAC;SAAM,CAAC;QACP,MAAM,CAAC;YACN,KAAK;YACL,UAAU;YACV,QAAQ;YACR,SAAS;YACT,WAAW;YACX,sBAAsB;YACtB,OAAO;YACP,wBAAwB;YACxB,OAAO;YACP,4BAA4B;YAC5B,SAAS;YACT,8DAA8D;YAC9D,KAAK;SACL,CAAC,CAAC;IACJ,CAAC;AACF,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"local-docker.d.ts","sourceRoot":"","sources":["../src/local-docker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,qCAAqC,EAAgB,MAAM,oBAAoB,CAAC;AAE9F,MAAM,MAAM,iBAAiB,GAAG,QAAQ,CAAC;IAAE,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAC,CAAC;AAEpH,wBAAgB,MAAM,CACrB,WAAW,EAAE,iBAAiB,EAC9B,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,OAAO,GAAE,qCAA4D,UAgBrE"}
1
+ {"version":3,"file":"local-docker.d.ts","sourceRoot":"","sources":["../src/local-docker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,qCAAqC,EAAgB,MAAM,oBAAoB,CAAC;AAE9F,MAAM,MAAM,iBAAiB,GAAG,QAAQ,CAAC;IAAE,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAC,CAAC;AAEpH,wBAAgB,MAAM,CACrB,WAAW,EAAE,iBAAiB,EAC9B,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,OAAO,GAAE,qCAA4D,UAmBrE"}
@@ -2,14 +2,15 @@ import { execFileSync } from "node:child_process";
2
2
  export function docker(environment, args, options = { encoding: "utf8" }) {
3
3
  const context = environment.DOCKER_CONTEXT;
4
4
  const host = environment.DOCKER_HOST;
5
- const endpoint = (!context && host) ||
6
- execFileSync("docker", ["context", "inspect", ...(context ? [context] : []), "--format", "{{.Endpoints.docker.Host}}"], {
5
+ const endpoint = (!context && host)
6
+ || execFileSync("docker", ["context", "inspect", ...(context ? [context] : []), "--format", "{{.Endpoints.docker.Host}}"], {
7
7
  encoding: "utf8",
8
8
  }).trim();
9
9
  const url = new URL(endpoint);
10
- if (!(["unix:", "npipe:"].includes(url.protocol) && ["", "localhost"].includes(url.hostname)) &&
11
- !(url.protocol === "tcp:" && ["localhost", "127.0.0.1", "[::1]"].includes(url.hostname)))
10
+ if (!((["unix:", "npipe:"].includes(url.protocol) && ["", "localhost"].includes(url.hostname))
11
+ || (url.protocol === "tcp:" && ["localhost", "127.0.0.1", "[::1]"].includes(url.hostname)))) {
12
12
  throw new Error("Local database setup requires a local Docker endpoint; remote contexts are refused.");
13
+ }
13
14
  return execFileSync("docker", args, options);
14
15
  }
15
16
  //# sourceMappingURL=local-docker.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"local-docker.js","sourceRoot":"","sources":["../src/local-docker.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8C,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAI9F,MAAM,UAAU,MAAM,CACrB,WAA8B,EAC9B,IAAuB,EACvB,UAAiD,EAAE,QAAQ,EAAE,MAAM,EAAE;IAErE,MAAM,OAAO,GAAG,WAAW,CAAC,cAAc,CAAC;IAC3C,MAAM,IAAI,GAAG,WAAW,CAAC,WAAW,CAAC;IACrC,MAAM,QAAQ,GACb,CAAC,CAAC,OAAO,IAAI,IAAI,CAAC;QAClB,YAAY,CAAC,QAAQ,EAAE,CAAC,SAAS,EAAE,SAAS,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,UAAU,EAAE,4BAA4B,CAAC,EAAE;YACvH,QAAQ,EAAE,MAAM;SAChB,CAAC,CAAC,IAAI,EAAE,CAAC;IACX,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC9B,IACC,CAAC,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACzF,CAAC,CAAC,GAAG,CAAC,QAAQ,KAAK,MAAM,IAAI,CAAC,WAAW,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAExF,MAAM,IAAI,KAAK,CAAC,qFAAqF,CAAC,CAAC;IACxG,OAAO,YAAY,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;AAC9C,CAAC"}
1
+ {"version":3,"file":"local-docker.js","sourceRoot":"","sources":["../src/local-docker.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8C,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAI9F,MAAM,UAAU,MAAM,CACrB,WAA8B,EAC9B,IAAuB,EACvB,UAAiD,EAAE,QAAQ,EAAE,MAAM,EAAE;IAErE,MAAM,OAAO,GAAG,WAAW,CAAC,cAAc,CAAC;IAC3C,MAAM,IAAI,GAAG,WAAW,CAAC,WAAW,CAAC;IACrC,MAAM,QAAQ,GACb,CAAC,CAAC,OAAO,IAAI,IAAI,CAAC;WACf,YAAY,CAAC,QAAQ,EAAE,CAAC,SAAS,EAAE,SAAS,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,UAAU,EAAE,4BAA4B,CAAC,EAAE;YAC1H,QAAQ,EAAE,MAAM;SAChB,CAAC,CAAC,IAAI,EAAE,CAAC;IACX,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC9B,IACC,CAAC,CACA,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;WACrF,CAAC,GAAG,CAAC,QAAQ,KAAK,MAAM,IAAI,CAAC,WAAW,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAC1F,EACA,CAAC;QACF,MAAM,IAAI,KAAK,CAAC,qFAAqF,CAAC,CAAC;IACxG,CAAC;IACD,OAAO,YAAY,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;AAC9C,CAAC"}
package/package.json CHANGED
@@ -1,28 +1,27 @@
1
1
  {
2
2
  "name": "@shivaedev/local-postgres",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Repeatable local PostgreSQL preparation with one shared persistent service",
5
- "type": "module",
6
- "license": "MIT",
7
- "repository": {
8
- "type": "git",
9
- "url": "git+https://github.com/ShivaeDev/platform.git",
10
- "directory": "packages/local-postgres"
11
- },
12
5
  "homepage": "https://github.com/ShivaeDev/platform/tree/main/packages/local-postgres#readme",
13
6
  "bugs": {
14
7
  "url": "https://github.com/ShivaeDev/platform/issues"
15
8
  },
16
- "engines": {
17
- "node": ">=24"
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/ShivaeDev/platform.git",
12
+ "directory": "packages/local-postgres"
18
13
  },
14
+ "license": "MIT",
19
15
  "sideEffects": false,
20
- "files": [
21
- "dist",
22
- "src",
23
- "CHANGELOG.md",
24
- "README.md"
25
- ],
16
+ "type": "module",
17
+ "imports": {
18
+ "#test/*": "./test/*",
19
+ "#*.ts": {
20
+ "source": "./src/*.ts",
21
+ "types": "./dist/*.d.ts",
22
+ "default": "./dist/*.js"
23
+ }
24
+ },
26
25
  "exports": {
27
26
  ".": {
28
27
  "types": "./dist/index.d.ts",
@@ -32,22 +31,30 @@
32
31
  },
33
32
  "./package.json": "./package.json"
34
33
  },
35
- "publishConfig": {
36
- "access": "public",
37
- "provenance": true
38
- },
34
+ "files": [
35
+ "dist",
36
+ "src",
37
+ "CHANGELOG.md",
38
+ "README.md"
39
+ ],
39
40
  "devDependencies": {
41
+ "@shivaedev/quality": "0.7.3",
40
42
  "@types/node": "24.10.1",
41
43
  "@typescript/native": "npm:typescript@7.0.2",
42
44
  "typescript": "npm:@typescript/typescript6@6.0.2",
43
45
  "vitest": "4.1.9"
44
46
  },
47
+ "engines": {
48
+ "node": ">=24"
49
+ },
50
+ "publishConfig": {
51
+ "access": "public",
52
+ "provenance": true
53
+ },
45
54
  "scripts": {
46
55
  "build": "node --eval \"import('node:fs').then(({ rmSync }) => rmSync('dist', { force: true, recursive: true }))\" && tsc6 --project tsconfig.build.json",
47
- "check": "biome check .",
56
+ "ready": "pnpm typecheck && pnpm test && pnpm build",
48
57
  "test": "vitest run",
49
- "typecheck": "tsc --noEmit",
50
- "typecheck:compat": "tsc6 --noEmit",
51
- "ready": "pnpm check && pnpm typecheck && pnpm typecheck:compat && pnpm test && pnpm build"
58
+ "typecheck": "tsc --noEmit"
52
59
  }
53
60
  }
package/src/index.ts CHANGED
@@ -8,13 +8,13 @@ export function assertLocalDatabase(value: string, names: readonly string[]) {
8
8
  const url = new URL(value);
9
9
  const name = url.pathname.slice(1);
10
10
  if (
11
- !["postgres:", "postgresql:"].includes(url.protocol) ||
12
- !["localhost", "127.0.0.1"].includes(url.hostname) ||
13
- url.port !== "55432" ||
14
- ["host", "hostaddr", "port", "dbname", "service"].some((key) => url.searchParams.has(key)) ||
15
- !names.includes(name)
16
- )
11
+ !(["postgres:", "postgresql:"].includes(url.protocol) && ["localhost", "127.0.0.1"].includes(url.hostname))
12
+ || url.port !== "55432"
13
+ || ["host", "hostaddr", "port", "dbname", "service"].some((key) => url.searchParams.has(key))
14
+ || !names.includes(name)
15
+ ) {
17
16
  throw new Error(`Use a local database on 127.0.0.1:55432 named ${names.join(" or ")}.`);
17
+ }
18
18
  return url;
19
19
  }
20
20
 
@@ -24,16 +24,21 @@ export function localPostgres(environment: DockerEnvironment) {
24
24
  function sql(value: string | URL, query: string) {
25
25
  const url = new URL(value);
26
26
  assertLocalDatabase(url.toString(), [url.pathname.slice(1)]);
27
- for (const key of ["schema", "connection_limit", "pool_timeout", "pgbouncer"]) url.searchParams.delete(key);
27
+ for (const key of ["schema", "connection_limit", "pool_timeout", "pgbouncer"]) {
28
+ url.searchParams.delete(key);
29
+ }
28
30
 
29
31
  const args = ["-X", "--set", "ON_ERROR_STOP=1", "-At", "-c", query];
30
- if (!url.searchParams.has("connect_timeout")) url.searchParams.set("connect_timeout", "3");
32
+ if (!url.searchParams.has("connect_timeout")) {
33
+ url.searchParams.set("connect_timeout", "3");
34
+ }
31
35
  const options = { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] } satisfies ExecFileSyncOptionsWithStringEncoding;
32
36
  try {
33
37
  return execFileSync("psql", [...args, "--dbname", String(url)], options).trim();
34
38
  } catch (error) {
35
- if (!(error instanceof Error && "code" in error && error.code === "ENOENT"))
39
+ if (!(error instanceof Error && "code" in error && error.code === "ENOENT")) {
36
40
  throw new Error(error instanceof Error && "stderr" in error ? String(error.stderr) : "PostgreSQL query failed.");
41
+ }
37
42
  return sqlInContainer(localDocker, url, args, options);
38
43
  }
39
44
  }
@@ -56,14 +61,18 @@ export function localPostgres(environment: DockerEnvironment) {
56
61
  }
57
62
  }
58
63
  }
59
- if (version !== "18.6") throw new Error("Expected local PostgreSQL 18.6. Check the existing service; setup never removes containers or data.");
64
+ if (version !== "18.6") {
65
+ throw new Error("Expected local PostgreSQL 18.6. Check the existing service; setup never removes containers or data.");
66
+ }
60
67
  }
61
68
 
62
69
  function prepareDatabases(values: readonly string[]) {
63
70
  for (const value of values) {
64
71
  const name = new URL(value).pathname.slice(1);
65
72
  assertLocalDatabase(value, [name]);
66
- if (!/^[a-z][a-z0-9_]{0,62}$/.test(name)) throw new Error("Invalid local database name.");
73
+ if (!/^[a-z][a-z0-9_]{0,62}$/u.test(name)) {
74
+ throw new Error("Invalid local database name.");
75
+ }
67
76
  }
68
77
  startPostgres(values[0]);
69
78
  for (const value of values) {
@@ -71,8 +80,10 @@ export function localPostgres(environment: DockerEnvironment) {
71
80
  const name = url.pathname.slice(1);
72
81
  const server = new URL(url);
73
82
  server.pathname = "/postgres";
74
- if (!sql(server, `SELECT 1 FROM pg_database WHERE datname = '${name}'`)) sql(server, `CREATE DATABASE "${name}"`);
83
+ if (!sql(server, `SELECT 1 FROM pg_database WHERE datname = '${name}'`)) {
84
+ sql(server, `CREATE DATABASE "${name}"`);
85
+ }
75
86
  }
76
87
  }
77
- return { sql, startPostgres, prepareDatabases };
88
+ return { prepareDatabases, sql, startPostgres };
78
89
  }
@@ -6,9 +6,12 @@ type Docker = (args: readonly string[], options?: ExecFileSyncOptionsWithStringE
6
6
 
7
7
  export function sqlInContainer(docker: Docker, url: URL, args: readonly string[], options: ExecFileSyncOptionsWithStringEncoding) {
8
8
  const id = docker(["ps", "--filter", "publish=55432", "--format", "{{.ID}}"], options).trim();
9
- if (!id || id.includes("\n")) throw new Error("Install psql or start the shared PostgreSQL service with Docker.");
10
- if (docker(["inspect", "--format", "{{.Config.Image}}", id], options).trim() !== image)
9
+ if (!id || id.includes("\n")) {
10
+ throw new Error("Install psql or start the shared PostgreSQL service with Docker.");
11
+ }
12
+ if (docker(["inspect", "--format", "{{.Config.Image}}", id], options).trim() !== image) {
11
13
  throw new Error("The shared PostgreSQL image differs from the pinned baseline. Upgrade explicitly, preserving data.");
14
+ }
12
15
  const inside = new URL(url);
13
16
  inside.hostname = "127.0.0.1";
14
17
  inside.port = "5432";
@@ -23,8 +26,9 @@ export function startContainer(docker: Docker) {
23
26
  existing = true;
24
27
  } catch {}
25
28
  if (existing) {
26
- if (docker(["inspect", "--format", "{{.Config.Image}}", container]).trim() !== image)
29
+ if (docker(["inspect", "--format", "{{.Config.Image}}", container]).trim() !== image) {
27
30
  throw new Error("The shared PostgreSQL container uses a different image. Preserve its volume and upgrade it explicitly.");
31
+ }
28
32
  docker(["start", container]);
29
33
  } else {
30
34
  docker([
@@ -10,15 +10,18 @@ export function docker(
10
10
  const context = environment.DOCKER_CONTEXT;
11
11
  const host = environment.DOCKER_HOST;
12
12
  const endpoint =
13
- (!context && host) ||
14
- execFileSync("docker", ["context", "inspect", ...(context ? [context] : []), "--format", "{{.Endpoints.docker.Host}}"], {
13
+ (!context && host)
14
+ || execFileSync("docker", ["context", "inspect", ...(context ? [context] : []), "--format", "{{.Endpoints.docker.Host}}"], {
15
15
  encoding: "utf8",
16
16
  }).trim();
17
17
  const url = new URL(endpoint);
18
18
  if (
19
- !(["unix:", "npipe:"].includes(url.protocol) && ["", "localhost"].includes(url.hostname)) &&
20
- !(url.protocol === "tcp:" && ["localhost", "127.0.0.1", "[::1]"].includes(url.hostname))
21
- )
19
+ !(
20
+ (["unix:", "npipe:"].includes(url.protocol) && ["", "localhost"].includes(url.hostname))
21
+ || (url.protocol === "tcp:" && ["localhost", "127.0.0.1", "[::1]"].includes(url.hostname))
22
+ )
23
+ ) {
22
24
  throw new Error("Local database setup requires a local Docker endpoint; remote contexts are refused.");
25
+ }
23
26
  return execFileSync("docker", args, options);
24
27
  }