@stratal/framework 0.0.0-canary-ccb3f17 → 0.0.0-canary-e5681b8
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 +655 -0
- package/README.md +166 -24
- package/dist/access-control/index.d.mts +8 -8
- package/dist/access-control/index.d.mts.map +1 -1
- package/dist/access-control/index.mjs +2 -2
- package/dist/{access.service-rsEreT-4.mjs → access.service-BjmnWBEo.mjs} +3 -3
- package/dist/{access.service-rsEreT-4.mjs.map → access.service-BjmnWBEo.mjs.map} +1 -1
- package/dist/auth/index.d.mts +49 -48
- package/dist/auth/index.d.mts.map +1 -1
- package/dist/auth/index.mjs +86 -17
- package/dist/auth/index.mjs.map +1 -1
- package/dist/{auth-context-CE_-TV27.mjs → auth-context-cNSS1rmh.mjs} +2 -2
- package/dist/{auth-context-CE_-TV27.mjs.map → auth-context-cNSS1rmh.mjs.map} +1 -1
- package/dist/context/index.d.mts +3 -3
- package/dist/context/index.d.mts.map +1 -1
- package/dist/context/index.mjs +1 -1
- package/dist/database/index.d.mts +3 -3
- package/dist/database/index.mjs +288 -9
- package/dist/database/index.mjs.map +1 -1
- package/dist/{decorate-ZDdbRmsv.mjs → decorate-RQD1h28J.mjs} +1 -1
- package/dist/{decorateParam-DQ95ttaa.mjs → decorateParam-xwTkq9gO.mjs} +2 -2
- package/dist/{decorateParam-DQ95ttaa.mjs.map → decorateParam-xwTkq9gO.mjs.map} +1 -1
- package/dist/factory/index.d.mts +3 -4
- package/dist/factory/index.d.mts.map +1 -1
- package/dist/guards/index.d.mts +3 -3
- package/dist/guards/index.d.mts.map +1 -1
- package/dist/guards/index.mjs +4 -4
- package/dist/index-e_u1SRyd.d.mts +921 -0
- package/dist/index-e_u1SRyd.d.mts.map +1 -0
- package/dist/index.d.mts +1 -1
- package/dist/{types-DjLXYLlD.d.mts → types-B35g-lXi.d.mts} +18 -3
- package/dist/types-B35g-lXi.d.mts.map +1 -0
- package/package.json +29 -25
- package/dist/index-B8EVn7T5.d.mts +0 -481
- package/dist/index-B8EVn7T5.d.mts.map +0 -1
- package/dist/types-DjLXYLlD.d.mts.map +0 -1
package/dist/database/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { t as __decorate } from "../decorate-
|
|
2
|
-
import { DI_TOKENS,
|
|
1
|
+
import { t as __decorate } from "../decorate-RQD1h28J.mjs";
|
|
2
|
+
import { DI_TOKENS, Request, inject, lazy } from "stratal/di";
|
|
3
3
|
import { Module } from "stratal/module";
|
|
4
|
-
import { DatabaseError, HttpException } from "stratal/errors";
|
|
4
|
+
import { ApplicationError, DatabaseError, HttpException } from "stratal/errors";
|
|
5
5
|
import { I18nModule } from "stratal/i18n";
|
|
6
6
|
import { Command } from "stratal/quarry";
|
|
7
7
|
import { ORMError, ORMErrorReason, ZenStackClient } from "@zenstackhq/orm";
|
|
@@ -124,6 +124,259 @@ var MigrateStatusCommand = class extends ZenStackCommand {
|
|
|
124
124
|
}
|
|
125
125
|
};
|
|
126
126
|
//#endregion
|
|
127
|
+
//#region src/database/errors/cursor-model-unavailable.error.ts
|
|
128
|
+
/**
|
|
129
|
+
* Raised when `db.$cursor.<model>` cannot reach a model delegate on the client
|
|
130
|
+
* it was built for — the schema declares the model, the client does not answer
|
|
131
|
+
* for it.
|
|
132
|
+
*
|
|
133
|
+
* This is a **programming error**, not bad input: the reader is built from the
|
|
134
|
+
* schema's own model list, so reaching it means the client and the schema it was
|
|
135
|
+
* given have come apart — a model sliced out of the client's options, or a
|
|
136
|
+
* hand-assembled client. No request recovers from it and no retry helps. It
|
|
137
|
+
* deliberately carries no HTTP status, so it is never mistaken for something the
|
|
138
|
+
* client sent wrong.
|
|
139
|
+
*
|
|
140
|
+
* `model` names the client key at fault, and is reported to observability so the
|
|
141
|
+
* raise site stays distinguishable without matching on message text.
|
|
142
|
+
*/
|
|
143
|
+
var CursorModelUnavailableError = class extends ApplicationError {
|
|
144
|
+
model;
|
|
145
|
+
constructor(model) {
|
|
146
|
+
super(`[stratal:database] $cursor cannot reach the "${model}" model on this client. The schema declares it, so the client was built with a different schema or with this model sliced out.`);
|
|
147
|
+
this.model = model;
|
|
148
|
+
}
|
|
149
|
+
reportContext() {
|
|
150
|
+
return { model: this.model };
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
//#endregion
|
|
154
|
+
//#region src/database/errors/cursor-ordering.error.ts
|
|
155
|
+
/**
|
|
156
|
+
* Raised when a `$cursor` read is asked for an ordering it cannot address a row
|
|
157
|
+
* in: no `orderBy`, a clause with no `asc`/`desc` direction, an ordering
|
|
158
|
+
* without the unique column that breaks ties, or an ordering column that is
|
|
159
|
+
* absent from the returned row or null on it.
|
|
160
|
+
*
|
|
161
|
+
* This is a **programming error**, not bad input — no request can recover from
|
|
162
|
+
* it and no retry helps, because the query as written cannot produce a stable
|
|
163
|
+
* position. Handlers should let it surface as a `500` and report it; the fix is
|
|
164
|
+
* always in the caller's `orderBy`, `uniqueBy` or `select`. It deliberately
|
|
165
|
+
* carries no HTTP status, so it is never mistaken for something the client sent
|
|
166
|
+
* wrong.
|
|
167
|
+
*
|
|
168
|
+
* `field` names the ordering column at fault where one is identifiable, and is
|
|
169
|
+
* reported to observability so the raise sites stay distinguishable without
|
|
170
|
+
* matching on message text.
|
|
171
|
+
*/
|
|
172
|
+
var CursorOrderingError = class extends ApplicationError {
|
|
173
|
+
field;
|
|
174
|
+
constructor(message, field) {
|
|
175
|
+
super(message);
|
|
176
|
+
this.field = field;
|
|
177
|
+
}
|
|
178
|
+
reportContext() {
|
|
179
|
+
return this.field === void 0 ? void 0 : { field: this.field };
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
//#endregion
|
|
183
|
+
//#region src/database/errors/malformed-cursor.error.ts
|
|
184
|
+
/**
|
|
185
|
+
* Raised when a pagination cursor cannot be read: it is not the base64url
|
|
186
|
+
* payload `$cursor` mints, or it decodes to something that is not a cursor.
|
|
187
|
+
*
|
|
188
|
+
* This is **bad input**, not a broken query. A cursor travels in a query string,
|
|
189
|
+
* so a truncated link, a hand-edited URL, or one minted by an older build all
|
|
190
|
+
* land here, and the request itself is still answerable. It carries its own
|
|
191
|
+
* `400`, so a handler lets it surface rather than catching it to serve the
|
|
192
|
+
* first page — the same refusal any other damaged parameter gets.
|
|
193
|
+
*/
|
|
194
|
+
var MalformedCursorError = class extends HttpException {
|
|
195
|
+
constructor(cause) {
|
|
196
|
+
super(400, "[stratal:database] Malformed pagination cursor.", cause);
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
//#endregion
|
|
200
|
+
//#region src/database/pagination/cursor.ts
|
|
201
|
+
const CURSOR_DIRECTION_KEY = "_next";
|
|
202
|
+
/**
|
|
203
|
+
* base64url, so a cursor survives a query string without escaping.
|
|
204
|
+
*
|
|
205
|
+
* The UTF-8 round trip is load-bearing, not ceremony: `btoa` accepts only
|
|
206
|
+
* Latin-1, and `JSON.stringify` leaves non-ASCII characters as they are. An
|
|
207
|
+
* ordering column is whatever the caller ordered by — a `title`, a `name`, a
|
|
208
|
+
* `slug` — so one row whose value carries CJK, Cyrillic or an emoji would throw
|
|
209
|
+
* `DOMException` while every ASCII row encoded fine. The first page would still
|
|
210
|
+
* answer, because it mints no cursor; the 500 would land on the follow-up.
|
|
211
|
+
*/
|
|
212
|
+
function base64UrlEncode(input) {
|
|
213
|
+
const bytes = new TextEncoder().encode(input);
|
|
214
|
+
const binary = Array.from(bytes, (byte) => String.fromCharCode(byte)).join("");
|
|
215
|
+
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
216
|
+
}
|
|
217
|
+
function base64UrlDecode(input) {
|
|
218
|
+
const padded = input.replace(/-/g, "+").replace(/_/g, "/");
|
|
219
|
+
const binary = atob(padded.padEnd(padded.length + (4 - padded.length % 4) % 4, "="));
|
|
220
|
+
return new TextDecoder().decode(Uint8Array.from(binary, (char) => char.charCodeAt(0)));
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Encodes the ordering values of a row plus the direction it points.
|
|
224
|
+
*
|
|
225
|
+
* The whole ordering tuple travels, not a row id, so the cursor still resolves
|
|
226
|
+
* after the row it was built from is deleted — which is the case cursors are
|
|
227
|
+
* for. The direction rides along because a caller sends every cursor under one
|
|
228
|
+
* query parameter name and nothing else distinguishes forward from backward.
|
|
229
|
+
*/
|
|
230
|
+
function encodeCursor(values, direction) {
|
|
231
|
+
return base64UrlEncode(JSON.stringify({
|
|
232
|
+
...values,
|
|
233
|
+
[CURSOR_DIRECTION_KEY]: direction === "next"
|
|
234
|
+
}));
|
|
235
|
+
}
|
|
236
|
+
/** Reads a cursor minted by {@link encodeCursor}. Throws on anything else. */
|
|
237
|
+
function decodeCursor(cursor) {
|
|
238
|
+
let parsed;
|
|
239
|
+
try {
|
|
240
|
+
parsed = JSON.parse(base64UrlDecode(cursor));
|
|
241
|
+
} catch (cause) {
|
|
242
|
+
throw new MalformedCursorError(cause);
|
|
243
|
+
}
|
|
244
|
+
if (typeof parsed !== "object" || parsed === null || !(CURSOR_DIRECTION_KEY in parsed)) throw new MalformedCursorError();
|
|
245
|
+
const { [CURSOR_DIRECTION_KEY]: pointsToNext, ...values } = parsed;
|
|
246
|
+
return {
|
|
247
|
+
values,
|
|
248
|
+
direction: pointsToNext ? "next" : "prev"
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
function normalizeOrderBy(orderBy) {
|
|
252
|
+
return (Array.isArray(orderBy) ? orderBy : [orderBy]).flatMap((clause) => Object.entries(clause)).map(([field, direction]) => {
|
|
253
|
+
if (direction !== "asc" && direction !== "desc") throw new CursorOrderingError(`[stratal:database] $cursor needs a direction for "${field}"; got ${JSON.stringify(direction)}.`, field);
|
|
254
|
+
return [field, direction];
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Builds the keyset condition for "the rows after (or before) this position".
|
|
259
|
+
*
|
|
260
|
+
* For `updatedAt desc, id desc` this is
|
|
261
|
+
* `updatedAt < :updatedAt OR (updatedAt = :updatedAt AND id < :id)` — one
|
|
262
|
+
* disjunct per ordering column, each pinning the columns to its left to
|
|
263
|
+
* equality. Reading backwards flips every comparison.
|
|
264
|
+
*/
|
|
265
|
+
function buildKeysetCondition(order, values, direction) {
|
|
266
|
+
const disjuncts = [];
|
|
267
|
+
for (let i = 0; i < order.length; i++) {
|
|
268
|
+
const conjunct = {};
|
|
269
|
+
for (let j = 0; j < i; j++) {
|
|
270
|
+
const [field] = order[j];
|
|
271
|
+
conjunct[field] = values[field];
|
|
272
|
+
}
|
|
273
|
+
const [field, sort] = order[i];
|
|
274
|
+
conjunct[field] = { [sort === "desc" === (direction === "next") ? "lt" : "gt"]: values[field] };
|
|
275
|
+
disjuncts.push(conjunct);
|
|
276
|
+
}
|
|
277
|
+
return { OR: disjuncts };
|
|
278
|
+
}
|
|
279
|
+
/** The ordering values of a row, which is what a cursor is made of. */
|
|
280
|
+
function cursorValuesOf(row, order) {
|
|
281
|
+
const values = {};
|
|
282
|
+
for (const [field] of order) {
|
|
283
|
+
if (!(field in row)) throw new CursorOrderingError(`[stratal:database] Cannot build a cursor: the ordering column "${field}" is not on the returned row. Either it is not a field of this model, or a \`select\` dropped it.`, field);
|
|
284
|
+
const value = row[field];
|
|
285
|
+
if (value === null || value === void 0) throw new CursorOrderingError(`[stratal:database] Cannot build a cursor: the ordering column "${field}" is null. \$cursor cannot order on a nullable column — null has no position in an ordering.`, field);
|
|
286
|
+
values[field] = value;
|
|
287
|
+
}
|
|
288
|
+
return values;
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Reads one page of rows by cursor.
|
|
292
|
+
*
|
|
293
|
+
* Fetches one row more than asked for, which is how the next page is known to
|
|
294
|
+
* exist without a `COUNT` — and a count is what a growing list cannot give a
|
|
295
|
+
* stable answer to anyway.
|
|
296
|
+
*
|
|
297
|
+
* @example
|
|
298
|
+
* ```typescript
|
|
299
|
+
* const page = await db.$cursor.$from(threadUnion, {
|
|
300
|
+
* cursor: ctx.query('cursor'),
|
|
301
|
+
* take: 20,
|
|
302
|
+
* orderBy: [{ updatedAt: 'desc' }, { id: 'desc' }],
|
|
303
|
+
* where: { boardId },
|
|
304
|
+
* })
|
|
305
|
+
* ```
|
|
306
|
+
*/
|
|
307
|
+
async function readCursorPage(delegate, args) {
|
|
308
|
+
const order = normalizeOrderBy(args.orderBy);
|
|
309
|
+
if (order.length === 0) throw new CursorOrderingError("[stratal:database] $cursor requires `orderBy`. A cursor addresses a row's position in an ordering, so there is no position to address without one.");
|
|
310
|
+
const uniqueBy = args.uniqueBy ?? "id";
|
|
311
|
+
if (!order.some(([field]) => field === uniqueBy)) throw new CursorOrderingError(`[stratal:database] $cursor requires the ordering to include the unique column "${uniqueBy}", otherwise tied rows share a position and paging over them skips or repeats. Add it last — e.g. \`orderBy: [{ ${order[0][0]}: '${order[0][1]}' }, { ${uniqueBy}: '${order[0][1]}' }]\` — or name a different unique column with \`uniqueBy\`.`);
|
|
312
|
+
const decoded = args.cursor ? decodeCursor(args.cursor) : null;
|
|
313
|
+
const readingBackwards = decoded?.direction === "prev";
|
|
314
|
+
const queryOrder = readingBackwards ? order.map(([field, sort]) => [field, sort === "asc" ? "desc" : "asc"]) : order;
|
|
315
|
+
const conditions = [];
|
|
316
|
+
if (args.where) conditions.push(args.where);
|
|
317
|
+
if (decoded) conditions.push(buildKeysetCondition(order, decoded.values, decoded.direction));
|
|
318
|
+
const query = {
|
|
319
|
+
...conditions.length > 0 ? { where: conditions.length === 1 ? conditions[0] : { AND: conditions } } : {},
|
|
320
|
+
orderBy: queryOrder.map(([field, sort]) => ({ [field]: sort })),
|
|
321
|
+
take: args.take + 1,
|
|
322
|
+
...args.include ? { include: args.include } : {},
|
|
323
|
+
...args.select ? { select: args.select } : {},
|
|
324
|
+
...args.omit ? { omit: args.omit } : {}
|
|
325
|
+
};
|
|
326
|
+
const rows = await delegate.findMany(query);
|
|
327
|
+
const hasExtraRow = rows.length > args.take;
|
|
328
|
+
const page = hasExtraRow ? rows.slice(0, args.take) : rows;
|
|
329
|
+
const data = readingBackwards ? [...page].reverse() : page;
|
|
330
|
+
const first = data[0];
|
|
331
|
+
const last = data[data.length - 1];
|
|
332
|
+
const nextCursor = last === void 0 ? null : readingBackwards ? encodeCursor(cursorValuesOf(last, order), "next") : hasExtraRow ? encodeCursor(cursorValuesOf(last, order), "next") : null;
|
|
333
|
+
const prevCursor = first === void 0 ? null : readingBackwards ? hasExtraRow ? encodeCursor(cursorValuesOf(first, order), "prev") : null : decoded ? encodeCursor(cursorValuesOf(first, order), "prev") : null;
|
|
334
|
+
return {
|
|
335
|
+
data,
|
|
336
|
+
perPage: args.take,
|
|
337
|
+
cursorName: args.cursorName ?? "cursor",
|
|
338
|
+
cursor: args.cursor ?? null,
|
|
339
|
+
nextCursor,
|
|
340
|
+
prevCursor
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
//#endregion
|
|
344
|
+
//#region src/database/pagination/cursor-reader.ts
|
|
345
|
+
/**
|
|
346
|
+
* Builds the reader eagerly, one entry per model the schema declares.
|
|
347
|
+
*
|
|
348
|
+
* A plain object rather than a `Proxy`: the model list is known here, and a
|
|
349
|
+
* proxy would answer every property — `then`, `constructor`, an inspector's
|
|
350
|
+
* probe — with something that looks like a reader.
|
|
351
|
+
*
|
|
352
|
+
* The delegate is resolved per call, not captured: ZenStack builds a fresh CRUD
|
|
353
|
+
* handler on each model access, and holding one would pin it for the life of
|
|
354
|
+
* the client.
|
|
355
|
+
*/
|
|
356
|
+
function createCursorReader(client, schema) {
|
|
357
|
+
const source = client;
|
|
358
|
+
const modelEntries = Object.keys(schema.models ?? {}).map((model) => {
|
|
359
|
+
const key = model.charAt(0).toLowerCase() + model.slice(1);
|
|
360
|
+
return [key, { findMany: (args) => {
|
|
361
|
+
const delegate = source[key];
|
|
362
|
+
if (!delegate) throw new CursorModelUnavailableError(key);
|
|
363
|
+
const { cursor, take, orderBy, uniqueBy, cursorName, where, include, select, omit } = args;
|
|
364
|
+
return readCursorPage(delegate, {
|
|
365
|
+
cursor,
|
|
366
|
+
take,
|
|
367
|
+
orderBy,
|
|
368
|
+
uniqueBy,
|
|
369
|
+
cursorName,
|
|
370
|
+
where,
|
|
371
|
+
include,
|
|
372
|
+
select,
|
|
373
|
+
omit
|
|
374
|
+
});
|
|
375
|
+
} }];
|
|
376
|
+
});
|
|
377
|
+
return Object.assign(Object.fromEntries(modelEntries), { $from: (delegate, args) => readCursorPage(delegate, args) });
|
|
378
|
+
}
|
|
379
|
+
//#endregion
|
|
127
380
|
//#region src/database/errors/record-not-found.error.ts
|
|
128
381
|
var RecordNotFoundError = class extends HttpException {
|
|
129
382
|
details;
|
|
@@ -352,6 +605,23 @@ object({
|
|
|
352
605
|
return new Set(names).size === names.length;
|
|
353
606
|
}, withZodI18n("database.duplicateConnections")), refine((config) => config.connections.some((c) => c.name === config.default), withZodI18n("database.defaultConnectionNotFound")));
|
|
354
607
|
/**
|
|
608
|
+
* Puts `$cursor` on a client, base or transaction.
|
|
609
|
+
*
|
|
610
|
+
* Defined on the client rather than contributed as a ZenStack plugin because
|
|
611
|
+
* the client proxy hands a plugin's member back unbound, and this one has to
|
|
612
|
+
* reach the client's own model delegates. Non-enumerable so it stays out of
|
|
613
|
+
* enumeration of the client, and skipped when already present — a reentrant
|
|
614
|
+
* `$transaction` hands back a client that has been through here.
|
|
615
|
+
*/
|
|
616
|
+
function defineCursorReader(client, schema) {
|
|
617
|
+
if ("$cursor" in client) return;
|
|
618
|
+
Object.defineProperty(client, "$cursor", {
|
|
619
|
+
value: createCursorReader(client, schema),
|
|
620
|
+
enumerable: false,
|
|
621
|
+
configurable: true
|
|
622
|
+
});
|
|
623
|
+
}
|
|
624
|
+
/**
|
|
355
625
|
* Wrap a ZenStack client so `$transaction` is reentrant: when a transaction is
|
|
356
626
|
* already open on this connection (tracked per-connection via
|
|
357
627
|
* {@link AsyncLocalStorage}), nested calls run within the active transaction's
|
|
@@ -367,8 +637,13 @@ object({
|
|
|
367
637
|
*
|
|
368
638
|
* ZenStackClient's constructor returns a Proxy (for dynamic model accessors), so
|
|
369
639
|
* a subclass method override is shadowed — hence the proxy wrapper here.
|
|
640
|
+
*
|
|
641
|
+
* `prepareTransactionClient` runs against every transaction client before the
|
|
642
|
+
* callback sees it, which is how the built-in members reach it. ZenStack builds
|
|
643
|
+
* that client itself and types it with its own contract, so there is no other
|
|
644
|
+
* point at which it passes through this package.
|
|
370
645
|
*/
|
|
371
|
-
function makeReentrantTransaction(client, activeTransaction) {
|
|
646
|
+
function makeReentrantTransaction(client, activeTransaction, prepareTransactionClient) {
|
|
372
647
|
return new Proxy(client, { get(target, prop, receiver) {
|
|
373
648
|
if (prop === Symbol.asyncDispose) return () => target.$disconnect();
|
|
374
649
|
if (prop !== "$transaction") return Reflect.get(target, prop, receiver);
|
|
@@ -377,7 +652,10 @@ function makeReentrantTransaction(client, activeTransaction) {
|
|
|
377
652
|
const active = activeTransaction.getStore();
|
|
378
653
|
if (active) return typeof input === "function" ? input(active) : active.$transaction(input, options);
|
|
379
654
|
if (typeof input !== "function") return transaction.call(target, input, options);
|
|
380
|
-
return transaction.call(target, (tx) =>
|
|
655
|
+
return transaction.call(target, (tx) => {
|
|
656
|
+
prepareTransactionClient?.(tx);
|
|
657
|
+
return activeTransaction.run(tx, () => input(tx));
|
|
658
|
+
}, options);
|
|
381
659
|
};
|
|
382
660
|
} });
|
|
383
661
|
}
|
|
@@ -397,7 +675,8 @@ function createDatabaseService(conn, eventRegistry) {
|
|
|
397
675
|
plugins,
|
|
398
676
|
computedFields: conn.computedFields
|
|
399
677
|
});
|
|
400
|
-
|
|
678
|
+
defineCursorReader(this, conn.schema);
|
|
679
|
+
const client = makeReentrantTransaction(this, activeTransaction, (tx) => defineCursorReader(tx, conn.schema));
|
|
401
680
|
for (const ref of instances) if (ref.deref() === void 0) instances.delete(ref);
|
|
402
681
|
instances.add(new WeakRef(client));
|
|
403
682
|
return client;
|
|
@@ -416,7 +695,7 @@ function createDatabaseService(conn, eventRegistry) {
|
|
|
416
695
|
}));
|
|
417
696
|
}
|
|
418
697
|
};
|
|
419
|
-
DatabaseClient = __decorate([
|
|
698
|
+
DatabaseClient = __decorate([Request()], DatabaseClient);
|
|
420
699
|
return DatabaseClient;
|
|
421
700
|
}
|
|
422
701
|
//#endregion
|
|
@@ -462,7 +741,7 @@ let DatabaseModule = _DatabaseModule = class DatabaseModule {
|
|
|
462
741
|
};
|
|
463
742
|
}
|
|
464
743
|
async onInitialize(context) {
|
|
465
|
-
const config = context.container.resolve(DATABASE_TOKENS.Options);
|
|
744
|
+
const config = await context.container.resolve(DATABASE_TOKENS.Options);
|
|
466
745
|
const eventRegistry = (await context.container.resolve(DI_TOKENS.LazyModuleLoader).load(() => import("stratal/events").then((m) => m.EventsModule))).get(DI_TOKENS.EventRegistry);
|
|
467
746
|
for (const conn of config.connections) {
|
|
468
747
|
const Service = createDatabaseService(conn, eventRegistry);
|
|
@@ -583,6 +862,6 @@ function InjectDB(name) {
|
|
|
583
862
|
return inject(connectionSymbol(name));
|
|
584
863
|
}
|
|
585
864
|
//#endregion
|
|
586
|
-
export { DATABASE_TOKENS, DB_SHARED_POOL_ENV, DatabaseModule, DbGenerateCommand, DbPullCommand, DbPushCommand, ErrorHandlerPlugin, EventEmitterPlugin, InjectDB, MigrateDeployCommand, MigrateDevCommand, MigrateResetCommand, MigrateStatusCommand, RecordNotFoundError, SchemaSwitcher, UniqueConstraintError, ZenStackCommand, connectionSymbol, createPoolFactory, databaseMessages, fromZenStackError };
|
|
865
|
+
export { CursorModelUnavailableError, CursorOrderingError, DATABASE_TOKENS, DB_SHARED_POOL_ENV, DatabaseModule, DbGenerateCommand, DbPullCommand, DbPushCommand, ErrorHandlerPlugin, EventEmitterPlugin, InjectDB, MalformedCursorError, MigrateDeployCommand, MigrateDevCommand, MigrateResetCommand, MigrateStatusCommand, RecordNotFoundError, SchemaSwitcher, UniqueConstraintError, ZenStackCommand, connectionSymbol, createCursorReader, createPoolFactory, databaseMessages, decodeCursor, encodeCursor, fromZenStackError };
|
|
587
866
|
|
|
588
867
|
//# sourceMappingURL=index.mjs.map
|