@web-ts-toolkit/access-router 0.43.0 → 0.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/advanced.mjs CHANGED
@@ -486,6 +486,29 @@ var cloneConfigValue = (value) => {
486
486
  ])
487
487
  );
488
488
  };
489
+ var cloneForRead = (value) => {
490
+ if (Array.isArray(value)) {
491
+ if (Object.isFrozen(value)) {
492
+ return value;
493
+ }
494
+ return value.map((item) => cloneForRead(item));
495
+ }
496
+ if (!value || typeof value !== "object") {
497
+ return value;
498
+ }
499
+ if (Object.getPrototypeOf(value) !== Object.prototype) {
500
+ return value;
501
+ }
502
+ if (Object.isFrozen(value)) {
503
+ return value;
504
+ }
505
+ return Object.fromEntries(
506
+ Object.entries(value).map(([entryKey, entryValue]) => [
507
+ entryKey,
508
+ cloneForRead(entryValue)
509
+ ])
510
+ );
511
+ };
489
512
  var freezeConfigValue = (value) => {
490
513
  if (!value || typeof value !== "object") {
491
514
  return value;
@@ -501,6 +524,7 @@ var freezeConfigValue = (value) => {
501
524
  }
502
525
  return value;
503
526
  };
527
+ var cloneAndFreezeForStore = (value) => freezeConfigValue(cloneForRead(value));
504
528
  var getNestedOption = (manager, key, defaultValue) => {
505
529
  const keys2 = String(key).split(".");
506
530
  if (keys2.length === 1) {
@@ -530,6 +554,14 @@ var OptionsManager = class {
530
554
  target[keystr] = value;
531
555
  _this.listeners[keystr] && _this.listeners[keystr].call(_this, value, keystr, target, oldvalue);
532
556
  return true;
557
+ },
558
+ defineProperty(target, key, descriptor) {
559
+ const keystr = String(key);
560
+ const oldvalue = target[keystr];
561
+ const result = Reflect.defineProperty(target, key, descriptor);
562
+ const newValue = target[keystr];
563
+ _this.listeners[keystr] && _this.listeners[keystr].call(_this, newValue, keystr, target, oldvalue);
564
+ return result;
533
565
  }
534
566
  });
535
567
  }
@@ -543,18 +575,18 @@ var OptionsManager = class {
543
575
  set(key, value) {
544
576
  const path = toPath(key);
545
577
  if (path.length <= 1) {
546
- set(this.currentOptions, path, this.preserveKeys.has(String(path[0])) ? value : cloneConfigValue(value));
578
+ set(this.currentOptions, path, this.preserveKeys.has(String(path[0])) ? value : cloneAndFreezeForStore(value));
547
579
  return;
548
580
  }
549
581
  const [rootKey, ...nestedPath] = path;
550
582
  const currentRoot = get(this.currentOptions, [rootKey], void 0);
551
583
  const baseRoot = isPlainObject7(currentRoot) ? currentRoot : {};
552
584
  const nextRoot = cloneConfigValue(baseRoot);
553
- set(nextRoot, nestedPath, cloneConfigValue(value));
554
- set(this.currentOptions, [rootKey], nextRoot);
585
+ set(nextRoot, nestedPath, cloneForRead(value));
586
+ set(this.currentOptions, [rootKey], freezeConfigValue(nextRoot));
555
587
  }
556
588
  fetch() {
557
- const cloned = cloneConfigValue(this.currentOptions);
589
+ const cloned = cloneForRead(this.currentOptions);
558
590
  for (const key of this.preserveKeys) {
559
591
  if (key in this.currentOptions) {
560
592
  cloned[key] = this.currentOptions[key];
@@ -563,20 +595,20 @@ var OptionsManager = class {
563
595
  return freezeConfigValue(cloned);
564
596
  }
565
597
  assign(options) {
566
- const cloned = cloneConfigValue(options);
598
+ const cloned = cloneForRead(options);
567
599
  for (const key of this.preserveKeys) {
568
600
  if (key in options) {
569
601
  cloned[key] = options[key];
570
602
  }
571
603
  }
572
- assign(this.currentOptions, cloned);
604
+ assign(this.currentOptions, freezeConfigValue(cloned));
573
605
  }
574
606
  onchange(key, func) {
575
607
  set(this.listeners, key, func);
576
608
  return this;
577
609
  }
578
610
  snapshot() {
579
- const cloned = cloneConfigValue(this.currentOptions);
611
+ const cloned = cloneForRead(this.currentOptions);
580
612
  for (const key of this.preserveKeys) {
581
613
  if (key in this.currentOptions) {
582
614
  cloned[key] = this.currentOptions[key];
@@ -592,13 +624,13 @@ var OptionsManager = class {
592
624
  delete current[key];
593
625
  }
594
626
  }
595
- const cloned = cloneConfigValue(snap);
627
+ const cloned = cloneForRead(snap);
596
628
  for (const key of this.preserveKeys) {
597
629
  if (key in snap) {
598
630
  cloned[key] = snap[key];
599
631
  }
600
632
  }
601
- assign(current, cloned);
633
+ assign(current, freezeConfigValue(cloned));
602
634
  }
603
635
  };
604
636
 
@@ -1068,8 +1100,7 @@ var AccessRuntime = class {
1068
1100
  }
1069
1101
  setDataOptions(dataName, options) {
1070
1102
  const manager = this.getOrCreateDataOptions(dataName);
1071
- const currentDataOptions = manager.fetch();
1072
- manager.assign({ ...currentDataOptions, ...options });
1103
+ manager.assign(options);
1073
1104
  }
1074
1105
  setDataOption(dataName, key, value) {
1075
1106
  const manager = this.getOrCreateDataOptions(dataName);
@@ -1079,6 +1110,11 @@ var AccessRuntime = class {
1079
1110
  const manager = this.getOrCreateDataOptions(dataName);
1080
1111
  return manager.fetch();
1081
1112
  }
1113
+ getDataSnapshot(dataName) {
1114
+ const manager = this.getOrCreateDataOptions(dataName);
1115
+ const snapshot = manager.get("data");
1116
+ return snapshot ?? [];
1117
+ }
1082
1118
  getDataOption(dataName, key, defaultValue) {
1083
1119
  const manager = this.getOrCreateDataOptions(dataName);
1084
1120
  return getNestedOption(manager, key, defaultValue);
@@ -1324,8 +1360,9 @@ function defineRequestSchema(validator, options = {}) {
1324
1360
  };
1325
1361
  }
1326
1362
  function fromZod(schema) {
1327
- return (value) => {
1328
- const result = schema.safeParse(value);
1363
+ return async (value) => {
1364
+ const candidate = schema;
1365
+ const result = typeof candidate.safeParseAsync === "function" ? await candidate.safeParseAsync.call(schema, value) : schema.safeParse(value);
1329
1366
  if (result.success) {
1330
1367
  return {
1331
1368
  success: true,
@@ -1362,6 +1399,9 @@ function fromYup(schema) {
1362
1399
  data
1363
1400
  };
1364
1401
  } catch (error) {
1402
+ if (!isYupValidationError(error)) {
1403
+ throw error;
1404
+ }
1365
1405
  return {
1366
1406
  success: false,
1367
1407
  issues: normalizeYupIssues(error)
@@ -1386,8 +1426,32 @@ function fromJoi(schema) {
1386
1426
  }
1387
1427
  function fromAjv(validator) {
1388
1428
  return async (value) => {
1389
- const valid = await validator(value);
1390
- if (valid) {
1429
+ const outcome = validator(value);
1430
+ if (isThenable(outcome)) {
1431
+ try {
1432
+ const data = await outcome;
1433
+ if (data === false) {
1434
+ return {
1435
+ success: false,
1436
+ issues: normalizeAjvIssues(validator.errors ?? [])
1437
+ };
1438
+ }
1439
+ return {
1440
+ success: true,
1441
+ data: data === true ? value : data
1442
+ };
1443
+ } catch (error) {
1444
+ if (!isAjvValidationError(error)) {
1445
+ throw error;
1446
+ }
1447
+ return {
1448
+ success: false,
1449
+ issues: normalizeAjvIssues(error.errors ?? [])
1450
+ };
1451
+ }
1452
+ }
1453
+ const errorsSnapshot = validator.errors ? [...validator.errors] : [];
1454
+ if (outcome) {
1391
1455
  return {
1392
1456
  success: true,
1393
1457
  data: value
@@ -1395,7 +1459,7 @@ function fromAjv(validator) {
1395
1459
  }
1396
1460
  return {
1397
1461
  success: false,
1398
- issues: normalizeAjvIssues(validator.errors ?? [])
1462
+ issues: normalizeAjvIssues(errorsSnapshot)
1399
1463
  };
1400
1464
  };
1401
1465
  }
@@ -1416,6 +1480,25 @@ function fromValibot(schema, safeParse) {
1416
1480
  }
1417
1481
  function fromArkType(type) {
1418
1482
  return async (value) => {
1483
+ if (isStandardSchema(type)) {
1484
+ const result2 = await type["~standard"].validate(value);
1485
+ if (isArkTypeErrors(result2)) {
1486
+ return {
1487
+ success: false,
1488
+ issues: normalizeArkTypeIssues(result2)
1489
+ };
1490
+ }
1491
+ if (isStandardSchemaFailure(result2)) {
1492
+ return {
1493
+ success: false,
1494
+ issues: normalizeArkTypeStandardIssues(result2.issues)
1495
+ };
1496
+ }
1497
+ return {
1498
+ success: true,
1499
+ data: result2.value
1500
+ };
1501
+ }
1419
1502
  const result = await type(value);
1420
1503
  if (!isArkTypeErrors(result)) {
1421
1504
  return {
@@ -1468,6 +1551,9 @@ function fromVine(validator) {
1468
1551
  data: output
1469
1552
  };
1470
1553
  } catch (error) {
1554
+ if (!isVineValidationError(error)) {
1555
+ throw error;
1556
+ }
1471
1557
  return {
1472
1558
  success: false,
1473
1559
  issues: normalizeVineError(error)
@@ -1528,6 +1614,13 @@ function normalizeArkTypeIssues(issues) {
1528
1614
  }));
1529
1615
  return normalized.length ? normalized : [{ message: issues.summary ?? "Validation failed" }];
1530
1616
  }
1617
+ function normalizeArkTypeStandardIssues(issues) {
1618
+ const normalized = issues.map((issue) => ({
1619
+ message: issue.message ?? issue.problem ?? "Validation failed",
1620
+ path: issue.path?.flatMap((segment) => normalizePathSegment(segment))
1621
+ }));
1622
+ return normalized.length ? normalized : [{ message: "Validation failed" }];
1623
+ }
1531
1624
  function normalizeIoTsIssues(issues) {
1532
1625
  return issues.map((issue) => ({
1533
1626
  message: issue.message ?? "Validation failed",
@@ -1562,25 +1655,64 @@ function normalizeVineField(message) {
1562
1655
  }
1563
1656
  return path.length ? path : void 0;
1564
1657
  }
1658
+ function decodeAjvSegment(segment) {
1659
+ return segment.replace(/~1/g, "/").replace(/~0/g, "~");
1660
+ }
1661
+ function encodePointerSegment(segment) {
1662
+ return encodeURIComponent(segment.replace(/~/g, "~0").replace(/\//g, "~1"));
1663
+ }
1565
1664
  function parseAjvPath(issue) {
1566
- const path = issue.instancePath?.split("/").filter(Boolean).map((segment) => /^\d+$/.test(segment) ? Number(segment) : segment);
1567
- if (issue.params?.missingProperty) {
1568
- return (path ?? []).concat(issue.params.missingProperty);
1665
+ const raw = issue.instancePath;
1666
+ const base = raw == null || raw === "" ? [] : (raw.startsWith("/") ? raw.slice(1) : raw).split("/").map(decodeAjvSegment);
1667
+ const missing = issue.params?.missingProperty;
1668
+ if (typeof missing === "string") {
1669
+ return [...base, missing];
1569
1670
  }
1570
- return path;
1671
+ return base;
1571
1672
  }
1572
1673
  function parsePathString(path) {
1573
1674
  if (!path) return void 0;
1574
1675
  return path.replace(/\[(\d+)\]/g, ".$1").split(".").filter(Boolean).map((segment) => /^\d+$/.test(segment) ? Number(segment) : segment);
1575
1676
  }
1576
1677
  function isYupValidationError(error) {
1577
- return typeof error === "object" && error !== null && "message" in error;
1678
+ if (typeof error !== "object" || error === null || !("message" in error)) {
1679
+ return false;
1680
+ }
1681
+ const candidate = error;
1682
+ return candidate.name === "ValidationError" && typeof candidate.message === "string" && Array.isArray(candidate.errors) && Array.isArray(candidate.inner);
1578
1683
  }
1579
1684
  function isArkTypeErrors(value) {
1580
- return Array.isArray(value);
1685
+ if (typeof value !== "object" || value === null) {
1686
+ return false;
1687
+ }
1688
+ const record = value;
1689
+ return record.arkKind === "errors" || record[" arkKind"] === "errors";
1690
+ }
1691
+ function isThenable(value) {
1692
+ return typeof value === "object" && value !== null && "then" in value && typeof value.then === "function";
1693
+ }
1694
+ function isAjvValidationError(error) {
1695
+ if (typeof error !== "object" || error === null || !("errors" in error)) {
1696
+ return false;
1697
+ }
1698
+ const errors = error.errors;
1699
+ return errors == null || Array.isArray(errors);
1581
1700
  }
1582
1701
  function isVineValidationError(error) {
1583
- return typeof error === "object" && error !== null && "messages" in error && Array.isArray(error.messages);
1702
+ if (typeof error !== "object" || error === null || !("messages" in error)) {
1703
+ return false;
1704
+ }
1705
+ const candidate = error;
1706
+ if (!Array.isArray(candidate.messages) || candidate.messages.length === 0) {
1707
+ return false;
1708
+ }
1709
+ const hasDiscriminator = candidate.code === "E_VALIDATION_ERROR" || candidate.name === "ValidationError";
1710
+ if (!hasDiscriminator) {
1711
+ return false;
1712
+ }
1713
+ return candidate.messages.every(
1714
+ (message) => typeof message === "object" && message !== null && typeof message.message === "string" && typeof message.field === "string"
1715
+ );
1584
1716
  }
1585
1717
  function formatIssue(issue, key, location = "pointer") {
1586
1718
  const path = (issue.path ?? []).map(String);
@@ -1597,7 +1729,7 @@ function formatIssue(issue, key, location = "pointer") {
1597
1729
  };
1598
1730
  }
1599
1731
  function buildPointer(path) {
1600
- return path.length === 0 ? "#" : `#/${path.join("/")}`;
1732
+ return path.length === 0 ? "#" : `#/${path.map(encodePointerSegment).join("/")}`;
1601
1733
  }
1602
1734
 
1603
1735
  // src/validation/model-router.ts
package/index.d.mts CHANGED
@@ -1,7 +1,7 @@
1
1
  import mongoose, { Schema } from 'mongoose';
2
2
  import { Response, NextFunction, RequestHandler, Router } from 'express';
3
- import { a8 as GlobalOptions, R as DefaultModelRouterOptions, az as ModelRouterOptions, N as DataRouterOptions, Z as ExtendedDefaultModelRouterOptions, _ as ExtendedModelRouterOptions, Y as ExtendedDataRouterOptions, A as AccessRouterBaseRequest, aa as GuardHook, ay as ModelRequest, L as DataRequest, cG as DataService, $ as Filter, aI as Projection, bD as Sort, aF as Populate, cH as Service, cI as PublicService, cj as Validation, bu as RootRouterOptions } from './parsers-PMWujHUV.mjs';
4
- export { cJ as AccessRouterPermissionMap, cK as AccessRouterPermissions, c as AccessRouterRequest, d as AccessRouterRequestExtensions, l as AjvErrorObjectLike, m as AjvValidatorLike, n as ArkTypeErrorsLike, o as ArkTypeLike, a9 as GlobalPermissionValue, ad as IoTsContextEntryLike, ae as IoTsDecodeErrorLike, af as IoTsDecoderLike, ag as JoiSchemaLike, ah as JoiValidationErrorDetailLike, am as MaybePromise, an as ModelBaseFilterHook, ap as ModelDeleteHook, aq as ModelDocPermissionsHook, as as ModelDocumentHook, at as ModelHook, av as ModelIdentifierHook, aw as ModelListHook, ax as ModelOverrideFilterHook, aA as ModelValidateHook, cL as Permissions, a_ as RequestSchemaAdapter, a$ as RequestSchemaFailure, b0 as RequestSchemaIssue, b1 as RequestSchemaLike, b2 as RequestSchemaOptions, b3 as RequestSchemaResult, b4 as RequestSchemaSuccess, b5 as RequestSchemaValidator, bx as RouteGuardAccess, bF as StandardSchemaFailure, bG as StandardSchemaInferOutput, bH as StandardSchemaIssue, bI as StandardSchemaPathSegment, bJ as StandardSchemaResult, bK as StandardSchemaSuccess, bL as StandardSchemaV1, c0 as SuperstructFailureLike, c1 as SuperstructValidateLike, cd as ValibotIssueLike, ce as ValibotPathItemLike, cf as ValibotSafeParseLike, cg as ValibotSafeParseResult, cl as VineValidationErrorLike, cm as VineValidationMessageLike, cn as VineValidatorLike, co as YupSchemaLike, cp as YupValidationErrorLike, cq as defineRequestSchema, cr as fromAjv, cs as fromArkType, ct as fromIoTs, cu as fromJoi, cv as fromStandardSchema, cw as fromSuperstruct, cx as fromValibot, cy as fromVine, cz as fromYup, cA as fromZod } from './parsers-PMWujHUV.mjs';
3
+ import { a9 as GlobalOptions, S as DefaultModelRouterOptions, aA as ModelRouterOptions, O as DataRouterOptions, _ as ExtendedDefaultModelRouterOptions, $ as ExtendedModelRouterOptions, Z as ExtendedDataRouterOptions, A as AccessRouterBaseRequest, ab as GuardHook, az as ModelRequest, M as DataRequest, cH as DataService, a0 as Filter, aJ as Projection, bE as Sort, aG as Populate, cI as Service, cJ as PublicService, ck as Validation, bv as RootRouterOptions } from './parsers-B5dbVmjm.mjs';
4
+ export { cK as AccessRouterPermissionMap, cL as AccessRouterPermissions, c as AccessRouterRequest, d as AccessRouterRequestExtensions, l as AjvErrorObjectLike, n as AjvValidatorLike, o as ArkTypeErrorsLike, p as ArkTypeLike, aa as GlobalPermissionValue, ae as IoTsContextEntryLike, af as IoTsDecodeErrorLike, ag as IoTsDecoderLike, ah as JoiSchemaLike, ai as JoiValidationErrorDetailLike, an as MaybePromise, ao as ModelBaseFilterHook, aq as ModelDeleteHook, ar as ModelDocPermissionsHook, at as ModelDocumentHook, au as ModelHook, aw as ModelIdentifierHook, ax as ModelListHook, ay as ModelOverrideFilterHook, aB as ModelValidateHook, cM as Permissions, a$ as RequestSchemaAdapter, b0 as RequestSchemaFailure, b1 as RequestSchemaIssue, b2 as RequestSchemaLike, b3 as RequestSchemaOptions, b4 as RequestSchemaResult, b5 as RequestSchemaSuccess, b6 as RequestSchemaValidator, by as RouteGuardAccess, bG as StandardSchemaFailure, bH as StandardSchemaInferOutput, bI as StandardSchemaIssue, bJ as StandardSchemaPathSegment, bK as StandardSchemaResult, bL as StandardSchemaSuccess, bM as StandardSchemaV1, c1 as SuperstructFailureLike, c2 as SuperstructValidateLike, ce as ValibotIssueLike, cf as ValibotPathItemLike, cg as ValibotSafeParseLike, ch as ValibotSafeParseResult, cm as VineValidationErrorLike, cn as VineValidationMessageLike, co as VineValidatorLike, cp as YupSchemaLike, cq as YupValidationErrorLike, cr as defineRequestSchema, cs as fromAjv, ct as fromArkType, cu as fromIoTs, cv as fromJoi, cw as fromStandardSchema, cx as fromSuperstruct, cy as fromValibot, cz as fromVine, cA as fromYup, cB as fromZod } from './parsers-B5dbVmjm.mjs';
5
5
  import JsonRouter from '@web-ts-toolkit/express-json-router';
6
6
  import 'zod';
7
7
 
@@ -103,9 +103,9 @@ declare class AccessRuntime {
103
103
  private readonly modelAtts;
104
104
  private readonly modelInstances;
105
105
  private readonly openApiRegistry;
106
- registerModelInstance(modelName: string, model: mongoose.Model<unknown>): void;
106
+ registerModelInstance<TModel>(modelName: string, model: mongoose.Model<TModel>): void;
107
107
  hasModelInstance(modelName: string): boolean;
108
- getModelInstance(modelName: string): mongoose.Model<unknown> | null;
108
+ getModelInstance<TModel = unknown>(modelName: string): mongoose.Model<TModel> | null;
109
109
  registerOpenApiRoute(route: OpenApiRouteDescriptor): void;
110
110
  /**
111
111
  * Enable strict OpenAPI collision detection for the remainder of this
@@ -177,6 +177,7 @@ declare class AccessRuntime {
177
177
  setDataOptions<TData = unknown>(dataName: string, options: DataRouterOptions<TData>): void;
178
178
  setDataOption<K extends keyof DataRouterOptions<TData>, TData = unknown>(dataName: string, key: K, value: DataRouterOptions<TData>[K]): void;
179
179
  getDataOptions<TData = unknown>(dataName: string): DataRouterOptions<TData>;
180
+ getDataSnapshot<TData = unknown>(dataName: string): readonly TData[];
180
181
  getDataOption<K extends keyof DataRouterOptions<TData>, TData = unknown>(dataName: string, key: K | string, defaultValue?: DataRouterOptions<TData>[K]): DataRouterOptions<TData>[K];
181
182
  getExactDataOption<K extends keyof ExtendedDataRouterOptions<TData>, TData = unknown>(dataName: string, key: K | string): ExtendedDataRouterOptions<TData>[K];
182
183
  getDataNames(): string[];
@@ -228,6 +229,11 @@ declare class DataRouter<TData = unknown> {
228
229
  permissionSchema: SetTargetOption$1<DataRouter<TData>, DataRouterOptions<TData>['permissionSchema']>;
229
230
  operationAccess: SetTargetOption$1<DataRouter<TData>, DataRouterOptions<TData>['operationAccess']>;
230
231
  baseFilter: SetTargetOption$1<DataRouter<TData>, DataRouterOptions<TData>['baseFilter']>;
232
+ /**
233
+ * Trusted filter replacements applied before base-filter composition.
234
+ * They may replace ordinary filters, but cannot replace an existing `false` denial.
235
+ * Returning `false` denies the transaction.
236
+ */
231
237
  overrideFilter: SetTargetOption$1<DataRouter<TData>, DataRouterOptions<TData>['overrideFilter']>;
232
238
  decorate: SetTargetOption$1<DataRouter<TData>, DataRouterOptions<TData>['decorate']>;
233
239
  decorateAll: SetTargetOption$1<DataRouter<TData>, DataRouterOptions<TData>['decorateAll']>;
@@ -281,7 +287,7 @@ declare class ModelRouter<TModel = unknown> {
281
287
  readonly options: ModelRouterOptions<TModel>;
282
288
  readonly fullBasePath: string;
283
289
  constructor(modelName: string, initialOptions: ModelRouterOptions<TModel>, runtime?: AccessRuntime);
284
- static fromModel<TModel = unknown>(model: mongoose.Model<unknown>, initialOptions: ModelRouterOptions<TModel>, runtime?: AccessRuntime): ModelRouter<TModel>;
290
+ static fromModel<TModel>(model: mongoose.Model<TModel>, initialOptions: ModelRouterOptions<TModel>, runtime?: AccessRuntime): ModelRouter<TModel>;
285
291
  private getRequestSchema;
286
292
  getService(req: ModelRequest): Service<TModel>;
287
293
  getPublicService(req: ModelRequest): PublicService<TModel>;
@@ -326,7 +332,9 @@ declare class ModelRouter<TModel = unknown> {
326
332
  */
327
333
  baseFilter: SetTargetOption<ModelRouter<TModel>, ModelRouterOptions<TModel>['baseFilter']>;
328
334
  /**
329
- * The override filter definitions applied in every query transaction.
335
+ * Trusted filter replacements applied before base-filter composition.
336
+ * They may replace ordinary filters, but cannot replace an existing `false` denial.
337
+ * Returning `false` denies the transaction.
330
338
  * @operation `list`, `read`, `update`, `delete`
331
339
  */
332
340
  overrideFilter: SetTargetOption<ModelRouter<TModel>, ModelRouterOptions<TModel>['overrideFilter']>;
@@ -517,9 +525,9 @@ declare const getModelOptions: <TModel = unknown>(modelName: string) => ModelRou
517
525
  declare const getModelOption: <K extends keyof ExtendedModelRouterOptions<TModel>, TModel = unknown>(modelName: string, key: K | string, defaultValue?: ExtendedModelRouterOptions<TModel>[K]) => ExtendedModelRouterOptions<TModel>[K];
518
526
  declare const getModelNames: () => string[];
519
527
  declare const getModelJsonSchema: (modelName: string) => Record<string, unknown>;
520
- declare const registerModelInstance: (modelName: string, model: mongoose.Model<unknown>) => void;
528
+ declare const registerModelInstance: <TModel>(modelName: string, model: mongoose.Model<TModel>) => void;
521
529
  declare const hasModelInstance: (modelName: string) => boolean;
522
- declare const getModelInstance: (modelName: string) => mongoose.Model<unknown> | null;
530
+ declare const getModelInstance: <TModel = unknown>(modelName: string) => mongoose.Model<TModel> | null;
523
531
 
524
532
  declare const setDefaultModelOptions: (options: DefaultModelRouterOptions) => void;
525
533
  declare const setDefaultModelOption: <K extends keyof ExtendedDefaultModelRouterOptions>(key: K, value: ExtendedDefaultModelRouterOptions[K]) => void;
@@ -590,9 +598,9 @@ interface Wtt {
590
598
  setDefaultModelOption: typeof setDefaultModelOption;
591
599
  getDefaultModelOptions: typeof getDefaultModelOptions;
592
600
  getDefaultModelOption: typeof getDefaultModelOption;
593
- registerModelInstance: (modelName: string, model: mongoose.Model<unknown>) => void;
601
+ registerModelInstance: <TModel>(modelName: string, model: mongoose.Model<TModel>) => void;
594
602
  hasModelInstance: (modelName: string) => boolean;
595
- getModelInstance: (modelName: string) => mongoose.Model<unknown> | null;
603
+ getModelInstance: <TModel = unknown>(modelName: string) => mongoose.Model<TModel> | null;
596
604
  RootRouter: typeof RootRouter;
597
605
  ModelRouter: typeof ModelRouter;
598
606
  DataRouter: typeof DataRouter;
package/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import mongoose, { Schema } from 'mongoose';
2
2
  import { Response, NextFunction, RequestHandler, Router } from 'express';
3
- import { a8 as GlobalOptions, R as DefaultModelRouterOptions, az as ModelRouterOptions, N as DataRouterOptions, Z as ExtendedDefaultModelRouterOptions, _ as ExtendedModelRouterOptions, Y as ExtendedDataRouterOptions, A as AccessRouterBaseRequest, aa as GuardHook, ay as ModelRequest, L as DataRequest, cG as DataService, $ as Filter, aI as Projection, bD as Sort, aF as Populate, cH as Service, cI as PublicService, cj as Validation, bu as RootRouterOptions } from './parsers-PMWujHUV.js';
4
- export { cJ as AccessRouterPermissionMap, cK as AccessRouterPermissions, c as AccessRouterRequest, d as AccessRouterRequestExtensions, l as AjvErrorObjectLike, m as AjvValidatorLike, n as ArkTypeErrorsLike, o as ArkTypeLike, a9 as GlobalPermissionValue, ad as IoTsContextEntryLike, ae as IoTsDecodeErrorLike, af as IoTsDecoderLike, ag as JoiSchemaLike, ah as JoiValidationErrorDetailLike, am as MaybePromise, an as ModelBaseFilterHook, ap as ModelDeleteHook, aq as ModelDocPermissionsHook, as as ModelDocumentHook, at as ModelHook, av as ModelIdentifierHook, aw as ModelListHook, ax as ModelOverrideFilterHook, aA as ModelValidateHook, cL as Permissions, a_ as RequestSchemaAdapter, a$ as RequestSchemaFailure, b0 as RequestSchemaIssue, b1 as RequestSchemaLike, b2 as RequestSchemaOptions, b3 as RequestSchemaResult, b4 as RequestSchemaSuccess, b5 as RequestSchemaValidator, bx as RouteGuardAccess, bF as StandardSchemaFailure, bG as StandardSchemaInferOutput, bH as StandardSchemaIssue, bI as StandardSchemaPathSegment, bJ as StandardSchemaResult, bK as StandardSchemaSuccess, bL as StandardSchemaV1, c0 as SuperstructFailureLike, c1 as SuperstructValidateLike, cd as ValibotIssueLike, ce as ValibotPathItemLike, cf as ValibotSafeParseLike, cg as ValibotSafeParseResult, cl as VineValidationErrorLike, cm as VineValidationMessageLike, cn as VineValidatorLike, co as YupSchemaLike, cp as YupValidationErrorLike, cq as defineRequestSchema, cr as fromAjv, cs as fromArkType, ct as fromIoTs, cu as fromJoi, cv as fromStandardSchema, cw as fromSuperstruct, cx as fromValibot, cy as fromVine, cz as fromYup, cA as fromZod } from './parsers-PMWujHUV.js';
3
+ import { a9 as GlobalOptions, S as DefaultModelRouterOptions, aA as ModelRouterOptions, O as DataRouterOptions, _ as ExtendedDefaultModelRouterOptions, $ as ExtendedModelRouterOptions, Z as ExtendedDataRouterOptions, A as AccessRouterBaseRequest, ab as GuardHook, az as ModelRequest, M as DataRequest, cH as DataService, a0 as Filter, aJ as Projection, bE as Sort, aG as Populate, cI as Service, cJ as PublicService, ck as Validation, bv as RootRouterOptions } from './parsers-B5dbVmjm.js';
4
+ export { cK as AccessRouterPermissionMap, cL as AccessRouterPermissions, c as AccessRouterRequest, d as AccessRouterRequestExtensions, l as AjvErrorObjectLike, n as AjvValidatorLike, o as ArkTypeErrorsLike, p as ArkTypeLike, aa as GlobalPermissionValue, ae as IoTsContextEntryLike, af as IoTsDecodeErrorLike, ag as IoTsDecoderLike, ah as JoiSchemaLike, ai as JoiValidationErrorDetailLike, an as MaybePromise, ao as ModelBaseFilterHook, aq as ModelDeleteHook, ar as ModelDocPermissionsHook, at as ModelDocumentHook, au as ModelHook, aw as ModelIdentifierHook, ax as ModelListHook, ay as ModelOverrideFilterHook, aB as ModelValidateHook, cM as Permissions, a$ as RequestSchemaAdapter, b0 as RequestSchemaFailure, b1 as RequestSchemaIssue, b2 as RequestSchemaLike, b3 as RequestSchemaOptions, b4 as RequestSchemaResult, b5 as RequestSchemaSuccess, b6 as RequestSchemaValidator, by as RouteGuardAccess, bG as StandardSchemaFailure, bH as StandardSchemaInferOutput, bI as StandardSchemaIssue, bJ as StandardSchemaPathSegment, bK as StandardSchemaResult, bL as StandardSchemaSuccess, bM as StandardSchemaV1, c1 as SuperstructFailureLike, c2 as SuperstructValidateLike, ce as ValibotIssueLike, cf as ValibotPathItemLike, cg as ValibotSafeParseLike, ch as ValibotSafeParseResult, cm as VineValidationErrorLike, cn as VineValidationMessageLike, co as VineValidatorLike, cp as YupSchemaLike, cq as YupValidationErrorLike, cr as defineRequestSchema, cs as fromAjv, ct as fromArkType, cu as fromIoTs, cv as fromJoi, cw as fromStandardSchema, cx as fromSuperstruct, cy as fromValibot, cz as fromVine, cA as fromYup, cB as fromZod } from './parsers-B5dbVmjm.js';
5
5
  import JsonRouter from '@web-ts-toolkit/express-json-router';
6
6
  import 'zod';
7
7
 
@@ -103,9 +103,9 @@ declare class AccessRuntime {
103
103
  private readonly modelAtts;
104
104
  private readonly modelInstances;
105
105
  private readonly openApiRegistry;
106
- registerModelInstance(modelName: string, model: mongoose.Model<unknown>): void;
106
+ registerModelInstance<TModel>(modelName: string, model: mongoose.Model<TModel>): void;
107
107
  hasModelInstance(modelName: string): boolean;
108
- getModelInstance(modelName: string): mongoose.Model<unknown> | null;
108
+ getModelInstance<TModel = unknown>(modelName: string): mongoose.Model<TModel> | null;
109
109
  registerOpenApiRoute(route: OpenApiRouteDescriptor): void;
110
110
  /**
111
111
  * Enable strict OpenAPI collision detection for the remainder of this
@@ -177,6 +177,7 @@ declare class AccessRuntime {
177
177
  setDataOptions<TData = unknown>(dataName: string, options: DataRouterOptions<TData>): void;
178
178
  setDataOption<K extends keyof DataRouterOptions<TData>, TData = unknown>(dataName: string, key: K, value: DataRouterOptions<TData>[K]): void;
179
179
  getDataOptions<TData = unknown>(dataName: string): DataRouterOptions<TData>;
180
+ getDataSnapshot<TData = unknown>(dataName: string): readonly TData[];
180
181
  getDataOption<K extends keyof DataRouterOptions<TData>, TData = unknown>(dataName: string, key: K | string, defaultValue?: DataRouterOptions<TData>[K]): DataRouterOptions<TData>[K];
181
182
  getExactDataOption<K extends keyof ExtendedDataRouterOptions<TData>, TData = unknown>(dataName: string, key: K | string): ExtendedDataRouterOptions<TData>[K];
182
183
  getDataNames(): string[];
@@ -228,6 +229,11 @@ declare class DataRouter<TData = unknown> {
228
229
  permissionSchema: SetTargetOption$1<DataRouter<TData>, DataRouterOptions<TData>['permissionSchema']>;
229
230
  operationAccess: SetTargetOption$1<DataRouter<TData>, DataRouterOptions<TData>['operationAccess']>;
230
231
  baseFilter: SetTargetOption$1<DataRouter<TData>, DataRouterOptions<TData>['baseFilter']>;
232
+ /**
233
+ * Trusted filter replacements applied before base-filter composition.
234
+ * They may replace ordinary filters, but cannot replace an existing `false` denial.
235
+ * Returning `false` denies the transaction.
236
+ */
231
237
  overrideFilter: SetTargetOption$1<DataRouter<TData>, DataRouterOptions<TData>['overrideFilter']>;
232
238
  decorate: SetTargetOption$1<DataRouter<TData>, DataRouterOptions<TData>['decorate']>;
233
239
  decorateAll: SetTargetOption$1<DataRouter<TData>, DataRouterOptions<TData>['decorateAll']>;
@@ -281,7 +287,7 @@ declare class ModelRouter<TModel = unknown> {
281
287
  readonly options: ModelRouterOptions<TModel>;
282
288
  readonly fullBasePath: string;
283
289
  constructor(modelName: string, initialOptions: ModelRouterOptions<TModel>, runtime?: AccessRuntime);
284
- static fromModel<TModel = unknown>(model: mongoose.Model<unknown>, initialOptions: ModelRouterOptions<TModel>, runtime?: AccessRuntime): ModelRouter<TModel>;
290
+ static fromModel<TModel>(model: mongoose.Model<TModel>, initialOptions: ModelRouterOptions<TModel>, runtime?: AccessRuntime): ModelRouter<TModel>;
285
291
  private getRequestSchema;
286
292
  getService(req: ModelRequest): Service<TModel>;
287
293
  getPublicService(req: ModelRequest): PublicService<TModel>;
@@ -326,7 +332,9 @@ declare class ModelRouter<TModel = unknown> {
326
332
  */
327
333
  baseFilter: SetTargetOption<ModelRouter<TModel>, ModelRouterOptions<TModel>['baseFilter']>;
328
334
  /**
329
- * The override filter definitions applied in every query transaction.
335
+ * Trusted filter replacements applied before base-filter composition.
336
+ * They may replace ordinary filters, but cannot replace an existing `false` denial.
337
+ * Returning `false` denies the transaction.
330
338
  * @operation `list`, `read`, `update`, `delete`
331
339
  */
332
340
  overrideFilter: SetTargetOption<ModelRouter<TModel>, ModelRouterOptions<TModel>['overrideFilter']>;
@@ -517,9 +525,9 @@ declare const getModelOptions: <TModel = unknown>(modelName: string) => ModelRou
517
525
  declare const getModelOption: <K extends keyof ExtendedModelRouterOptions<TModel>, TModel = unknown>(modelName: string, key: K | string, defaultValue?: ExtendedModelRouterOptions<TModel>[K]) => ExtendedModelRouterOptions<TModel>[K];
518
526
  declare const getModelNames: () => string[];
519
527
  declare const getModelJsonSchema: (modelName: string) => Record<string, unknown>;
520
- declare const registerModelInstance: (modelName: string, model: mongoose.Model<unknown>) => void;
528
+ declare const registerModelInstance: <TModel>(modelName: string, model: mongoose.Model<TModel>) => void;
521
529
  declare const hasModelInstance: (modelName: string) => boolean;
522
- declare const getModelInstance: (modelName: string) => mongoose.Model<unknown> | null;
530
+ declare const getModelInstance: <TModel = unknown>(modelName: string) => mongoose.Model<TModel> | null;
523
531
 
524
532
  declare const setDefaultModelOptions: (options: DefaultModelRouterOptions) => void;
525
533
  declare const setDefaultModelOption: <K extends keyof ExtendedDefaultModelRouterOptions>(key: K, value: ExtendedDefaultModelRouterOptions[K]) => void;
@@ -590,9 +598,9 @@ interface Wtt {
590
598
  setDefaultModelOption: typeof setDefaultModelOption;
591
599
  getDefaultModelOptions: typeof getDefaultModelOptions;
592
600
  getDefaultModelOption: typeof getDefaultModelOption;
593
- registerModelInstance: (modelName: string, model: mongoose.Model<unknown>) => void;
601
+ registerModelInstance: <TModel>(modelName: string, model: mongoose.Model<TModel>) => void;
594
602
  hasModelInstance: (modelName: string) => boolean;
595
- getModelInstance: (modelName: string) => mongoose.Model<unknown> | null;
603
+ getModelInstance: <TModel = unknown>(modelName: string) => mongoose.Model<TModel> | null;
596
604
  RootRouter: typeof RootRouter;
597
605
  ModelRouter: typeof ModelRouter;
598
606
  DataRouter: typeof DataRouter;