@classytic/mongokit 3.43.0 → 3.44.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/README.md +14 -0
- package/dist/{PaginationEngine-DZnkbSrr.mjs → PaginationEngine-C9iS0U5l.mjs} +13 -27
- package/dist/{PaginationEngine-CRHyuUtw.d.mts → PaginationEngine-D17AthKw.d.mts} +1 -3
- package/dist/{Repository-DnL4xk5w.d.mts → Repository-B6oL6OMv.d.mts} +33 -11
- package/dist/{Repository-Dj6xqPxJ.mjs → Repository-eMRYZ_2Y.mjs} +204 -92
- package/dist/actions/index.d.mts +1 -1
- package/dist/actions/index.mjs +2 -12
- package/dist/actions-DExyXMTy.mjs +11 -0
- package/dist/adapter/index.d.mts +6 -10
- package/dist/adapter/index.mjs +1 -2
- package/dist/{adapter-CkMoMF83.mjs → adapter-Qzgc3ZD_.mjs} +4 -6
- package/dist/ai/index.d.mts +21 -8
- package/dist/ai/index.mjs +15 -9
- package/dist/better-auth/index.d.mts +18 -32
- package/dist/better-auth/index.mjs +3 -4
- package/dist/{coercion-BjdPX3YF.d.mts → coercion-COp9DRNw.d.mts} +0 -2
- package/dist/{create-repository-CJtVdwig.d.mts → create-repository-BOFUYj1l.d.mts} +5 -7
- package/dist/{create-repository-UjwPWR1z.mjs → create-repository-D7MQpIZo.mjs} +4 -5
- package/dist/{derive-DRBiegRH.mjs → derive-Dxsc31fV.mjs} +3 -6
- package/dist/{error-BuByZwKU.mjs → error-DjdmPLWO.mjs} +1 -2
- package/dist/{field-selection-FSQFLpsU.mjs → field-selection-DPFaFw9Y.mjs} +1 -2
- package/dist/{id-chunks-BmAwsqNk.mjs → id-chunks-DH-RAZWG.mjs} +13 -8
- package/dist/{id-resolution-BqDrk0S2.mjs → id-resolution-Cqh49d9J.mjs} +1 -2
- package/dist/idempotency/index.d.mts +4 -7
- package/dist/idempotency/index.mjs +1 -2
- package/dist/{index-SYF8N28D.d.mts → index-8QUEsOFI.d.mts} +3 -4
- package/dist/{index-C0AjVqX3.d.mts → index-ehGZLbrd.d.mts} +2 -8
- package/dist/index.d.mts +63 -96
- package/dist/index.mjs +36 -52
- package/dist/indexes/verify-indexes.d.mts +8 -11
- package/dist/indexes/verify-indexes.mjs +1 -2
- package/dist/{indexes-DIjMpYES.d.mts → indexes-FfyOuhDK.d.mts} +0 -2
- package/dist/{join-scope-DSAznE8E.mjs → join-scope-C1gOtZ59.mjs} +2 -3
- package/dist/kernel-conformance/index.d.mts +39 -13
- package/dist/kernel-conformance/index.mjs +4 -7
- package/dist/lock/index.d.mts +134 -7
- package/dist/lock/index.mjs +349 -14
- package/dist/{logger-K7dPmu2U.mjs → logger-hbWOlj_X.mjs} +1 -2
- package/dist/{method-registry.plugin-C63pGn1d.mjs → method-registry.plugin-CGAepsBU.mjs} +3 -5
- package/dist/{model-registry-ClKtWiHa.mjs → model-registry-DrVfJ3Nt.mjs} +1 -2
- package/dist/{mongooseToJsonSchema-C3k4ide0.mjs → mongooseToJsonSchema-DMDotz4_.mjs} +2 -3
- package/dist/{multi-tenant.plugin-B_q9NUHc.d.mts → multi-tenant.plugin-DfeDMiI8.d.mts} +143 -11
- package/dist/{operations-XiFgG5US.d.mts → operations-Dw9OFV0V.d.mts} +14 -5
- package/dist/outbox/index.d.mts +24 -9
- package/dist/outbox/index.mjs +17 -6
- package/dist/pagination/PaginationEngine.d.mts +1 -1
- package/dist/pagination/PaginationEngine.mjs +1 -2
- package/dist/pagination/utils/limits.d.mts +6 -9
- package/dist/pagination/utils/limits.mjs +2 -3
- package/dist/{pagination-D6psses0.d.mts → pagination-DAUg5zOY.d.mts} +2 -10
- package/dist/{plugin-options-Cirmb4Kp.d.mts → plugin-options-Bpcuz9kS.d.mts} +2 -4
- package/dist/plugins/index.d.mts +6 -7
- package/dist/plugins/index.mjs +6 -7
- package/dist/query/primitives/coercion.d.mts +1 -1
- package/dist/query/primitives/coercion.mjs +2 -3
- package/dist/query/primitives/geo.d.mts +11 -14
- package/dist/query/primitives/geo.mjs +1 -2
- package/dist/query/primitives/indexes.d.mts +1 -1
- package/dist/query/primitives/indexes.mjs +1 -2
- package/dist/{query-defaults-BxUcSOoF.mjs → query-defaults-aUoKlEbh.mjs} +2 -3
- package/dist/read-model/index.d.mts +18 -21
- package/dist/read-model/index.mjs +3 -4
- package/dist/{repository-MqAP409e.d.mts → repository-DzVIwhU2.d.mts} +25 -29
- package/dist/retention-purge-DqcYvRnG.d.mts +35 -0
- package/dist/{rolldown-runtime-D7D4PA-g.mjs → rolldown-runtime-D8jQpDG7.mjs} +1 -2
- package/dist/search/index.d.mts +1 -1
- package/dist/search/index.mjs +1 -2
- package/dist/sync/index.d.mts +95 -15
- package/dist/sync/index.mjs +308 -62
- package/dist/tenant/index.d.mts +8 -11
- package/dist/tenant/index.mjs +1 -2
- package/dist/testkit/index.d.mts +179 -23
- package/dist/testkit/index.mjs +421 -23
- package/dist/{timestamp.plugin-DpOWavVI.mjs → timestamp.plugin-Bz_zL9PX.mjs} +192 -49
- package/dist/{to-plain-vksRrLtc.mjs → to-plain-CEKv_ylg.mjs} +2 -4
- package/dist/{to-plain-o5tUY2nV.d.mts → to-plain-PO5r1Qoy.d.mts} +2 -16
- package/dist/{transaction-DmiB4k2P.mjs → transaction-C2PFxfIv.mjs} +5 -8
- package/dist/{type-utils-CLzRFtIA.d.mts → type-utils-CKvuewAL.d.mts} +0 -2
- package/dist/{update-WgeAUJ_I.mjs → update-DcfmNbJe.mjs} +12 -20
- package/dist/usage/index.d.mts +2 -5
- package/dist/usage/index.mjs +8 -6
- package/dist/utils/index.d.mts +8 -10
- package/dist/utils/index.mjs +7 -7
- package/dist/{validation-chain.plugin-BAeC5eVT.d.mts → validation-chain.plugin-B3gZCZj4.d.mts} +135 -48
- package/dist/{validation-chain.plugin-DRApTmkN.mjs → validation-chain.plugin-DNY6MIF6.mjs} +207 -55
- package/llms.txt +33 -0
- package/package.json +29 -25
- package/skills/mongokit/SKILL.md +112 -0
- package/skills/mongokit/references/pagination-search.md +87 -0
- package/skills/mongokit/references/plugins-tenancy.md +102 -0
- package/skills/mongokit/references/repository-api.md +83 -0
- package/skills/mongokit/references/transactions-outbox.md +101 -0
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { A as ObjectId, D as AnyDocument, F as SortSpec, M as ReadPreferenceType, N as SelectSpec, _ as QueryDefaults, b as WriteConcernSpec, i as CountStrategy, j as PopulateSpec, k as FilterQuery, p as AggregateDefaults, v as ReadConcernLevel } from "./pagination-
|
|
2
|
-
import { r as DocField } from "./type-utils-
|
|
1
|
+
import { A as ObjectId, D as AnyDocument, F as SortSpec, M as ReadPreferenceType, N as SelectSpec, _ as QueryDefaults, b as WriteConcernSpec, i as CountStrategy, j as PopulateSpec, k as FilterQuery, p as AggregateDefaults, v as ReadConcernLevel } from "./pagination-DAUg5zOY.mjs";
|
|
2
|
+
import { r as DocField } from "./type-utils-CKvuewAL.mjs";
|
|
3
3
|
import { DistributionConfig, DistributionMissHandler, RepoCapabilities, RepositoryBase } from "@classytic/repo-core/repository";
|
|
4
4
|
import { Model, PipelineStage } from "mongoose";
|
|
5
5
|
import { HttpError } from "@classytic/repo-core/errors";
|
|
6
6
|
import { OffsetPaginationResult } from "@classytic/repo-core/pagination";
|
|
7
|
-
//#region src/plugins/names.d.ts
|
|
8
7
|
/**
|
|
9
8
|
* Canonical identifiers exposed by mongokit's bundled plugins.
|
|
10
9
|
*
|
|
@@ -13,34 +12,32 @@ import { OffsetPaginationResult } from "@classytic/repo-core/pagination";
|
|
|
13
12
|
* The values intentionally preserve the plugins' existing public names.
|
|
14
13
|
*/
|
|
15
14
|
declare const MONGOKIT_PLUGIN_NAMES: {
|
|
16
|
-
readonly aggregateHelpers:
|
|
17
|
-
readonly appendOnly:
|
|
18
|
-
readonly auditLog:
|
|
19
|
-
readonly auditTrail:
|
|
20
|
-
readonly batchOperations:
|
|
21
|
-
readonly cache:
|
|
22
|
-
readonly cascade:
|
|
23
|
-
readonly changeLog:
|
|
24
|
-
readonly customId:
|
|
25
|
-
readonly elasticSearch:
|
|
26
|
-
readonly fieldFilter:
|
|
27
|
-
readonly immutableStates:
|
|
28
|
-
readonly lease:
|
|
29
|
-
readonly methodRegistry:
|
|
30
|
-
readonly mongoOperations:
|
|
31
|
-
readonly multiTenant:
|
|
32
|
-
readonly observability:
|
|
33
|
-
readonly searchKeys:
|
|
34
|
-
readonly softDelete:
|
|
35
|
-
readonly subdocument:
|
|
36
|
-
readonly timestamp:
|
|
37
|
-
readonly validationChain:
|
|
15
|
+
readonly aggregateHelpers: 'aggregate-helpers';
|
|
16
|
+
readonly appendOnly: 'appendOnly';
|
|
17
|
+
readonly auditLog: 'auditLog';
|
|
18
|
+
readonly auditTrail: 'auditTrail';
|
|
19
|
+
readonly batchOperations: 'batch-operations';
|
|
20
|
+
readonly cache: 'cache';
|
|
21
|
+
readonly cascade: 'cascade';
|
|
22
|
+
readonly changeLog: 'changeLog';
|
|
23
|
+
readonly customId: 'custom-id';
|
|
24
|
+
readonly elasticSearch: 'elastic-search';
|
|
25
|
+
readonly fieldFilter: 'fieldFilter';
|
|
26
|
+
readonly immutableStates: 'immutableStates';
|
|
27
|
+
readonly lease: 'lease';
|
|
28
|
+
readonly methodRegistry: 'method-registry';
|
|
29
|
+
readonly mongoOperations: 'mongo-operations';
|
|
30
|
+
readonly multiTenant: 'multi-tenant';
|
|
31
|
+
readonly observability: 'observability';
|
|
32
|
+
readonly searchKeys: 'search-keys';
|
|
33
|
+
readonly softDelete: 'softDelete';
|
|
34
|
+
readonly subdocument: 'subdocument';
|
|
35
|
+
readonly timestamp: 'timestamp';
|
|
36
|
+
readonly validationChain: 'validation-chain';
|
|
38
37
|
};
|
|
39
38
|
type MongoKitPluginName = (typeof MONGOKIT_PLUGIN_NAMES)[keyof typeof MONGOKIT_PLUGIN_NAMES];
|
|
40
39
|
/** Bundled-name autocomplete while remaining open to third-party plugins. */
|
|
41
40
|
type RepositoryPluginName = MongoKitPluginName | (string & Record<never, never>);
|
|
42
|
-
//#endregion
|
|
43
|
-
//#region src/types/repository.d.ts
|
|
44
41
|
/** Hook execution mode */
|
|
45
42
|
type HookMode = 'sync' | 'async';
|
|
46
43
|
/**
|
|
@@ -533,7 +530,7 @@ type AllPluginMethods<TDoc> = {
|
|
|
533
530
|
setMin(id: string | ObjectId, field: DocField<TDoc>, value: unknown, options?: Record<string, unknown>): Promise<TDoc>;
|
|
534
531
|
setMax(id: string | ObjectId, field: DocField<TDoc>, value: unknown, options?: Record<string, unknown>): Promise<TDoc>;
|
|
535
532
|
atomicUpdate(id: string | ObjectId, operators: Record<string, Record<string, unknown>>, options?: Record<string, unknown>): Promise<TDoc>;
|
|
536
|
-
bulkWrite(operations: Record<string, unknown>[], options?: {
|
|
533
|
+
bulkWrite(operations: readonly Record<string, unknown>[], options?: {
|
|
537
534
|
session?: unknown;
|
|
538
535
|
ordered?: boolean;
|
|
539
536
|
}): Promise<{
|
|
@@ -602,5 +599,4 @@ type AllPluginMethods<TDoc> = {
|
|
|
602
599
|
* ```
|
|
603
600
|
*/
|
|
604
601
|
type WithPlugins<TDoc, TRepo extends RepositoryInstance = RepositoryInstance> = TRepo & AllPluginMethods<TDoc>;
|
|
605
|
-
//#endregion
|
|
606
602
|
export { RepositoryPluginName as C, MongoKitPluginName as S, RepositoryOptions as _, HookMode as a, WithPlugins as b, MinimalRepoView as c, PluginType as d, PrioritizedHook as f, RepositoryOperation as g, RepositoryInstance as h, EventPhase as i, Plugin as l, RepositoryEvent as m, EventHandlers as n, Middleware as o, RepositoryContext as p, EventPayload as r, MiddlewareContext as s, AllPluginMethods as t, PluginFunction as u, RepositorySearchMode as v, MONGOKIT_PLUGIN_NAMES as x, UserContext as y };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { p as RepositoryContext } from "./repository-DzVIwhU2.mjs";
|
|
2
|
+
/** Per-call retention purge request (`options.retentionPurge`). */
|
|
3
|
+
interface RetentionPurgeRequest {
|
|
4
|
+
/** Why the rows are removed (e.g. `'retention: 7 years'`). Required, non-blank. */
|
|
5
|
+
reason: string;
|
|
6
|
+
/** Who or what purges (user id, `'job:retention'`). Carried to the audit events. */
|
|
7
|
+
actor?: string | undefined;
|
|
8
|
+
}
|
|
9
|
+
/** Common payload of the per-plugin purge audit events, one per successful delete call. */
|
|
10
|
+
interface RetentionPurgeEvent {
|
|
11
|
+
operation: 'delete' | 'deleteMany';
|
|
12
|
+
reason: string;
|
|
13
|
+
actor: string | undefined;
|
|
14
|
+
/** `delete`: the id. */
|
|
15
|
+
id: unknown;
|
|
16
|
+
/** `deleteMany`: the final filter (after policy hooks such as tenant scope). */
|
|
17
|
+
filter: Record<string, unknown> | undefined;
|
|
18
|
+
/** Rows removed (`delete`: 1 or 0). */
|
|
19
|
+
deletedCount: number;
|
|
20
|
+
/**
|
|
21
|
+
* The delete's session, when the call ran in one. Write the audit row with it
|
|
22
|
+
* (`{ session: event.session }`) so the delete and its audit commit or abort
|
|
23
|
+
* together. Listeners are awaited and a throwing one fails the purge call.
|
|
24
|
+
*/
|
|
25
|
+
session: unknown;
|
|
26
|
+
context: RepositoryContext;
|
|
27
|
+
}
|
|
28
|
+
/** Error codes thrown for a malformed or unauthorized retention purge. */
|
|
29
|
+
declare const RETENTION_PURGE_ERROR_CODES: {
|
|
30
|
+
readonly DISABLED: 'RETENTION_PURGE_DISABLED';
|
|
31
|
+
readonly REASON_REQUIRED: 'RETENTION_PURGE_REASON_REQUIRED';
|
|
32
|
+
readonly INVALID_ACTOR: 'RETENTION_PURGE_INVALID_ACTOR';
|
|
33
|
+
readonly HARD_ONLY: 'RETENTION_PURGE_HARD_ONLY';
|
|
34
|
+
};
|
|
35
|
+
export { RetentionPurgeEvent as n, RetentionPurgeRequest as r, RETENTION_PURGE_ERROR_CODES as t };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
// \0rolldown/runtime.js
|
|
2
2
|
var __defProp = Object.defineProperty;
|
|
3
3
|
var __exportAll = (all, no_symbols) => {
|
|
4
4
|
let target = {};
|
|
@@ -9,5 +9,4 @@ var __exportAll = (all, no_symbols) => {
|
|
|
9
9
|
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
10
10
|
return target;
|
|
11
11
|
};
|
|
12
|
-
//#endregion
|
|
13
12
|
export { __exportAll as t };
|
package/dist/search/index.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as prefixSearchFilter, c as SearchMatchRange, d as tokenizeSearchText, f as SEARCH_KEYS_ERROR_CODES, i as buildSearchKeys, l as findSearchMatches, n as MAX_PREFIX_SEARCH_TERMS, o as searchKeysIndex, p as SearchKeysWriteError, r as PrefixSearchFilterOptions, s as searchKeysPath, t as DEFAULT_SEARCH_KEYS_FIELD, u as normalizeSearchText } from "../index-
|
|
1
|
+
import { a as prefixSearchFilter, c as SearchMatchRange, d as tokenizeSearchText, f as SEARCH_KEYS_ERROR_CODES, i as buildSearchKeys, l as findSearchMatches, n as MAX_PREFIX_SEARCH_TERMS, o as searchKeysIndex, p as SearchKeysWriteError, r as PrefixSearchFilterOptions, s as searchKeysPath, t as DEFAULT_SEARCH_KEYS_FIELD, u as normalizeSearchText } from "../index-ehGZLbrd.mjs";
|
|
2
2
|
export { DEFAULT_SEARCH_KEYS_FIELD, MAX_PREFIX_SEARCH_TERMS, type PrefixSearchFilterOptions, SEARCH_KEYS_ERROR_CODES, SearchKeysWriteError, type SearchMatchRange, buildSearchKeys, findSearchMatches, normalizeSearchText, prefixSearchFilter, searchKeysIndex, searchKeysPath, tokenizeSearchText };
|
package/dist/search/index.mjs
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export { DEFAULT_SEARCH_KEYS_FIELD, MAX_PREFIX_SEARCH_TERMS, SEARCH_KEYS_ERROR_CODES, SearchKeysWriteError, buildSearchKeys, findSearchMatches, normalizeSearchText, prefixSearchFilter, searchKeysIndex, searchKeysPath, tokenizeSearchText };
|
|
1
|
+
export { l as DEFAULT_SEARCH_KEYS_FIELD, u as MAX_PREFIX_SEARCH_TERMS, t as SEARCH_KEYS_ERROR_CODES, n as SearchKeysWriteError, d as buildSearchKeys, h as findSearchMatches, g as normalizeSearchText, f as prefixSearchFilter, p as searchKeysIndex, m as searchKeysPath, _ as tokenizeSearchText } from "../derive-Dxsc31fV.mjs";
|
package/dist/sync/index.d.mts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { ClientSession, Connection, Model } from "mongoose";
|
|
2
|
-
import { ChangeLogAppendOptions, ChangeLogStore, CommandStreamStore, CommandStreamTx } from "@classytic/repo-core/sync";
|
|
3
|
-
|
|
4
|
-
interface ChangeLogModelOptions {
|
|
2
|
+
import { ChangeEntry, ChangeLogAppendOptions, ChangeLogStore, ChangesSinceOptions, CommandStreamStore, CommandStreamTx } from "@classytic/repo-core/sync";
|
|
3
|
+
export interface ChangeLogModelOptions {
|
|
5
4
|
/** Entries collection. Default `sync_changes`; its counter lives in `<collection>_counter`. */
|
|
6
5
|
collection?: string;
|
|
7
6
|
/** Mongoose model name prefix. Default `SyncChange`. Must be unique per connection. */
|
|
@@ -14,21 +13,40 @@ interface ChangeLogModelOptions {
|
|
|
14
13
|
* before, so no reader can checkpoint past an entry that appears later.
|
|
15
14
|
*/
|
|
16
15
|
sequencing?: 'in-transaction' | 'deferred';
|
|
16
|
+
/**
|
|
17
|
+
* Deferred sequencing: how long the sequencer lease lasts, in ms (default {@link DEFAULT_SEQUENCER_LEASE_MS}).
|
|
18
|
+
* The holder renews it with every batch it commits, so this bounds one batch, not one pass, and it is the longest
|
|
19
|
+
* a sequencer that dies mid-pass can delay numbering. Expiry is judged on the database clock (`$$NOW`), so
|
|
20
|
+
* process clock skew does not stretch it. A holder whose lease was taken over cannot write: each batch commits
|
|
21
|
+
* in one transaction gated on the lease token. Integer, at least 100.
|
|
22
|
+
*/
|
|
23
|
+
sequencerLeaseMs?: number;
|
|
17
24
|
}
|
|
18
|
-
|
|
25
|
+
/** Default deferred-sequencer lease: a crashed holder delays numbering at most this long. */
|
|
26
|
+
export declare const DEFAULT_SEQUENCER_LEASE_MS = 5000;
|
|
27
|
+
export interface ChangeLogModels {
|
|
19
28
|
entries: Model<Record<string, unknown>>;
|
|
20
29
|
counter: Model<Record<string, unknown>>;
|
|
30
|
+
/**
|
|
31
|
+
* `prune`'s horizons per `(tenantId, scope)` (`<collection>_horizon`, `tenantId: null` for untenanted entries):
|
|
32
|
+
* the highest seq it deleted there. A filtered reader is expired only by the horizons of what it can see.
|
|
33
|
+
* Always set by `createChangeLogModels`; a hand-built models object without it falls back to the feed-wide
|
|
34
|
+
* horizon for every reader.
|
|
35
|
+
*/
|
|
36
|
+
horizons?: Model<Record<string, unknown>>;
|
|
21
37
|
/** Staged, not-yet-numbered entries — present only under `sequencing: 'deferred'`. */
|
|
22
38
|
pending?: Model<Record<string, unknown>>;
|
|
23
39
|
sequencing: 'in-transaction' | 'deferred';
|
|
40
|
+
/** Deferred sequencer lease in ms; {@link DEFAULT_SEQUENCER_LEASE_MS} when absent (a hand-built models object). */
|
|
41
|
+
sequencerLeaseMs?: number;
|
|
24
42
|
/** The counter document's id (one feed per entries collection). */
|
|
25
43
|
feed: string;
|
|
26
44
|
}
|
|
27
|
-
declare function createChangeLogModels(connection: Connection, options?: ChangeLogModelOptions): ChangeLogModels;
|
|
45
|
+
export declare function createChangeLogModels(connection: Connection, options?: ChangeLogModelOptions): ChangeLogModels;
|
|
28
46
|
/** The mongo change feed: the `ChangeLogStore` contract plus superseded-entry compaction. */
|
|
29
|
-
interface MongoChangeLogStore extends ChangeLogStore {
|
|
47
|
+
export interface MongoChangeLogStore extends ChangeLogStore {
|
|
30
48
|
/**
|
|
31
|
-
* Delete every entry a later COMMITTED entry of the same `(scope, docId)` replaced. Safe for any client
|
|
49
|
+
* Delete every entry a later COMMITTED entry of the same `(tenantId, scope, docId)` replaced. Safe for any client
|
|
32
50
|
* cursor: entries carry whole documents, so a reader only ever needs the latest one; tombstones and
|
|
33
51
|
* each document's latest entry stay. Idempotent; run it on a schedule.
|
|
34
52
|
*/
|
|
@@ -37,6 +55,29 @@ interface MongoChangeLogStore extends ChangeLogStore {
|
|
|
37
55
|
}): Promise<{
|
|
38
56
|
removed: number;
|
|
39
57
|
}>;
|
|
58
|
+
/**
|
|
59
|
+
* Retention with a horizon (the `ChangeLogStore.prune` contract). Deletes every entry older than
|
|
60
|
+
* `before` (`at < before`) that a later entry of the same `(tenantId, scope, docId)` replaced:
|
|
61
|
+
* each document's latest entry stays, tombstone or not, so a full reload still sees every
|
|
62
|
+
* document. Records a HORIZON (the highest deleted cursor, never lowered) per `(tenantId, scope)`
|
|
63
|
+
* and feed-wide, BEFORE deleting, and returns the feed-wide one, `''` while nothing was ever
|
|
64
|
+
* pruned. `since(cursor, options)` with a cursor below the horizon of what that reader can see
|
|
65
|
+
* (its tenant, shared scopes and `scopes`; the feed-wide horizon when unfiltered; `''` included)
|
|
66
|
+
* throws repo-core's `CursorExpiredError(cursor, horizon)`: that reader missed deleted
|
|
67
|
+
* intermediate entries and must resync from `latestCursor(options)`, which never answers below
|
|
68
|
+
* that horizon. Pruning one tenant never expires another tenant's cursor. Unlike
|
|
69
|
+
* `compactSuperseded`, which is safe for any cursor but silently drops intermediate entries a
|
|
70
|
+
* resuming reader has not seen, a reader never gets a silent gap here. Idempotent; schedule it
|
|
71
|
+
* (e.g. hourly with `before = now - 24h`).
|
|
72
|
+
*/
|
|
73
|
+
prune(before: Date, options?: {
|
|
74
|
+
batchSize?: number;
|
|
75
|
+
}): Promise<string>;
|
|
76
|
+
/**
|
|
77
|
+
* The compaction horizon cursor a reader with these options is held to (`''` while nothing it
|
|
78
|
+
* can see was pruned); feed-wide without options.
|
|
79
|
+
*/
|
|
80
|
+
horizon(options?: Pick<ChangesSinceOptions, 'tenantId' | 'scopes' | 'sharedScopes'>): Promise<string>;
|
|
40
81
|
/**
|
|
41
82
|
* Number every staged entry (deferred sequencing; a no-op otherwise). Reads call it first; a scheduler may too.
|
|
42
83
|
* Returns how many it numbered, or `null` when another sequencer holds the lease.
|
|
@@ -47,21 +88,62 @@ interface MongoChangeLogStore extends ChangeLogStore {
|
|
|
47
88
|
* never use the cursor (`changeLogPlugin`). Under in-transaction sequencing it is `append`.
|
|
48
89
|
*/
|
|
49
90
|
stage(entry: Parameters<ChangeLogStore['append']>[0], options?: ChangeLogAppendOptions): Promise<void>;
|
|
91
|
+
/**
|
|
92
|
+
* Point read of ONE document's latest recorded change: its last staged entry when one waits for a cursor
|
|
93
|
+
* (deferred sequencing; `cursor: ''`, as `append` answers inside a transaction), else its highest numbered
|
|
94
|
+
* entry; `null` when the feed holds none. Reads only (it never runs the sequencer), so it is cheap on a hot
|
|
95
|
+
* path, e.g. a writer that needs the last recorded state of a record before it appends the next change.
|
|
96
|
+
* A document is `(tenantId, scope, docId)`: `tenantId` omitted or `null` reads the untenanted document.
|
|
97
|
+
* Pass `session` to see what the caller staged or appended in its own transaction. A pruned or compacted
|
|
98
|
+
* document still has its latest entry (both keep it).
|
|
99
|
+
*/
|
|
100
|
+
latestOf(scope: string, docId: string, options?: {
|
|
101
|
+
tenantId?: string | null;
|
|
102
|
+
session?: unknown;
|
|
103
|
+
}): Promise<ChangeEntry | null>;
|
|
104
|
+
}
|
|
105
|
+
/** What {@link ChangeLogStoreOptions.onSequenced} is told: new entries now have cursors up to `cursor`. */
|
|
106
|
+
export interface ChangeLogSequencedEvent {
|
|
107
|
+
/** The highest numbered cursor of the feed after the pass (readers reading past their cursor see the new entries). */
|
|
108
|
+
cursor: string;
|
|
109
|
+
/** How many entries were numbered since this store last looked (by this store, or by another holder). */
|
|
110
|
+
numbered: number;
|
|
111
|
+
/** `'self'`: this store's pass numbered them. `'other'`: another holder did, while a read of this store waited. */
|
|
112
|
+
by: 'self' | 'other';
|
|
113
|
+
}
|
|
114
|
+
/** Runtime options of {@link createChangeLogStore} (the models carry the storage options). */
|
|
115
|
+
export interface ChangeLogStoreOptions {
|
|
116
|
+
/**
|
|
117
|
+
* Clock for every entry's `at` (staged and in-transaction appends). Default `() => new Date()`. Inject the host's
|
|
118
|
+
* clock so `at` and `prune(before)` cutoffs agree with a driven test clock. The deferred sequencer's LEASE stays on
|
|
119
|
+
* the database clock (`$$NOW`): it is shared by every process, so it must not depend on any one process's clock.
|
|
120
|
+
*/
|
|
121
|
+
now?: () => Date;
|
|
122
|
+
/**
|
|
123
|
+
* Deferred sequencing: called after new entries got cursors, so a host's replay hub can `notify()` its tails at
|
|
124
|
+
* once. Fires when this store's pass numbered entries (`by: 'self'`), and when a read of this store found the
|
|
125
|
+
* sequencer lease held by another holder: the store then retries in the background (short backoff, unref'd
|
|
126
|
+
* timers, for at most three leases) until that holder is done, and reports what it numbered meanwhile
|
|
127
|
+
* (`by: 'other'`), or takes over a lease left by a holder that died and numbers the entries itself
|
|
128
|
+
* (`by: 'self'`). Without this hook nothing is retried in the background. A throwing hook is ignored. Never
|
|
129
|
+
* called under in-transaction sequencing (every append already has its cursor).
|
|
130
|
+
*/
|
|
131
|
+
onSequenced?: (event: ChangeLogSequencedEvent) => void;
|
|
50
132
|
}
|
|
51
|
-
declare function createChangeLogStore(models: ChangeLogModels): MongoChangeLogStore;
|
|
52
|
-
interface CommandStreamModelOptions {
|
|
133
|
+
export declare function createChangeLogStore(models: ChangeLogModels, storeOptions?: ChangeLogStoreOptions): MongoChangeLogStore;
|
|
134
|
+
export interface CommandStreamModelOptions {
|
|
53
135
|
/** Collection prefix: `<prefix>_streams`, `<prefix>_verdicts`, `<prefix>_aliases`. Default `sync`. */
|
|
54
136
|
prefix?: string;
|
|
55
137
|
/** Mongoose model name prefix. Default `SyncStream`. Must be unique per connection. */
|
|
56
138
|
modelName?: string;
|
|
57
139
|
}
|
|
58
|
-
interface CommandStreamModels {
|
|
140
|
+
export interface CommandStreamModels {
|
|
59
141
|
streams: Model<Record<string, unknown>>;
|
|
60
142
|
verdicts: Model<Record<string, unknown>>;
|
|
61
143
|
aliases: Model<Record<string, unknown>>;
|
|
62
144
|
}
|
|
63
|
-
declare function createCommandStreamModels(connection: Connection, options?: CommandStreamModelOptions): CommandStreamModels;
|
|
64
|
-
interface MongoCommandStreamTx extends CommandStreamTx {
|
|
145
|
+
export declare function createCommandStreamModels(connection: Connection, options?: CommandStreamModelOptions): CommandStreamModels;
|
|
146
|
+
export interface MongoCommandStreamTx extends CommandStreamTx {
|
|
65
147
|
readonly session: ClientSession;
|
|
66
148
|
}
|
|
67
149
|
/**
|
|
@@ -69,6 +151,4 @@ interface MongoCommandStreamTx extends CommandStreamTx {
|
|
|
69
151
|
* Concurrent transactions on one stream write-conflict on its document and `withTransaction`
|
|
70
152
|
* retries the loser, which then reads the winner's watermark.
|
|
71
153
|
*/
|
|
72
|
-
declare function createCommandStreamStore(connection: Pick<Connection, 'startSession'>, models: CommandStreamModels, changes: ChangeLogStore): CommandStreamStore<MongoCommandStreamTx>;
|
|
73
|
-
//#endregion
|
|
74
|
-
export { ChangeLogModelOptions, ChangeLogModels, CommandStreamModelOptions, CommandStreamModels, MongoChangeLogStore, MongoCommandStreamTx, createChangeLogModels, createChangeLogStore, createCommandStreamModels, createCommandStreamStore };
|
|
154
|
+
export declare function createCommandStreamStore(connection: Pick<Connection, 'startSession'>, models: CommandStreamModels, changes: ChangeLogStore): CommandStreamStore<MongoCommandStreamTx>;
|