@narrative.io/data-collaboration-sdk-ts 2.90.0 → 2.90.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -35,7 +35,7 @@ export function validatePolicyAgainstDataset(policy, _dataset, attributes) {
35
35
  for (const filter of filters) {
36
36
  collectMissingAttributesFromFilter(filter, attributeByName, missingFilterAttributes);
37
37
  }
38
- visitStructureFilters(policy.policy.definition.structure, (filter) => collectMissingAttributesFromFilter(filter, attributeByName, missingFilterAttributes));
38
+ visitStructureFilters(policy.policy.definition.structure, (filter) => collectMissingAttributesFromFilter(filter, attributeByName, missingFilterAttributes), attributeByName);
39
39
  if (missingFilterAttributes.size > 0) {
40
40
  result.isValid = false;
41
41
  const missingList = Array.from(missingFilterAttributes).sort();
@@ -115,27 +115,64 @@ function validatePolicyStructure(structure, attributeByName) {
115
115
  }
116
116
  return { isValid: true, errors: [] };
117
117
  }
118
- function visitStructureFilters(node, visitor) {
118
+ /**
119
+ * Checks if a branch is satisfied (all required attributes exist).
120
+ * For anyOf: at least one child must be satisfied.
121
+ * For allOf: all children must be satisfied.
122
+ * For field nodes: the attribute must exist.
123
+ */
124
+ function isBranchSatisfied(node, attributeByName) {
125
+ if (!node || typeof node !== "object") {
126
+ return true;
127
+ }
128
+ if ("field" in node) {
129
+ const field = node.field;
130
+ if (field.type === "attribute" && field.attribute_name) {
131
+ return attributeByName.has(field.attribute_name);
132
+ }
133
+ return true;
134
+ }
135
+ if ("anyOf" in node && Array.isArray(node.anyOf)) {
136
+ return node.anyOf.some((child) => isBranchSatisfied(child, attributeByName));
137
+ }
138
+ if ("allOf" in node && Array.isArray(node.allOf)) {
139
+ return node.allOf.every((child) => isBranchSatisfied(child, attributeByName));
140
+ }
141
+ return true;
142
+ }
143
+ /**
144
+ * Visits filters only in satisfied branches of the policy structure.
145
+ * For anyOf nodes, only visits filters in branches where the required attributes exist.
146
+ * For allOf nodes, visits filters in all branches (since all must be satisfied).
147
+ */
148
+ function visitStructureFilters(node, visitor, attributeByName) {
119
149
  if (!node || typeof node !== "object") {
120
150
  return;
121
151
  }
122
152
  if ("field" in node) {
123
- const filters = node.filters;
124
- if (filters) {
125
- for (const filter of filters) {
126
- visitor(filter);
153
+ // Only visit filters if this branch is satisfied
154
+ if (isBranchSatisfied(node, attributeByName)) {
155
+ const filters = node.filters;
156
+ if (filters) {
157
+ for (const filter of filters) {
158
+ visitor(filter);
159
+ }
127
160
  }
128
161
  }
129
162
  return;
130
163
  }
131
164
  if ("anyOf" in node && Array.isArray(node.anyOf)) {
165
+ // Only visit filters in satisfied branches
132
166
  for (const child of node.anyOf) {
133
- visitStructureFilters(child, visitor);
167
+ if (isBranchSatisfied(child, attributeByName)) {
168
+ visitStructureFilters(child, visitor, attributeByName);
169
+ }
134
170
  }
135
171
  }
136
172
  if ("allOf" in node && Array.isArray(node.allOf)) {
173
+ // For allOf, visit all branches (they all must be satisfied)
137
174
  for (const child of node.allOf) {
138
- visitStructureFilters(child, visitor);
175
+ visitStructureFilters(child, visitor, attributeByName);
139
176
  }
140
177
  }
141
178
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@narrative.io/data-collaboration-sdk-ts",
3
- "version": "2.90.0",
3
+ "version": "2.90.1",
4
4
  "main": "build/index.js",
5
5
  "repository": "github:narrative-io/data-collaboration-sdk-ts",
6
6
  "source": "src/index.ts",