@classytic/mongokit 3.28.0 → 3.29.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/LICENSE +1 -1
- package/README.md +11 -1
- package/TRADEMARK.md +22 -0
- package/dist/{Repository-BFBTAMlA.mjs → Repository-DThvFCaV.mjs} +123 -7
- package/dist/actions/index.mjs +1 -1
- package/dist/better-auth/index.mjs +1 -1
- package/dist/{create-repository-2DMwkYVz.mjs → create-repository-uhKt_oUT.mjs} +2 -2
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +5 -5
- package/dist/plugins/index.d.mts +1 -1
- package/dist/plugins/index.mjs +2 -2
- package/dist/testkit/index.mjs +1 -1
- package/dist/{timestamp.plugin-ennbatTW.mjs → timestamp.plugin-CFL6LlYZ.mjs} +1 -1
- package/dist/{update-1Lq9OMD2.mjs → update-CI2NdAW6.mjs} +23 -29
- package/dist/{validation-chain.plugin-Cm0Ttnd8.d.mts → validation-chain.plugin-BLecaKa0.d.mts} +42 -42
- package/dist/{validation-chain.plugin-k9joH2qw.mjs → validation-chain.plugin-CwOcUJC1.mjs} +137 -137
- package/package.json +185 -178
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -18,7 +18,10 @@ Requirements:
|
|
|
18
18
|
|
|
19
19
|
- Node.js `>=22`
|
|
20
20
|
- Mongoose `>=9.4.1`
|
|
21
|
-
- `@classytic/repo-core >=0.
|
|
21
|
+
- `@classytic/repo-core >=0.19.0`
|
|
22
|
+
- `mongodb-memory-server >=10.4.3` — **optional**, needed only by the
|
|
23
|
+
`@classytic/mongokit/testkit` subpath (declared as an optional peer, so it is
|
|
24
|
+
never installed for consumers that don't use it)
|
|
22
25
|
|
|
23
26
|
## Quick Start
|
|
24
27
|
|
|
@@ -430,3 +433,10 @@ All accept `{ replset?, dbName?, uri? }`.
|
|
|
430
433
|
## License
|
|
431
434
|
|
|
432
435
|
MIT
|
|
436
|
+
|
|
437
|
+
|
|
438
|
+
## Trademark
|
|
439
|
+
|
|
440
|
+
The code is MIT-licensed. **"Classytic", "arc", and the logos are trademarks of
|
|
441
|
+
Classytic LLC** and are **not** licensed under MIT — see [TRADEMARK.md](TRADEMARK.md).
|
|
442
|
+
Forks must be renamed; the license covers the code, not the brand.
|
package/TRADEMARK.md
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Trademark Notice
|
|
2
|
+
|
|
3
|
+
The **source code** in this package is licensed under the MIT License (see
|
|
4
|
+
[LICENSE](LICENSE)). Trademarks are **not** part of that license.
|
|
5
|
+
|
|
6
|
+
**"Classytic", "arc", the Classytic and arc logos**, and related names and marks
|
|
7
|
+
are trademarks of **Classytic LLC** (Wyoming, USA). The MIT License covers the
|
|
8
|
+
code only — it grants **no right** to use Classytic LLC's names, logos, or brand.
|
|
9
|
+
|
|
10
|
+
## You may
|
|
11
|
+
- use, fork, modify, and redistribute the **code** under the MIT License;
|
|
12
|
+
- state truthfully that your product "uses" or "is built on" arc / Classytic
|
|
13
|
+
software, without implying endorsement.
|
|
14
|
+
|
|
15
|
+
## You may not (without written permission from Classytic LLC)
|
|
16
|
+
- use "Classytic", "arc", or confusingly similar names as the name of your own
|
|
17
|
+
product, package, company, or service;
|
|
18
|
+
- use the Classytic / arc logos or brand styling;
|
|
19
|
+
- imply sponsorship, affiliation, or endorsement by Classytic LLC.
|
|
20
|
+
|
|
21
|
+
Forks or redistributions must be **renamed** so they are not confused with the
|
|
22
|
+
official project. Permission / questions: **trademark@classytic.com**.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { i as isValidIdForType, t as getSchemaIdType } from "./id-resolution-BqDrk0S2.mjs";
|
|
2
|
-
import { a as count, b as LookupBuilder, c as getByQuery, d as deleteById, f as deleteByQuery, h as createMany, l as getOrCreate, m as create, n as update, o as exists, r as updateByQuery, s as getById, t as findOneAndUpdate, x as compileFilterToMongo, y as distinct } from "./update-
|
|
2
|
+
import { a as count, b as LookupBuilder, c as getByQuery, d as deleteById, f as deleteByQuery, h as createMany, l as getOrCreate, m as create, n as update, o as exists, r as updateByQuery, s as getById, t as findOneAndUpdate, x as compileFilterToMongo, y as distinct } from "./update-CI2NdAW6.mjs";
|
|
3
3
|
import { n as warn } from "./logger-K7dPmu2U.mjs";
|
|
4
4
|
import { n as isDuplicateKeyError, r as parseDuplicateKeyError, t as createError } from "./error-BuByZwKU.mjs";
|
|
5
5
|
import { t as PaginationEngine } from "./PaginationEngine-CczbvCAq.mjs";
|
|
@@ -317,6 +317,122 @@ function applyExecutionHints(aggregation, hints) {
|
|
|
317
317
|
if (hints.indexHint !== void 0) aggregation.option({ hint: hints.indexHint });
|
|
318
318
|
}
|
|
319
319
|
//#endregion
|
|
320
|
+
//#region src/filter/cast-schema.ts
|
|
321
|
+
/** Operators whose operand is a single scalar to cast. */
|
|
322
|
+
const SCALAR_OPS = /* @__PURE__ */ new Set([
|
|
323
|
+
"$eq",
|
|
324
|
+
"$ne",
|
|
325
|
+
"$gt",
|
|
326
|
+
"$gte",
|
|
327
|
+
"$lt",
|
|
328
|
+
"$lte"
|
|
329
|
+
]);
|
|
330
|
+
/** Operators whose operand is an array of scalars to cast element-wise. */
|
|
331
|
+
const ARRAY_OPS = /* @__PURE__ */ new Set(["$in", "$nin"]);
|
|
332
|
+
/** Logical operators whose operand is an ARRAY of sub-filters. */
|
|
333
|
+
const LOGICAL_ARRAY_OPS = /* @__PURE__ */ new Set([
|
|
334
|
+
"$and",
|
|
335
|
+
"$or",
|
|
336
|
+
"$nor"
|
|
337
|
+
]);
|
|
338
|
+
/** Logical operators whose operand is a SINGLE nested sub-filter. */
|
|
339
|
+
const LOGICAL_OBJECT_OPS = /* @__PURE__ */ new Set(["$not"]);
|
|
340
|
+
function isPlainObject(value) {
|
|
341
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) && !(value instanceof Date);
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Cast one value through a schema path. Returns the original value when the
|
|
345
|
+
* path is unknown, the value is nullish, or the cast throws — never raises.
|
|
346
|
+
*/
|
|
347
|
+
function castValue(schema, field, value) {
|
|
348
|
+
if (value === null || value === void 0) return value;
|
|
349
|
+
if (typeof value === "object" && !(value instanceof Date)) return value;
|
|
350
|
+
let schemaType;
|
|
351
|
+
try {
|
|
352
|
+
schemaType = schema.path(field);
|
|
353
|
+
} catch {
|
|
354
|
+
return value;
|
|
355
|
+
}
|
|
356
|
+
if (!schemaType || typeof schemaType.cast !== "function") return value;
|
|
357
|
+
try {
|
|
358
|
+
return schemaType.cast(value);
|
|
359
|
+
} catch {
|
|
360
|
+
return value;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* Cast the operand(s) of a field-level operator object, leaving operators we
|
|
365
|
+
* don't understand (`$regex`, `$exists`, `$size`, `$elemMatch`, …) alone.
|
|
366
|
+
*/
|
|
367
|
+
function castOperatorObject(schema, field, ops) {
|
|
368
|
+
let changed = false;
|
|
369
|
+
const out = {};
|
|
370
|
+
for (const [op, operand] of Object.entries(ops)) if (SCALAR_OPS.has(op)) {
|
|
371
|
+
const next = castValue(schema, field, operand);
|
|
372
|
+
out[op] = next;
|
|
373
|
+
if (next !== operand) changed = true;
|
|
374
|
+
} else if (ARRAY_OPS.has(op) && Array.isArray(operand)) {
|
|
375
|
+
const arr = operand.map((entry) => castValue(schema, field, entry));
|
|
376
|
+
out[op] = arr;
|
|
377
|
+
if (arr.some((v, i) => v !== operand[i])) changed = true;
|
|
378
|
+
} else out[op] = operand;
|
|
379
|
+
return changed ? out : ops;
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* Cast a record-shape Mongo filter against a Mongoose schema so it is safe to
|
|
383
|
+
* hand to a `$match` stage. Recurses `$and` / `$or` / `$nor` / `$not`, since a
|
|
384
|
+
* policy/tenant scope conjoined with a caller filter nests one level down.
|
|
385
|
+
*
|
|
386
|
+
* Filter IR nodes and non-objects pass through untouched — IR values are built
|
|
387
|
+
* in code (already correctly typed) and carry no schema paths to resolve.
|
|
388
|
+
*
|
|
389
|
+
* @example
|
|
390
|
+
* ```ts
|
|
391
|
+
* // organizationId is an ObjectId column; arc supplies the scope id as a string
|
|
392
|
+
* castFilterToSchema({ organizationId: '6a6a…' }, Order.schema)
|
|
393
|
+
* // → { organizationId: ObjectId('6a6a…') }
|
|
394
|
+
* ```
|
|
395
|
+
*/
|
|
396
|
+
function castFilterToSchema(filter, schema) {
|
|
397
|
+
if (!isPlainObject(filter)) return filter;
|
|
398
|
+
if (typeof filter.op === "string") return filter;
|
|
399
|
+
let changed = false;
|
|
400
|
+
const out = {};
|
|
401
|
+
for (const [key, value] of Object.entries(filter)) {
|
|
402
|
+
if (LOGICAL_ARRAY_OPS.has(key) && Array.isArray(value)) {
|
|
403
|
+
const arr = value.map((entry) => castFilterToSchema(entry, schema));
|
|
404
|
+
out[key] = arr;
|
|
405
|
+
if (arr.some((v, i) => v !== value[i])) changed = true;
|
|
406
|
+
continue;
|
|
407
|
+
}
|
|
408
|
+
if (LOGICAL_OBJECT_OPS.has(key) && isPlainObject(value)) {
|
|
409
|
+
const nested = castFilterToSchema(value, schema);
|
|
410
|
+
out[key] = nested;
|
|
411
|
+
if (nested !== value) changed = true;
|
|
412
|
+
continue;
|
|
413
|
+
}
|
|
414
|
+
if (key.startsWith("$")) {
|
|
415
|
+
out[key] = value;
|
|
416
|
+
continue;
|
|
417
|
+
}
|
|
418
|
+
if (isPlainObject(value)) {
|
|
419
|
+
const keys = Object.keys(value);
|
|
420
|
+
if (keys.length > 0 && keys.every((k) => k.startsWith("$"))) {
|
|
421
|
+
const nextOps = castOperatorObject(schema, key, value);
|
|
422
|
+
out[key] = nextOps;
|
|
423
|
+
if (nextOps !== value) changed = true;
|
|
424
|
+
continue;
|
|
425
|
+
}
|
|
426
|
+
out[key] = value;
|
|
427
|
+
continue;
|
|
428
|
+
}
|
|
429
|
+
const next = castValue(schema, key, value);
|
|
430
|
+
out[key] = next;
|
|
431
|
+
if (next !== value) changed = true;
|
|
432
|
+
}
|
|
433
|
+
return changed ? out : filter;
|
|
434
|
+
}
|
|
435
|
+
//#endregion
|
|
320
436
|
//#region src/actions/aggregate-ir/normalize.ts
|
|
321
437
|
/**
|
|
322
438
|
* AggRequest → input normalization (mongokit binding).
|
|
@@ -580,14 +696,14 @@ function compileMeasure(measure) {
|
|
|
580
696
|
}
|
|
581
697
|
//#endregion
|
|
582
698
|
//#region src/actions/aggregate-ir/pipeline.ts
|
|
583
|
-
function buildAggPipeline(req) {
|
|
699
|
+
function buildAggPipeline(req, schema) {
|
|
584
700
|
validateMeasures$1(req.measures);
|
|
585
701
|
const groupCols = normalizeGroupBy(req.groupBy);
|
|
586
702
|
const bucketAliases = req.dateBuckets ? Object.keys(req.dateBuckets) : [];
|
|
587
703
|
validateBucketAliases(bucketAliases, groupCols, req.measures);
|
|
588
704
|
const stages = [];
|
|
589
705
|
const aliasSet = new Set((req.lookups ?? []).map((l) => l.as ?? l.from));
|
|
590
|
-
const { base: baseFilter, joined: joinedFilter } = splitFilterByAlias(req.filter, aliasSet);
|
|
706
|
+
const { base: baseFilter, joined: joinedFilter } = splitFilterByAlias(schema !== void 0 && req.filter !== void 0 ? castFilterToSchema(req.filter, schema) : req.filter, aliasSet);
|
|
591
707
|
if (baseFilter !== void 0) {
|
|
592
708
|
const match = compileFilterToMongo(baseFilter);
|
|
593
709
|
if (Object.keys(match).length > 0) stages.push({ $match: match });
|
|
@@ -869,7 +985,7 @@ async function countAggGroups(Model, req, options = {}) {
|
|
|
869
985
|
const hasDottedGroupBy = groupCols.some((f) => f.includes("."));
|
|
870
986
|
const hasDateBuckets = !!req.dateBuckets && Object.keys(req.dateBuckets).length > 0;
|
|
871
987
|
if (req.having !== void 0 || req.lookups !== void 0 && req.lookups.length > 0 || hasDottedGroupBy || hasDateBuckets) {
|
|
872
|
-
const { pipeline, prePaginationIndex } = buildAggPipeline(req);
|
|
988
|
+
const { pipeline, prePaginationIndex } = buildAggPipeline(req, Model.schema);
|
|
873
989
|
const finalPipeline = [...pipeline.slice(0, prePaginationIndex), { $count: "n" }];
|
|
874
990
|
const aggregation = Model.aggregate(finalPipeline);
|
|
875
991
|
if (session) aggregation.session(session);
|
|
@@ -877,7 +993,7 @@ async function countAggGroups(Model, req, options = {}) {
|
|
|
877
993
|
const [row] = await aggregation.exec();
|
|
878
994
|
return row?.n ?? 0;
|
|
879
995
|
}
|
|
880
|
-
const match = req.filter ? compileFilterToMongo(req.filter) : {};
|
|
996
|
+
const match = req.filter ? compileFilterToMongo(castFilterToSchema(req.filter, Model.schema)) : {};
|
|
881
997
|
if (groupCols.length === 0) {
|
|
882
998
|
const pipeline = [];
|
|
883
999
|
if (Object.keys(match).length > 0) pipeline.push({ $match: match });
|
|
@@ -906,7 +1022,7 @@ async function countAggGroups(Model, req, options = {}) {
|
|
|
906
1022
|
//#region src/actions/aggregate-ir/execute.ts
|
|
907
1023
|
async function executeAgg(Model, req, options = {}) {
|
|
908
1024
|
const session = options.session;
|
|
909
|
-
const { pipeline } = buildAggPipeline(req);
|
|
1025
|
+
const { pipeline } = buildAggPipeline(req, Model.schema);
|
|
910
1026
|
const aggregation = Model.aggregate(pipeline);
|
|
911
1027
|
if (session) aggregation.session(session);
|
|
912
1028
|
applyExecutionHints(aggregation, req.executionHints);
|
|
@@ -3746,7 +3862,7 @@ var Repository = class extends RepositoryBase {
|
|
|
3746
3862
|
if (!finalReq.sort || Object.keys(finalReq.sort).length === 0) throw new Error("mongokit/aggregatePaginate: keyset pagination requires `sort` — the cursor anchors on the sort-key tuple");
|
|
3747
3863
|
const cursor = finalReq.after ? decodeAggCursor$1(finalReq.after) : void 0;
|
|
3748
3864
|
const keysetMatch = cursor ? buildKeysetPredicate(finalReq.sort, cursor) : void 0;
|
|
3749
|
-
const { pipeline, prePaginationIndex } = buildAggPipeline(finalReq);
|
|
3865
|
+
const { pipeline, prePaginationIndex } = buildAggPipeline(finalReq, this.Model.schema);
|
|
3750
3866
|
const headStages = pipeline.slice(0, prePaginationIndex);
|
|
3751
3867
|
const tailStages = [];
|
|
3752
3868
|
if (keysetMatch) tailStages.push(keysetMatch);
|
package/dist/actions/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as __exportAll } from "../rolldown-runtime-D7D4PA-g.mjs";
|
|
2
|
-
import { g as create_exports, i as update_exports, p as delete_exports, u as read_exports, v as aggregate_exports } from "../update-
|
|
2
|
+
import { g as create_exports, i as update_exports, p as delete_exports, u as read_exports, v as aggregate_exports } from "../update-CI2NdAW6.mjs";
|
|
3
3
|
//#region src/actions/index.ts
|
|
4
4
|
var actions_exports = /* @__PURE__ */ __exportAll({
|
|
5
5
|
aggregate: () => aggregate_exports,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as Repository } from "../Repository-
|
|
1
|
+
import { n as Repository } from "../Repository-DThvFCaV.mjs";
|
|
2
2
|
import { n as createMongooseAdapter } from "../adapter-CLvUHiTW.mjs";
|
|
3
3
|
import { pluralizeBetterAuthCollection, resolveBetterAuthCollections } from "@classytic/repo-core/better-auth";
|
|
4
4
|
//#region src/better-auth/index.ts
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { n as Repository } from "./Repository-
|
|
2
|
-
import { a as methodRegistryPlugin, d as cachePlugin, f as batchOperationsPlugin, g as auditLogPlugin, i as multiTenantPlugin, m as auditTrailPlugin, n as softDeletePlugin, o as customIdPlugin, t as timestampPlugin } from "./timestamp.plugin-
|
|
1
|
+
import { n as Repository } from "./Repository-DThvFCaV.mjs";
|
|
2
|
+
import { a as methodRegistryPlugin, d as cachePlugin, f as batchOperationsPlugin, g as auditLogPlugin, i as multiTenantPlugin, m as auditTrailPlugin, n as softDeletePlugin, o as customIdPlugin, t as timestampPlugin } from "./timestamp.plugin-CFL6LlYZ.mjs";
|
|
3
3
|
//#region src/create-repository.ts
|
|
4
4
|
function isLoggerAudit(value) {
|
|
5
5
|
const v = value;
|
package/dist/index.d.mts
CHANGED
|
@@ -8,7 +8,7 @@ import { A as ensureAuditTrailReady, C as AuditTrailMethods, D as AuditTrailQuer
|
|
|
8
8
|
import { t as PaginationEngine } from "./PaginationEngine-CBS1XGzp.mjs";
|
|
9
9
|
import { a as Repository, i as HOOK_PRIORITY, n as CreateRepositoryConfig, o as TransitionMachine, r as createRepository, s as AggregationBuilder, t as AuditConfig } from "./create-repository-D4ZU94b3.mjs";
|
|
10
10
|
import { a as SoftDeleteFilterMode, c as ValidationChainOptions, i as Logger, l as ValidatorDefinition, n as CascadeRelation, o as SoftDeleteOptions, r as FieldPreset, s as SoftDeleteRepository, t as CascadeOptions } from "./plugin-options-vFufQZMZ.mjs";
|
|
11
|
-
import { A as
|
|
11
|
+
import { A as IdempotencyStorePluginOptions, B as AppendOnlyPluginOptions, C as LeasePluginOptions, D as immutableStatesPlugin, E as ImmutableStatesPluginOptions, F as cascadePlugin, H as AggregateHelpersMethods, I as BatchOperationsMethods, L as BulkWriteResult, M as fieldFilterPlugin, N as ElasticSearchOptions, O as IdempotencyClaim, P as elasticSearchPlugin, R as batchOperationsPlugin, S as LeaseMethods, T as ImmutableClaimView, U as aggregateHelpersPlugin, V as appendOnlyPlugin, _ as observabilityPlugin, a as uniqueField, c as TenantContext, d as SubdocumentMethods, f as subdocumentPlugin, g as OperationMetric, h as ObservabilityOptions, i as requireField, j as idempotencyStorePlugin, k as IdempotencyStoreMethods, l as TenantStore, m as softDeletePlugin, n as blockIf, o as validationChainPlugin, p as SoftDeleteMethods, r as immutableField, s as timestampPlugin, t as autoInject, u as createTenantContext, v as MongoOperationsMethods, w as leasePlugin, x as methodRegistryPlugin, y as mongoOperationsPlugin, z as auditLogPlugin } from "./validation-chain.plugin-BLecaKa0.mjs";
|
|
12
12
|
import { n as SchemaPathsLike, t as FieldType$1 } from "./coercion-BjdPX3YF.mjs";
|
|
13
13
|
import { n as SchemaIndexes } from "./indexes-DIjMpYES.mjs";
|
|
14
14
|
import { _ as isDuplicateKeyError, a as configureLogger, c as idVariants, f as createFieldPreset, g as createError, h as getMongooseProjection, i as createMemoryCache, m as getFieldsForUser, n as buildCrudSchemasFromModel, p as filterResponseData, r as buildCrudSchemasFromMongooseSchema, t as toPlain, v as parseDuplicateKeyError } from "./to-plain-DkF5px0R.mjs";
|
package/dist/index.mjs
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { n as idVariants } from "./id-resolution-BqDrk0S2.mjs";
|
|
2
|
-
import { a as supportsTransactions, c as ALL_OPERATIONS, d as READ_OPERATIONS, f as operationsByPolicyKey, i as isTransactionUnsupported, l as MUTATING_OPERATIONS, m as createMongoPurgePort, n as Repository, o as withTransaction, p as MONGOKIT_CAPABILITIES, r as batchTransaction, s as AggregationBuilder, t as HOOK_PRIORITY, u as OP_REGISTRY } from "./Repository-
|
|
3
|
-
import { b as LookupBuilder, x as compileFilterToMongo } from "./update-
|
|
2
|
+
import { a as supportsTransactions, c as ALL_OPERATIONS, d as READ_OPERATIONS, f as operationsByPolicyKey, i as isTransactionUnsupported, l as MUTATING_OPERATIONS, m as createMongoPurgePort, n as Repository, o as withTransaction, p as MONGOKIT_CAPABILITIES, r as batchTransaction, s as AggregationBuilder, t as HOOK_PRIORITY, u as OP_REGISTRY } from "./Repository-DThvFCaV.mjs";
|
|
3
|
+
import { b as LookupBuilder, x as compileFilterToMongo } from "./update-CI2NdAW6.mjs";
|
|
4
4
|
import { n as warn, t as configureLogger } from "./logger-K7dPmu2U.mjs";
|
|
5
5
|
import { n as isDuplicateKeyError, r as parseDuplicateKeyError, t as createError } from "./error-BuByZwKU.mjs";
|
|
6
6
|
import { t as actions_exports } from "./actions/index.mjs";
|
|
7
|
-
import { a as methodRegistryPlugin, c as getNextSequence, d as cachePlugin, f as batchOperationsPlugin, g as auditLogPlugin, h as ensureAuditTrailReady, i as multiTenantPlugin, l as prefixedId, m as auditTrailPlugin, n as softDeletePlugin, o as customIdPlugin, p as AuditTrailQuery, r as adminBypass, s as dateSequentialId, t as timestampPlugin, u as sequentialId } from "./timestamp.plugin-
|
|
7
|
+
import { a as methodRegistryPlugin, c as getNextSequence, d as cachePlugin, f as batchOperationsPlugin, g as auditLogPlugin, h as ensureAuditTrailReady, i as multiTenantPlugin, l as prefixedId, m as auditTrailPlugin, n as softDeletePlugin, o as customIdPlugin, p as AuditTrailQuery, r as adminBypass, s as dateSequentialId, t as timestampPlugin, u as sequentialId } from "./timestamp.plugin-CFL6LlYZ.mjs";
|
|
8
8
|
import { t as PaginationEngine } from "./PaginationEngine-CczbvCAq.mjs";
|
|
9
9
|
import { isGeoOperator, parseGeoFilter } from "./query/primitives/geo.mjs";
|
|
10
|
-
import { t as createRepository } from "./create-repository-
|
|
11
|
-
import { _ as cascadePlugin, a as uniqueField, c as subdocumentPlugin, d as mongoOperationsPlugin, f as leasePlugin, g as elasticSearchPlugin, h as fieldFilterPlugin, i as requireField, l as observabilityPlugin, m as
|
|
10
|
+
import { t as createRepository } from "./create-repository-uhKt_oUT.mjs";
|
|
11
|
+
import { _ as cascadePlugin, a as uniqueField, c as subdocumentPlugin, d as mongoOperationsPlugin, f as leasePlugin, g as elasticSearchPlugin, h as fieldFilterPlugin, i as requireField, l as observabilityPlugin, m as idempotencyStorePlugin, n as blockIf, o as validationChainPlugin, p as immutableStatesPlugin, r as immutableField, s as createTenantContext, t as autoInject, u as MONGOKIT_PLUGIN_NAMES, v as appendOnlyPlugin, y as aggregateHelpersPlugin } from "./validation-chain.plugin-CwOcUJC1.mjs";
|
|
12
12
|
import { i as getMongooseProjection, n as filterResponseData, r as getFieldsForUser, t as createFieldPreset } from "./field-selection-FSQFLpsU.mjs";
|
|
13
13
|
import { buildFieldTypeMap, coerceFieldValue, coerceHeuristic } from "./query/primitives/coercion.mjs";
|
|
14
14
|
import { extractSchemaIndexes } from "./query/primitives/indexes.mjs";
|
package/dist/plugins/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { S as RepositoryPluginName, b as MONGOKIT_PLUGIN_NAMES, l as Plugin, x as MongoKitPluginName } from "../repository-DCHRWRXw.mjs";
|
|
2
2
|
import { A as ensureAuditTrailReady, C as AuditTrailMethods, D as AuditTrailQueryOptions, E as AuditTrailQuery, O as EnsureAuditTrailReadyOptions, S as AuditQueryResult, T as AuditTrailOptions, _ as RepositoryCachePluginOptions, a as DateSequentialIdOptions, b as AuditOperation, c as SequentialIdOptions, d as getNextSequence, f as prefixedId, g as RepositoryCacheHandle, h as CacheOptions, i as CustomIdOptions, k as auditTrailPlugin, l as customIdPlugin, m as CacheAdapter, o as IdGenerator, p as sequentialId, r as multiTenantPlugin, s as PrefixedIdOptions, t as MultiTenantOptions, u as dateSequentialId, v as cachePlugin, w as AuditTrailMode, x as AuditQueryOptions, y as AuditEntry } from "../multi-tenant.plugin-DVyVGREb.mjs";
|
|
3
|
-
import { A as
|
|
3
|
+
import { A as IdempotencyStorePluginOptions, B as AppendOnlyPluginOptions, C as LeasePluginOptions, D as immutableStatesPlugin, E as ImmutableStatesPluginOptions, F as cascadePlugin, H as AggregateHelpersMethods, I as BatchOperationsMethods, M as fieldFilterPlugin, N as ElasticSearchOptions, O as IdempotencyClaim, P as elasticSearchPlugin, R as batchOperationsPlugin, S as LeaseMethods, T as ImmutableClaimView, U as aggregateHelpersPlugin, V as appendOnlyPlugin, _ as observabilityPlugin, a as uniqueField, b as MethodRegistryRepository, c as TenantContext, d as SubdocumentMethods, f as subdocumentPlugin, g as OperationMetric, h as ObservabilityOptions, i as requireField, j as idempotencyStorePlugin, k as IdempotencyStoreMethods, l as TenantStore, m as softDeletePlugin, n as blockIf, o as validationChainPlugin, p as SoftDeleteMethods, r as immutableField, s as timestampPlugin, t as autoInject, u as createTenantContext, v as MongoOperationsMethods, w as leasePlugin, x as methodRegistryPlugin, y as mongoOperationsPlugin, z as auditLogPlugin } from "../validation-chain.plugin-BLecaKa0.mjs";
|
|
4
4
|
import { ChangeLogStore } from "@classytic/repo-core/sync";
|
|
5
5
|
//#region src/plugins/change-log.plugin.d.ts
|
|
6
6
|
interface ChangeLogPluginOptions {
|
package/dist/plugins/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as methodRegistryPlugin, c as getNextSequence, d as cachePlugin, f as batchOperationsPlugin, g as auditLogPlugin, h as ensureAuditTrailReady, i as multiTenantPlugin, l as prefixedId, m as auditTrailPlugin, n as softDeletePlugin, o as customIdPlugin, p as AuditTrailQuery, s as dateSequentialId, t as timestampPlugin, u as sequentialId } from "../timestamp.plugin-
|
|
2
|
-
import { _ as cascadePlugin, a as uniqueField, c as subdocumentPlugin, d as mongoOperationsPlugin, f as leasePlugin, g as elasticSearchPlugin, h as fieldFilterPlugin, i as requireField, l as observabilityPlugin, m as
|
|
1
|
+
import { a as methodRegistryPlugin, c as getNextSequence, d as cachePlugin, f as batchOperationsPlugin, g as auditLogPlugin, h as ensureAuditTrailReady, i as multiTenantPlugin, l as prefixedId, m as auditTrailPlugin, n as softDeletePlugin, o as customIdPlugin, p as AuditTrailQuery, s as dateSequentialId, t as timestampPlugin, u as sequentialId } from "../timestamp.plugin-CFL6LlYZ.mjs";
|
|
2
|
+
import { _ as cascadePlugin, a as uniqueField, c as subdocumentPlugin, d as mongoOperationsPlugin, f as leasePlugin, g as elasticSearchPlugin, h as fieldFilterPlugin, i as requireField, l as observabilityPlugin, m as idempotencyStorePlugin, n as blockIf, o as validationChainPlugin, p as immutableStatesPlugin, r as immutableField, s as createTenantContext, t as autoInject, u as MONGOKIT_PLUGIN_NAMES, v as appendOnlyPlugin, y as aggregateHelpersPlugin } from "../validation-chain.plugin-CwOcUJC1.mjs";
|
|
3
3
|
//#region src/plugins/change-log.plugin.ts
|
|
4
4
|
const PLUGIN_NAME = "changeLog";
|
|
5
5
|
function isSkipped(context) {
|
package/dist/testkit/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as ALL_OPERATIONS, t as HOOK_PRIORITY, u as OP_REGISTRY } from "./Repository-
|
|
1
|
+
import { c as ALL_OPERATIONS, t as HOOK_PRIORITY, u as OP_REGISTRY } from "./Repository-DThvFCaV.mjs";
|
|
2
2
|
import { n as warn } from "./logger-K7dPmu2U.mjs";
|
|
3
3
|
import { t as createError } from "./error-BuByZwKU.mjs";
|
|
4
4
|
import { throwIfAborted, withRetry } from "@classytic/repo-core/repository";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
|
|
2
2
|
import { n as warn } from "./logger-K7dPmu2U.mjs";
|
|
3
3
|
import { t as createError } from "./error-BuByZwKU.mjs";
|
|
4
|
-
import { isFilter } from "@classytic/repo-core/filter";
|
|
4
|
+
import { coerceFilterDates, isFilter } from "@classytic/repo-core/filter";
|
|
5
5
|
//#region src/filter/compile.ts
|
|
6
6
|
/**
|
|
7
7
|
* Compile a Filter IR node to a MongoDB query object. Returns `{}`
|
|
@@ -34,47 +34,41 @@ const SHORTHAND_OPS = /* @__PURE__ */ new Set([
|
|
|
34
34
|
"regex",
|
|
35
35
|
"mod"
|
|
36
36
|
]);
|
|
37
|
-
/**
|
|
38
|
-
const
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"lte"
|
|
37
|
+
/** Logical operators whose operand is an array of sub-queries to recurse into. */
|
|
38
|
+
const LOGICAL_ARRAY_OPS = /* @__PURE__ */ new Set([
|
|
39
|
+
"$and",
|
|
40
|
+
"$or",
|
|
41
|
+
"$nor"
|
|
43
42
|
]);
|
|
44
|
-
/** ISO-8601 date-only or datetime string pattern. */
|
|
45
|
-
const ISO_DATE_RE = /^\d{4}-\d{2}-\d{2}/;
|
|
46
|
-
/**
|
|
47
|
-
* Coerce a string value to a Date when it looks like an ISO-8601 date.
|
|
48
|
-
* Needed because MongoDB won't match a BSON Date field against a string
|
|
49
|
-
* value even when using range operators — BSON type comparison treats
|
|
50
|
-
* Date (type 9) and String (type 2) as distinct, so `{ createdAt: {
|
|
51
|
-
* $gte: "2026-05-01" } }` never matches a Date-typed field.
|
|
52
|
-
*/
|
|
53
|
-
function tryCoerceDate(value) {
|
|
54
|
-
if (typeof value === "string" && ISO_DATE_RE.test(value)) {
|
|
55
|
-
const d = new Date(value);
|
|
56
|
-
return Number.isNaN(d.getTime()) ? value : d;
|
|
57
|
-
}
|
|
58
|
-
return value;
|
|
59
|
-
}
|
|
60
43
|
/**
|
|
61
|
-
* Expand operator shorthand values in a plain Mongo-style query object
|
|
44
|
+
* Expand operator shorthand values in a plain Mongo-style query object —
|
|
45
|
+
* `$`-prefixing is the ONE Mongo-dialect concern this function owns. Date
|
|
46
|
+
* coercion is delegated to `coerceFilterDates` (repo-core) so the ISO
|
|
47
|
+
* pattern has a single source of truth shared with the URL-parsing boundary.
|
|
48
|
+
*
|
|
62
49
|
* Only expands nested objects whose keys are ALL in `SHORTHAND_OPS` — so
|
|
63
50
|
* real nested documents (e.g. `address: { city: 'Dhaka' }`) pass through
|
|
64
51
|
* unchanged, while `createdAt: { gte: '2026-04-01', lte: '2026-05-01' }`
|
|
65
|
-
* becomes `createdAt: { $gte:
|
|
66
|
-
*
|
|
67
|
-
*
|
|
52
|
+
* becomes `createdAt: { $gte: '2026-04-01', $lte: '2026-05-01' }` for the
|
|
53
|
+
* coercion pass to type.
|
|
54
|
+
*
|
|
55
|
+
* Recurses `$and` / `$or` / `$nor` because a policy-scope merge conjoins the
|
|
56
|
+
* caller filter under `$and`, and un-prefixed shorthand nested there would
|
|
57
|
+
* otherwise reach `$match` as a literal field named `gte`.
|
|
68
58
|
*/
|
|
69
59
|
function expandShorthands(obj) {
|
|
70
60
|
const out = {};
|
|
71
61
|
for (const [key, value] of Object.entries(obj)) {
|
|
62
|
+
if (LOGICAL_ARRAY_OPS.has(key) && Array.isArray(value)) {
|
|
63
|
+
out[key] = value.map((entry) => entry !== null && typeof entry === "object" && !Array.isArray(entry) ? expandShorthands(entry) : entry);
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
72
66
|
if (value !== null && typeof value === "object" && !Array.isArray(value)) {
|
|
73
67
|
const nested = value;
|
|
74
68
|
const keys = Object.keys(nested);
|
|
75
69
|
if (keys.length > 0 && keys.every((k) => !k.startsWith("$") && SHORTHAND_OPS.has(k))) {
|
|
76
70
|
const expanded = {};
|
|
77
|
-
for (const [op, opVal] of Object.entries(nested)) expanded[`$${op}`] =
|
|
71
|
+
for (const [op, opVal] of Object.entries(nested)) expanded[`$${op}`] = opVal;
|
|
78
72
|
out[key] = expanded;
|
|
79
73
|
continue;
|
|
80
74
|
}
|
|
@@ -85,7 +79,7 @@ function expandShorthands(obj) {
|
|
|
85
79
|
}
|
|
86
80
|
function compileFilterToMongo(input) {
|
|
87
81
|
if (!input) return {};
|
|
88
|
-
if (!isFilter(input)) return expandShorthands(input);
|
|
82
|
+
if (!isFilter(input)) return coerceFilterDates(expandShorthands(input));
|
|
89
83
|
return compile(input);
|
|
90
84
|
}
|
|
91
85
|
function compile(filter) {
|
package/dist/{validation-chain.plugin-Cm0Ttnd8.d.mts → validation-chain.plugin-BLecaKa0.d.mts}
RENAMED
|
@@ -185,47 +185,6 @@ declare function elasticSearchPlugin(options: ElasticSearchOptions): Plugin;
|
|
|
185
185
|
*/
|
|
186
186
|
declare function fieldFilterPlugin(fieldPreset: FieldPreset): Plugin;
|
|
187
187
|
//#endregion
|
|
188
|
-
//#region src/plugins/immutable-states.plugin.d.ts
|
|
189
|
-
/** The slice of a `before:claim` context `allowClaim` predicates see. */
|
|
190
|
-
interface ImmutableClaimView {
|
|
191
|
-
id: unknown;
|
|
192
|
-
transition: {
|
|
193
|
-
from?: unknown | readonly unknown[];
|
|
194
|
-
to?: unknown;
|
|
195
|
-
field?: string;
|
|
196
|
-
where?: Record<string, unknown>;
|
|
197
|
-
};
|
|
198
|
-
/** Operator-form patch (`{ $set: {...}, ... }`). */
|
|
199
|
-
data: Record<string, unknown> | undefined;
|
|
200
|
-
}
|
|
201
|
-
interface ImmutableStatesPluginOptions {
|
|
202
|
-
/** States in which the document is frozen (e.g. `['posted']`). */
|
|
203
|
-
states: readonly string[];
|
|
204
|
-
/** State field on the doc — dotted paths supported. Default `'state'`. */
|
|
205
|
-
field?: string | undefined;
|
|
206
|
-
/**
|
|
207
|
-
* Context flag the OWNING ENGINE's verbs set to pass the guard
|
|
208
|
-
* (private handshake — see module doc). Default `'_immutableInternal'`.
|
|
209
|
-
*/
|
|
210
|
-
internalFlag?: string | undefined;
|
|
211
|
-
/** Tenant field used to scope state lookups (mirrors the repo's scope). */
|
|
212
|
-
tenantField?: string | undefined;
|
|
213
|
-
/**
|
|
214
|
-
* Exempt specific claim shapes that legitimately touch frozen rows
|
|
215
|
-
* (audit-trail stamps like ledger's reverse-mark). Return `true` to
|
|
216
|
-
* allow. Runs only after the claim was determined to reach a frozen
|
|
217
|
-
* state — keep the predicate a strict fingerprint.
|
|
218
|
-
*/
|
|
219
|
-
allowClaim?: ((view: ImmutableClaimView) => boolean) | undefined;
|
|
220
|
-
/** Domain error to throw. Default: 403 `IMMUTABLE_STATE_VIOLATION`. */
|
|
221
|
-
errorFactory?: ((ctx: {
|
|
222
|
-
id: unknown;
|
|
223
|
-
operation: string;
|
|
224
|
-
state?: string | undefined;
|
|
225
|
-
}) => Error) | undefined;
|
|
226
|
-
}
|
|
227
|
-
declare function immutableStatesPlugin(options: ImmutableStatesPluginOptions): Plugin;
|
|
228
|
-
//#endregion
|
|
229
188
|
//#region src/plugins/idempotency-store.plugin.d.ts
|
|
230
189
|
interface IdempotencyStorePluginOptions {
|
|
231
190
|
/** Field carrying the deterministic operation key. @default `'key'` */
|
|
@@ -362,6 +321,47 @@ interface IdempotencyStoreMethods<TProgress = Record<string, unknown>, TResult =
|
|
|
362
321
|
}
|
|
363
322
|
declare function idempotencyStorePlugin(options?: IdempotencyStorePluginOptions): Plugin;
|
|
364
323
|
//#endregion
|
|
324
|
+
//#region src/plugins/immutable-states.plugin.d.ts
|
|
325
|
+
/** The slice of a `before:claim` context `allowClaim` predicates see. */
|
|
326
|
+
interface ImmutableClaimView {
|
|
327
|
+
id: unknown;
|
|
328
|
+
transition: {
|
|
329
|
+
from?: unknown | readonly unknown[];
|
|
330
|
+
to?: unknown;
|
|
331
|
+
field?: string;
|
|
332
|
+
where?: Record<string, unknown>;
|
|
333
|
+
};
|
|
334
|
+
/** Operator-form patch (`{ $set: {...}, ... }`). */
|
|
335
|
+
data: Record<string, unknown> | undefined;
|
|
336
|
+
}
|
|
337
|
+
interface ImmutableStatesPluginOptions {
|
|
338
|
+
/** States in which the document is frozen (e.g. `['posted']`). */
|
|
339
|
+
states: readonly string[];
|
|
340
|
+
/** State field on the doc — dotted paths supported. Default `'state'`. */
|
|
341
|
+
field?: string | undefined;
|
|
342
|
+
/**
|
|
343
|
+
* Context flag the OWNING ENGINE's verbs set to pass the guard
|
|
344
|
+
* (private handshake — see module doc). Default `'_immutableInternal'`.
|
|
345
|
+
*/
|
|
346
|
+
internalFlag?: string | undefined;
|
|
347
|
+
/** Tenant field used to scope state lookups (mirrors the repo's scope). */
|
|
348
|
+
tenantField?: string | undefined;
|
|
349
|
+
/**
|
|
350
|
+
* Exempt specific claim shapes that legitimately touch frozen rows
|
|
351
|
+
* (audit-trail stamps like ledger's reverse-mark). Return `true` to
|
|
352
|
+
* allow. Runs only after the claim was determined to reach a frozen
|
|
353
|
+
* state — keep the predicate a strict fingerprint.
|
|
354
|
+
*/
|
|
355
|
+
allowClaim?: ((view: ImmutableClaimView) => boolean) | undefined;
|
|
356
|
+
/** Domain error to throw. Default: 403 `IMMUTABLE_STATE_VIOLATION`. */
|
|
357
|
+
errorFactory?: ((ctx: {
|
|
358
|
+
id: unknown;
|
|
359
|
+
operation: string;
|
|
360
|
+
state?: string | undefined;
|
|
361
|
+
}) => Error) | undefined;
|
|
362
|
+
}
|
|
363
|
+
declare function immutableStatesPlugin(options: ImmutableStatesPluginOptions): Plugin;
|
|
364
|
+
//#endregion
|
|
365
365
|
//#region src/plugins/lease.plugin.d.ts
|
|
366
366
|
interface LeasePluginOptions {
|
|
367
367
|
/** Field carrying the row's status. @default `'status'` */
|
|
@@ -958,4 +958,4 @@ declare function immutableField(field: string): ValidatorDefinition;
|
|
|
958
958
|
*/
|
|
959
959
|
declare function uniqueField(field: string, errorMessage?: string): ValidatorDefinition;
|
|
960
960
|
//#endregion
|
|
961
|
-
export {
|
|
961
|
+
export { IdempotencyStorePluginOptions as A, AppendOnlyPluginOptions as B, LeasePluginOptions as C, immutableStatesPlugin as D, ImmutableStatesPluginOptions as E, cascadePlugin as F, AggregateHelpersMethods as H, BatchOperationsMethods as I, BulkWriteResult as L, fieldFilterPlugin as M, ElasticSearchOptions as N, IdempotencyClaim as O, elasticSearchPlugin as P, batchOperationsPlugin as R, LeaseMethods as S, ImmutableClaimView as T, aggregateHelpersPlugin as U, appendOnlyPlugin as V, observabilityPlugin as _, uniqueField as a, MethodRegistryRepository as b, TenantContext as c, SubdocumentMethods as d, subdocumentPlugin as f, OperationMetric as g, ObservabilityOptions as h, requireField as i, idempotencyStorePlugin as j, IdempotencyStoreMethods as k, TenantStore as l, softDeletePlugin as m, blockIf as n, validationChainPlugin as o, SoftDeleteMethods as p, immutableField as r, timestampPlugin as s, autoInject as t, createTenantContext as u, MongoOperationsMethods as v, leasePlugin as w, methodRegistryPlugin as x, mongoOperationsPlugin as y, auditLogPlugin as z };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { c as ALL_OPERATIONS, u as OP_REGISTRY } from "./Repository-
|
|
2
|
-
import { _ as upsert } from "./update-
|
|
1
|
+
import { c as ALL_OPERATIONS, u as OP_REGISTRY } from "./Repository-DThvFCaV.mjs";
|
|
2
|
+
import { _ as upsert } from "./update-CI2NdAW6.mjs";
|
|
3
3
|
import { n as warn } from "./logger-K7dPmu2U.mjs";
|
|
4
4
|
import { t as createError } from "./error-BuByZwKU.mjs";
|
|
5
5
|
import { r as getFieldsForUser } from "./field-selection-FSQFLpsU.mjs";
|
|
@@ -476,140 +476,6 @@ function fieldFilterPlugin(fieldPreset) {
|
|
|
476
476
|
};
|
|
477
477
|
}
|
|
478
478
|
//#endregion
|
|
479
|
-
//#region src/plugins/immutable-states.plugin.ts
|
|
480
|
-
/** Ops this plugin has an explicit strategy for (see module doc). */
|
|
481
|
-
const STRATEGY_OPS = /* @__PURE__ */ new Set([
|
|
482
|
-
"create",
|
|
483
|
-
"createMany",
|
|
484
|
-
"update",
|
|
485
|
-
"delete",
|
|
486
|
-
"claimVersion",
|
|
487
|
-
"restore",
|
|
488
|
-
"findOneAndUpdate",
|
|
489
|
-
"updateMany",
|
|
490
|
-
"deleteMany",
|
|
491
|
-
"bulkWrite",
|
|
492
|
-
"claim"
|
|
493
|
-
]);
|
|
494
|
-
function immutableStatesPlugin(options) {
|
|
495
|
-
const field = options.field ?? "state";
|
|
496
|
-
const internalFlag = options.internalFlag ?? "_immutableInternal";
|
|
497
|
-
const frozen = new Set(options.states);
|
|
498
|
-
const throwViolation = (ctx) => {
|
|
499
|
-
if (options.errorFactory) throw options.errorFactory(ctx);
|
|
500
|
-
throw createError(403, `Document ${String(ctx.id)} is in immutable state${ctx.state !== void 0 ? ` '${ctx.state}'` : ""} — '${ctx.operation}' is not permitted. Frozen rows change only through the owning engine's transition verbs.`, {
|
|
501
|
-
code: "IMMUTABLE_STATE_VIOLATION",
|
|
502
|
-
meta: { ...ctx }
|
|
503
|
-
});
|
|
504
|
-
};
|
|
505
|
-
return {
|
|
506
|
-
name: "immutableStates",
|
|
507
|
-
apply(repo) {
|
|
508
|
-
const unhandled = Object.entries(OP_REGISTRY).filter(([op, meta]) => meta.mutates && !STRATEGY_OPS.has(op)).map(([op]) => op);
|
|
509
|
-
if (unhandled.length > 0) throw createError(500, `immutableStatesPlugin has no strategy for mutating op(s): ${unhandled.join(", ")}. Mongokit added write ops this plugin predates — extend the plugin before using it.`, {
|
|
510
|
-
code: "IMMUTABLE_STATES_UNHANDLED_OPS",
|
|
511
|
-
meta: { unhandled }
|
|
512
|
-
});
|
|
513
|
-
const Model = repo.Model;
|
|
514
|
-
const getState = (doc) => field.split(".").reduce((acc, key) => acc?.[key], doc);
|
|
515
|
-
const scoped = (base, ctx) => {
|
|
516
|
-
const q = { ...base };
|
|
517
|
-
if (options.tenantField && ctx.query && options.tenantField in ctx.query) q[options.tenantField] = ctx.query[options.tenantField];
|
|
518
|
-
return q;
|
|
519
|
-
};
|
|
520
|
-
/** Raw-Model read — never re-enters the repo hook pipeline. */
|
|
521
|
-
const readStateById = async (ctx) => {
|
|
522
|
-
if (ctx.id === void 0 || ctx.id === null) return void 0;
|
|
523
|
-
const doc = await Model.findOne(scoped({ _id: ctx.id }, ctx)).select({ [field]: 1 }).lean();
|
|
524
|
-
return doc ? getState(doc) : void 0;
|
|
525
|
-
};
|
|
526
|
-
const guardById = (op) => async (ctx) => {
|
|
527
|
-
if (ctx[internalFlag]) return;
|
|
528
|
-
const state = await readStateById(ctx);
|
|
529
|
-
if (state !== void 0 && frozen.has(state)) throwViolation({
|
|
530
|
-
id: ctx.id,
|
|
531
|
-
operation: op,
|
|
532
|
-
state
|
|
533
|
-
});
|
|
534
|
-
};
|
|
535
|
-
for (const op of [
|
|
536
|
-
"update",
|
|
537
|
-
"delete",
|
|
538
|
-
"claimVersion",
|
|
539
|
-
"restore"
|
|
540
|
-
]) repo.on(`before:${op}`, guardById(op));
|
|
541
|
-
repo.on("before:findOneAndUpdate", async (ctx) => {
|
|
542
|
-
if (ctx[internalFlag]) return;
|
|
543
|
-
const filter = ctx.query ?? {};
|
|
544
|
-
const doc = await Model.findOne(filter).select({
|
|
545
|
-
[field]: 1,
|
|
546
|
-
_id: 1
|
|
547
|
-
}).lean();
|
|
548
|
-
if (!doc) return;
|
|
549
|
-
const state = getState(doc);
|
|
550
|
-
if (state !== void 0 && frozen.has(state)) throwViolation({
|
|
551
|
-
id: doc._id,
|
|
552
|
-
operation: "findOneAndUpdate",
|
|
553
|
-
state
|
|
554
|
-
});
|
|
555
|
-
});
|
|
556
|
-
const guardMany = (op) => async (ctx) => {
|
|
557
|
-
if (ctx[internalFlag]) return;
|
|
558
|
-
const filter = ctx.query ?? {};
|
|
559
|
-
const hit = await Model.exists({ $and: [filter, { [field]: { $in: [...frozen] } }] });
|
|
560
|
-
if (hit) throwViolation({
|
|
561
|
-
id: hit._id,
|
|
562
|
-
operation: op,
|
|
563
|
-
state: void 0
|
|
564
|
-
});
|
|
565
|
-
};
|
|
566
|
-
repo.on("before:updateMany", guardMany("updateMany"));
|
|
567
|
-
repo.on("before:deleteMany", guardMany("deleteMany"));
|
|
568
|
-
repo.on("before:bulkWrite", (ctx) => {
|
|
569
|
-
if (ctx[internalFlag]) return;
|
|
570
|
-
throwViolation({
|
|
571
|
-
id: void 0,
|
|
572
|
-
operation: "bulkWrite",
|
|
573
|
-
state: void 0
|
|
574
|
-
});
|
|
575
|
-
});
|
|
576
|
-
repo.on("before:claim", async (rawCtx) => {
|
|
577
|
-
const ctx = rawCtx;
|
|
578
|
-
if (ctx[internalFlag]) return;
|
|
579
|
-
const t = ctx.transition;
|
|
580
|
-
if (!t) return;
|
|
581
|
-
if ((t.field ?? "status") === field) {
|
|
582
|
-
const fromSpec = t.from;
|
|
583
|
-
if (!(Array.isArray(fromSpec) ? fromSpec.some((f) => frozen.has(String(f))) : frozen.has(String(fromSpec)))) return;
|
|
584
|
-
if (options.allowClaim?.({
|
|
585
|
-
id: ctx.id,
|
|
586
|
-
transition: t,
|
|
587
|
-
data: ctx.data
|
|
588
|
-
})) return;
|
|
589
|
-
throwViolation({
|
|
590
|
-
id: ctx.id,
|
|
591
|
-
operation: "claim",
|
|
592
|
-
state: void 0
|
|
593
|
-
});
|
|
594
|
-
}
|
|
595
|
-
const state = await readStateById(ctx);
|
|
596
|
-
if (state !== void 0 && frozen.has(state)) {
|
|
597
|
-
if (options.allowClaim?.({
|
|
598
|
-
id: ctx.id,
|
|
599
|
-
transition: t,
|
|
600
|
-
data: ctx.data
|
|
601
|
-
})) return;
|
|
602
|
-
throwViolation({
|
|
603
|
-
id: ctx.id,
|
|
604
|
-
operation: "claim",
|
|
605
|
-
state
|
|
606
|
-
});
|
|
607
|
-
}
|
|
608
|
-
});
|
|
609
|
-
}
|
|
610
|
-
};
|
|
611
|
-
}
|
|
612
|
-
//#endregion
|
|
613
479
|
//#region src/plugins/idempotency-store.plugin.ts
|
|
614
480
|
function randomToken() {
|
|
615
481
|
const bytes = /* @__PURE__ */ new Uint8Array(16);
|
|
@@ -757,6 +623,140 @@ function idempotencyStorePlugin(options = {}) {
|
|
|
757
623
|
};
|
|
758
624
|
}
|
|
759
625
|
//#endregion
|
|
626
|
+
//#region src/plugins/immutable-states.plugin.ts
|
|
627
|
+
/** Ops this plugin has an explicit strategy for (see module doc). */
|
|
628
|
+
const STRATEGY_OPS = /* @__PURE__ */ new Set([
|
|
629
|
+
"create",
|
|
630
|
+
"createMany",
|
|
631
|
+
"update",
|
|
632
|
+
"delete",
|
|
633
|
+
"claimVersion",
|
|
634
|
+
"restore",
|
|
635
|
+
"findOneAndUpdate",
|
|
636
|
+
"updateMany",
|
|
637
|
+
"deleteMany",
|
|
638
|
+
"bulkWrite",
|
|
639
|
+
"claim"
|
|
640
|
+
]);
|
|
641
|
+
function immutableStatesPlugin(options) {
|
|
642
|
+
const field = options.field ?? "state";
|
|
643
|
+
const internalFlag = options.internalFlag ?? "_immutableInternal";
|
|
644
|
+
const frozen = new Set(options.states);
|
|
645
|
+
const throwViolation = (ctx) => {
|
|
646
|
+
if (options.errorFactory) throw options.errorFactory(ctx);
|
|
647
|
+
throw createError(403, `Document ${String(ctx.id)} is in immutable state${ctx.state !== void 0 ? ` '${ctx.state}'` : ""} — '${ctx.operation}' is not permitted. Frozen rows change only through the owning engine's transition verbs.`, {
|
|
648
|
+
code: "IMMUTABLE_STATE_VIOLATION",
|
|
649
|
+
meta: { ...ctx }
|
|
650
|
+
});
|
|
651
|
+
};
|
|
652
|
+
return {
|
|
653
|
+
name: "immutableStates",
|
|
654
|
+
apply(repo) {
|
|
655
|
+
const unhandled = Object.entries(OP_REGISTRY).filter(([op, meta]) => meta.mutates && !STRATEGY_OPS.has(op)).map(([op]) => op);
|
|
656
|
+
if (unhandled.length > 0) throw createError(500, `immutableStatesPlugin has no strategy for mutating op(s): ${unhandled.join(", ")}. Mongokit added write ops this plugin predates — extend the plugin before using it.`, {
|
|
657
|
+
code: "IMMUTABLE_STATES_UNHANDLED_OPS",
|
|
658
|
+
meta: { unhandled }
|
|
659
|
+
});
|
|
660
|
+
const Model = repo.Model;
|
|
661
|
+
const getState = (doc) => field.split(".").reduce((acc, key) => acc?.[key], doc);
|
|
662
|
+
const scoped = (base, ctx) => {
|
|
663
|
+
const q = { ...base };
|
|
664
|
+
if (options.tenantField && ctx.query && options.tenantField in ctx.query) q[options.tenantField] = ctx.query[options.tenantField];
|
|
665
|
+
return q;
|
|
666
|
+
};
|
|
667
|
+
/** Raw-Model read — never re-enters the repo hook pipeline. */
|
|
668
|
+
const readStateById = async (ctx) => {
|
|
669
|
+
if (ctx.id === void 0 || ctx.id === null) return void 0;
|
|
670
|
+
const doc = await Model.findOne(scoped({ _id: ctx.id }, ctx)).select({ [field]: 1 }).lean();
|
|
671
|
+
return doc ? getState(doc) : void 0;
|
|
672
|
+
};
|
|
673
|
+
const guardById = (op) => async (ctx) => {
|
|
674
|
+
if (ctx[internalFlag]) return;
|
|
675
|
+
const state = await readStateById(ctx);
|
|
676
|
+
if (state !== void 0 && frozen.has(state)) throwViolation({
|
|
677
|
+
id: ctx.id,
|
|
678
|
+
operation: op,
|
|
679
|
+
state
|
|
680
|
+
});
|
|
681
|
+
};
|
|
682
|
+
for (const op of [
|
|
683
|
+
"update",
|
|
684
|
+
"delete",
|
|
685
|
+
"claimVersion",
|
|
686
|
+
"restore"
|
|
687
|
+
]) repo.on(`before:${op}`, guardById(op));
|
|
688
|
+
repo.on("before:findOneAndUpdate", async (ctx) => {
|
|
689
|
+
if (ctx[internalFlag]) return;
|
|
690
|
+
const filter = ctx.query ?? {};
|
|
691
|
+
const doc = await Model.findOne(filter).select({
|
|
692
|
+
[field]: 1,
|
|
693
|
+
_id: 1
|
|
694
|
+
}).lean();
|
|
695
|
+
if (!doc) return;
|
|
696
|
+
const state = getState(doc);
|
|
697
|
+
if (state !== void 0 && frozen.has(state)) throwViolation({
|
|
698
|
+
id: doc._id,
|
|
699
|
+
operation: "findOneAndUpdate",
|
|
700
|
+
state
|
|
701
|
+
});
|
|
702
|
+
});
|
|
703
|
+
const guardMany = (op) => async (ctx) => {
|
|
704
|
+
if (ctx[internalFlag]) return;
|
|
705
|
+
const filter = ctx.query ?? {};
|
|
706
|
+
const hit = await Model.exists({ $and: [filter, { [field]: { $in: [...frozen] } }] });
|
|
707
|
+
if (hit) throwViolation({
|
|
708
|
+
id: hit._id,
|
|
709
|
+
operation: op,
|
|
710
|
+
state: void 0
|
|
711
|
+
});
|
|
712
|
+
};
|
|
713
|
+
repo.on("before:updateMany", guardMany("updateMany"));
|
|
714
|
+
repo.on("before:deleteMany", guardMany("deleteMany"));
|
|
715
|
+
repo.on("before:bulkWrite", (ctx) => {
|
|
716
|
+
if (ctx[internalFlag]) return;
|
|
717
|
+
throwViolation({
|
|
718
|
+
id: void 0,
|
|
719
|
+
operation: "bulkWrite",
|
|
720
|
+
state: void 0
|
|
721
|
+
});
|
|
722
|
+
});
|
|
723
|
+
repo.on("before:claim", async (rawCtx) => {
|
|
724
|
+
const ctx = rawCtx;
|
|
725
|
+
if (ctx[internalFlag]) return;
|
|
726
|
+
const t = ctx.transition;
|
|
727
|
+
if (!t) return;
|
|
728
|
+
if ((t.field ?? "status") === field) {
|
|
729
|
+
const fromSpec = t.from;
|
|
730
|
+
if (!(Array.isArray(fromSpec) ? fromSpec.some((f) => frozen.has(String(f))) : frozen.has(String(fromSpec)))) return;
|
|
731
|
+
if (options.allowClaim?.({
|
|
732
|
+
id: ctx.id,
|
|
733
|
+
transition: t,
|
|
734
|
+
data: ctx.data
|
|
735
|
+
})) return;
|
|
736
|
+
throwViolation({
|
|
737
|
+
id: ctx.id,
|
|
738
|
+
operation: "claim",
|
|
739
|
+
state: void 0
|
|
740
|
+
});
|
|
741
|
+
}
|
|
742
|
+
const state = await readStateById(ctx);
|
|
743
|
+
if (state !== void 0 && frozen.has(state)) {
|
|
744
|
+
if (options.allowClaim?.({
|
|
745
|
+
id: ctx.id,
|
|
746
|
+
transition: t,
|
|
747
|
+
data: ctx.data
|
|
748
|
+
})) return;
|
|
749
|
+
throwViolation({
|
|
750
|
+
id: ctx.id,
|
|
751
|
+
operation: "claim",
|
|
752
|
+
state
|
|
753
|
+
});
|
|
754
|
+
}
|
|
755
|
+
});
|
|
756
|
+
}
|
|
757
|
+
};
|
|
758
|
+
}
|
|
759
|
+
//#endregion
|
|
760
760
|
//#region src/plugins/lease.plugin.ts
|
|
761
761
|
function leasePlugin(options = {}) {
|
|
762
762
|
const statusField = options.statusField ?? "status";
|
|
@@ -1451,4 +1451,4 @@ function uniqueField(field, errorMessage) {
|
|
|
1451
1451
|
};
|
|
1452
1452
|
}
|
|
1453
1453
|
//#endregion
|
|
1454
|
-
export { cascadePlugin as _, uniqueField as a, subdocumentPlugin as c, mongoOperationsPlugin as d, leasePlugin as f, elasticSearchPlugin as g, fieldFilterPlugin as h, requireField as i, observabilityPlugin as l,
|
|
1454
|
+
export { cascadePlugin as _, uniqueField as a, subdocumentPlugin as c, mongoOperationsPlugin as d, leasePlugin as f, elasticSearchPlugin as g, fieldFilterPlugin as h, requireField as i, observabilityPlugin as l, idempotencyStorePlugin as m, blockIf as n, validationChainPlugin as o, immutableStatesPlugin as p, immutableField as r, createTenantContext as s, autoInject as t, MONGOKIT_PLUGIN_NAMES as u, appendOnlyPlugin as v, aggregateHelpersPlugin as y };
|
package/package.json
CHANGED
|
@@ -1,180 +1,187 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
2
|
+
"name": "@classytic/mongokit",
|
|
3
|
+
"version": "3.29.0",
|
|
4
|
+
"description": "Production-grade MongoDB repositories - smart pagination, events, and plugins. Built on @classytic/repo-core.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"sideEffects": false,
|
|
7
|
+
"main": "./dist/index.mjs",
|
|
8
|
+
"module": "./dist/index.mjs",
|
|
9
|
+
"types": "./dist/index.d.mts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.mts",
|
|
13
|
+
"default": "./dist/index.mjs"
|
|
14
|
+
},
|
|
15
|
+
"./pagination": {
|
|
16
|
+
"types": "./dist/pagination/PaginationEngine.d.mts",
|
|
17
|
+
"default": "./dist/pagination/PaginationEngine.mjs"
|
|
18
|
+
},
|
|
19
|
+
"./plugins": {
|
|
20
|
+
"types": "./dist/plugins/index.d.mts",
|
|
21
|
+
"default": "./dist/plugins/index.mjs"
|
|
22
|
+
},
|
|
23
|
+
"./utils": {
|
|
24
|
+
"types": "./dist/utils/index.d.mts",
|
|
25
|
+
"default": "./dist/utils/index.mjs"
|
|
26
|
+
},
|
|
27
|
+
"./actions": {
|
|
28
|
+
"types": "./dist/actions/index.d.mts",
|
|
29
|
+
"default": "./dist/actions/index.mjs"
|
|
30
|
+
},
|
|
31
|
+
"./ai": {
|
|
32
|
+
"types": "./dist/ai/index.d.mts",
|
|
33
|
+
"default": "./dist/ai/index.mjs"
|
|
34
|
+
},
|
|
35
|
+
"./adapter": {
|
|
36
|
+
"types": "./dist/adapter/index.d.mts",
|
|
37
|
+
"default": "./dist/adapter/index.mjs"
|
|
38
|
+
},
|
|
39
|
+
"./better-auth": {
|
|
40
|
+
"types": "./dist/better-auth/index.d.mts",
|
|
41
|
+
"default": "./dist/better-auth/index.mjs"
|
|
42
|
+
},
|
|
43
|
+
"./lock": {
|
|
44
|
+
"types": "./dist/lock/index.d.mts",
|
|
45
|
+
"default": "./dist/lock/index.mjs"
|
|
46
|
+
},
|
|
47
|
+
"./usage": {
|
|
48
|
+
"types": "./dist/usage/index.d.mts",
|
|
49
|
+
"default": "./dist/usage/index.mjs"
|
|
50
|
+
},
|
|
51
|
+
"./query/primitives/geo": {
|
|
52
|
+
"types": "./dist/query/primitives/geo.d.mts",
|
|
53
|
+
"default": "./dist/query/primitives/geo.mjs"
|
|
54
|
+
},
|
|
55
|
+
"./query/primitives/coercion": {
|
|
56
|
+
"types": "./dist/query/primitives/coercion.d.mts",
|
|
57
|
+
"default": "./dist/query/primitives/coercion.mjs"
|
|
58
|
+
},
|
|
59
|
+
"./query/primitives/indexes": {
|
|
60
|
+
"types": "./dist/query/primitives/indexes.d.mts",
|
|
61
|
+
"default": "./dist/query/primitives/indexes.mjs"
|
|
62
|
+
},
|
|
63
|
+
"./testkit": {
|
|
64
|
+
"types": "./dist/testkit/index.d.mts",
|
|
65
|
+
"default": "./dist/testkit/index.mjs"
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
"files": [
|
|
69
|
+
"dist",
|
|
70
|
+
"README.md",
|
|
71
|
+
"LICENSE",
|
|
72
|
+
"TRADEMARK.md"
|
|
73
|
+
],
|
|
74
|
+
"keywords": [
|
|
75
|
+
"mongodb",
|
|
76
|
+
"mongoose",
|
|
77
|
+
"repository",
|
|
78
|
+
"repository-pattern",
|
|
79
|
+
"data-access",
|
|
80
|
+
"pagination",
|
|
81
|
+
"cursor-pagination",
|
|
82
|
+
"infinite-scroll",
|
|
83
|
+
"offset-pagination",
|
|
84
|
+
"keyset-pagination",
|
|
85
|
+
"caching",
|
|
86
|
+
"redis",
|
|
87
|
+
"cache",
|
|
88
|
+
"multi-tenant",
|
|
89
|
+
"multi-tenancy",
|
|
90
|
+
"vector-search",
|
|
91
|
+
"embeddings",
|
|
92
|
+
"atlas-search",
|
|
93
|
+
"observability",
|
|
94
|
+
"event-driven",
|
|
95
|
+
"plugin-based",
|
|
96
|
+
"zero-dependencies",
|
|
97
|
+
"express",
|
|
98
|
+
"fastify",
|
|
99
|
+
"nestjs",
|
|
100
|
+
"nextjs",
|
|
101
|
+
"typescript"
|
|
102
|
+
],
|
|
103
|
+
"author": "Classytic <classytic.dev@gmail.com> (https://github.com/classytic)",
|
|
104
|
+
"contributors": [
|
|
105
|
+
"Sadman Chowdhury (https://github.com/siam923)"
|
|
106
|
+
],
|
|
107
|
+
"license": "MIT",
|
|
108
|
+
"repository": {
|
|
109
|
+
"type": "git",
|
|
110
|
+
"url": "git+https://github.com/classytic/mongokit.git"
|
|
111
|
+
},
|
|
112
|
+
"bugs": {
|
|
113
|
+
"url": "https://github.com/classytic/mongokit/issues"
|
|
114
|
+
},
|
|
115
|
+
"homepage": "https://github.com/classytic/mongokit#readme",
|
|
116
|
+
"peerDependencies": {
|
|
117
|
+
"@classytic/repo-core": ">=0.19.0",
|
|
118
|
+
"mongodb-memory-server": ">=10.4.3",
|
|
119
|
+
"mongoose": ">=9.4.1"
|
|
120
|
+
},
|
|
121
|
+
"peerDependenciesMeta": {
|
|
122
|
+
"mongodb-memory-server": {
|
|
123
|
+
"optional": true
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
"engines": {
|
|
127
|
+
"node": ">=22"
|
|
128
|
+
},
|
|
129
|
+
"publishConfig": {
|
|
130
|
+
"access": "public"
|
|
131
|
+
},
|
|
132
|
+
"scripts": {
|
|
133
|
+
"build": "tsdown",
|
|
134
|
+
"dev": "tsdown --watch",
|
|
135
|
+
"test": "vitest run --project unit --project integration",
|
|
136
|
+
"test:unit": "vitest run --project unit",
|
|
137
|
+
"test:integration": "vitest run --project integration",
|
|
138
|
+
"test:e2e": "vitest run --project e2e",
|
|
139
|
+
"test:all": "vitest run --project unit --project integration --project e2e",
|
|
140
|
+
"test:watch": "vitest --project unit --project integration",
|
|
141
|
+
"test:coverage": "vitest run --coverage",
|
|
142
|
+
"typecheck": "tsc --noEmit",
|
|
143
|
+
"typecheck:tests": "tsc --noEmit -p tsconfig.tests.json",
|
|
144
|
+
"lint": "biome check src/",
|
|
145
|
+
"lint:fix": "biome check src/ --write",
|
|
146
|
+
"lint:package": "publint && attw --pack . --profile esm-only",
|
|
147
|
+
"format": "biome format src/ --write",
|
|
148
|
+
"check": "biome ci src/ --diagnostic-level=error",
|
|
149
|
+
"check:dead-code": "knip",
|
|
150
|
+
"ci": "npm run check && npm run typecheck && npm run typecheck:tests && npm run build && npm run lint:package && npm run check:dead-code && npm test",
|
|
151
|
+
"push": "classytic-push",
|
|
152
|
+
"prepublishOnly": "npm run ci",
|
|
153
|
+
"publish:dry": "npm publish --dry-run --access public",
|
|
154
|
+
"publish:npm": "npm publish --access public",
|
|
155
|
+
"release:tag": "node -e \"require('child_process').execSync('npm run push -- v'+require('./package.json').version,{stdio:'inherit'})\"",
|
|
156
|
+
"release": "npm run push -- main && npm run release:tag && npm publish --access public",
|
|
157
|
+
"release:patch": "npm version patch && npm run release",
|
|
158
|
+
"release:minor": "npm version minor && npm run release",
|
|
159
|
+
"release:major": "npm version major && npm run release"
|
|
160
|
+
},
|
|
161
|
+
"devDependencies": {
|
|
162
|
+
"@arethetypeswrong/cli": "^0.18.2",
|
|
163
|
+
"@better-auth/api-key": "^1.6.22",
|
|
164
|
+
"@better-auth/mongo-adapter": "^1.6.22",
|
|
165
|
+
"@biomejs/biome": "^2.4.10",
|
|
166
|
+
"@classytic/dev-tools": "^0.2.0",
|
|
167
|
+
"@classytic/repo-core": "^0.19.0",
|
|
168
|
+
"@types/node": "^22.0.0",
|
|
169
|
+
"@vitest/coverage-v8": "^4.1.4",
|
|
170
|
+
"ajv": "^8.18.0",
|
|
171
|
+
"ajv-formats": "^3.0.1",
|
|
172
|
+
"better-auth": "^1.6.23",
|
|
173
|
+
"dotenv": "^17.4.2",
|
|
174
|
+
"knip": "^6.3.0",
|
|
175
|
+
"mongodb": "7.2.0",
|
|
176
|
+
"mongodb-memory-server": "^10.4.3",
|
|
177
|
+
"mongoose": "^9.4.1",
|
|
178
|
+
"publint": "^0.3.18",
|
|
179
|
+
"tsdown": "^0.22.5",
|
|
180
|
+
"typescript": "~5.9.0",
|
|
181
|
+
"vitest": "^4.1.4"
|
|
182
|
+
},
|
|
183
|
+
"overrides": {
|
|
184
|
+
"mongodb": "7.2.0",
|
|
185
|
+
"bson": "7.2.0"
|
|
186
|
+
}
|
|
180
187
|
}
|