@crvouga/mockingbird-service-postgres 1.6.0 → 1.7.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 +17 -0
- package/COMPATIBILITY.md +4 -0
- package/README.md +7 -0
- package/dist/admin.js +64 -13
- package/dist/admin.js.map +2 -2
- package/dist/server.d.ts +9 -0
- package/dist/server.js +25808 -0
- package/dist/server.js.map +7 -0
- package/dist/wire/cli.js +1190 -107
- package/dist/wire/cli.js.map +4 -4
- package/dist/wire/cluster.d.ts +3 -0
- package/dist/wire/fleet.d.ts +80 -0
- package/dist/wire/index.d.ts +6 -0
- package/dist/wire/index.js +23 -3
- package/dist/wire/index.js.map +2 -2
- package/dist/wire/probe.d.ts +2 -0
- package/package.json +13 -2
package/dist/wire/cluster.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Database } from "../api/database.js";
|
|
2
|
+
import type { Snapshot } from "../api/snapshot.js";
|
|
2
3
|
/**
|
|
3
4
|
* What every connection of one server shares: the engine, and the coordination the engine
|
|
4
5
|
* (single-session, synchronous) does not do itself.
|
|
@@ -31,6 +32,8 @@ export declare class Cluster {
|
|
|
31
32
|
/** The initial database, retained for the server's backwards-compatible public handle. */
|
|
32
33
|
get db(): Database;
|
|
33
34
|
databaseNames(): string[];
|
|
35
|
+
snapshotAll(): Map<string, Snapshot>;
|
|
36
|
+
restoreAll(points: ReadonlyMap<string, Snapshot>): void;
|
|
34
37
|
getDatabase(name: string): Database | undefined;
|
|
35
38
|
requireDatabase(name: string): Database;
|
|
36
39
|
createDatabase(name: string, template?: string): void;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The single source of time for a service.
|
|
3
|
+
*
|
|
4
|
+
* Every timestamp a mock writes reads from here, so a suite moves time instead of
|
|
5
|
+
* sleeping: appointment windows, result delays and expiries become reachable in
|
|
6
|
+
* milliseconds. A frozen clock also makes timestamps reproducible from a seed.
|
|
7
|
+
*/
|
|
8
|
+
type ClockState = {
|
|
9
|
+
/** Current epoch milliseconds. */
|
|
10
|
+
now: number;
|
|
11
|
+
/** True while time does not advance on its own. */
|
|
12
|
+
frozen: boolean;
|
|
13
|
+
/** Milliseconds this clock adds to its underlying source. */
|
|
14
|
+
offsetMs: number;
|
|
15
|
+
};
|
|
16
|
+
type Clock = {
|
|
17
|
+
now(): number;
|
|
18
|
+
/** Pin the clock to an exact instant, keeping it frozen if it already was. */
|
|
19
|
+
set(epochMs: number): void;
|
|
20
|
+
/** Move the clock forward, or back with a negative delta. */
|
|
21
|
+
advance(deltaMs: number): void;
|
|
22
|
+
/** Stop time at the current instant. */
|
|
23
|
+
freeze(): void;
|
|
24
|
+
/** Resume from the current instant. */
|
|
25
|
+
unfreeze(): void;
|
|
26
|
+
/** Drop back to the underlying source, live. */
|
|
27
|
+
reset(): void;
|
|
28
|
+
state(): ClockState;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
type FleetDiagnostics = {
|
|
32
|
+
activeRequests: number;
|
|
33
|
+
activeConnections: number;
|
|
34
|
+
blockedCommands: number;
|
|
35
|
+
pendingJobs: number;
|
|
36
|
+
activeJobs?: number;
|
|
37
|
+
pendingWebhooks: number;
|
|
38
|
+
unmatchedRequests: number;
|
|
39
|
+
};
|
|
40
|
+
/** Protocol packages own their state, listeners, credentials and namespace selection. */
|
|
41
|
+
type FleetChild = {
|
|
42
|
+
protocol: "http" | "postgres" | "redis";
|
|
43
|
+
url: string;
|
|
44
|
+
connection?: string;
|
|
45
|
+
connections?: Record<string, string>;
|
|
46
|
+
healthUrl?: string;
|
|
47
|
+
adminUrl?: string;
|
|
48
|
+
namespaces: Record<string, unknown>;
|
|
49
|
+
ready(): Promise<boolean>;
|
|
50
|
+
close(): Promise<void>;
|
|
51
|
+
/** Fence new work synchronously; diagnostics must also account for work already in flight. */
|
|
52
|
+
lock(namespace: string): () => void;
|
|
53
|
+
diagnostics(namespace: string): FleetDiagnostics;
|
|
54
|
+
checkpoint(namespace: string): Promise<unknown>;
|
|
55
|
+
restore(namespace: string, checkpoint: unknown): Promise<void>;
|
|
56
|
+
reset(namespace: string): Promise<void>;
|
|
57
|
+
clock(namespace: string): Clock;
|
|
58
|
+
settle?(namespace: string): Promise<void>;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
/** A service entry in `mockingbird.json`. */
|
|
62
|
+
type ConfigService = {
|
|
63
|
+
protocol?: "http" | "postgres" | "redis";
|
|
64
|
+
port?: number;
|
|
65
|
+
host?: string;
|
|
66
|
+
adminKey?: string;
|
|
67
|
+
seed?: string;
|
|
68
|
+
password?: string;
|
|
69
|
+
user?: string;
|
|
70
|
+
database?: string;
|
|
71
|
+
/** Protocol namespace selectors: database names for Postgres, logical DB indexes for Redis. */
|
|
72
|
+
namespaces?: Record<string, string | number>;
|
|
73
|
+
/** Service-specific serve flags, by long name: `{ "webhook-url": "…" }`. */
|
|
74
|
+
options?: Record<string, string | boolean>;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
/** Separate database listeners make the protocol namespace explicit in discovery. */
|
|
78
|
+
declare function startProtocol(entry: ConfigService): Promise<FleetChild>;
|
|
79
|
+
|
|
80
|
+
export { startProtocol };
|
package/dist/wire/index.d.ts
CHANGED
|
@@ -55,6 +55,8 @@ export type ServeOptions = {
|
|
|
55
55
|
* SQLSTATE `3D000`. Set from `url` when the path is non-empty. Unset accepts any name.
|
|
56
56
|
*/
|
|
57
57
|
databaseName?: string;
|
|
58
|
+
/** Accept other databases in this listener's catalog while retaining its default URL. */
|
|
59
|
+
allowDatabaseSelection?: boolean;
|
|
58
60
|
/** Role shown in `connectionString`. A URI's username fills this. Default `postgres`. */
|
|
59
61
|
user?: string;
|
|
60
62
|
};
|
|
@@ -77,8 +79,12 @@ export type PostgresServer = {
|
|
|
77
79
|
readonly connections: number;
|
|
78
80
|
/** Arm a fault preset for the next statement / connection (see {@link ServerFaults}). */
|
|
79
81
|
fault(fault: ServerFaults): void;
|
|
82
|
+
clearFaults(): void;
|
|
80
83
|
/** Freeze the live state (the admin `snapshot()` control). */
|
|
81
84
|
snapshot(name?: string): Snapshot;
|
|
85
|
+
snapshotAll(): Map<string, Snapshot>;
|
|
86
|
+
restoreAll(points: ReadonlyMap<string, Snapshot>): void;
|
|
87
|
+
faultState(): ServerFaults;
|
|
82
88
|
/** Stop listening and close every connection. */
|
|
83
89
|
close(): Promise<void>;
|
|
84
90
|
};
|
package/dist/wire/index.js
CHANGED
|
@@ -23733,6 +23733,16 @@ var Cluster = class {
|
|
|
23733
23733
|
databaseNames() {
|
|
23734
23734
|
return [...this.databases.keys()].sort();
|
|
23735
23735
|
}
|
|
23736
|
+
snapshotAll() {
|
|
23737
|
+
return new Map([...this.databases].map(([name, db]) => [name, db.snapshot()]));
|
|
23738
|
+
}
|
|
23739
|
+
restoreAll(points) {
|
|
23740
|
+
if (this.sessions.size > 0) throw new Error("cannot restore a catalog with active sessions");
|
|
23741
|
+
if (!points.has(this.defaultDatabaseName)) throw new Error("snapshot lacks default database");
|
|
23742
|
+
for (const db of this.databases.values()) db.close();
|
|
23743
|
+
this.databases.clear();
|
|
23744
|
+
for (const [name, point] of points) this.installDatabase(name, point.open());
|
|
23745
|
+
}
|
|
23736
23746
|
getDatabase(name) {
|
|
23737
23747
|
return this.databases.get(name);
|
|
23738
23748
|
}
|
|
@@ -23745,7 +23755,7 @@ var Cluster = class {
|
|
|
23745
23755
|
if (this.databases.has(name)) {
|
|
23746
23756
|
throw new PostgresError("duplicate_object", `database "${name}" already exists`, "42P04");
|
|
23747
23757
|
}
|
|
23748
|
-
const db = template === void 0 ? new Database() : this.requireTemplate(template).snapshot().open();
|
|
23758
|
+
const db = template === void 0 ? new Database({ now: this.db.now, seed: this.db.seed }) : this.requireTemplate(template).snapshot().open();
|
|
23749
23759
|
this.installDatabase(name, db);
|
|
23750
23760
|
}
|
|
23751
23761
|
dropDatabase(name, requester) {
|
|
@@ -25469,7 +25479,7 @@ var serve = (input = {}) => {
|
|
|
25469
25479
|
serverVersion: options.serverVersion ?? "18.3",
|
|
25470
25480
|
parameters: options.parameters ?? {},
|
|
25471
25481
|
faults,
|
|
25472
|
-
...options.databaseName !== void 0 ? { database: options.databaseName } : {},
|
|
25482
|
+
...options.databaseName !== void 0 && !options.allowDatabaseSelection ? { database: options.databaseName } : {},
|
|
25473
25483
|
...options.onLog ? { onLog: options.onLog } : {}
|
|
25474
25484
|
});
|
|
25475
25485
|
connections.add(connection);
|
|
@@ -25487,7 +25497,9 @@ var serve = (input = {}) => {
|
|
|
25487
25497
|
port,
|
|
25488
25498
|
host,
|
|
25489
25499
|
connectionString: `postgres://${auth}${host}:${port}/${encodeURIComponent(name)}`,
|
|
25490
|
-
database
|
|
25500
|
+
get database() {
|
|
25501
|
+
return cluster.db;
|
|
25502
|
+
},
|
|
25491
25503
|
databaseNames() {
|
|
25492
25504
|
return cluster.databaseNames();
|
|
25493
25505
|
},
|
|
@@ -25501,6 +25513,14 @@ var serve = (input = {}) => {
|
|
|
25501
25513
|
fault(next) {
|
|
25502
25514
|
Object.assign(faults, next);
|
|
25503
25515
|
},
|
|
25516
|
+
clearFaults() {
|
|
25517
|
+
for (const key of Object.keys(faults)) delete faults[key];
|
|
25518
|
+
},
|
|
25519
|
+
faultState() {
|
|
25520
|
+
return structuredClone(faults);
|
|
25521
|
+
},
|
|
25522
|
+
snapshotAll: () => cluster.snapshotAll(),
|
|
25523
|
+
restoreAll: (points) => cluster.restoreAll(points),
|
|
25504
25524
|
snapshot(databaseName = initialName) {
|
|
25505
25525
|
return cluster.requireDatabase(databaseName).snapshot();
|
|
25506
25526
|
},
|