@web-ts-toolkit/access-router 0.55.0 → 0.56.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +128 -23
- package/advanced.d.mts +1 -1
- package/advanced.d.ts +1 -1
- package/advanced.js +12 -2
- package/advanced.mjs +12 -2
- package/index.d.mts +2 -2
- package/index.d.ts +2 -2
- package/index.js +103 -43
- package/index.mjs +103 -43
- package/llms.txt +3 -2
- package/package.json +3 -3
- package/{parsers-BrVRL2fg.d.mts → parsers-BXKoUKMa.d.mts} +59 -8
- package/{parsers-BrVRL2fg.d.ts → parsers-BXKoUKMa.d.ts} +59 -8
package/llms.txt
CHANGED
|
@@ -35,8 +35,9 @@
|
|
|
35
35
|
- [Includes/count cardinality](README.md#include-cardinality) · [Bounded numeric Map counts and Set-to-number migration](README.md#numeric-grouped-count-service-api-breaking-migration) · [Source/attachment provenance](README.md#safe-include-output-paths)
|
|
36
36
|
- [Correlated includes and literal escapes](README.md#correlated-includes) · [Nested writes and trusted hooks](README.md#nested-updates-and-trusted-hooks)
|
|
37
37
|
- [Virtuals, literal-filter preservation and output compatibility](README.md#virtuals-computed-fields) · [Request/runtime reentrant hook chains](README.md#hook-admission-and-reentrant-service-calls) · [Separate persistence limits](README.md#persistence-concurrency-and-resource-limits)
|
|
38
|
-
- [Private populated dependencies](README.md#private-populated-dependencies) · [Runnable
|
|
39
|
-
- [
|
|
38
|
+
- [Private populated dependencies](README.md#private-populated-dependencies) · [Runnable example](README.md#runnable-private-dependency-example): server virtual `dependsOnPopulate: [{ path, select? }]`, automatically retained scope-local static ObjectId ref/1D array, eagerly registered same-runtime/same-connection target. Explicit `ModelVirtualDescriptor<Source, Value, { ref: Target }>` types only optional getter argument four (`populated = {}`); argument one/local dependsOn and persisted/write/public types stay unchanged. Root/advanced types: ModelVirtualPopulateDependency, ModelVirtualPopulateInputs. No client/query authority or new entrypoint.
|
|
39
|
+
- [Runtime private-read mode](README.md#runtime-private-read-mode): `api.setGlobalOptions({ requireReadOperationAccessForPopulateDependencies: false })` opts out of private target operationAccess.read only; default true, only literal false bypasses, malformed JS/undefined stays conservative true. Typed GlobalOptions/exact setters/getters; server/runtime-only, isolated and captured with source/target/query intent before awaits, including nested output. Not requireRegisteredPopulateModels: eager private registration/static declarations remain. Source/target input-field permissions are already bypassed; virtual output authorization and request baseFilter.read/overrideFilter.read/retained IDs still govern. False + virtual-only selection adds no operation check solely to fetch.
|
|
40
|
+
- [Private target/read/selection rules](README.md#target-authority-selection-and-reconstruction) · [Release compatibility](README.md#release-compatibility-dependency-reference-omission): BOTH modes apply an independent captured caller target BASE-read visibility gate to active selected/applicable dependency refs. Source unselected/denied -> omit; target read denied/failed -> omit entire ref INCLUDING ID, outranking list/custom populate access and public related-operation grants. Read allowed + ordinary population -> original authorized mask; read allowed + no population -> exact original refs/arrays/nulls/misses/order/duplicates/presence. This intentionally supersedes prior D1 denied-ID fallback even in default mode; no active plan/no feature keeps ordinary behavior. Private availability/getter outcomes never grant reference output. Compatible positive fetch unions retain separate masks/private request row scope, independent of public match/access/related grants. Each getter gets only its declared fourth-argument mask; no implicit DTO/handle/metadata/hook/task transport, only its authorized deliberate return. No recursive private target virtuals or successful-write retries. See README for selection/errors/inheritance/native isolation/hydration caveats and measured compatible-group batching.
|
|
40
41
|
|
|
41
42
|
## Additional examples
|
|
42
43
|
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@web-ts-toolkit/access-router",
|
|
3
3
|
"description": "ACL-aware Express routers and in-memory data services for Mongoose-backed APIs",
|
|
4
4
|
"homepage": "https://web-ts-toolkit.pages.dev/docs/packages/access-router",
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.56.0",
|
|
6
6
|
"sideEffects": [
|
|
7
7
|
"./**/index.js",
|
|
8
8
|
"./**/index.mjs",
|
|
@@ -57,8 +57,8 @@
|
|
|
57
57
|
"node": ">=22"
|
|
58
58
|
},
|
|
59
59
|
"dependencies": {
|
|
60
|
-
"@web-ts-toolkit/express-json-router": "0.
|
|
61
|
-
"@web-ts-toolkit/utils": "0.
|
|
60
|
+
"@web-ts-toolkit/express-json-router": "0.56.0",
|
|
61
|
+
"@web-ts-toolkit/utils": "0.56.0",
|
|
62
62
|
"just-diff": "^6.0.2",
|
|
63
63
|
"mongoose-schema-jsonschema": "^4.0.1",
|
|
64
64
|
"sift": "^17.1.3",
|
|
@@ -420,10 +420,19 @@ type ModelVirtualDoc<TModel = unknown> = IsUnknownVirtual<TModel> extends true ?
|
|
|
420
420
|
* and traversal through target refs are rejected. `_id` is included unless excluded.
|
|
421
421
|
* Static string refs must bind the actual same-connection ObjectId model; register
|
|
422
422
|
* its model instance AND options first. Validation is eager/atomic, including setters.
|
|
423
|
-
* This
|
|
424
|
-
*
|
|
425
|
-
* the
|
|
423
|
+
* This bypasses source/target input-field permissions, not the virtual's own output
|
|
424
|
+
* authorization. GlobalOptions.requireReadOperationAccessForPopulateDependencies defaults
|
|
425
|
+
* to true, requiring the captured caller's target base operationAccess.read for private
|
|
426
|
+
* loading. Only literal false bypasses that gate; private-only loading then adds no
|
|
427
|
+
* operation check solely for the fetch. Target overrideFilter.read/baseFilter.read and
|
|
428
|
+
* retained source IDs always use request authority/tenant scope, independently of ordinary
|
|
426
429
|
* populate match/access and authorization.related. Private target virtuals never run.
|
|
430
|
+
* In both modes, active selected/applicable dependency refs denied caller-context base
|
|
431
|
+
* read visibility are omitted entirely, including IDs; public list/custom access or a
|
|
432
|
+
* related-operation grant cannot override this. Allowed selected/permitted refs keep the
|
|
433
|
+
* original authorized populate mask or exact original refs. No active plan keeps ordinary
|
|
434
|
+
* behavior. The mode and source/target policy are captured before awaits; registration
|
|
435
|
+
* remains mandatory independently of requireRegisteredPopulateModels.
|
|
427
436
|
*/
|
|
428
437
|
interface ModelVirtualPopulateDependency<TModel = unknown> {
|
|
429
438
|
/** Top-level ref relative to this virtual's scope; no dotted source paths. Retained automatically. */
|
|
@@ -468,7 +477,7 @@ type ModelVirtualPopulateInputs<TModel = unknown, TPopulated extends VirtualPopu
|
|
|
468
477
|
* It is separate from `doc`, whose persisted/public-related typing is unchanged.
|
|
469
478
|
* The runtime supplies it (empty without a declaration); the empty default generic
|
|
470
479
|
* guesses no target shape. Optionality preserves legacy three-argument direct calls
|
|
471
|
-
* and callbacks. Absent source refs or unavailable
|
|
480
|
+
* and callbacks. Absent source refs or unavailable private inputs skip invocation;
|
|
472
481
|
* present null/empty refs and missing target rows yield null/[]/null array slots.
|
|
473
482
|
* Private values are not implicitly transported to output or authorization metadata;
|
|
474
483
|
* an authorized getter can deliberately return a computed value using them.
|
|
@@ -494,7 +503,8 @@ type ModelVirtualGetter<TModel = unknown, TValue = unknown, TPopulated extends V
|
|
|
494
503
|
* generic never changes the persisted model, write types or public output.
|
|
495
504
|
* Use `populated = {}` or guard undefined to retain three-argument direct calls.
|
|
496
505
|
* See the shipped README's "Private populated dependencies" for registration,
|
|
497
|
-
*
|
|
506
|
+
* reference omission/population/ID shapes, captured private-read mode, mandatory row
|
|
507
|
+
* gates and absence/error rules. Private computation does not imply reference visibility.
|
|
498
508
|
*
|
|
499
509
|
* @example
|
|
500
510
|
* ```ts
|
|
@@ -1143,6 +1153,10 @@ interface AuthorizationConfiguration {
|
|
|
1143
1153
|
readonly catalog: AuthorizationFieldCatalog;
|
|
1144
1154
|
/** Opaque terminal private-input capture. Never related authority or public document metadata. */
|
|
1145
1155
|
readonly virtualPopulateSnapshot?: VirtualPopulateSnapshotToken;
|
|
1156
|
+
/** Runtime-owned private input admission mode, not public output/related authority. */
|
|
1157
|
+
readonly requireReadOperationAccessForPopulateDependencies?: boolean;
|
|
1158
|
+
/** Independent ordinary-populate registration posture from the same global snapshot. */
|
|
1159
|
+
readonly requireRegisteredPopulateModels?: boolean;
|
|
1146
1160
|
readonly documentPermissionField?: string;
|
|
1147
1161
|
/** Captured permission schema, virtual descriptors, always-select and metadata posture. */
|
|
1148
1162
|
readonly [key: string]: unknown;
|
|
@@ -3116,7 +3130,7 @@ interface AccessRouterLogger {
|
|
|
3116
3130
|
isLevelEnabled?: (level: string) => boolean;
|
|
3117
3131
|
}
|
|
3118
3132
|
/**
|
|
3119
|
-
* Runtime-wide request initialization and resource settings, configured with
|
|
3133
|
+
* Runtime-wide request initialization, private-input policy and resource settings, configured with
|
|
3120
3134
|
* api.setGlobalOptions / api.setGlobalOption. These are not model options or wire
|
|
3121
3135
|
* options. Object assignment is shallow; nested requestComplexity replaces as a unit.
|
|
3122
3136
|
*/
|
|
@@ -3134,6 +3148,39 @@ interface GlobalOptions {
|
|
|
3134
3148
|
globalPermissions?: (this: AccessRouterRequest, req: AccessRouterRequest) => MaybePromise<GlobalPermissionValue>;
|
|
3135
3149
|
/** Require populate target models to be registered in the active runtime. Defaults to `true`. */
|
|
3136
3150
|
requireRegisteredPopulateModels?: boolean;
|
|
3151
|
+
/**
|
|
3152
|
+
* Require the original caller's target base `operationAccess.read` before loading
|
|
3153
|
+
* declared private `dependsOnPopulate` inputs (default `true`). Only literal boolean
|
|
3154
|
+
* `false` bypasses that operation gate; undefined/malformed JS values normalize to
|
|
3155
|
+
* `true`. Source/target input-field permissions are already bypassed by the server
|
|
3156
|
+
* declaration; the virtual's own output authorization still applies. Target request-mode
|
|
3157
|
+
* `baseFilter.read`, `overrideFilter.read` and retained reference IDs always constrain rows.
|
|
3158
|
+
* Captured with source/target policy and query intent before the first await, including
|
|
3159
|
+
* nested output scopes. In-flight calls retain their mode; later calls see updates.
|
|
3160
|
+
* Runtime-isolated server configuration only: no caller/query or per-model override.
|
|
3161
|
+
*
|
|
3162
|
+
* In BOTH modes, references in an active selected/applicable dependency plan require
|
|
3163
|
+
* source selection/field permission AND the captured caller-context target base read
|
|
3164
|
+
* grant. Denied/failed read visibility omits the entire reference, including its ID,
|
|
3165
|
+
* even with ordinary list/custom populate access or a public related-operation grant.
|
|
3166
|
+
* Allowed read keeps the original authorized public populate mask, or exact original
|
|
3167
|
+
* refs without population. No active dependency plan leaves ordinary behavior intact.
|
|
3168
|
+
* False-mode private-only loading adds no operation check solely for that fetch.
|
|
3169
|
+
* This never grants public fields, row/write authority or query controls. Registration
|
|
3170
|
+
* and static input declarations remain required, independently of requireRegisteredPopulateModels.
|
|
3171
|
+
*
|
|
3172
|
+
* @example
|
|
3173
|
+
* ```ts
|
|
3174
|
+
* import { createAccessRuntime, type GlobalOptions } from '@web-ts-toolkit/access-router';
|
|
3175
|
+
* const api = createAccessRuntime();
|
|
3176
|
+
* const policy = { requireReadOperationAccessForPopulateDependencies: false } satisfies GlobalOptions;
|
|
3177
|
+
* api.setGlobalOptions(policy); // privileged computation inputs; no public target-read grant
|
|
3178
|
+
* const snapshot: GlobalOptions = api.getGlobalOptions();
|
|
3179
|
+
* api.setGlobalOption('requireReadOperationAccessForPopulateDependencies', true);
|
|
3180
|
+
* void snapshot; // stored snapshot; read again to observe the setter
|
|
3181
|
+
* ```
|
|
3182
|
+
*/
|
|
3183
|
+
requireReadOperationAccessForPopulateDependencies?: boolean;
|
|
3137
3184
|
logger?: AccessRouterLogger;
|
|
3138
3185
|
/** Request budgets and separate hook/persistence pools; concurrency limits are captured on first owner use. */
|
|
3139
3186
|
requestComplexity?: RequestComplexityOptions;
|
|
@@ -3441,8 +3488,12 @@ interface ModelRouterOptions<TModel = unknown, TVirtuals extends object = Record
|
|
|
3441
3488
|
* that getter's fourth argument. Annotate ModelVirtualDescriptor<Source, Value,
|
|
3442
3489
|
* { ref: Target }> separately, then assign here; persisted/write/public types
|
|
3443
3490
|
* stay unchanged. Register target models/options first in this runtime. Source
|
|
3444
|
-
* refs are retained automatically
|
|
3445
|
-
*
|
|
3491
|
+
* refs are retained automatically. GlobalOptions.requireReadOperationAccessForPopulateDependencies
|
|
3492
|
+
* defaults to true; false bypasses only private target-operation admission, never
|
|
3493
|
+
* request read-row filters/retained IDs. In both modes an active dependency ref's
|
|
3494
|
+
* denied caller-context target base read omits the entire ref, including its ID.
|
|
3495
|
+
* Allowed refs keep the original authorized populate mask or exact original IDs;
|
|
3496
|
+
* unselected/denied source fields remain hidden. No active plan keeps ordinary behavior.
|
|
3446
3497
|
*
|
|
3447
3498
|
* @example Shortest typed happy-path (persisted model lacks `fullAddress`):
|
|
3448
3499
|
* ```ts
|
|
@@ -420,10 +420,19 @@ type ModelVirtualDoc<TModel = unknown> = IsUnknownVirtual<TModel> extends true ?
|
|
|
420
420
|
* and traversal through target refs are rejected. `_id` is included unless excluded.
|
|
421
421
|
* Static string refs must bind the actual same-connection ObjectId model; register
|
|
422
422
|
* its model instance AND options first. Validation is eager/atomic, including setters.
|
|
423
|
-
* This
|
|
424
|
-
*
|
|
425
|
-
* the
|
|
423
|
+
* This bypasses source/target input-field permissions, not the virtual's own output
|
|
424
|
+
* authorization. GlobalOptions.requireReadOperationAccessForPopulateDependencies defaults
|
|
425
|
+
* to true, requiring the captured caller's target base operationAccess.read for private
|
|
426
|
+
* loading. Only literal false bypasses that gate; private-only loading then adds no
|
|
427
|
+
* operation check solely for the fetch. Target overrideFilter.read/baseFilter.read and
|
|
428
|
+
* retained source IDs always use request authority/tenant scope, independently of ordinary
|
|
426
429
|
* populate match/access and authorization.related. Private target virtuals never run.
|
|
430
|
+
* In both modes, active selected/applicable dependency refs denied caller-context base
|
|
431
|
+
* read visibility are omitted entirely, including IDs; public list/custom access or a
|
|
432
|
+
* related-operation grant cannot override this. Allowed selected/permitted refs keep the
|
|
433
|
+
* original authorized populate mask or exact original refs. No active plan keeps ordinary
|
|
434
|
+
* behavior. The mode and source/target policy are captured before awaits; registration
|
|
435
|
+
* remains mandatory independently of requireRegisteredPopulateModels.
|
|
427
436
|
*/
|
|
428
437
|
interface ModelVirtualPopulateDependency<TModel = unknown> {
|
|
429
438
|
/** Top-level ref relative to this virtual's scope; no dotted source paths. Retained automatically. */
|
|
@@ -468,7 +477,7 @@ type ModelVirtualPopulateInputs<TModel = unknown, TPopulated extends VirtualPopu
|
|
|
468
477
|
* It is separate from `doc`, whose persisted/public-related typing is unchanged.
|
|
469
478
|
* The runtime supplies it (empty without a declaration); the empty default generic
|
|
470
479
|
* guesses no target shape. Optionality preserves legacy three-argument direct calls
|
|
471
|
-
* and callbacks. Absent source refs or unavailable
|
|
480
|
+
* and callbacks. Absent source refs or unavailable private inputs skip invocation;
|
|
472
481
|
* present null/empty refs and missing target rows yield null/[]/null array slots.
|
|
473
482
|
* Private values are not implicitly transported to output or authorization metadata;
|
|
474
483
|
* an authorized getter can deliberately return a computed value using them.
|
|
@@ -494,7 +503,8 @@ type ModelVirtualGetter<TModel = unknown, TValue = unknown, TPopulated extends V
|
|
|
494
503
|
* generic never changes the persisted model, write types or public output.
|
|
495
504
|
* Use `populated = {}` or guard undefined to retain three-argument direct calls.
|
|
496
505
|
* See the shipped README's "Private populated dependencies" for registration,
|
|
497
|
-
*
|
|
506
|
+
* reference omission/population/ID shapes, captured private-read mode, mandatory row
|
|
507
|
+
* gates and absence/error rules. Private computation does not imply reference visibility.
|
|
498
508
|
*
|
|
499
509
|
* @example
|
|
500
510
|
* ```ts
|
|
@@ -1143,6 +1153,10 @@ interface AuthorizationConfiguration {
|
|
|
1143
1153
|
readonly catalog: AuthorizationFieldCatalog;
|
|
1144
1154
|
/** Opaque terminal private-input capture. Never related authority or public document metadata. */
|
|
1145
1155
|
readonly virtualPopulateSnapshot?: VirtualPopulateSnapshotToken;
|
|
1156
|
+
/** Runtime-owned private input admission mode, not public output/related authority. */
|
|
1157
|
+
readonly requireReadOperationAccessForPopulateDependencies?: boolean;
|
|
1158
|
+
/** Independent ordinary-populate registration posture from the same global snapshot. */
|
|
1159
|
+
readonly requireRegisteredPopulateModels?: boolean;
|
|
1146
1160
|
readonly documentPermissionField?: string;
|
|
1147
1161
|
/** Captured permission schema, virtual descriptors, always-select and metadata posture. */
|
|
1148
1162
|
readonly [key: string]: unknown;
|
|
@@ -3116,7 +3130,7 @@ interface AccessRouterLogger {
|
|
|
3116
3130
|
isLevelEnabled?: (level: string) => boolean;
|
|
3117
3131
|
}
|
|
3118
3132
|
/**
|
|
3119
|
-
* Runtime-wide request initialization and resource settings, configured with
|
|
3133
|
+
* Runtime-wide request initialization, private-input policy and resource settings, configured with
|
|
3120
3134
|
* api.setGlobalOptions / api.setGlobalOption. These are not model options or wire
|
|
3121
3135
|
* options. Object assignment is shallow; nested requestComplexity replaces as a unit.
|
|
3122
3136
|
*/
|
|
@@ -3134,6 +3148,39 @@ interface GlobalOptions {
|
|
|
3134
3148
|
globalPermissions?: (this: AccessRouterRequest, req: AccessRouterRequest) => MaybePromise<GlobalPermissionValue>;
|
|
3135
3149
|
/** Require populate target models to be registered in the active runtime. Defaults to `true`. */
|
|
3136
3150
|
requireRegisteredPopulateModels?: boolean;
|
|
3151
|
+
/**
|
|
3152
|
+
* Require the original caller's target base `operationAccess.read` before loading
|
|
3153
|
+
* declared private `dependsOnPopulate` inputs (default `true`). Only literal boolean
|
|
3154
|
+
* `false` bypasses that operation gate; undefined/malformed JS values normalize to
|
|
3155
|
+
* `true`. Source/target input-field permissions are already bypassed by the server
|
|
3156
|
+
* declaration; the virtual's own output authorization still applies. Target request-mode
|
|
3157
|
+
* `baseFilter.read`, `overrideFilter.read` and retained reference IDs always constrain rows.
|
|
3158
|
+
* Captured with source/target policy and query intent before the first await, including
|
|
3159
|
+
* nested output scopes. In-flight calls retain their mode; later calls see updates.
|
|
3160
|
+
* Runtime-isolated server configuration only: no caller/query or per-model override.
|
|
3161
|
+
*
|
|
3162
|
+
* In BOTH modes, references in an active selected/applicable dependency plan require
|
|
3163
|
+
* source selection/field permission AND the captured caller-context target base read
|
|
3164
|
+
* grant. Denied/failed read visibility omits the entire reference, including its ID,
|
|
3165
|
+
* even with ordinary list/custom populate access or a public related-operation grant.
|
|
3166
|
+
* Allowed read keeps the original authorized public populate mask, or exact original
|
|
3167
|
+
* refs without population. No active dependency plan leaves ordinary behavior intact.
|
|
3168
|
+
* False-mode private-only loading adds no operation check solely for that fetch.
|
|
3169
|
+
* This never grants public fields, row/write authority or query controls. Registration
|
|
3170
|
+
* and static input declarations remain required, independently of requireRegisteredPopulateModels.
|
|
3171
|
+
*
|
|
3172
|
+
* @example
|
|
3173
|
+
* ```ts
|
|
3174
|
+
* import { createAccessRuntime, type GlobalOptions } from '@web-ts-toolkit/access-router';
|
|
3175
|
+
* const api = createAccessRuntime();
|
|
3176
|
+
* const policy = { requireReadOperationAccessForPopulateDependencies: false } satisfies GlobalOptions;
|
|
3177
|
+
* api.setGlobalOptions(policy); // privileged computation inputs; no public target-read grant
|
|
3178
|
+
* const snapshot: GlobalOptions = api.getGlobalOptions();
|
|
3179
|
+
* api.setGlobalOption('requireReadOperationAccessForPopulateDependencies', true);
|
|
3180
|
+
* void snapshot; // stored snapshot; read again to observe the setter
|
|
3181
|
+
* ```
|
|
3182
|
+
*/
|
|
3183
|
+
requireReadOperationAccessForPopulateDependencies?: boolean;
|
|
3137
3184
|
logger?: AccessRouterLogger;
|
|
3138
3185
|
/** Request budgets and separate hook/persistence pools; concurrency limits are captured on first owner use. */
|
|
3139
3186
|
requestComplexity?: RequestComplexityOptions;
|
|
@@ -3441,8 +3488,12 @@ interface ModelRouterOptions<TModel = unknown, TVirtuals extends object = Record
|
|
|
3441
3488
|
* that getter's fourth argument. Annotate ModelVirtualDescriptor<Source, Value,
|
|
3442
3489
|
* { ref: Target }> separately, then assign here; persisted/write/public types
|
|
3443
3490
|
* stay unchanged. Register target models/options first in this runtime. Source
|
|
3444
|
-
* refs are retained automatically
|
|
3445
|
-
*
|
|
3491
|
+
* refs are retained automatically. GlobalOptions.requireReadOperationAccessForPopulateDependencies
|
|
3492
|
+
* defaults to true; false bypasses only private target-operation admission, never
|
|
3493
|
+
* request read-row filters/retained IDs. In both modes an active dependency ref's
|
|
3494
|
+
* denied caller-context target base read omits the entire ref, including its ID.
|
|
3495
|
+
* Allowed refs keep the original authorized populate mask or exact original IDs;
|
|
3496
|
+
* unselected/denied source fields remain hidden. No active plan keeps ordinary behavior.
|
|
3446
3497
|
*
|
|
3447
3498
|
* @example Shortest typed happy-path (persisted model lacks `fullAddress`):
|
|
3448
3499
|
* ```ts
|