@classytic/mongokit 3.39.0 → 3.40.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +71 -0
- package/dist/{PaginationEngine-D-P19Y9m.d.mts → PaginationEngine-CRHyuUtw.d.mts} +17 -3
- package/dist/{PaginationEngine-DQ7beTCR.mjs → PaginationEngine-CfT2Cxkj.mjs} +320 -145
- package/dist/{Repository-D7fDpyFx.mjs → Repository-CYhSC9ut.mjs} +844 -794
- package/dist/{Repository-IxI983_m.d.mts → Repository-pnLw1rG5.d.mts} +113 -47
- package/dist/actions/index.d.mts +1 -1
- package/dist/actions/index.mjs +1 -1
- package/dist/adapter/index.mjs +1 -1
- package/dist/{adapter-BrVfPFSW.mjs → adapter-CkMoMF83.mjs} +1 -1
- package/dist/ai/index.d.mts +1 -1
- package/dist/better-auth/index.mjs +2 -2
- package/dist/{create-repository-CRXjDa3N.d.mts → create-repository-BUx9vfG9.d.mts} +5 -5
- package/dist/{create-repository-DOe9E_5F.mjs → create-repository-BYyWzLbt.mjs} +2 -2
- package/dist/idempotency/index.d.mts +23 -0
- package/dist/idempotency/index.mjs +134 -0
- package/dist/{index-CmjNyulu.d.mts → index-SYF8N28D.d.mts} +37 -19
- package/dist/index.d.mts +105 -39
- package/dist/index.mjs +332 -676
- package/dist/indexes/verify-indexes.d.mts +14 -1
- package/dist/indexes/verify-indexes.mjs +54 -7
- package/dist/join-scope-DSAznE8E.mjs +168 -0
- package/dist/{mongooseToJsonSchema-waUVQwK4.mjs → mongooseToJsonSchema-C3k4ide0.mjs} +5 -1
- package/dist/{multi-tenant.plugin-B-tzNeYL.d.mts → multi-tenant.plugin-a3UhQARj.d.mts} +19 -3
- package/dist/{operations-CrRIoc8Z.d.mts → operations-XiFgG5US.d.mts} +36 -13
- package/dist/outbox/index.d.mts +1 -1
- package/dist/outbox/index.mjs +6 -4
- package/dist/pagination/PaginationEngine.d.mts +2 -2
- package/dist/pagination/PaginationEngine.mjs +1 -1
- package/dist/pagination/utils/limits.d.mts +1 -1
- package/dist/{pagination-BpIv2bdS.d.mts → pagination-D6psses0.d.mts} +116 -13
- package/dist/{plugin-options-BuvtOSZf.d.mts → plugin-options-CRhIvSzx.d.mts} +16 -2
- package/dist/plugins/index.d.mts +8 -3
- package/dist/plugins/index.mjs +98 -25
- package/dist/query-defaults-BxUcSOoF.mjs +208 -0
- package/dist/read-model/index.d.mts +66 -0
- package/dist/read-model/index.mjs +193 -0
- package/dist/{repository-ZbLtL7Nk.d.mts → repository-DNHfjAZX.d.mts} +36 -4
- package/dist/sync/index.d.mts +53 -0
- package/dist/sync/index.mjs +371 -0
- package/dist/tenant/index.mjs +2 -0
- package/dist/testkit/index.d.mts +40 -3
- package/dist/testkit/index.mjs +113 -2
- package/dist/{timestamp.plugin-B5eiaItQ.mjs → timestamp.plugin-zfdLYZiO.mjs} +135 -32
- package/dist/{to-plain-B8ufk3Qz.d.mts → to-plain-CjgEInWV.d.mts} +2 -2
- package/dist/transaction-BrRYtH_b.mjs +655 -0
- package/dist/{update-c_01A0if.mjs → update-WgeAUJ_I.mjs} +212 -33
- package/dist/utils/index.d.mts +1 -1
- package/dist/utils/index.mjs +1 -1
- package/dist/{validation-chain.plugin-Bju1D1Sn.mjs → validation-chain.plugin-CHUHWMtk.mjs} +204 -279
- package/dist/{validation-chain.plugin-DvrLJIbJ.d.mts → validation-chain.plugin-CTcNJCmV.d.mts} +27 -5
- package/package.json +18 -4
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { _ as RepositoryOptions, d as PluginType, f as PrioritizedHook, o as Middleware, p as RepositoryContext } from "./repository-
|
|
4
|
-
import {
|
|
5
|
-
import { AggPaginationRequest, AggRequest, AggResult, ArchiveOptions, ArchiveResult, ArchiveSink, ChangeEvent, FilterInput, KeysetAggPaginationResult, QueryOptions, RepoCapabilities, RepositoryBase, TenantPurgeOptions, TenantPurgeResult, TenantPurgeStrategy, WatchOptions } from "@classytic/repo-core/repository";
|
|
1
|
+
import { S as LookupOptions, _ as SessionOptions, b as WithTransactionOptions, c as DeleteResult, f as LookupPopulateOptions, g as ReadOptions, h as OperationOptions, i as CacheableOptions, l as FindOneAndUpdateOptions, n as AggregateOptions, o as CreateOptions, p as LookupPopulateResult, s as DeleteManyResult, t as AggregateCallOptions, u as GetByIdsOptions, v as UpdateManyResult, x as LookupBuilder, y as UpdateOptions } from "./operations-XiFgG5US.mjs";
|
|
2
|
+
import { A as ObjectId, F as SortSpec$1, M as ReadPreferenceType, N as SelectSpec, c as MongokitPageExtras, i as CountStrategy, j as PopulateSpec, r as CollationOptions, t as AggregatePaginationOptions, u as PaginationConfig } from "./pagination-D6psses0.mjs";
|
|
3
|
+
import { _ as RepositoryOptions, d as PluginType, f as PrioritizedHook, o as Middleware, p as RepositoryContext } from "./repository-DNHfjAZX.mjs";
|
|
4
|
+
import { n as PaginationEngine } from "./PaginationEngine-CRHyuUtw.mjs";
|
|
5
|
+
import { AggPaginationRequest, AggRequest, AggResult, ArchiveOptions, ArchiveResult, ArchiveSink, BulkUpsertOptions, BulkUpsertResult, ChangeEvent, FilterInput, KeysetAggPaginationResult, QueryOptions, RepoCapabilities, RepositoryBase, TenantPurgeOptions, TenantPurgeResult, TenantPurgeStrategy, WatchOptions } from "@classytic/repo-core/repository";
|
|
6
6
|
import { ClientSession, Expression, Model, PipelineStage, PopulateOptions } from "mongoose";
|
|
7
7
|
import { Filter } from "@classytic/repo-core/filter";
|
|
8
8
|
import { RepositoryCacheHandle } from "@classytic/repo-core/cache";
|
|
@@ -519,6 +519,37 @@ interface TransitionMachine {
|
|
|
519
519
|
readonly name: string;
|
|
520
520
|
assertTransition(entityId: string, from: string, to: string): void;
|
|
521
521
|
}
|
|
522
|
+
/** `Repository.getAll` parameters. */
|
|
523
|
+
type GetAllParams = {
|
|
524
|
+
filters?: Record<string, unknown>;
|
|
525
|
+
sort?: SortSpec$1 | string;
|
|
526
|
+
cursor?: string;
|
|
527
|
+
after?: string;
|
|
528
|
+
/** Cursor for the PREVIOUS page. Mutually exclusive with `after`/`cursor`. */
|
|
529
|
+
before?: string;
|
|
530
|
+
page?: number;
|
|
531
|
+
pagination?: {
|
|
532
|
+
page?: number;
|
|
533
|
+
limit?: number;
|
|
534
|
+
};
|
|
535
|
+
limit?: number;
|
|
536
|
+
search?: string;
|
|
537
|
+
mode?: 'offset' | 'keyset';
|
|
538
|
+
hint?: string | Record<string, 1 | -1>;
|
|
539
|
+
maxTimeMS?: number;
|
|
540
|
+
countStrategy?: CountStrategy;
|
|
541
|
+
/** Ceiling for `countStrategy: 'capped'`. */
|
|
542
|
+
countLimit?: number;
|
|
543
|
+
readPreference?: ReadPreferenceType;
|
|
544
|
+
/** Advanced populate options (from QueryParser or Arc's BaseController) */
|
|
545
|
+
populateOptions?: PopulateOptions[];
|
|
546
|
+
/** Collation for locale-aware string comparison */
|
|
547
|
+
collation?: CollationOptions;
|
|
548
|
+
/** Lookup configurations for $lookup joins (from QueryParser or manual) */
|
|
549
|
+
lookups?: LookupOptions[];
|
|
550
|
+
/** Skip pagination entirely — returns raw TDoc[] (same as findAll) */
|
|
551
|
+
noPagination?: boolean;
|
|
552
|
+
};
|
|
522
553
|
declare class Repository<TDoc = unknown> extends RepositoryBase {
|
|
523
554
|
/**
|
|
524
555
|
* Cache handle ATTACHED BY the unified cache plugin at wiring time —
|
|
@@ -591,6 +622,8 @@ declare class Repository<TDoc = unknown> extends RepositoryBase {
|
|
|
591
622
|
* {@link ID_ADDRESSED_OPERATIONS}.
|
|
592
623
|
*/
|
|
593
624
|
private readonly _guardIdAddressed;
|
|
625
|
+
/** This repository's own `queryDefaults` / `aggregateDefaults` (deployment ones fill the gaps). */
|
|
626
|
+
private readonly _queryDefaults;
|
|
594
627
|
constructor(Model: Model<TDoc, any, any, any>, plugins?: PluginType[], paginationConfig?: PaginationConfig, options?: RepositoryOptions);
|
|
595
628
|
/**
|
|
596
629
|
* Live read-through view of the hook engine's listener registry.
|
|
@@ -741,6 +774,12 @@ declare class Repository<TDoc = unknown> extends RepositoryBase {
|
|
|
741
774
|
* `_buildContext` inputs), so every op routed through `_runOp` — and the
|
|
742
775
|
* inline-try methods that call this directly — honors them uniformly.
|
|
743
776
|
*/
|
|
777
|
+
/** One command's time bound and concerns: per call, then this repository, then the deployment. */
|
|
778
|
+
private _opts;
|
|
779
|
+
/** How an IR request runs: per-call hints, then this repository's and the deployment's defaults. */
|
|
780
|
+
private _aggRun;
|
|
781
|
+
/** Scope every join in `pipeline` under its owning collection's policy (see `join-scope.ts`). */
|
|
782
|
+
private _scopeJoins;
|
|
744
783
|
private _withResilience;
|
|
745
784
|
/**
|
|
746
785
|
* Create single document
|
|
@@ -774,16 +813,15 @@ declare class Repository<TDoc = unknown> extends RepositoryBase {
|
|
|
774
813
|
* const byId = await repo.getByIds(offerIds, ctx);
|
|
775
814
|
* const doc = byId.get(offerId); // O(1); undefined if not found
|
|
776
815
|
*
|
|
777
|
-
*
|
|
778
|
-
*
|
|
779
|
-
*
|
|
780
|
-
*
|
|
781
|
-
* it.
|
|
816
|
+
* Chunking: ids are split into `$in` slices of `chunkSize` (default `DEFAULT_ID_CHUNK`), one
|
|
817
|
+
* command each — sequential inside a session (a transaction runs one operation at a time),
|
|
818
|
+
* at most `concurrency` (default 4) in flight outside one. `preserveOrder: true` returns an
|
|
819
|
+
* array aligned with `ids` (`undefined` for a miss). Don't exclude the id field via `select`.
|
|
782
820
|
*/
|
|
783
|
-
getByIds(ids: ReadonlyArray<string | ObjectId>, options
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
821
|
+
getByIds(ids: ReadonlyArray<string | ObjectId>, options: GetByIdsOptions & {
|
|
822
|
+
preserveOrder: true;
|
|
823
|
+
}): Promise<Array<TDoc | undefined>>;
|
|
824
|
+
getByIds(ids: ReadonlyArray<string | ObjectId>, options?: GetByIdsOptions): Promise<Map<string, TDoc>>;
|
|
787
825
|
/**
|
|
788
826
|
* Get single document by query
|
|
789
827
|
*/
|
|
@@ -813,6 +851,31 @@ declare class Repository<TDoc = unknown> extends RepositoryBase {
|
|
|
813
851
|
sort?: SortSpec$1 | string;
|
|
814
852
|
limit?: number;
|
|
815
853
|
}): Promise<TDoc[]>;
|
|
854
|
+
/**
|
|
855
|
+
* The keyset cursor `getAll({ sort, filters, mode: 'keyset' })` would mint for `row`, under the
|
|
856
|
+
* same policy scope, so a page resumes AFTER it. For composing keyset walks (repo-core
|
|
857
|
+
* `mergeKeysetPages` via `keysetSource`), where the last CONSUMED row is not a page's last row.
|
|
858
|
+
*/
|
|
859
|
+
keysetCursor(row: unknown, options: ReadOptions & {
|
|
860
|
+
sort: SortSpec$1 | string;
|
|
861
|
+
filters?: Record<string, unknown>;
|
|
862
|
+
collation?: CollationOptions;
|
|
863
|
+
}): Promise<string>;
|
|
864
|
+
/**
|
|
865
|
+
* Resumable keyset batches over `_id`: each batch is ONE bounded `find` (no long-lived server
|
|
866
|
+
* cursor, so no cursor timeout and no CSOT lifetime budget), memory is one batch, and every
|
|
867
|
+
* batch carries a `checkpoint`. Pass a checkpoint back as `after` to resume: rows written
|
|
868
|
+
* behind it are not revisited, rows ahead of it are reached. A checkpoint is bound to the
|
|
869
|
+
* collection, the post-policy filter (tenant included) and is refused elsewhere.
|
|
870
|
+
*/
|
|
871
|
+
iterate(filter?: Record<string, unknown>, options?: ReadOptions & {
|
|
872
|
+
after?: string;
|
|
873
|
+
batchSize?: number;
|
|
874
|
+
select?: SelectSpec;
|
|
875
|
+
}): AsyncIterableIterator<{
|
|
876
|
+
docs: TDoc[];
|
|
877
|
+
checkpoint: string;
|
|
878
|
+
}>;
|
|
816
879
|
/**
|
|
817
880
|
* Streaming reads — async iterator over data, suitable for migrations,
|
|
818
881
|
* backfills, schema audits, and any once-a-quarter "touch every row"
|
|
@@ -916,36 +979,19 @@ declare class Repository<TDoc = unknown> extends RepositoryBase {
|
|
|
916
979
|
* // Skip cache for fresh data
|
|
917
980
|
* await repo.getAll({ filters: { status: 'active' } }, { skipCache: true });
|
|
918
981
|
*/
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
search?: string;
|
|
933
|
-
mode?: 'offset' | 'keyset';
|
|
934
|
-
hint?: string | Record<string, 1 | -1>;
|
|
935
|
-
maxTimeMS?: number;
|
|
936
|
-
countStrategy?: CountStrategy;
|
|
937
|
-
/** Ceiling for `countStrategy: 'capped'`. */
|
|
938
|
-
countLimit?: number;
|
|
939
|
-
readPreference?: ReadPreferenceType;
|
|
940
|
-
/** Advanced populate options (from QueryParser or Arc's BaseController) */
|
|
941
|
-
populateOptions?: PopulateOptions[];
|
|
942
|
-
/** Collation for locale-aware string comparison */
|
|
943
|
-
collation?: CollationOptions;
|
|
944
|
-
/** Lookup configurations for $lookup joins (from QueryParser or manual) */
|
|
945
|
-
lookups?: LookupOptions[];
|
|
946
|
-
/** Skip pagination entirely — returns raw TDoc[] (same as findAll) */
|
|
947
|
-
noPagination?: boolean;
|
|
948
|
-
}, options?: CacheableOptions): Promise<OffsetPaginationResult<TDoc> | KeysetPaginationResult<TDoc> | TDoc[]>;
|
|
982
|
+
/** An explicit `mode` (or `noPagination`) decides the envelope, so the result type follows it. */
|
|
983
|
+
getAll(params: GetAllParams & {
|
|
984
|
+
mode: 'offset';
|
|
985
|
+
noPagination?: false;
|
|
986
|
+
}, options?: CacheableOptions): Promise<OffsetPaginationResult<TDoc>>;
|
|
987
|
+
getAll(params: GetAllParams & {
|
|
988
|
+
mode: 'keyset';
|
|
989
|
+
noPagination?: false;
|
|
990
|
+
}, options?: CacheableOptions): Promise<KeysetPaginationResult<TDoc>>;
|
|
991
|
+
getAll(params: GetAllParams & {
|
|
992
|
+
noPagination: true;
|
|
993
|
+
}, options?: CacheableOptions): Promise<TDoc[]>;
|
|
994
|
+
getAll(params?: GetAllParams, options?: CacheableOptions): Promise<OffsetPaginationResult<TDoc> | KeysetPaginationResult<TDoc> | TDoc[]>;
|
|
949
995
|
/**
|
|
950
996
|
* Atomic "look up by filter, insert `data` if missing, return the doc."
|
|
951
997
|
*
|
|
@@ -1268,6 +1314,11 @@ declare class Repository<TDoc = unknown> extends RepositoryBase {
|
|
|
1268
1314
|
}, patch?: Record<string, unknown>, options?: SessionOptions & {
|
|
1269
1315
|
idField?: string;
|
|
1270
1316
|
upsert?: boolean;
|
|
1317
|
+
/**
|
|
1318
|
+
* The document as the caller just read it in this session. Hooks' `loadTarget()`
|
|
1319
|
+
* returns it instead of reading again. Pass only a read taken in the same session.
|
|
1320
|
+
*/
|
|
1321
|
+
target?: Record<string, unknown>;
|
|
1271
1322
|
}): Promise<TDoc | null>;
|
|
1272
1323
|
/**
|
|
1273
1324
|
* State-machine-backed CAS transition with status history — the
|
|
@@ -1543,6 +1594,13 @@ declare class Repository<TDoc = unknown> extends RepositoryBase {
|
|
|
1543
1594
|
archiveByFilter(filter: Record<string, unknown> | Filter, sink: ArchiveSink<TDoc>, options?: ArchiveOptions & {
|
|
1544
1595
|
session?: ClientSession;
|
|
1545
1596
|
}): Promise<ArchiveResult>;
|
|
1597
|
+
/**
|
|
1598
|
+
* Many keyed upserts in ONE command with an exact per-row outcome (repo-core `bulkUpsert` IR).
|
|
1599
|
+
* Sub-ops pass through the `before:bulkUpsert` policy hooks (tenant, soft-delete) like bulkWrite
|
|
1600
|
+
* sub-ops. Refused unless a unique index is pinned by the key plus the policy scope. Needs
|
|
1601
|
+
* MongoDB 8.0 (client bulkWrite with verbose results).
|
|
1602
|
+
*/
|
|
1603
|
+
bulkUpsert(rows: readonly Record<string, unknown>[], options: BulkUpsertOptions): Promise<BulkUpsertResult>;
|
|
1546
1604
|
/**
|
|
1547
1605
|
* Kit-native aggregation pipeline — takes a MongoDB stage array and
|
|
1548
1606
|
* returns the raw pipeline output. Use this for `$lookup`, `$unwind`,
|
|
@@ -1582,7 +1640,7 @@ declare class Repository<TDoc = unknown> extends RepositoryBase {
|
|
|
1582
1640
|
* Policy hooks (multi-tenant, soft-delete) inject context.filters
|
|
1583
1641
|
* which are prepended as a `$match` stage.
|
|
1584
1642
|
*/
|
|
1585
|
-
aggregatePipelinePaginate(options?: AggregatePaginationOptions): Promise<AggregatePaginationResult<TDoc>>;
|
|
1643
|
+
aggregatePipelinePaginate(options?: AggregatePaginationOptions): Promise<AggregatePaginationResult<TDoc, MongokitPageExtras>>;
|
|
1586
1644
|
/**
|
|
1587
1645
|
* Portable aggregation. Compiles the repo-core `AggRequest` IR to
|
|
1588
1646
|
* `[{$match}, {$group}, {$addFields}, {$project}, {$match}, {$sort},
|
|
@@ -1605,7 +1663,9 @@ declare class Repository<TDoc = unknown> extends RepositoryBase {
|
|
|
1605
1663
|
* `context.filter`, which is merged into the pre-aggregate `$match`
|
|
1606
1664
|
* before compilation.
|
|
1607
1665
|
*/
|
|
1608
|
-
aggregate<TRow extends Record<string, unknown> = Record<string, unknown>>(req: AggRequest, options?: QueryOptions): Promise<AggResult<TRow
|
|
1666
|
+
aggregate<TRow extends Record<string, unknown> = Record<string, unknown>>(req: AggRequest, options?: QueryOptions & AggregateCallOptions): Promise<AggResult<TRow> & {
|
|
1667
|
+
plan?: unknown;
|
|
1668
|
+
}>;
|
|
1609
1669
|
/**
|
|
1610
1670
|
* Invalidate every aggregate-cache entry tagged with ANY of the
|
|
1611
1671
|
* given tags. Delegates to the unified cache plugin's handle
|
|
@@ -1801,6 +1861,12 @@ declare class Repository<TDoc = unknown> extends RepositoryBase {
|
|
|
1801
1861
|
* 4. DEFAULT (500) — user-registered hooks
|
|
1802
1862
|
*/
|
|
1803
1863
|
_buildContext(operation: string, options: Record<string, unknown> | object): Promise<RepositoryContext>;
|
|
1864
|
+
/**
|
|
1865
|
+
* `memo` and (for an id-addressed op) `loadTarget` — attached before the before-hooks
|
|
1866
|
+
* run so every hook of one operation shares one read. A caller that has just read the
|
|
1867
|
+
* document in the same session passes it as `target`, and nothing is read at all.
|
|
1868
|
+
*/
|
|
1869
|
+
private _sharedReadSeams;
|
|
1804
1870
|
/**
|
|
1805
1871
|
* Feed the resolved filter of a guarded verb to the distribution guard.
|
|
1806
1872
|
* The slot follows `OP_REGISTRY[op].policyKey` (`query` vs `filters`);
|
|
@@ -1916,4 +1982,4 @@ declare class Repository<TDoc = unknown> extends RepositoryBase {
|
|
|
1916
1982
|
private _translateError;
|
|
1917
1983
|
}
|
|
1918
1984
|
//#endregion
|
|
1919
|
-
export {
|
|
1985
|
+
export { AggregationBuilder as a, ProjectionSpec as c, VectorSearchOptions as d, TransitionMachine as i, SortOrder as l, HOOK_PRIORITY as n, AggregationPlan as o, Repository as r, GroupSpec as s, GetAllParams as t, SortSpec as u };
|
package/dist/actions/index.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { c as create_d_exports, i as delete_d_exports, n as update_d_exports, r as read_d_exports, u as aggregate_d_exports } from "../index-
|
|
1
|
+
import { c as create_d_exports, i as delete_d_exports, n as update_d_exports, r as read_d_exports, u as aggregate_d_exports } from "../index-SYF8N28D.mjs";
|
|
2
2
|
export { aggregate_d_exports as aggregate, create_d_exports as create, delete_d_exports as deleteActions, read_d_exports as read, update_d_exports as update };
|
package/dist/actions/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as __exportAll } from "../rolldown-runtime-D7D4PA-g.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { S as create_exports, i as update_exports, m as aggregate_exports, p as delete_exports, u as read_exports } from "../update-WgeAUJ_I.mjs";
|
|
3
3
|
//#region src/actions/index.ts
|
|
4
4
|
var actions_exports = /* @__PURE__ */ __exportAll({
|
|
5
5
|
aggregate: () => aggregate_exports,
|
package/dist/adapter/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as createMongooseAdapter, r as isMongooseModel, t as MongooseAdapter } from "../adapter-
|
|
1
|
+
import { n as createMongooseAdapter, r as isMongooseModel, t as MongooseAdapter } from "../adapter-CkMoMF83.mjs";
|
|
2
2
|
export { MongooseAdapter, createMongooseAdapter, isMongooseModel };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as warn } from "./logger-K7dPmu2U.mjs";
|
|
2
|
-
import { t as buildCrudSchemasFromModel } from "./mongooseToJsonSchema-
|
|
2
|
+
import { t as buildCrudSchemasFromModel } from "./mongooseToJsonSchema-C3k4ide0.mjs";
|
|
3
3
|
import { matchesRecordFilter } from "@classytic/repo-core/filter";
|
|
4
4
|
import { mergeFieldRuleConstraints } from "@classytic/repo-core/schema";
|
|
5
5
|
import { asRepositoryLike, isRepository } from "@classytic/repo-core/adapter";
|
package/dist/ai/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { n as Repository } from "../Repository-
|
|
2
|
-
import { n as createMongooseAdapter } from "../adapter-
|
|
1
|
+
import { n as Repository } from "../Repository-CYhSC9ut.mjs";
|
|
2
|
+
import { n as createMongooseAdapter } from "../adapter-CkMoMF83.mjs";
|
|
3
3
|
import { asReadOnlyRepo } from "@classytic/repo-core/repository";
|
|
4
4
|
import { pluralizeBetterAuthCollection, resolveBetterAuthCollections } from "@classytic/repo-core/better-auth";
|
|
5
5
|
//#region src/better-auth/index.ts
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { u as PaginationConfig } from "./pagination-
|
|
2
|
-
import { _ as RepositoryOptions, d as PluginType } from "./repository-
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { i as Logger, o as SoftDeleteOptions } from "./plugin-options-
|
|
1
|
+
import { u as PaginationConfig } from "./pagination-D6psses0.mjs";
|
|
2
|
+
import { _ as RepositoryOptions, d as PluginType } from "./repository-DNHfjAZX.mjs";
|
|
3
|
+
import { D as AuditTrailOptions, i as CustomIdOptions, t as MultiTenantOptions, y as RepositoryCachePluginOptions } from "./multi-tenant.plugin-a3UhQARj.mjs";
|
|
4
|
+
import { r as Repository } from "./Repository-pnLw1rG5.mjs";
|
|
5
|
+
import { i as Logger, o as SoftDeleteOptions } from "./plugin-options-CRhIvSzx.mjs";
|
|
6
6
|
import { Model } from "mongoose";
|
|
7
7
|
//#region src/create-repository.d.ts
|
|
8
8
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { n as Repository } from "./Repository-
|
|
2
|
-
import {
|
|
1
|
+
import { n as Repository } from "./Repository-CYhSC9ut.mjs";
|
|
2
|
+
import { b as auditLogPlugin, g as cachePlugin, i as multiTenantPlugin, l as customIdPlugin, n as softDeletePlugin, t as timestampPlugin, v as auditTrailPlugin } from "./timestamp.plugin-zfdLYZiO.mjs";
|
|
3
3
|
import { n as batchOperationsPlugin, t as methodRegistryPlugin } from "./method-registry.plugin-C63pGn1d.mjs";
|
|
4
4
|
//#region src/create-repository.ts
|
|
5
5
|
function isLoggerAudit(value) {
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Connection, Model } from "mongoose";
|
|
2
|
+
import { IdempotencyClaimStore } from "@classytic/repo-core/idempotency";
|
|
3
|
+
//#region src/idempotency/index.d.ts
|
|
4
|
+
interface IdempotencyModelOptions {
|
|
5
|
+
/** Collection name. Default `idempotency_claims`. */
|
|
6
|
+
collection?: string;
|
|
7
|
+
/** Mongoose model name. Default `IdempotencyClaim`. Must be unique per connection. */
|
|
8
|
+
modelName?: string;
|
|
9
|
+
}
|
|
10
|
+
interface IdempotencyStoreOptions {
|
|
11
|
+
/**
|
|
12
|
+
* How long a claim is kept after its last write before the TTL monitor removes it.
|
|
13
|
+
* Default 7 days. Size it to the longest a caller may retry — a retry after the claim
|
|
14
|
+
* is gone executes again. An offline till that syncs days later needs more.
|
|
15
|
+
*/
|
|
16
|
+
retentionSeconds?: number;
|
|
17
|
+
}
|
|
18
|
+
/** Build (or return) the claims model on `connection`. Idempotent per connection. */
|
|
19
|
+
declare function createIdempotencyModel(connection: Connection, options?: IdempotencyModelOptions): Model<Record<string, unknown>>;
|
|
20
|
+
/** The store over a model from {@link createIdempotencyModel}. */
|
|
21
|
+
declare function createIdempotencyStore(model: Model<Record<string, unknown>>, options?: IdempotencyStoreOptions): IdempotencyClaimStore;
|
|
22
|
+
//#endregion
|
|
23
|
+
export { IdempotencyModelOptions, IdempotencyStoreOptions, createIdempotencyModel, createIdempotencyStore };
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { Schema } from "mongoose";
|
|
2
|
+
import { identityKey } from "@classytic/repo-core/idempotency";
|
|
3
|
+
//#region src/idempotency/index.ts
|
|
4
|
+
/**
|
|
5
|
+
* The mongo {@link IdempotencyClaimStore} — use this with `runIdempotent` from
|
|
6
|
+
* `@classytic/repo-core/idempotency`; never keep a per-module claims table.
|
|
7
|
+
*
|
|
8
|
+
* ```ts
|
|
9
|
+
* const store = createIdempotencyStore(createIdempotencyModel(connection));
|
|
10
|
+
* const run = await runIdempotent({ store, identity, requestFingerprint, execute });
|
|
11
|
+
* ```
|
|
12
|
+
*
|
|
13
|
+
* One document per identity, `_id` = `identityKey(identity)`, so "insert iff absent" is
|
|
14
|
+
* the `_id` index and every compare-and-set is a single-document filter. Proven by
|
|
15
|
+
* `runIdempotencyStoreConformance` (`@classytic/repo-core/testing`) in this package's tests.
|
|
16
|
+
*/
|
|
17
|
+
const DEFAULT_RETENTION_SECONDS = 604800;
|
|
18
|
+
/** Build (or return) the claims model on `connection`. Idempotent per connection. */
|
|
19
|
+
function createIdempotencyModel(connection, options = {}) {
|
|
20
|
+
const { collection = "idempotency_claims", modelName = "IdempotencyClaim" } = options;
|
|
21
|
+
const existing = connection.models[modelName];
|
|
22
|
+
if (existing) return existing;
|
|
23
|
+
const schema = new Schema({
|
|
24
|
+
_id: {
|
|
25
|
+
type: String,
|
|
26
|
+
required: true
|
|
27
|
+
},
|
|
28
|
+
identity: {
|
|
29
|
+
type: Schema.Types.Mixed,
|
|
30
|
+
required: true
|
|
31
|
+
},
|
|
32
|
+
requestFingerprint: {
|
|
33
|
+
type: String,
|
|
34
|
+
required: true
|
|
35
|
+
},
|
|
36
|
+
state: {
|
|
37
|
+
type: String,
|
|
38
|
+
enum: [
|
|
39
|
+
"in_flight",
|
|
40
|
+
"succeeded",
|
|
41
|
+
"failed"
|
|
42
|
+
],
|
|
43
|
+
required: true
|
|
44
|
+
},
|
|
45
|
+
leaseToken: {
|
|
46
|
+
type: String,
|
|
47
|
+
required: true
|
|
48
|
+
},
|
|
49
|
+
leaseExpiresAt: {
|
|
50
|
+
type: Date,
|
|
51
|
+
required: true
|
|
52
|
+
},
|
|
53
|
+
createdAt: {
|
|
54
|
+
type: Date,
|
|
55
|
+
required: true
|
|
56
|
+
},
|
|
57
|
+
completedAt: { type: Date },
|
|
58
|
+
result: { type: Schema.Types.Mixed },
|
|
59
|
+
attempts: {
|
|
60
|
+
type: Number,
|
|
61
|
+
required: true
|
|
62
|
+
},
|
|
63
|
+
progress: { type: Schema.Types.Mixed },
|
|
64
|
+
context: { type: Schema.Types.Mixed },
|
|
65
|
+
lastError: { type: String },
|
|
66
|
+
purgeAt: {
|
|
67
|
+
type: Date,
|
|
68
|
+
required: true
|
|
69
|
+
}
|
|
70
|
+
}, {
|
|
71
|
+
collection,
|
|
72
|
+
versionKey: false,
|
|
73
|
+
minimize: false
|
|
74
|
+
});
|
|
75
|
+
schema.index({ purgeAt: 1 }, {
|
|
76
|
+
expireAfterSeconds: 0,
|
|
77
|
+
name: "retention"
|
|
78
|
+
});
|
|
79
|
+
schema.index({
|
|
80
|
+
"identity.operation": 1,
|
|
81
|
+
state: 1,
|
|
82
|
+
leaseExpiresAt: 1
|
|
83
|
+
}, { name: "lapsed_sweep" });
|
|
84
|
+
return connection.model(modelName, schema);
|
|
85
|
+
}
|
|
86
|
+
/** The store over a model from {@link createIdempotencyModel}. */
|
|
87
|
+
function createIdempotencyStore(model, options = {}) {
|
|
88
|
+
const retentionMs = (options.retentionSeconds ?? DEFAULT_RETENTION_SECONDS) * 1e3;
|
|
89
|
+
const claims = () => model.collection;
|
|
90
|
+
const toDoc = (claim) => ({
|
|
91
|
+
...claim,
|
|
92
|
+
_id: identityKey(claim.identity),
|
|
93
|
+
purgeAt: new Date(Date.now() + retentionMs)
|
|
94
|
+
});
|
|
95
|
+
/** The caller's transaction, so a claim commits or rolls back with the writes it describes. */
|
|
96
|
+
const withSession = (options) => options?.session ? { session: options.session } : {};
|
|
97
|
+
const ownedInFlight = (identity, leaseToken) => ({
|
|
98
|
+
_id: identityKey(identity),
|
|
99
|
+
state: "in_flight",
|
|
100
|
+
leaseToken
|
|
101
|
+
});
|
|
102
|
+
return {
|
|
103
|
+
async get(identity, options) {
|
|
104
|
+
const doc = await claims().findOne({ _id: identityKey(identity) }, withSession(options));
|
|
105
|
+
if (!doc) return null;
|
|
106
|
+
const { _id, purgeAt, ...claim } = doc;
|
|
107
|
+
return claim;
|
|
108
|
+
},
|
|
109
|
+
async insert(claim, options) {
|
|
110
|
+
try {
|
|
111
|
+
await claims().insertOne(toDoc(claim), withSession(options));
|
|
112
|
+
return true;
|
|
113
|
+
} catch (error) {
|
|
114
|
+
if (error.code === 11e3) return false;
|
|
115
|
+
throw error;
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
async swap(identity, expectedLeaseToken, next, options) {
|
|
119
|
+
return (await claims().replaceOne(ownedInFlight(identity, expectedLeaseToken), toDoc(next), withSession(options))).matchedCount === 1;
|
|
120
|
+
},
|
|
121
|
+
async release(identity, expectedLeaseToken, options) {
|
|
122
|
+
return (await claims().deleteOne(ownedInFlight(identity, expectedLeaseToken), withSession(options))).deletedCount === 1;
|
|
123
|
+
},
|
|
124
|
+
async listLapsed(operation, now, limit) {
|
|
125
|
+
return (await claims().find({
|
|
126
|
+
"identity.operation": operation,
|
|
127
|
+
state: "in_flight",
|
|
128
|
+
leaseExpiresAt: { $lte: now }
|
|
129
|
+
}).sort({ leaseExpiresAt: 1 }).limit(limit).toArray()).map(({ _id, purgeAt, ...claim }) => claim);
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
//#endregion
|
|
134
|
+
export { createIdempotencyModel, createIdempotencyStore };
|