@aooth/arbac 0.1.77 → 0.1.78
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/dist/index.cjs +16 -3
- package/dist/index.d.cts +6 -5
- package/dist/index.d.mts +6 -5
- package/dist/index.mjs +16 -3
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -780,8 +780,8 @@ const NO_FIELDS = Object.freeze({});
|
|
|
780
780
|
* conjunction — so every row path sees the restriction. The custom value
|
|
781
781
|
* stays on the scope. Scopes are never mutated: a changed scope is a copy.
|
|
782
782
|
* Memoized per rule registry and scope object (process-wide), and
|
|
783
|
-
* idempotent (a folded scope folds to itself); without row rules
|
|
784
|
-
*
|
|
783
|
+
* idempotent (a folded scope folds to itself); without row rules the input
|
|
784
|
+
* list is returned as is (after the `onUnknownField` report, if any).
|
|
785
785
|
*
|
|
786
786
|
* @since 0.1.72
|
|
787
787
|
*/
|
|
@@ -799,7 +799,10 @@ function applyScopeFieldFilters(scopes, fields, opts = {}) {
|
|
|
799
799
|
}
|
|
800
800
|
const { rules, memo } = state;
|
|
801
801
|
const { onUnknownField } = opts;
|
|
802
|
-
if (rules.length === 0
|
|
802
|
+
if (rules.length === 0) {
|
|
803
|
+
if (onUnknownField) for (const scope of scopes) reportUnknownFields(scope, registry, onUnknownField);
|
|
804
|
+
return scopes;
|
|
805
|
+
}
|
|
803
806
|
const fold = (scope) => {
|
|
804
807
|
if (scope === null || typeof scope !== "object") return scope;
|
|
805
808
|
const hit = memo.get(scope);
|
|
@@ -837,6 +840,16 @@ function applyScopeFieldFilters(scopes, fields, opts = {}) {
|
|
|
837
840
|
const out = scopes.map(fold);
|
|
838
841
|
return out.every((s, i) => s === scopes[i]) ? scopes : out;
|
|
839
842
|
}
|
|
843
|
+
/** {@link applyScopeFieldFilters}' unknown-field report without row rules, recursing into `with`. */
|
|
844
|
+
function reportUnknownFields(scope, registry, onUnknownField) {
|
|
845
|
+
if (scope === null || typeof scope !== "object") return;
|
|
846
|
+
const record = scope;
|
|
847
|
+
for (const key of Object.keys(scope)) {
|
|
848
|
+
if (BUILT_IN_KEYS.has(key) || Object.hasOwn(registry, key)) continue;
|
|
849
|
+
if (record[key] !== void 0) onUnknownField(key);
|
|
850
|
+
}
|
|
851
|
+
if (scope.with) for (const sub of Object.values(scope.with)) reportUnknownFields(sub, registry, onUnknownField);
|
|
852
|
+
}
|
|
840
853
|
/**
|
|
841
854
|
* Marks a `with.<rel>` sub-scope {@link conjoinScopes} built from ONE side's
|
|
842
855
|
* declaration. The other side is silent on the relation, so ITS policy for
|
package/dist/index.d.cts
CHANGED
|
@@ -619,9 +619,10 @@ declare function conjoinScopes<S extends TDbScope>(a: readonly S[], b: readonly
|
|
|
619
619
|
/** Options of {@link applyScopeFieldFilters}. @since 0.1.72 */
|
|
620
620
|
interface TApplyScopeFieldFiltersOptions {
|
|
621
621
|
/**
|
|
622
|
-
* Called for a non-built-in scope key with no rule in `fields`
|
|
623
|
-
*
|
|
624
|
-
*
|
|
622
|
+
* Called for a non-built-in scope key with no rule in `fields` — e.g. to
|
|
623
|
+
* warn about a field that will fail the first attenuated conjunction. With
|
|
624
|
+
* row rules registered it fires once per scope object carrying the key
|
|
625
|
+
* (memoized fold); without any, on every call.
|
|
625
626
|
*/
|
|
626
627
|
onUnknownField?: (field: string) => void;
|
|
627
628
|
}
|
|
@@ -632,8 +633,8 @@ interface TApplyScopeFieldFiltersOptions {
|
|
|
632
633
|
* conjunction — so every row path sees the restriction. The custom value
|
|
633
634
|
* stays on the scope. Scopes are never mutated: a changed scope is a copy.
|
|
634
635
|
* Memoized per rule registry and scope object (process-wide), and
|
|
635
|
-
* idempotent (a folded scope folds to itself); without row rules
|
|
636
|
-
*
|
|
636
|
+
* idempotent (a folded scope folds to itself); without row rules the input
|
|
637
|
+
* list is returned as is (after the `onUnknownField` report, if any).
|
|
637
638
|
*
|
|
638
639
|
* @since 0.1.72
|
|
639
640
|
*/
|
package/dist/index.d.mts
CHANGED
|
@@ -619,9 +619,10 @@ declare function conjoinScopes<S extends TDbScope>(a: readonly S[], b: readonly
|
|
|
619
619
|
/** Options of {@link applyScopeFieldFilters}. @since 0.1.72 */
|
|
620
620
|
interface TApplyScopeFieldFiltersOptions {
|
|
621
621
|
/**
|
|
622
|
-
* Called for a non-built-in scope key with no rule in `fields`
|
|
623
|
-
*
|
|
624
|
-
*
|
|
622
|
+
* Called for a non-built-in scope key with no rule in `fields` — e.g. to
|
|
623
|
+
* warn about a field that will fail the first attenuated conjunction. With
|
|
624
|
+
* row rules registered it fires once per scope object carrying the key
|
|
625
|
+
* (memoized fold); without any, on every call.
|
|
625
626
|
*/
|
|
626
627
|
onUnknownField?: (field: string) => void;
|
|
627
628
|
}
|
|
@@ -632,8 +633,8 @@ interface TApplyScopeFieldFiltersOptions {
|
|
|
632
633
|
* conjunction — so every row path sees the restriction. The custom value
|
|
633
634
|
* stays on the scope. Scopes are never mutated: a changed scope is a copy.
|
|
634
635
|
* Memoized per rule registry and scope object (process-wide), and
|
|
635
|
-
* idempotent (a folded scope folds to itself); without row rules
|
|
636
|
-
*
|
|
636
|
+
* idempotent (a folded scope folds to itself); without row rules the input
|
|
637
|
+
* list is returned as is (after the `onUnknownField` report, if any).
|
|
637
638
|
*
|
|
638
639
|
* @since 0.1.72
|
|
639
640
|
*/
|
package/dist/index.mjs
CHANGED
|
@@ -780,8 +780,8 @@ const NO_FIELDS = Object.freeze({});
|
|
|
780
780
|
* conjunction — so every row path sees the restriction. The custom value
|
|
781
781
|
* stays on the scope. Scopes are never mutated: a changed scope is a copy.
|
|
782
782
|
* Memoized per rule registry and scope object (process-wide), and
|
|
783
|
-
* idempotent (a folded scope folds to itself); without row rules
|
|
784
|
-
*
|
|
783
|
+
* idempotent (a folded scope folds to itself); without row rules the input
|
|
784
|
+
* list is returned as is (after the `onUnknownField` report, if any).
|
|
785
785
|
*
|
|
786
786
|
* @since 0.1.72
|
|
787
787
|
*/
|
|
@@ -799,7 +799,10 @@ function applyScopeFieldFilters(scopes, fields, opts = {}) {
|
|
|
799
799
|
}
|
|
800
800
|
const { rules, memo } = state;
|
|
801
801
|
const { onUnknownField } = opts;
|
|
802
|
-
if (rules.length === 0
|
|
802
|
+
if (rules.length === 0) {
|
|
803
|
+
if (onUnknownField) for (const scope of scopes) reportUnknownFields(scope, registry, onUnknownField);
|
|
804
|
+
return scopes;
|
|
805
|
+
}
|
|
803
806
|
const fold = (scope) => {
|
|
804
807
|
if (scope === null || typeof scope !== "object") return scope;
|
|
805
808
|
const hit = memo.get(scope);
|
|
@@ -837,6 +840,16 @@ function applyScopeFieldFilters(scopes, fields, opts = {}) {
|
|
|
837
840
|
const out = scopes.map(fold);
|
|
838
841
|
return out.every((s, i) => s === scopes[i]) ? scopes : out;
|
|
839
842
|
}
|
|
843
|
+
/** {@link applyScopeFieldFilters}' unknown-field report without row rules, recursing into `with`. */
|
|
844
|
+
function reportUnknownFields(scope, registry, onUnknownField) {
|
|
845
|
+
if (scope === null || typeof scope !== "object") return;
|
|
846
|
+
const record = scope;
|
|
847
|
+
for (const key of Object.keys(scope)) {
|
|
848
|
+
if (BUILT_IN_KEYS.has(key) || Object.hasOwn(registry, key)) continue;
|
|
849
|
+
if (record[key] !== void 0) onUnknownField(key);
|
|
850
|
+
}
|
|
851
|
+
if (scope.with) for (const sub of Object.values(scope.with)) reportUnknownFields(sub, registry, onUnknownField);
|
|
852
|
+
}
|
|
840
853
|
/**
|
|
841
854
|
* Marks a `with.<rel>` sub-scope {@link conjoinScopes} built from ONE side's
|
|
842
855
|
* declaration. The other side is silent on the relation, so ITS policy for
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aooth/arbac",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.78",
|
|
4
4
|
"description": "Batteries-included RBAC: builder API, privilege factories, scope merge utilities",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"access-control",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"access": "public"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@aooth/arbac-core": "0.1.
|
|
48
|
+
"@aooth/arbac-core": "0.1.78"
|
|
49
49
|
},
|
|
50
50
|
"scripts": {
|
|
51
51
|
"build": "vp pack",
|