@shivaedev/local-postgres 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/CHANGELOG.md +24 -0
- package/README.md +1 -1
- package/dist/local-container.d.ts.map +1 -1
- package/dist/local-container.js +6 -3
- package/dist/local-container.js.map +1 -1
- package/dist/local-docker.d.ts.map +1 -1
- package/dist/local-docker.js +5 -4
- package/dist/local-docker.js.map +1 -1
- package/dist/{index.d.ts → localPostgres.d.ts} +3 -3
- package/dist/localPostgres.d.ts.map +1 -0
- package/dist/{index.js → localPostgres.js} +19 -13
- package/dist/localPostgres.js.map +1 -0
- package/package.json +33 -26
- package/src/local-container.ts +7 -3
- package/src/local-docker.ts +8 -5
- package/src/{index.ts → localPostgres.ts} +24 -13
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.2.0 - 2026-10-04
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- Breaking: no root entry and no module that re-exports another. `exports` maps one `"./*.ts"` pattern to every module (`src` under the `source` condition, `dist` otherwise), so you import the module that defines a name, and a bundler sees only the modules you use. Where each name now lives:
|
|
8
|
+
- `@shivaedev/local-postgres`: `@shivaedev/local-postgres/localPostgres.ts` (`assertLocalDatabase`, `localPostgres`, `localServer`)
|
|
9
|
+
- The module that was the package entry is `localPostgres.ts`.
|
|
10
|
+
|
|
11
|
+
## 0.1.1 - 2026-10-04
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
|
|
15
|
+
- 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.
|
|
16
|
+
|
|
17
|
+
- Build with the `@shivaedev/quality` tsconfig presets, which target ESNext and allow only erasable TypeScript syntax.
|
|
18
|
+
|
|
19
|
+
- Type-check with TypeScript 7 only. TypeScript 6 still builds the package.
|
|
20
|
+
|
|
21
|
+
- Lint and format with the `@shivaedev/quality` Biome preset through `quality lint` at the repository root, which replaces the package's `check` script.
|
|
22
|
+
|
|
23
|
+
- 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`.
|
|
24
|
+
|
|
25
|
+
- Keep `package.json` in sort-package-json key order, checked by `quality lint`.
|
|
26
|
+
|
|
3
27
|
## 0.1.0
|
|
4
28
|
|
|
5
29
|
- Prepare one persistent local PostgreSQL 18.6 service and create missing databases without resetting existing data.
|
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@ Prepare one shared local PostgreSQL service without replacing containers, deleti
|
|
|
5
5
|
This Node 24+ package has no runtime dependencies. It uses a local Docker daemon when no service is available; an existing native service requires host `psql`. With Docker, the container provides `psql` when it is absent from the host.
|
|
6
6
|
|
|
7
7
|
```ts
|
|
8
|
-
import { assertLocalDatabase, localPostgres, localServer } from "@shivaedev/local-postgres";
|
|
8
|
+
import { assertLocalDatabase, localPostgres, localServer } from "@shivaedev/local-postgres/localPostgres.ts";
|
|
9
9
|
|
|
10
10
|
const development = `${localServer}/example_dev`;
|
|
11
11
|
assertLocalDatabase(development, ["example_dev"]);
|
|
@@ -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,
|
|
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"}
|
package/dist/local-container.js
CHANGED
|
@@ -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
|
-
|
|
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;
|
|
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,
|
|
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"}
|
package/dist/local-docker.js
CHANGED
|
@@ -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
|
-
|
|
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
|
package/dist/local-docker.js.map
CHANGED
|
@@ -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;
|
|
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"}
|
|
@@ -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
|
-
//# sourceMappingURL=
|
|
9
|
+
//# sourceMappingURL=localPostgres.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"localPostgres.d.ts","sourceRoot":"","sources":["../src/localPostgres.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"}
|
|
@@ -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
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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}
|
|
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
|
|
82
|
+
return { prepareDatabases, sql, startPostgres };
|
|
77
83
|
}
|
|
78
|
-
//# sourceMappingURL=
|
|
84
|
+
//# sourceMappingURL=localPostgres.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"localPostgres.js","sourceRoot":"","sources":["../src/localPostgres.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8C,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAC9F,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtE,OAAO,EAA0B,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAEnE,MAAM,CAAC,MAAM,WAAW,GAAG,gDAAgD,CAAC;AAE5E,MAAM,UAAU,mBAAmB,CAAC,KAAa,EAAE,KAAwB;IAC1E,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;IAC3B,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnC,IACC,CAAC,CAAC,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;WACxG,GAAG,CAAC,IAAI,KAAK,OAAO;WACpB,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;WAC1F,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EACvB,CAAC;QACF,MAAM,IAAI,KAAK,CAAC,iDAAiD,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACzF,CAAC;IACD,OAAO,GAAG,CAAC;AACZ,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,WAA8B;IAC3D,MAAM,WAAW,GAAG,CAAC,IAAuB,EAAE,UAAiD,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,CACtH,MAAM,CAAC,WAAW,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IACpC,SAAS,GAAG,CAAC,KAAmB,EAAE,KAAa;QAC9C,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;QAC3B,mBAAmB,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7D,KAAK,MAAM,GAAG,IAAI,CAAC,QAAQ,EAAE,kBAAkB,EAAE,cAAc,EAAE,WAAW,CAAC,EAAE,CAAC;YAC/E,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC9B,CAAC;QAED,MAAM,IAAI,GAAG,CAAC,IAAI,EAAE,OAAO,EAAE,iBAAiB,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;QACpE,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,iBAAiB,CAAC,EAAE,CAAC;YAC9C,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC;QAC9C,CAAC;QACD,MAAM,OAAO,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAkD,CAAC;QACxH,IAAI,CAAC;YACJ,OAAO,YAAY,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,UAAU,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;QACjF,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,IAAI,CAAC,CAAC,KAAK,YAAY,KAAK,IAAI,MAAM,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,EAAE,CAAC;gBAC7E,MAAM,IAAI,KAAK,CAAC,KAAK,YAAY,KAAK,IAAI,QAAQ,IAAI,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,0BAA0B,CAAC,CAAC;YAClH,CAAC;YACD,OAAO,cAAc,CAAC,WAAW,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;QACxD,CAAC;IACF,CAAC;IAED,SAAS,aAAa,CAAC,UAAU,GAAG,WAAW;QAC9C,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC;QACnC,MAAM,CAAC,QAAQ,GAAG,WAAW,CAAC;QAC9B,mBAAmB,CAAC,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;QACrD,IAAI,OAA2B,CAAC;QAChC,IAAI,CAAC;YACJ,OAAO,GAAG,GAAG,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;QAC9C,CAAC;QAAC,MAAM,CAAC;YACR,cAAc,CAAC,WAAW,CAAC,CAAC;YAC5B,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC;gBAC/C,IAAI,CAAC;oBACJ,OAAO,GAAG,GAAG,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;oBAC7C,MAAM;gBACP,CAAC;gBAAC,MAAM,CAAC;oBACR,OAAO,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,IAAI,iBAAiB,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC;gBACpE,CAAC;YACF,CAAC;QACF,CAAC;QACD,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,qGAAqG,CAAC,CAAC;QACxH,CAAC;IACF,CAAC;IAED,SAAS,gBAAgB,CAAC,MAAyB;QAClD,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC5B,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAC9C,mBAAmB,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;YACnC,IAAI,CAAC,yBAAyB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC3C,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;YACjD,CAAC;QACF,CAAC;QACD,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QACzB,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC5B,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;YAC3B,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACnC,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;YAC5B,MAAM,CAAC,QAAQ,GAAG,WAAW,CAAC;YAC9B,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,8CAA8C,IAAI,GAAG,CAAC,EAAE,CAAC;gBACzE,GAAG,CAAC,MAAM,EAAE,oBAAoB,IAAI,GAAG,CAAC,CAAC;YAC1C,CAAC;QACF,CAAC;IACF,CAAC;IACD,OAAO,EAAE,gBAAgB,EAAE,GAAG,EAAE,aAAa,EAAE,CAAC;AACjD,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,53 +1,60 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shivaedev/local-postgres",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Repeatable local PostgreSQL preparation with one shared persistent service",
|
|
5
|
-
"
|
|
6
|
-
"
|
|
5
|
+
"homepage": "https://github.com/ShivaeDev/platform/tree/main/packages/local-postgres#readme",
|
|
6
|
+
"bugs": {
|
|
7
|
+
"url": "https://github.com/ShivaeDev/platform/issues"
|
|
8
|
+
},
|
|
7
9
|
"repository": {
|
|
8
10
|
"type": "git",
|
|
9
11
|
"url": "git+https://github.com/ShivaeDev/platform.git",
|
|
10
12
|
"directory": "packages/local-postgres"
|
|
11
13
|
},
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"sideEffects": false,
|
|
16
|
+
"type": "module",
|
|
17
|
+
"imports": {
|
|
18
|
+
"#test/*": "./test/*",
|
|
19
|
+
"#*.ts": {
|
|
20
|
+
"source": "./src/*.ts",
|
|
21
|
+
"types": "./dist/*.d.ts",
|
|
22
|
+
"default": "./dist/*.js"
|
|
23
|
+
}
|
|
15
24
|
},
|
|
16
|
-
"
|
|
17
|
-
"
|
|
25
|
+
"exports": {
|
|
26
|
+
"./*.ts": {
|
|
27
|
+
"types": "./dist/*.d.ts",
|
|
28
|
+
"source": "./src/*.ts",
|
|
29
|
+
"import": "./dist/*.js",
|
|
30
|
+
"default": "./dist/*.js"
|
|
31
|
+
},
|
|
32
|
+
"./package.json": "./package.json"
|
|
18
33
|
},
|
|
19
|
-
"sideEffects": false,
|
|
20
34
|
"files": [
|
|
21
35
|
"dist",
|
|
22
36
|
"src",
|
|
23
37
|
"CHANGELOG.md",
|
|
24
38
|
"README.md"
|
|
25
39
|
],
|
|
26
|
-
"exports": {
|
|
27
|
-
".": {
|
|
28
|
-
"types": "./dist/index.d.ts",
|
|
29
|
-
"source": "./src/index.ts",
|
|
30
|
-
"import": "./dist/index.js",
|
|
31
|
-
"default": "./dist/index.js"
|
|
32
|
-
},
|
|
33
|
-
"./package.json": "./package.json"
|
|
34
|
-
},
|
|
35
|
-
"publishConfig": {
|
|
36
|
-
"access": "public",
|
|
37
|
-
"provenance": true
|
|
38
|
-
},
|
|
39
40
|
"devDependencies": {
|
|
41
|
+
"@shivaedev/quality": "0.9.0",
|
|
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
|
-
"
|
|
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/local-container.ts
CHANGED
|
@@ -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"))
|
|
10
|
-
|
|
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([
|
package/src/local-docker.ts
CHANGED
|
@@ -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
|
-
!(
|
|
20
|
-
|
|
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
|
}
|
|
@@ -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
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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"])
|
|
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"))
|
|
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")
|
|
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}
|
|
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}'`))
|
|
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
|
|
88
|
+
return { prepareDatabases, sql, startPostgres };
|
|
78
89
|
}
|
package/dist/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
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"}
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|