@spine-event-engine/storage-postgres 2.0.0-snapshot.13
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/LICENSE +201 -0
- package/README.md +102 -0
- package/REFERENCE.md +85 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/postgres/column-mapping.d.ts +33 -0
- package/dist/postgres/column-mapping.d.ts.map +1 -0
- package/dist/postgres/column-mapping.js +93 -0
- package/dist/postgres/column-mapping.js.map +1 -0
- package/dist/postgres/data-type.d.ts +25 -0
- package/dist/postgres/data-type.d.ts.map +1 -0
- package/dist/postgres/data-type.js +29 -0
- package/dist/postgres/data-type.js.map +1 -0
- package/dist/postgres/delivery-cleanup.d.ts +76 -0
- package/dist/postgres/delivery-cleanup.d.ts.map +1 -0
- package/dist/postgres/delivery-cleanup.js +224 -0
- package/dist/postgres/delivery-cleanup.js.map +1 -0
- package/dist/postgres/entity-commit.d.ts +114 -0
- package/dist/postgres/entity-commit.d.ts.map +1 -0
- package/dist/postgres/entity-commit.js +385 -0
- package/dist/postgres/entity-commit.js.map +1 -0
- package/dist/postgres/entity-history.d.ts +85 -0
- package/dist/postgres/entity-history.d.ts.map +1 -0
- package/dist/postgres/entity-history.js +840 -0
- package/dist/postgres/entity-history.js.map +1 -0
- package/dist/postgres/errors.d.ts +51 -0
- package/dist/postgres/errors.d.ts.map +1 -0
- package/dist/postgres/errors.js +113 -0
- package/dist/postgres/errors.js.map +1 -0
- package/dist/postgres/id-column.d.ts +61 -0
- package/dist/postgres/id-column.d.ts.map +1 -0
- package/dist/postgres/id-column.js +165 -0
- package/dist/postgres/id-column.js.map +1 -0
- package/dist/postgres/parameter.d.ts +5 -0
- package/dist/postgres/parameter.d.ts.map +1 -0
- package/dist/postgres/parameter.js +15 -0
- package/dist/postgres/parameter.js.map +1 -0
- package/dist/postgres/record-storage.d.ts +514 -0
- package/dist/postgres/record-storage.d.ts.map +1 -0
- package/dist/postgres/record-storage.js +849 -0
- package/dist/postgres/record-storage.js.map +1 -0
- package/dist/postgres/storage-factory.d.ts +321 -0
- package/dist/postgres/storage-factory.d.ts.map +1 -0
- package/dist/postgres/storage-factory.js +584 -0
- package/dist/postgres/storage-factory.js.map +1 -0
- package/dist/postgres/table-initializer.d.ts +66 -0
- package/dist/postgres/table-initializer.d.ts.map +1 -0
- package/dist/postgres/table-initializer.js +301 -0
- package/dist/postgres/table-initializer.js.map +1 -0
- package/dist/postgres/table-resolver.d.ts +41 -0
- package/dist/postgres/table-resolver.d.ts.map +1 -0
- package/dist/postgres/table-resolver.js +225 -0
- package/dist/postgres/table-resolver.js.map +1 -0
- package/dist/postgres/table-spec.d.ts +40 -0
- package/dist/postgres/table-spec.d.ts.map +1 -0
- package/dist/postgres/table-spec.js +126 -0
- package/dist/postgres/table-spec.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +40 -0
|
@@ -0,0 +1,584 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2026, CodeMatters. All rights reserved.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
|
5
|
+
* in compliance with the License. You may obtain a copy of the License at
|
|
6
|
+
*
|
|
7
|
+
* https://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
*
|
|
9
|
+
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
|
10
|
+
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
|
11
|
+
* or implied. See the License for the specific language governing permissions and limitations under
|
|
12
|
+
* the License.
|
|
13
|
+
*/
|
|
14
|
+
import { StringifierRegistry } from "@spine-event-engine/core";
|
|
15
|
+
import { StorageFactory, } from "@spine-event-engine/storage";
|
|
16
|
+
import { TenantBoundary } from "@spine-event-engine/storage/provider";
|
|
17
|
+
import { DeliveryCleanupStorageFactories, EntityCommitStorageFactories, } from "@spine-event-engine/storage/provider";
|
|
18
|
+
import { Pool } from "pg";
|
|
19
|
+
import { PostgresStorageConfigurationError, PostgresStorageConnectionError } from "./errors.js";
|
|
20
|
+
import { PostgresRecordStorage } from "./record-storage.js";
|
|
21
|
+
import { PostgresEntityStorage } from "./entity-history.js";
|
|
22
|
+
import { PostgresEntityCommitStorage } from "./entity-commit.js";
|
|
23
|
+
import { PostgresDeliveryCleanupStorage } from "./delivery-cleanup.js";
|
|
24
|
+
import { PostgresTableResolver } from "./table-resolver.js";
|
|
25
|
+
import { PostgresTableSpecs } from "./table-spec.js";
|
|
26
|
+
/**
|
|
27
|
+
* Provides the PostgreSQL storage-factory public contract.
|
|
28
|
+
*/
|
|
29
|
+
export class PostgresStorageFactory extends StorageFactory {
|
|
30
|
+
resolver;
|
|
31
|
+
operation;
|
|
32
|
+
stringifiers;
|
|
33
|
+
#handles = new Set();
|
|
34
|
+
#databases;
|
|
35
|
+
#catalog;
|
|
36
|
+
#closed;
|
|
37
|
+
/**
|
|
38
|
+
* Creates a connected factory from validated database resources.
|
|
39
|
+
*
|
|
40
|
+
* @param databases Supply the configured tenant databases.
|
|
41
|
+
* @param resolver Resolves record families to physical table names.
|
|
42
|
+
* @param operation Optionally creates custom table SQL.
|
|
43
|
+
* @param stringifiers Convert message IDs and columns reversibly.
|
|
44
|
+
*/
|
|
45
|
+
constructor(databases, resolver, operation, stringifiers) {
|
|
46
|
+
super();
|
|
47
|
+
this.resolver = resolver;
|
|
48
|
+
this.operation = operation;
|
|
49
|
+
this.stringifiers = stringifiers;
|
|
50
|
+
this.#databases = new Map(databases.map((database) => [database.boundary.key, database]));
|
|
51
|
+
this.#catalog = new PostgresTenantCatalog(databases.map(({ boundary }) => boundary));
|
|
52
|
+
EntityCommitStorageFactories.register(this, {
|
|
53
|
+
createEntityCommitStorage: (input) => this.createEntityCommitStorage(input),
|
|
54
|
+
});
|
|
55
|
+
DeliveryCleanupStorageFactories.register(this, {
|
|
56
|
+
createDeliveryCleanupStorage: () => this.createDeliveryCleanupStorage(),
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Creates a PostgreSQL storage factory builder.
|
|
61
|
+
*
|
|
62
|
+
* @returns A new builder.
|
|
63
|
+
*/
|
|
64
|
+
static newBuilder() {
|
|
65
|
+
return new Builder((entries, resolver, operation, stringifiers) => PostgresStorageFactory.connect(entries, resolver, operation, stringifiers));
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Returns the configured provider tenant catalog.
|
|
69
|
+
*
|
|
70
|
+
* @returns The configured tenant catalog.
|
|
71
|
+
*/
|
|
72
|
+
tenantCatalog() {
|
|
73
|
+
return this.#catalog;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Closes the factory and begins idempotent PostgreSQL pool draining.
|
|
77
|
+
*/
|
|
78
|
+
close() {
|
|
79
|
+
this.#closed ??= this.drain();
|
|
80
|
+
void this.#closed.catch(() => undefined);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Creates a record-storage handle for the selected PostgreSQL tenant.
|
|
84
|
+
*
|
|
85
|
+
* @typeParam I The storage identifier type.
|
|
86
|
+
* @typeParam R The stored Protobuf record type.
|
|
87
|
+
* @param context Identifies the requested storage boundary.
|
|
88
|
+
* @param recordSpec Describes the requested record family.
|
|
89
|
+
* @param group Separates records that share a source type.
|
|
90
|
+
* @returns A live handle bound to the resolved tenant table.
|
|
91
|
+
*/
|
|
92
|
+
onCreateRecordStorage(context, recordSpec, group) {
|
|
93
|
+
return this.createPostgresRecordStorage(context, recordSpec, group);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Creates one PostgreSQL record handle and tracks it until closure.
|
|
97
|
+
*
|
|
98
|
+
* @typeParam I The storage identifier type.
|
|
99
|
+
* @typeParam R The stored Protobuf record type.
|
|
100
|
+
* @param context Identifies the storage boundary.
|
|
101
|
+
* @param recordSpec Describes the record family.
|
|
102
|
+
* @param group Optionally separates records sharing a source type.
|
|
103
|
+
* @returns The live PostgreSQL record handle.
|
|
104
|
+
*/
|
|
105
|
+
createPostgresRecordStorage(context, recordSpec, group) {
|
|
106
|
+
const database = this.database(context);
|
|
107
|
+
const table = this.resolver.resolve(recordSpec.sourceType.typeName, group?.name, undefined, recordSpec.recordType.typeName);
|
|
108
|
+
const spec = PostgresTableSpecs.resolvedPostgresTableSpec({
|
|
109
|
+
schema: database.schema,
|
|
110
|
+
tableName: table.tableName,
|
|
111
|
+
sourceType: recordSpec.sourceType,
|
|
112
|
+
recordType: recordSpec.recordType,
|
|
113
|
+
idType: recordSpec.idType,
|
|
114
|
+
...(group === undefined ? {} : { groupName: group.name }),
|
|
115
|
+
declaredColumns: recordSpec.columns,
|
|
116
|
+
});
|
|
117
|
+
const handle = new PostgresRecordStorage(context, recordSpec, spec, this.connections(database), () => this.#handles.delete(handle), this.operation === undefined ? undefined : createOperation(this.operation, spec), this.stringifiers);
|
|
118
|
+
this.#handles.add(handle);
|
|
119
|
+
return handle;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Creates the internal Entity-current and history storage seam.
|
|
123
|
+
*
|
|
124
|
+
* @typeParam I The Entity identifier type.
|
|
125
|
+
* @typeParam S The Entity state message type.
|
|
126
|
+
* @param input Supplies the Entity storage configuration.
|
|
127
|
+
* @returns A factory-managed PostgreSQL Entity handle.
|
|
128
|
+
*/
|
|
129
|
+
createEntityStorage(input) {
|
|
130
|
+
if (!this.isOpen())
|
|
131
|
+
throw new Error("StorageFactory is closed.");
|
|
132
|
+
const registration = {};
|
|
133
|
+
const handle = new PostgresEntityStorage(input, this.createPostgresRecordStorage(input.context, input.recordSpec), (spec, group) => this.createPostgresRecordStorage(input.context, spec, group), () => this.#handles.delete(registration.handle));
|
|
134
|
+
registration.handle = handle;
|
|
135
|
+
this.#handles.add(handle);
|
|
136
|
+
return handle;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Creates the transaction coordinator for Entity current state and history.
|
|
140
|
+
*
|
|
141
|
+
* @typeParam I The Entity identifier type.
|
|
142
|
+
* @typeParam S The Entity state message type.
|
|
143
|
+
* @param input Supplies the Entity storage configuration.
|
|
144
|
+
* @returns A factory-managed commit coordinator.
|
|
145
|
+
*/
|
|
146
|
+
createEntityCommitStorage(input) {
|
|
147
|
+
if (!this.isOpen())
|
|
148
|
+
throw new Error("StorageFactory is closed.");
|
|
149
|
+
const registration = {};
|
|
150
|
+
const database = this.database(input.context);
|
|
151
|
+
const handle = new PostgresEntityCommitStorage(input, (spec, group) => this.createPostgresRecordStorage(input.context, spec, group), this.connections(database), () => this.#handles.delete(registration.handle));
|
|
152
|
+
registration.handle = handle;
|
|
153
|
+
this.#handles.add(handle);
|
|
154
|
+
return handle;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Creates the provider's delivered-Inbox cleanup coordinator.
|
|
158
|
+
*
|
|
159
|
+
* @returns A factory-managed cleanup coordinator.
|
|
160
|
+
*/
|
|
161
|
+
createDeliveryCleanupStorage() {
|
|
162
|
+
if (!this.isOpen())
|
|
163
|
+
throw new Error("StorageFactory is closed.");
|
|
164
|
+
const registration = {};
|
|
165
|
+
const handle = new PostgresDeliveryCleanupStorage((context, spec) => this.createPostgresRecordStorage(context, spec), (context) => this.connections(this.database(context)), () => this.#handles.delete(registration.handle));
|
|
166
|
+
registration.handle = handle;
|
|
167
|
+
this.#handles.add(handle);
|
|
168
|
+
return handle;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Closes live handles, the tenant catalog, and all pools.
|
|
172
|
+
*
|
|
173
|
+
* @returns A promise that resolves after every pool closes.
|
|
174
|
+
*/
|
|
175
|
+
async drain() {
|
|
176
|
+
super.close();
|
|
177
|
+
for (const handle of this.#handles)
|
|
178
|
+
handle.close();
|
|
179
|
+
await this.#catalog.close();
|
|
180
|
+
await Promise.all([...this.#databases.values()].map(({ pool }) => pool.end()));
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Connects every configured database before exposing a factory.
|
|
184
|
+
*
|
|
185
|
+
* @param entries Supply validated database configurations.
|
|
186
|
+
* @param resolver Resolves physical table names.
|
|
187
|
+
* @param operation Optionally creates custom table SQL.
|
|
188
|
+
* @param stringifiers Convert message values reversibly.
|
|
189
|
+
* @returns The connected factory.
|
|
190
|
+
*/
|
|
191
|
+
static async connect(entries, resolver = new PostgresTableResolver(), operation, stringifiers = new StringifierRegistry()) {
|
|
192
|
+
const connected = [];
|
|
193
|
+
try {
|
|
194
|
+
for (const entry of entries)
|
|
195
|
+
connected.push(await PostgresStorageFactory.prove(entry));
|
|
196
|
+
return new PostgresStorageFactory(connected, resolver, operation, stringifiers);
|
|
197
|
+
}
|
|
198
|
+
catch (error) {
|
|
199
|
+
await Promise.all(connected.map(({ pool }) => pool.end().catch(() => undefined)));
|
|
200
|
+
if (error instanceof PostgresStorageConfigurationError)
|
|
201
|
+
throw error;
|
|
202
|
+
throw new PostgresStorageConnectionError("Unable to connect to PostgreSQL.");
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Opens one pool and proves its selected schema is usable.
|
|
207
|
+
*
|
|
208
|
+
* @param entry Supplies one database configuration.
|
|
209
|
+
* @returns The connected database resource.
|
|
210
|
+
*/
|
|
211
|
+
static async prove(entry) {
|
|
212
|
+
const pool = new Pool(entry.poolOptions);
|
|
213
|
+
try {
|
|
214
|
+
const client = await pool.connect();
|
|
215
|
+
try {
|
|
216
|
+
const schema = await PostgresSchemas.resolve(client, entry.schema);
|
|
217
|
+
await PostgresSchemas.assertUsable(client, schema);
|
|
218
|
+
return { boundary: entry.boundary, pool, schema, databaseName: entry.databaseName };
|
|
219
|
+
}
|
|
220
|
+
finally {
|
|
221
|
+
client.release();
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
catch (error) {
|
|
225
|
+
await pool.end().catch(() => undefined);
|
|
226
|
+
throw error;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Finds the configured database for a storage context.
|
|
231
|
+
*
|
|
232
|
+
* @param context Identifies the tenant boundary.
|
|
233
|
+
* @returns The matching database resource.
|
|
234
|
+
*/
|
|
235
|
+
database(context) {
|
|
236
|
+
const boundary = TenantBoundary.of(context);
|
|
237
|
+
const database = this.#databases.get(boundary.key);
|
|
238
|
+
if (database !== undefined)
|
|
239
|
+
return database;
|
|
240
|
+
throw new PostgresStorageConfigurationError(boundary.single
|
|
241
|
+
? "PostgreSQL storage is configured for multiple tenants."
|
|
242
|
+
: "PostgreSQL storage has no configured database for the requested tenant.");
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Exposes record-lifecycle operations for one database resource.
|
|
246
|
+
*
|
|
247
|
+
* @param database Supplies the connected database.
|
|
248
|
+
* @returns Its package-local record lifecycle.
|
|
249
|
+
*/
|
|
250
|
+
connections(database) {
|
|
251
|
+
return {
|
|
252
|
+
databaseName: database.databaseName,
|
|
253
|
+
schema: database.schema,
|
|
254
|
+
acquire: () => database.pool.connect(),
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Collects validated options before connecting a PostgreSQL storage factory.
|
|
260
|
+
*/
|
|
261
|
+
class Builder {
|
|
262
|
+
connect;
|
|
263
|
+
#options;
|
|
264
|
+
#tenantOptions;
|
|
265
|
+
#operationFactory;
|
|
266
|
+
#stringifiers = new StringifierRegistry();
|
|
267
|
+
#resolver = new PostgresTableResolver();
|
|
268
|
+
/**
|
|
269
|
+
* Sets the single-database connection options.
|
|
270
|
+
*
|
|
271
|
+
* @param options Specify the PostgreSQL connection.
|
|
272
|
+
* @returns This builder.
|
|
273
|
+
*/
|
|
274
|
+
setOptions(options) {
|
|
275
|
+
this.#options = {
|
|
276
|
+
...options,
|
|
277
|
+
...(options.tls === undefined ? {} : { tls: { ...options.tls } }),
|
|
278
|
+
};
|
|
279
|
+
return this;
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Sets the complete tenant-to-database registry.
|
|
283
|
+
*
|
|
284
|
+
* @param entries Assign tenants to distinct databases.
|
|
285
|
+
* @returns This builder.
|
|
286
|
+
*/
|
|
287
|
+
setTenantOptions(entries) {
|
|
288
|
+
this.#tenantOptions = entries.map(({ tenantId, options }) => ({
|
|
289
|
+
tenantId,
|
|
290
|
+
options: { ...options, ...(options.tls === undefined ? {} : { tls: { ...options.tls } }) },
|
|
291
|
+
}));
|
|
292
|
+
return this;
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Sets custom reversible message stringifiers.
|
|
296
|
+
*
|
|
297
|
+
* @param registry Supplies the schema-bound registry.
|
|
298
|
+
* @returns This builder.
|
|
299
|
+
*/
|
|
300
|
+
setStringifierRegistry(registry) {
|
|
301
|
+
this.#stringifiers = new StringifierRegistry(registry);
|
|
302
|
+
return this;
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Applies either supported table-name overload.
|
|
306
|
+
*
|
|
307
|
+
* @param args Supply the overload arguments.
|
|
308
|
+
* @returns This builder.
|
|
309
|
+
*/
|
|
310
|
+
setTableName(...args) {
|
|
311
|
+
if (args.length === 2)
|
|
312
|
+
this.#resolver.setRecordName(args[0].typeName, args[1]);
|
|
313
|
+
else
|
|
314
|
+
this.#resolver.setGroupName(args[0].typeName, args[1].typeName, args[2]);
|
|
315
|
+
return this;
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Sets the custom create-table operation factory.
|
|
319
|
+
*
|
|
320
|
+
* @param factory Creates SQL for resolved table specifications.
|
|
321
|
+
* @returns This builder.
|
|
322
|
+
*/
|
|
323
|
+
useOperationFactory(factory) {
|
|
324
|
+
this.#operationFactory = factory;
|
|
325
|
+
return this;
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Creates a builder with its factory connection function.
|
|
329
|
+
*
|
|
330
|
+
* @param connect Connects validated database configurations.
|
|
331
|
+
*/
|
|
332
|
+
constructor(connect) {
|
|
333
|
+
this.connect = connect;
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Validates the selected mode and connects a factory.
|
|
337
|
+
*
|
|
338
|
+
* @returns The connected PostgreSQL storage factory.
|
|
339
|
+
*/
|
|
340
|
+
build() {
|
|
341
|
+
try {
|
|
342
|
+
if (this.#options === undefined && this.#tenantOptions === undefined)
|
|
343
|
+
throw new PostgresStorageConfigurationError("PostgreSQL storage options are required.");
|
|
344
|
+
if (this.#options !== undefined && this.#tenantOptions !== undefined)
|
|
345
|
+
throw new PostgresStorageConfigurationError("Configure either single-tenant or multitenant PostgreSQL storage, not both.");
|
|
346
|
+
const entries = this.#options === undefined
|
|
347
|
+
? PostgresConfigurations.multitenant(this.#tenantOptions ?? [])
|
|
348
|
+
: [PostgresConfigurations.single(this.#options)];
|
|
349
|
+
return this.connect(entries, this.#resolver, this.#operationFactory, this.#stringifiers);
|
|
350
|
+
}
|
|
351
|
+
catch (error) {
|
|
352
|
+
return Promise.reject(error instanceof Error
|
|
353
|
+
? error
|
|
354
|
+
: new PostgresStorageConfigurationError("PostgreSQL storage configuration is invalid."));
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Reports the immutable tenant boundaries configured by the factory.
|
|
360
|
+
*/
|
|
361
|
+
class PostgresTenantCatalog {
|
|
362
|
+
boundaries;
|
|
363
|
+
/**
|
|
364
|
+
* Creates a catalog from configured tenant boundaries.
|
|
365
|
+
*
|
|
366
|
+
* @param boundaries Supply the configured boundaries.
|
|
367
|
+
*/
|
|
368
|
+
constructor(boundaries) {
|
|
369
|
+
this.boundaries = boundaries;
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* Returns every configured boundary.
|
|
373
|
+
*
|
|
374
|
+
* @returns The configured boundaries.
|
|
375
|
+
*/
|
|
376
|
+
all() {
|
|
377
|
+
return Promise.resolve(this.boundaries);
|
|
378
|
+
}
|
|
379
|
+
/**
|
|
380
|
+
* Checks that a boundary belongs to this fixed catalog.
|
|
381
|
+
*
|
|
382
|
+
* @param boundary Supplies the boundary to confirm.
|
|
383
|
+
* @returns A promise that resolves when the boundary is configured.
|
|
384
|
+
*/
|
|
385
|
+
keep(boundary) {
|
|
386
|
+
if (!this.boundaries.some(({ key }) => key === boundary.key)) {
|
|
387
|
+
return Promise.reject(new PostgresStorageConfigurationError("PostgreSQL tenant is not configured."));
|
|
388
|
+
}
|
|
389
|
+
return Promise.resolve();
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* Closes the catalog, which holds no external resources.
|
|
393
|
+
*
|
|
394
|
+
* @returns An already resolved promise.
|
|
395
|
+
*/
|
|
396
|
+
close() {
|
|
397
|
+
return Promise.resolve();
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Validates public options and builds internal database configurations.
|
|
402
|
+
*/
|
|
403
|
+
const PostgresConfigurations = Object.freeze({
|
|
404
|
+
/**
|
|
405
|
+
* Builds the single-tenant database configuration.
|
|
406
|
+
*
|
|
407
|
+
* @param options Specify the database connection.
|
|
408
|
+
* @returns The validated internal configuration.
|
|
409
|
+
*/
|
|
410
|
+
single(options) {
|
|
411
|
+
return PostgresConfigurations.parse(TenantBoundary.single, options);
|
|
412
|
+
},
|
|
413
|
+
/**
|
|
414
|
+
* Builds configurations for the complete tenant registry.
|
|
415
|
+
*
|
|
416
|
+
* @param entries Assign tenants to their databases.
|
|
417
|
+
* @returns Validated internal configurations.
|
|
418
|
+
*/
|
|
419
|
+
multitenant(entries) {
|
|
420
|
+
if (entries.length === 0) {
|
|
421
|
+
throw new PostgresStorageConfigurationError("Multitenant PostgreSQL storage requires tenants.");
|
|
422
|
+
}
|
|
423
|
+
const configured = entries.map(({ tenantId, options }) => PostgresConfigurations.parse(TenantBoundary.from(tenantId), options));
|
|
424
|
+
PostgresConfigurations.assertDistinct(configured);
|
|
425
|
+
return configured;
|
|
426
|
+
},
|
|
427
|
+
/**
|
|
428
|
+
* Rejects duplicate tenants and shared physical database targets.
|
|
429
|
+
*
|
|
430
|
+
* @param entries Supply validated database configurations.
|
|
431
|
+
*/
|
|
432
|
+
assertDistinct(entries) {
|
|
433
|
+
const tenants = new Set();
|
|
434
|
+
const targets = new Set();
|
|
435
|
+
for (const entry of entries) {
|
|
436
|
+
if (tenants.has(entry.boundary.key)) {
|
|
437
|
+
throw new PostgresStorageConfigurationError("PostgreSQL storage has a duplicate tenant.");
|
|
438
|
+
}
|
|
439
|
+
if (targets.has(entry.target)) {
|
|
440
|
+
throw new PostgresStorageConfigurationError("PostgreSQL tenants must use distinct physical databases.");
|
|
441
|
+
}
|
|
442
|
+
tenants.add(entry.boundary.key);
|
|
443
|
+
targets.add(entry.target);
|
|
444
|
+
}
|
|
445
|
+
},
|
|
446
|
+
/**
|
|
447
|
+
* Converts one public database configuration to pool settings.
|
|
448
|
+
*
|
|
449
|
+
* @param boundary Identifies the tenant boundary.
|
|
450
|
+
* @param options Specify the database connection.
|
|
451
|
+
* @returns The internal database configuration.
|
|
452
|
+
*/
|
|
453
|
+
parse(boundary, options) {
|
|
454
|
+
const url = PostgresConfigurations.url(options.url);
|
|
455
|
+
PostgresConfigurations.validate(options);
|
|
456
|
+
const port = url.port === "" ? 5432 : Number(url.port);
|
|
457
|
+
const database = decodeURIComponent(url.pathname.slice(1));
|
|
458
|
+
return {
|
|
459
|
+
boundary,
|
|
460
|
+
schema: options.schema,
|
|
461
|
+
target: `${url.hostname.toLowerCase()}:${String(port)}/${database.toLowerCase()}`,
|
|
462
|
+
databaseName: database,
|
|
463
|
+
poolOptions: {
|
|
464
|
+
host: url.hostname,
|
|
465
|
+
...(url.port === "" ? {} : { port }),
|
|
466
|
+
database,
|
|
467
|
+
...(url.username === "" ? {} : { user: decodeURIComponent(url.username) }),
|
|
468
|
+
...(url.password === "" ? {} : { password: decodeURIComponent(url.password) }),
|
|
469
|
+
...(options.connectionLimit === undefined ? {} : { max: options.connectionLimit }),
|
|
470
|
+
...(options.connectTimeoutMs === undefined
|
|
471
|
+
? {}
|
|
472
|
+
: { connectionTimeoutMillis: options.connectTimeoutMs }),
|
|
473
|
+
...(options.tls === undefined ? {} : { ssl: options.tls }),
|
|
474
|
+
},
|
|
475
|
+
};
|
|
476
|
+
},
|
|
477
|
+
/**
|
|
478
|
+
* Parses and validates a PostgreSQL database URL.
|
|
479
|
+
*
|
|
480
|
+
* @param value Supplies the configured URL.
|
|
481
|
+
* @returns The parsed URL.
|
|
482
|
+
*/
|
|
483
|
+
url(value) {
|
|
484
|
+
let url;
|
|
485
|
+
try {
|
|
486
|
+
url = new URL(value);
|
|
487
|
+
}
|
|
488
|
+
catch {
|
|
489
|
+
throw new PostgresStorageConfigurationError("PostgreSQL storage requires a valid URL.");
|
|
490
|
+
}
|
|
491
|
+
if ((url.protocol !== "postgres:" && url.protocol !== "postgresql:") ||
|
|
492
|
+
url.pathname.length <= 1 ||
|
|
493
|
+
url.hash !== "" ||
|
|
494
|
+
url.search !== "") {
|
|
495
|
+
throw new PostgresStorageConfigurationError("PostgreSQL storage URL requires a database.");
|
|
496
|
+
}
|
|
497
|
+
return url;
|
|
498
|
+
},
|
|
499
|
+
/**
|
|
500
|
+
* Validates scalar connection and schema options.
|
|
501
|
+
*
|
|
502
|
+
* @param options Supply the public configuration.
|
|
503
|
+
*/
|
|
504
|
+
validate(options) {
|
|
505
|
+
if (!PostgresConfigurations.positive(options.connectionLimit)) {
|
|
506
|
+
throw new PostgresStorageConfigurationError("PostgreSQL connection limit is invalid.");
|
|
507
|
+
}
|
|
508
|
+
if (!PostgresConfigurations.positive(options.connectTimeoutMs)) {
|
|
509
|
+
throw new PostgresStorageConfigurationError("PostgreSQL connection timeout is invalid.");
|
|
510
|
+
}
|
|
511
|
+
if (options.schema !== undefined && !/^[A-Za-z_][A-Za-z0-9_]{0,62}$/u.test(options.schema)) {
|
|
512
|
+
throw new PostgresStorageConfigurationError("PostgreSQL schema name is invalid.");
|
|
513
|
+
}
|
|
514
|
+
},
|
|
515
|
+
/**
|
|
516
|
+
* Checks whether an optional numeric setting is a positive integer.
|
|
517
|
+
*
|
|
518
|
+
* @param value Supplies the optional setting.
|
|
519
|
+
* @returns Whether the setting is absent or valid.
|
|
520
|
+
*/
|
|
521
|
+
positive(value) {
|
|
522
|
+
return value === undefined || (Number.isInteger(value) && value > 0);
|
|
523
|
+
},
|
|
524
|
+
});
|
|
525
|
+
/**
|
|
526
|
+
* Adapts a public create-table operation to the record handle callback.
|
|
527
|
+
*
|
|
528
|
+
* @typeParam I The storage identifier type.
|
|
529
|
+
* @typeParam R The stored Protobuf record type.
|
|
530
|
+
* @param operation Creates a public operation for a resolved table.
|
|
531
|
+
* @param table Supplies the resolved table specification.
|
|
532
|
+
* @returns A callback that returns the operation SQL.
|
|
533
|
+
*/
|
|
534
|
+
function createOperation(operation, table) {
|
|
535
|
+
return () => operation(table).sql;
|
|
536
|
+
}
|
|
537
|
+
/**
|
|
538
|
+
* Resolves and validates schemas used by connected pools.
|
|
539
|
+
*/
|
|
540
|
+
const PostgresSchemas = Object.freeze({
|
|
541
|
+
/**
|
|
542
|
+
* Resolves an explicit or connection-default schema.
|
|
543
|
+
*
|
|
544
|
+
* @param client Provides a connected client.
|
|
545
|
+
* @param explicit Optionally names the configured schema.
|
|
546
|
+
* @returns The existing schema name.
|
|
547
|
+
*/
|
|
548
|
+
async resolve(client, explicit) {
|
|
549
|
+
const schema = explicit ?? (await PostgresSchemas.current(client));
|
|
550
|
+
const result = await client.query("SELECT 1 FROM information_schema.schemata WHERE schema_name = $1", [schema]);
|
|
551
|
+
if (result.rowCount !== 1)
|
|
552
|
+
throw new PostgresStorageConfigurationError("PostgreSQL schema does not exist.");
|
|
553
|
+
return schema;
|
|
554
|
+
},
|
|
555
|
+
/**
|
|
556
|
+
* Reads and validates the connection's current schema.
|
|
557
|
+
*
|
|
558
|
+
* @param client Provides a connected client.
|
|
559
|
+
* @returns The current schema name.
|
|
560
|
+
*/
|
|
561
|
+
async current(client) {
|
|
562
|
+
const result = await client.query("SELECT current_schema() AS schema");
|
|
563
|
+
const schema = result.rows[0]?.schema;
|
|
564
|
+
if (schema === null || schema === undefined || !/^[A-Za-z_][A-Za-z0-9_]{0,62}$/u.test(schema)) {
|
|
565
|
+
throw new PostgresStorageConfigurationError("PostgreSQL schema is invalid.");
|
|
566
|
+
}
|
|
567
|
+
return schema;
|
|
568
|
+
},
|
|
569
|
+
/**
|
|
570
|
+
* Rejects schemas that contain the retired storage layout.
|
|
571
|
+
*
|
|
572
|
+
* @param client Provides a connected client.
|
|
573
|
+
* @param schema Names the selected schema.
|
|
574
|
+
* @returns A promise that resolves when the schema is usable.
|
|
575
|
+
*/
|
|
576
|
+
async assertUsable(client, schema) {
|
|
577
|
+
const result = await client.query("SELECT 1 FROM information_schema.columns WHERE table_schema = $1 " +
|
|
578
|
+
"AND LOWER(column_name) IN ('_scope', '_revision') LIMIT 1", [schema]);
|
|
579
|
+
if ((result.rowCount ?? 0) > 0) {
|
|
580
|
+
throw new PostgresStorageConfigurationError("The configured database contains the retired storage layout.");
|
|
581
|
+
}
|
|
582
|
+
},
|
|
583
|
+
});
|
|
584
|
+
//# sourceMappingURL=storage-factory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage-factory.js","sourceRoot":"","sources":["../../src/postgres/storage-factory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { PoolClient } from "pg";
|
|
2
|
+
import type { PostgresTableSpec } from "./storage-factory.js";
|
|
3
|
+
/**
|
|
4
|
+
* Prepares one PostgreSQL record-family table.
|
|
5
|
+
*/
|
|
6
|
+
export declare class PostgresTableInitializer {
|
|
7
|
+
#private;
|
|
8
|
+
private readonly lifecycle;
|
|
9
|
+
private readonly schema;
|
|
10
|
+
private readonly table;
|
|
11
|
+
private readonly customCreate?;
|
|
12
|
+
/**
|
|
13
|
+
* Creates a private initializer for one resolved PostgreSQL table.
|
|
14
|
+
*
|
|
15
|
+
* @param lifecycle Acquires clients and supplies the stable database lock identity.
|
|
16
|
+
* @param schema Names the resolved PostgreSQL schema.
|
|
17
|
+
* @param table Describes the canonical record-family layout.
|
|
18
|
+
* @param customCreate Optionally supplies caller-defined create-table SQL.
|
|
19
|
+
*/
|
|
20
|
+
constructor(lifecycle: PostgresClientLifecycle, schema: string, table: PostgresTableSpec<unknown, never>, customCreate?: (() => string) | undefined);
|
|
21
|
+
/**
|
|
22
|
+
* Prepares the table once.
|
|
23
|
+
*
|
|
24
|
+
* @returns Completion of initialization.
|
|
25
|
+
*/
|
|
26
|
+
prepare(): Promise<void>;
|
|
27
|
+
/**
|
|
28
|
+
* Retries initialization only after an admitted transaction conflict.
|
|
29
|
+
*
|
|
30
|
+
* @param error Initial table-preparation failure.
|
|
31
|
+
* @returns Completion of the retry attempt.
|
|
32
|
+
*/
|
|
33
|
+
private retry;
|
|
34
|
+
/**
|
|
35
|
+
* Creates and verifies the table inside one transaction.
|
|
36
|
+
*
|
|
37
|
+
* @returns Completion after commit.
|
|
38
|
+
*/
|
|
39
|
+
private attempt;
|
|
40
|
+
/**
|
|
41
|
+
* Acquires the transaction lock for this physical table.
|
|
42
|
+
*
|
|
43
|
+
* @param client PostgreSQL transaction client.
|
|
44
|
+
* @returns PostgreSQL lock-query result.
|
|
45
|
+
*/
|
|
46
|
+
private lock;
|
|
47
|
+
/**
|
|
48
|
+
* Builds the default idempotent table-creation statement.
|
|
49
|
+
*
|
|
50
|
+
* @returns Schema-qualified PostgreSQL DDL.
|
|
51
|
+
*/
|
|
52
|
+
private create;
|
|
53
|
+
/**
|
|
54
|
+
* Verifies columns, primary key, and unsupported unique constraints.
|
|
55
|
+
*
|
|
56
|
+
* @param client PostgreSQL transaction client.
|
|
57
|
+
* @returns Completion after catalog verification.
|
|
58
|
+
*/
|
|
59
|
+
private verify;
|
|
60
|
+
}
|
|
61
|
+
interface PostgresClientLifecycle {
|
|
62
|
+
readonly acquire: () => Promise<PoolClient>;
|
|
63
|
+
readonly lockIdentity?: string;
|
|
64
|
+
}
|
|
65
|
+
export {};
|
|
66
|
+
//# sourceMappingURL=table-initializer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"table-initializer.d.ts","sourceRoot":"","sources":["../../src/postgres/table-initializer.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAGrC,OAAO,KAAK,EAAsB,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AASlF;;GAEG;AACH,qBAAa,wBAAwB;;IAYjC,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC;IAZhC;;;;;;;OAOG;gBAEgB,SAAS,EAAE,uBAAuB,EAClC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,iBAAiB,CAAC,OAAO,EAAE,KAAK,CAAC,EACxC,YAAY,CAAC,GAAE,MAAM,MAAM,aAAA;IAG9C;;;;OAIG;IACH,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAKxB;;;;;OAKG;IACH,OAAO,CAAC,KAAK;IAKb;;;;OAIG;YACW,OAAO;IAqBrB;;;;;OAKG;IACH,OAAO,CAAC,IAAI;IAMZ;;;;OAIG;IACH,OAAO,CAAC,MAAM;IAOd;;;;;OAKG;YACW,MAAM;CASrB;AAED,UAAU,uBAAuB;IAC/B,QAAQ,CAAC,OAAO,EAAE,MAAM,OAAO,CAAC,UAAU,CAAC,CAAC;IAC5C,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAChC"}
|