@shivaedev/local-postgres 0.4.0 → 0.4.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 +7 -0
- package/README.md +7 -14
- package/dist/server/localConnections.d.ts +8 -0
- package/dist/server/localConnections.d.ts.map +1 -0
- package/dist/server/localConnections.js +34 -0
- package/dist/server/localConnections.js.map +1 -0
- package/dist/server/localPostgres.d.ts.map +1 -1
- package/dist/server/localPostgres.js +18 -10
- package/dist/server/localPostgres.js.map +1 -1
- package/package.json +4 -6
- package/src/server/localConnections.ts +35 -0
- package/src/server/localPostgres.ts +21 -9
- package/docs/north-star.md +0 -41
- package/docs/roadmap.md +0 -24
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.4.1 - 2026-10-18
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- The shared development PostgreSQL container now allows 500 connections. Existing containers are raised on their next start, preserving their data; containers already allowing 500 or more connections are left running unchanged.
|
|
8
|
+
- Setting failures throw `PostgresSettingError` from `localConnections.ts`, identifying the container and `max_connections` setting. The lower-level `ensureConnections(docker, sql, ready)` function applies and verifies the setting through the existing synchronous setup API.
|
|
9
|
+
|
|
3
10
|
## 0.4.0 - 2026-10-18
|
|
4
11
|
|
|
5
12
|
### Breaking
|
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ assertLocalDatabase(development, ["example_dev"]);
|
|
|
14
14
|
localPostgres(process.env).prepareDatabases([development]);
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
The application chooses `example_dev`. Preparation can run again
|
|
17
|
+
The application chooses `example_dev`. Preparation can run again without losing the data already in the database.
|
|
18
18
|
|
|
19
19
|
## Using it
|
|
20
20
|
|
|
@@ -49,7 +49,7 @@ Keep the explicit name checks even though the preparation functions check their
|
|
|
49
49
|
|
|
50
50
|
### 2. Once per feature: prepare its schema in application tooling
|
|
51
51
|
|
|
52
|
-
After `prepareDatabases`, run the application's own schema or migration entry point. This package provides no schema model, migration ledger, fixture catalogue or seed convention.
|
|
52
|
+
After `prepareDatabases`, run the application's own schema or migration entry point. This package provides no schema model, migration ledger, fixture catalogue or seed convention. `@shivaedev/effect-sql` owns the SQL and migration APIs.
|
|
53
53
|
|
|
54
54
|
### 3. In daily setup: prepare again and inspect with SQL
|
|
55
55
|
|
|
@@ -68,6 +68,8 @@ The version query returns the string `18.6`. `sql` also accepts a `URL` and retu
|
|
|
68
68
|
|
|
69
69
|
`startPostgres(connection)` prepares the service without choosing an application database to create. Its connection defaults to `localServer`. Prefer `prepareDatabases` when the setup script needs named databases as well.
|
|
70
70
|
|
|
71
|
+
On each start, setup reads `SHOW max_connections`. When the shared container allows fewer than 500 connections, setup applies `ALTER SYSTEM SET max_connections = 500`, restarts that same container, waits for readiness and confirms the setting. Existing data stays in place. A limit of 500 or higher causes no setting change or restart. If the setting cannot be applied, setup throws `PostgresSettingError` from `localConnections.ts`, with `_tag`, `container`, `setting` and the original `cause`.
|
|
72
|
+
|
|
71
73
|
### API
|
|
72
74
|
|
|
73
75
|
Import the setup API from `@shivaedev/local-postgres/localPostgres.ts`:
|
|
@@ -83,14 +85,7 @@ Import the setup API from `@shivaedev/local-postgres/localPostgres.ts`:
|
|
|
83
85
|
|
|
84
86
|
The last three functions are members of the object returned by `localPostgres`, not module-level exports. They throw on failure; they are synchronous Node functions rather than Effects.
|
|
85
87
|
|
|
86
|
-
The
|
|
87
|
-
|
|
88
|
-
| Module | Exports |
|
|
89
|
-
| --- | --- |
|
|
90
|
-
| `@shivaedev/local-postgres/localDocker.ts` | `DockerEnvironment`, the type with optional `DOCKER_CONTEXT` and `DOCKER_HOST`; `docker(environment, args, options?)`, the local-endpoint-checked Docker command function. |
|
|
91
|
-
| `@shivaedev/local-postgres/localContainer.ts` | `startContainer(docker)`, the container-start function; `sqlInContainer(docker, url, args, options)`, the container SQL-client function. Both take a Docker command callback. |
|
|
92
|
-
|
|
93
|
-
Use `localPostgres.ts` for application preparation. The lower-level functions describe the command paths it uses and take Node child-process options where shown.
|
|
88
|
+
The module export pattern also exposes the lower-level Docker and container command functions in `localDocker.ts` and `localContainer.ts`. Use `localPostgres.ts` for application preparation.
|
|
94
89
|
|
|
95
90
|
### Install and machine setup
|
|
96
91
|
|
|
@@ -106,7 +101,7 @@ The shared baseline is PostgreSQL 18.6 on loopback port 55432. Docker preparatio
|
|
|
106
101
|
postgres:18.6-alpine@sha256:77f585114c32fbca283dc835b0596f4e52b51b4c6662d7810b2f4084f60a1873
|
|
107
102
|
```
|
|
108
103
|
|
|
109
|
-
A newly created container uses username and password `postgres`; connection URLs supply credentials for client commands.
|
|
104
|
+
A newly created container uses username and password `postgres`; connection URLs supply credentials for client commands. Setup stops when a running service reports a version other than 18.6 and never replaces it; upgrading it while preserving its data is your job. No test covers that running-version check. Container preparation and container-client fallback also check the managed image; a successful host-`psql` version probe does not inspect that image.
|
|
110
105
|
|
|
111
106
|
Pass the process's actual Docker settings to `localPostgres`, as `process.env` in the examples does. With `DOCKER_CONTEXT`, endpoint validation uses that context and ignores `DOCKER_HOST`; otherwise it validates `DOCKER_HOST` or the active context. Remote endpoints are rejected before a Docker operation. Docker subprocesses inherit the process environment. Supplying a different object does not configure those subprocesses.
|
|
112
107
|
|
|
@@ -116,6 +111,4 @@ Pass the process's actual Docker settings to `localPostgres`, as `process.env` i
|
|
|
116
111
|
- Commands block the calling thread. Keep them in development and test setup tooling.
|
|
117
112
|
- Keep allowed names, schema changes, test isolation and cleanup in the application. Preparation is not a database reset.
|
|
118
113
|
- A prepared database name has 1–63 lowercase letters, digits or underscores and starts with a letter. An allowlisted connection URL does not bypass this SQL-name constraint.
|
|
119
|
-
-
|
|
120
|
-
- Rejection of an exact running PostgreSQL version mismatch still needs a test; image-mismatch command tests do not prove that check.
|
|
121
|
-
- Concurrent creation of the same absent database is not covered by the package's tests. Prepare databases before parallel tests begin.
|
|
114
|
+
- Concurrent creation of the same absent database is not supported. Prepare databases before parallel tests begin.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare class PostgresSettingError extends Error {
|
|
2
|
+
readonly _tag = "PostgresSettingError";
|
|
3
|
+
readonly container = "development-postgres";
|
|
4
|
+
readonly setting = "max_connections";
|
|
5
|
+
constructor(message: string, options: ErrorOptions);
|
|
6
|
+
}
|
|
7
|
+
export declare function ensureConnections(docker: (args: readonly string[]) => string, sql: (query: string) => string, ready: () => void): void;
|
|
8
|
+
//# sourceMappingURL=localConnections.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"localConnections.d.ts","sourceRoot":"","sources":["../../src/server/localConnections.ts"],"names":[],"mappings":"AAEA,qBAAa,oBAAqB,SAAQ,KAAK;IAC9C,QAAQ,CAAC,IAAI,0BAA0B;IACvC,QAAQ,CAAC,SAAS,0BAA0B;IAC5C,QAAQ,CAAC,OAAO,qBAAqB;IAErC,YAAY,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAGjD;CACD;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,KAAK,MAAM,EAAE,GAAG,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,EAAE,KAAK,EAAE,MAAM,IAAI,QAqB/H"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { POSTGRES_IMAGE } from "./localContainer.js";
|
|
2
|
+
export class PostgresSettingError extends Error {
|
|
3
|
+
_tag = "PostgresSettingError";
|
|
4
|
+
container = "development-postgres";
|
|
5
|
+
setting = "max_connections";
|
|
6
|
+
constructor(message, options) {
|
|
7
|
+
super(message, options);
|
|
8
|
+
this.name = "PostgresSettingError";
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export function ensureConnections(docker, sql, ready) {
|
|
12
|
+
try {
|
|
13
|
+
const current = Number(sql("SHOW max_connections"));
|
|
14
|
+
if (!Number.isInteger(current) || current <= 0) {
|
|
15
|
+
throw new Error("PostgreSQL returned an invalid max_connections value.");
|
|
16
|
+
}
|
|
17
|
+
if (current >= 500) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
if (docker(["inspect", "--format", "{{.Config.Image}}", "development-postgres"]).trim() !== POSTGRES_IMAGE) {
|
|
21
|
+
throw new Error("The shared PostgreSQL container uses a different image. Preserve its data and upgrade it explicitly.");
|
|
22
|
+
}
|
|
23
|
+
sql("ALTER SYSTEM SET max_connections = 500");
|
|
24
|
+
docker(["restart", "development-postgres"]);
|
|
25
|
+
ready();
|
|
26
|
+
if (!(Number(sql("SHOW max_connections")) >= 500)) {
|
|
27
|
+
throw new Error("PostgreSQL did not apply max_connections after restarting.");
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
catch (cause) {
|
|
31
|
+
throw new PostgresSettingError("Could not set max_connections to at least 500 in container development-postgres.", { cause });
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=localConnections.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"localConnections.js","sourceRoot":"","sources":["../../src/server/localConnections.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IACrC,IAAI,GAAG,sBAAsB,CAAC;IAC9B,SAAS,GAAG,sBAAsB,CAAC;IACnC,OAAO,GAAG,iBAAiB,CAAC;IAErC,YAAY,OAAe,EAAE,OAAqB;QACjD,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACxB,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;IACpC,CAAC;CACD;AAED,MAAM,UAAU,iBAAiB,CAAC,MAA2C,EAAE,GAA8B,EAAE,KAAiB;IAC/H,IAAI,CAAC;QACJ,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC,CAAC;QACpD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,OAAO,IAAI,CAAC,EAAE,CAAC;YAChD,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;QAC1E,CAAC;QACD,IAAI,OAAO,IAAI,GAAG,EAAE,CAAC;YACpB,OAAO;QACR,CAAC;QACD,IAAI,MAAM,CAAC,CAAC,SAAS,EAAE,UAAU,EAAE,mBAAmB,EAAE,sBAAsB,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,cAAc,EAAE,CAAC;YAC5G,MAAM,IAAI,KAAK,CAAC,sGAAsG,CAAC,CAAC;QACzH,CAAC;QACD,GAAG,CAAC,wCAAwC,CAAC,CAAC;QAC9C,MAAM,CAAC,CAAC,SAAS,EAAE,sBAAsB,CAAC,CAAC,CAAC;QAC5C,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;YACnD,MAAM,IAAI,KAAK,CAAC,4DAA4D,CAAC,CAAC;QAC/E,CAAC;IACF,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,MAAM,IAAI,oBAAoB,CAAC,kFAAkF,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IAC/H,CAAC;AACF,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"localPostgres.d.ts","sourceRoot":"","sources":["../../src/server/localPostgres.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"localPostgres.d.ts","sourceRoot":"","sources":["../../src/server/localPostgres.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,iBAAiB,EAAU,MAAM,kBAAkB,CAAC;AAElE,eAAO,MAAM,WAAW,mDAAmD,CAAC;AAE5E,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,qBAY1E;AAQD,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,wBAAgB,aAAa,CAAC,WAAW,EAAE,iBAAiB,EAAE,EAAE,QAAa,EAAE,WAAkB,EAAE,GAAE,gBAAqB;+BAmEvF,SAAS,MAAM,EAAE;iBA/D/B,MAAM,GAAG,GAAG,SAAS,MAAM;;EAmF/C"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { execFileSync } from "node:child_process";
|
|
2
2
|
import { env } from "node:process";
|
|
3
|
+
import { ensureConnections } from "./localConnections.js";
|
|
3
4
|
import { sqlInContainer, startContainer } from "./localContainer.js";
|
|
4
5
|
import { docker } from "./localDocker.js";
|
|
5
6
|
export const localServer = "postgresql://postgres:postgres@127.0.0.1:55432";
|
|
@@ -55,25 +56,32 @@ export function localPostgres(environment, { attempts = 30, delayMillis = 1000 }
|
|
|
55
56
|
const server = new URL(connection);
|
|
56
57
|
server.pathname = "/postgres";
|
|
57
58
|
assertLocalDatabase(server.toString(), ["postgres"]);
|
|
58
|
-
|
|
59
|
-
try {
|
|
60
|
-
version = sql(server, "SHOW server_version");
|
|
61
|
-
}
|
|
62
|
-
catch {
|
|
63
|
-
startContainer(localDocker);
|
|
59
|
+
function waitForVersion() {
|
|
64
60
|
for (let attempt = 0; attempt < attempts; attempt += 1) {
|
|
65
61
|
try {
|
|
66
|
-
|
|
67
|
-
break;
|
|
62
|
+
return sql(server, "SHOW server_version");
|
|
68
63
|
}
|
|
69
64
|
catch {
|
|
70
65
|
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, delayMillis);
|
|
71
66
|
}
|
|
72
67
|
}
|
|
68
|
+
return undefined;
|
|
69
|
+
}
|
|
70
|
+
function confirmVersion(observed) {
|
|
71
|
+
if (observed !== "18.6") {
|
|
72
|
+
throw new Error("Expected local PostgreSQL 18.6. Check the existing service; setup never removes containers or data.");
|
|
73
|
+
}
|
|
73
74
|
}
|
|
74
|
-
|
|
75
|
-
|
|
75
|
+
let version;
|
|
76
|
+
try {
|
|
77
|
+
version = sql(server, "SHOW server_version");
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
startContainer(localDocker);
|
|
81
|
+
version = waitForVersion();
|
|
76
82
|
}
|
|
83
|
+
confirmVersion(version);
|
|
84
|
+
ensureConnections(localDocker, (query) => sql(server, query), () => confirmVersion(waitForVersion()));
|
|
77
85
|
}
|
|
78
86
|
function prepareDatabases(values) {
|
|
79
87
|
for (const value of values) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"localPostgres.js","sourceRoot":"","sources":["../../src/server/localPostgres.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"localPostgres.js","sourceRoot":"","sources":["../../src/server/localPostgres.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shivaedev/local-postgres",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "Repeatable local PostgreSQL preparation with one shared persistent service",
|
|
5
5
|
"homepage": "https://github.com/ShivaeDev/platform/tree/main/packages/local-postgres#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -36,17 +36,15 @@
|
|
|
36
36
|
"!src/**/*.test.ts",
|
|
37
37
|
"!src/**/*.spec.ts",
|
|
38
38
|
"!src/**/test-support",
|
|
39
|
-
"docs",
|
|
40
39
|
"CHANGELOG.md",
|
|
41
40
|
"README.md"
|
|
42
41
|
],
|
|
43
42
|
"devDependencies": {
|
|
44
|
-
"@shivaedev/quality": "0.
|
|
45
|
-
"@shivaedev/test-story": "0.
|
|
43
|
+
"@shivaedev/quality": "0.27.0",
|
|
44
|
+
"@shivaedev/test-story": "0.9.0",
|
|
46
45
|
"@types/node": "24.19.2",
|
|
47
|
-
"@typescript/native": "npm:typescript@7.0.2",
|
|
48
46
|
"effect": "4.0.4",
|
|
49
|
-
"typescript": "
|
|
47
|
+
"typescript": "7.0.2",
|
|
50
48
|
"vitest": "5.0.3"
|
|
51
49
|
},
|
|
52
50
|
"engines": {
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { POSTGRES_IMAGE } from "./localContainer.ts";
|
|
2
|
+
|
|
3
|
+
export class PostgresSettingError extends Error {
|
|
4
|
+
readonly _tag = "PostgresSettingError";
|
|
5
|
+
readonly container = "development-postgres";
|
|
6
|
+
readonly setting = "max_connections";
|
|
7
|
+
|
|
8
|
+
constructor(message: string, options: ErrorOptions) {
|
|
9
|
+
super(message, options);
|
|
10
|
+
this.name = "PostgresSettingError";
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function ensureConnections(docker: (args: readonly string[]) => string, sql: (query: string) => string, ready: () => void) {
|
|
15
|
+
try {
|
|
16
|
+
const current = Number(sql("SHOW max_connections"));
|
|
17
|
+
if (!Number.isInteger(current) || current <= 0) {
|
|
18
|
+
throw new Error("PostgreSQL returned an invalid max_connections value.");
|
|
19
|
+
}
|
|
20
|
+
if (current >= 500) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
if (docker(["inspect", "--format", "{{.Config.Image}}", "development-postgres"]).trim() !== POSTGRES_IMAGE) {
|
|
24
|
+
throw new Error("The shared PostgreSQL container uses a different image. Preserve its data and upgrade it explicitly.");
|
|
25
|
+
}
|
|
26
|
+
sql("ALTER SYSTEM SET max_connections = 500");
|
|
27
|
+
docker(["restart", "development-postgres"]);
|
|
28
|
+
ready();
|
|
29
|
+
if (!(Number(sql("SHOW max_connections")) >= 500)) {
|
|
30
|
+
throw new Error("PostgreSQL did not apply max_connections after restarting.");
|
|
31
|
+
}
|
|
32
|
+
} catch (cause) {
|
|
33
|
+
throw new PostgresSettingError("Could not set max_connections to at least 500 in container development-postgres.", { cause });
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type ExecFileSyncOptionsWithStringEncoding, execFileSync } from "node:child_process";
|
|
2
2
|
import { env } from "node:process";
|
|
3
|
+
import { ensureConnections } from "./localConnections.ts";
|
|
3
4
|
import { sqlInContainer, startContainer } from "./localContainer.ts";
|
|
4
5
|
import { type DockerEnvironment, docker } from "./localDocker.ts";
|
|
5
6
|
|
|
@@ -67,23 +68,34 @@ export function localPostgres(environment: DockerEnvironment, { attempts = 30, d
|
|
|
67
68
|
const server = new URL(connection);
|
|
68
69
|
server.pathname = "/postgres";
|
|
69
70
|
assertLocalDatabase(server.toString(), ["postgres"]);
|
|
70
|
-
|
|
71
|
-
try {
|
|
72
|
-
version = sql(server, "SHOW server_version");
|
|
73
|
-
} catch {
|
|
74
|
-
startContainer(localDocker);
|
|
71
|
+
function waitForVersion() {
|
|
75
72
|
for (let attempt = 0; attempt < attempts; attempt += 1) {
|
|
76
73
|
try {
|
|
77
|
-
|
|
78
|
-
break;
|
|
74
|
+
return sql(server, "SHOW server_version");
|
|
79
75
|
} catch {
|
|
80
76
|
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, delayMillis);
|
|
81
77
|
}
|
|
82
78
|
}
|
|
79
|
+
return undefined;
|
|
80
|
+
}
|
|
81
|
+
function confirmVersion(observed: string | undefined) {
|
|
82
|
+
if (observed !== "18.6") {
|
|
83
|
+
throw new Error("Expected local PostgreSQL 18.6. Check the existing service; setup never removes containers or data.");
|
|
84
|
+
}
|
|
83
85
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
+
let version: string | undefined;
|
|
87
|
+
try {
|
|
88
|
+
version = sql(server, "SHOW server_version");
|
|
89
|
+
} catch {
|
|
90
|
+
startContainer(localDocker);
|
|
91
|
+
version = waitForVersion();
|
|
86
92
|
}
|
|
93
|
+
confirmVersion(version);
|
|
94
|
+
ensureConnections(
|
|
95
|
+
localDocker,
|
|
96
|
+
(query) => sql(server, query),
|
|
97
|
+
() => confirmVersion(waitForVersion()),
|
|
98
|
+
);
|
|
87
99
|
}
|
|
88
100
|
|
|
89
101
|
function prepareDatabases(values: readonly string[]) {
|
package/docs/north-star.md
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
# North star
|
|
2
|
-
|
|
3
|
-
## The problem
|
|
4
|
-
|
|
5
|
-
Development and integration tests need PostgreSQL, but each repository has its own database names, schemas and test fixtures. Copying the whole setup script between repositories mixes those application choices with service management. A later shortcut in one copy can replace a container, lose a persistent volume or point a local setup command at a remote machine.
|
|
6
|
-
|
|
7
|
-
Setup also runs more than once. The developer's useful state must survive another checkout, another dependency install and another test run. A mismatch is a reason to stop and inspect the machine, not a reason to rebuild its database service automatically.
|
|
8
|
-
|
|
9
|
-
## The ideal
|
|
10
|
-
|
|
11
|
-
There is one small utility for preparing the shared local service, and each application writes only its own choices. A caller chooses explicit database names, checks incoming URLs against those names, prepares absent databases, and then runs its own schema and seed work. The common utility handles reaching the service and PostgreSQL's command-line client.
|
|
12
|
-
|
|
13
|
-
Repeated preparation preserves existing data. Locality checks come before a command can act on a database or Docker endpoint. Upgrades are explicit decisions with a data-preservation plan rather than recovery work hidden inside a readiness check.
|
|
14
|
-
|
|
15
|
-
## What good looks like
|
|
16
|
-
|
|
17
|
-
- A setup script names the databases it owns and validates configured URLs against those names.
|
|
18
|
-
- A service mismatch fails clearly without destructive repair.
|
|
19
|
-
- The application owns schemas, migrations, fixture loading, production guards and test cleanup. The package knows none of its domain tables or database naming conventions.
|
|
20
|
-
- The common setup path stays visible: ordinary Node tools, PostgreSQL client commands and a fixed local baseline. Application runtime persistence goes through its database client and the framework's SQL path.
|
|
21
|
-
- Tests distinguish real database preservation from inspection of generated commands. A test against an already-running PostgreSQL service cannot stand in for a test that starts Docker or exercises a missing client.
|
|
22
|
-
|
|
23
|
-
## Trade-offs
|
|
24
|
-
|
|
25
|
-
When these goals conflict, prefer existing data, then an explicit local destination, then application ownership, then a small setup utility.
|
|
26
|
-
|
|
27
|
-
A fixed service baseline is less flexible than a configurable process manager. It makes one shared machine service easier to reason about and avoids changing the version as a side effect of setup. A machine that needs an upgrade requires a deliberate action outside preparation.
|
|
28
|
-
|
|
29
|
-
Explicit application name checks add a line to a setup script. That line records which database the script is authorized to prepare; an environment URL alone cannot answer that question.
|
|
30
|
-
|
|
31
|
-
Synchronous commands are a fit for setup tooling. They should not become an application request path or a second database abstraction. A need for runtime SQL belongs with the native Effect SQL client and repository packages.
|
|
32
|
-
|
|
33
|
-
## What it deliberately leaves out
|
|
34
|
-
|
|
35
|
-
- Remote or production database provisioning.
|
|
36
|
-
- Automatic upgrades, container replacement, volume removal, database resets and test cleanup policy.
|
|
37
|
-
- An application database catalogue, schema authoring, migrations and seeds.
|
|
38
|
-
- Query composition, connection pooling, repository APIs or an Effect runtime owner.
|
|
39
|
-
- A configurable multi-service process manager.
|
|
40
|
-
|
|
41
|
-
The [package roadmap](./roadmap.md) owns implementation work and open decisions. The [framework roadmap](https://github.com/ShivaeDev/platform/blob/main/docs/framework/roadmap.md) owns composed database fixtures and host-level validation.
|
package/docs/roadmap.md
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
# Roadmap
|
|
2
|
-
|
|
3
|
-
This file owns local service preparation, its command paths and package API questions. The [framework roadmap](https://github.com/ShivaeDev/platform/blob/main/docs/framework/roadmap.md) owns composed repository and migration fixtures, application adoption and host-level validation. Their completion status is recorded there rather than repeated here.
|
|
4
|
-
|
|
5
|
-
## Built
|
|
6
|
-
|
|
7
|
-
- [x] The main setup module exposes an explicit local server URL, application name validation, service preparation, missing-database preparation and SQL execution.
|
|
8
|
-
- [x] Tests reject a remote database host, the wrong port, an unapproved database name and each redirecting query parameter (`host`, `hostaddr`, `port`, `dbname` and `service`). Invalid database identifiers are rejected before preparation. All three setup functions reject remote database targets before connecting.
|
|
9
|
-
- [x] A real PostgreSQL test retains an inserted row across repeated preparation and checks PostgreSQL 18.6, including queries whose URLs carry `schema` and `connection_limit` settings.
|
|
10
|
-
- [x] Scripted container tests cover daemon failures, starting an existing pinned container, creating a missing container with persistent storage and loopback publication, refusing image mismatches without replacement, and refusing client selection when discovery finds zero or multiple containers.
|
|
11
|
-
- [x] Scripted Docker tests cover active and explicit context selection, context precedence over `DOCKER_HOST`, remote endpoint refusal, and local Unix socket, Windows pipe and loopback TCP endpoints.
|
|
12
|
-
- [x] The lifecycle test simulates missing host `psql` and delayed container discovery, then checks readiness through the real Docker client and PostgreSQL service. It scripts container startup rather than starting or creating a real container.
|
|
13
|
-
- [x] Real PostgreSQL tests check supplied container-client credentials and failure diagnostics on both host and Docker clients, including password-free original errors retained as causes.
|
|
14
|
-
- [x] The installed consumer fixture checks the main module's exports and types.
|
|
15
|
-
|
|
16
|
-
## Next
|
|
17
|
-
|
|
18
|
-
- [ ] Add a test for rejection of an exact running PostgreSQL version mismatch. Scripted image-mismatch checks do not prove this service-version check.
|
|
19
|
-
- [ ] Establish whether parallel setup needs coordinated creation of an absent database; keep application test startup ordered until there is evidence for another contract.
|
|
20
|
-
|
|
21
|
-
## Open questions
|
|
22
|
-
|
|
23
|
-
- Should `localPostgres(environment)` configure the environment of its Docker subprocesses, or only validate it? The implementation validates the supplied settings while Docker commands inherit the process environment. The README therefore asks callers to pass the actual process settings. Selecting a different context through the argument would need an explicit API decision and tests.
|
|
24
|
-
- Should `docker`, `startContainer` and `sqlInContainer` be supported standalone public APIs? The package's wildcard module exports expose them, while the usage examples and installed consumer fixture use `localPostgres.ts`. Narrowing the exports would change the public API; supporting the helpers would need direct consumer and command-path tests.
|