@narrative.io/data-collaboration-sdk-ts 2.103.0 → 2.105.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.
Files changed (38) hide show
  1. package/build/access-tokens/types.d.ts +1 -0
  2. package/build/access-tokens/types.js +1 -0
  3. package/build/apps/index.d.ts +7 -0
  4. package/build/apps/index.js +9 -0
  5. package/build/collaboration-policy/core/filter-builder.js +7 -1
  6. package/build/collaboration-policy/core/jsonschema/json-schema-types.d.ts +45 -0
  7. package/build/collaboration-policy/core/jsonschema/json-schema-types.js +1 -0
  8. package/build/collaboration-policy/core/jsonschema/policy-branches.d.ts +49 -0
  9. package/build/collaboration-policy/core/jsonschema/policy-branches.js +1 -0
  10. package/build/collaboration-policy/core/jsonschema/policy-evaluator.d.ts +22 -0
  11. package/build/collaboration-policy/core/jsonschema/policy-evaluator.js +250 -0
  12. package/build/collaboration-policy/core/jsonschema/sql-builder.d.ts +79 -0
  13. package/build/collaboration-policy/core/jsonschema/sql-builder.js +306 -0
  14. package/build/collaboration-policy/core/types.d.ts +81 -10
  15. package/build/collaboration-policy/index.d.ts +5 -4
  16. package/build/collaboration-policy/index.js +4 -3
  17. package/build/collaboration-policy/useCollaborationPolicy.d.ts +13 -4
  18. package/build/collaboration-policy/useCollaborationPolicy.js +23 -1
  19. package/build/collaboration-policy/utils/path-helpers.d.ts +7 -3
  20. package/build/collaboration-policy/utils/path-helpers.js +6 -22
  21. package/build/datasets/index.d.ts +11 -2
  22. package/build/datasets/index.js +12 -0
  23. package/build/datasets/types.d.ts +25 -0
  24. package/package.json +2 -1
  25. package/build/collaboration-policy/core/filter-utils.d.ts +0 -6
  26. package/build/collaboration-policy/core/filter-utils.js +0 -49
  27. package/build/collaboration-policy/core/policy-traverser.d.ts +0 -4
  28. package/build/collaboration-policy/core/policy-traverser.js +0 -99
  29. package/build/collaboration-policy/core/policy-validator.d.ts +0 -11
  30. package/build/collaboration-policy/core/policy-validator.js +0 -185
  31. package/build/collaboration-policy/core/sql-builder.d.ts +0 -37
  32. package/build/collaboration-policy/core/sql-builder.js +0 -346
  33. package/build/collaboration-policy/scripts/generate-policy-schema.d.ts +0 -2
  34. package/build/collaboration-policy/scripts/generate-policy-schema.js +0 -4
  35. package/build/collaboration-policy/types/collaboration-policy.d.ts +0 -1370
  36. package/build/collaboration-policy/types/collaboration-policy.js +0 -274
  37. package/build/collaboration-policy/types/index.d.ts +0 -2
  38. package/build/collaboration-policy/types/index.js +0 -1
@@ -1,49 +0,0 @@
1
- import { normalizePathValue } from "../utils/path-helpers";
2
- export function visitFilterAttributes(filter, visitor) {
3
- traverseFilter(filter, visitor);
4
- }
5
- function traverseFilter(node, visitor) {
6
- if (!node || typeof node !== "object") {
7
- return;
8
- }
9
- if (isAttributeReference(node)) {
10
- const normalizedPath = normalizePathValue(node.path);
11
- visitor(node.attribute_name, normalizedPath);
12
- return;
13
- }
14
- if ("left" in node) {
15
- traverseFilter(node.left, visitor);
16
- }
17
- if ("right" in node) {
18
- const right = node.right;
19
- if (Array.isArray(right)) {
20
- for (const item of right) {
21
- traverseFilter(item, visitor);
22
- }
23
- }
24
- else {
25
- traverseFilter(right, visitor);
26
- }
27
- }
28
- if ("args" in node && Array.isArray(node.args)) {
29
- for (const arg of node.args) {
30
- traverseFilter(arg, visitor);
31
- }
32
- }
33
- if ("operand" in node) {
34
- traverseFilter(node.operand, visitor);
35
- }
36
- if ("lower" in node) {
37
- traverseFilter(node.lower, visitor);
38
- }
39
- if ("upper" in node) {
40
- traverseFilter(node.upper, visitor);
41
- }
42
- }
43
- export function isAttributeReference(node) {
44
- return (!!node &&
45
- typeof node === "object" &&
46
- "type" in node &&
47
- node.type === "attribute" &&
48
- "attribute_name" in node);
49
- }
@@ -1,4 +0,0 @@
1
- import type { Attribute } from "../../attributes/types";
2
- import type { CollaborationPolicyType } from "../types";
3
- import type { AttributePathIndex } from "./types";
4
- export declare function traversePolicy(policy: CollaborationPolicyType, attributeByName: Map<string, Attribute>, requiredAttributePaths: AttributePathIndex, whereClauses: Set<string>, datasetName: string): void;
@@ -1,99 +0,0 @@
1
- import { markAttributePath, normalizePathValue } from "../utils/path-helpers";
2
- import { filterToSql } from "./filter-builder";
3
- import { visitFilterAttributes } from "./filter-utils";
4
- export function traversePolicy(policy, attributeByName, requiredAttributePaths, whereClauses, datasetName) {
5
- const definition = policy.policy.definition;
6
- // Only traverse satisfied parts of the structure
7
- traverseSatisfiedStructure(definition.structure, attributeByName, (node) => {
8
- const field = node.field;
9
- const attributeName = field.attribute_name;
10
- const attribute = attributeByName.get(attributeName);
11
- if (!attribute) {
12
- throw new Error(`Attribute "${attributeName}" referenced in policy but not provided.`);
13
- }
14
- // Always mark the root attribute (without path) for SELECT clause
15
- markAttributePath(requiredAttributePaths, attribute, normalizePathValue(undefined));
16
- if (field.additional_required_properties) {
17
- for (const path of field.additional_required_properties) {
18
- // Add IS NOT NULL filter for each additional required property
19
- const pathStr = normalizePathValue(path);
20
- const expression = `company_data."${datasetName}"."_rosetta_stone"."${attribute.name}"."${pathStr}"`;
21
- whereClauses.add(`(${expression} IS NOT NULL)`);
22
- }
23
- }
24
- if (node.filters) {
25
- for (const filter of node.filters) {
26
- visitFilterAttributes(filter, (attributeName, path) => {
27
- const attribute = attributeByName.get(attributeName);
28
- if (!attribute) {
29
- throw new Error(`Attribute "${attributeName}" referenced in filter but not provided.`);
30
- }
31
- markAttributePath(requiredAttributePaths, attribute, path);
32
- });
33
- const sql = filterToSql(filter, attributeByName, datasetName);
34
- whereClauses.add(sql);
35
- }
36
- }
37
- });
38
- if (definition.filters) {
39
- for (const filter of definition.filters) {
40
- visitFilterAttributes(filter, (attributeName, path) => {
41
- const attribute = attributeByName.get(attributeName);
42
- if (!attribute) {
43
- throw new Error(`Attribute "${attributeName}" referenced in filter but not provided.`);
44
- }
45
- markAttributePath(requiredAttributePaths, attribute, path);
46
- });
47
- const sql = filterToSql(filter, attributeByName, datasetName);
48
- whereClauses.add(sql);
49
- }
50
- }
51
- }
52
- function traverseSatisfiedStructure(node, attributeByName, visitor) {
53
- if (!node || typeof node !== "object") {
54
- return;
55
- }
56
- if ("field" in node) {
57
- visitor(node);
58
- return;
59
- }
60
- if ("anyOf" in node && Array.isArray(node.anyOf)) {
61
- // For anyOf, traverse ALL satisfied branches
62
- for (const child of node.anyOf) {
63
- if (isBranchSatisfied(child, attributeByName)) {
64
- traverseSatisfiedStructure(child, attributeByName, visitor);
65
- }
66
- }
67
- return;
68
- }
69
- if ("allOf" in node && Array.isArray(node.allOf)) {
70
- // For allOf, traverse all branches (they must all be satisfied)
71
- for (const child of node.allOf) {
72
- traverseSatisfiedStructure(child, attributeByName, visitor);
73
- }
74
- }
75
- }
76
- function isBranchSatisfied(node, attributeByName) {
77
- if (!node || typeof node !== "object") {
78
- return true;
79
- }
80
- if ("field" in node) {
81
- const field = node
82
- .field;
83
- if (field.type === "attribute") {
84
- const attributeName = field.attribute_name;
85
- // Only check if attribute exists, not mappings since we use company_data format
86
- return attributeByName.has(attributeName);
87
- }
88
- return true;
89
- }
90
- if ("anyOf" in node && Array.isArray(node.anyOf)) {
91
- // For anyOf, at least one child must be satisfied
92
- return node.anyOf.some((child) => isBranchSatisfied(child, attributeByName));
93
- }
94
- if ("allOf" in node && Array.isArray(node.allOf)) {
95
- // For allOf, all children must be satisfied
96
- return node.allOf.every((child) => isBranchSatisfied(child, attributeByName));
97
- }
98
- return true;
99
- }
@@ -1,11 +0,0 @@
1
- import type { Attribute } from "../../attributes/types";
2
- import type { Dataset } from "../../datasets/types";
3
- import type { CollaborationPolicyType } from "../types";
4
- interface PolicyValidationResult {
5
- isValid: boolean;
6
- missingAttributes: string[];
7
- missingMappings: string[];
8
- errors: string[];
9
- }
10
- export declare function validatePolicyAgainstDataset(policy: CollaborationPolicyType, _dataset: Dataset, attributes: Attribute[]): PolicyValidationResult;
11
- export {};
@@ -1,185 +0,0 @@
1
- import { visitFilterAttributes } from "./filter-utils";
2
- export function validatePolicyAgainstDataset(policy, _dataset, attributes) {
3
- const result = {
4
- isValid: true,
5
- missingAttributes: [],
6
- missingMappings: [],
7
- errors: [],
8
- };
9
- const attributeByName = new Map();
10
- for (const attribute of attributes) {
11
- attributeByName.set(attribute.name, attribute);
12
- }
13
- // Validate the policy structure considering logical operators
14
- const validation = validatePolicyStructure(policy.policy.definition.structure, attributeByName);
15
- if (!validation.isValid) {
16
- result.isValid = false;
17
- result.errors.push(...validation.errors);
18
- // Extract unique missing attributes for backwards compatibility
19
- const allMissingAttributes = new Set();
20
- for (const error of validation.errors) {
21
- if (error.includes("Missing attributes:")) {
22
- const attrs = error
23
- .split("Missing attributes:")[1]
24
- ?.split(",")
25
- .map((s) => s.trim()) || [];
26
- for (const attr of attrs) {
27
- allMissingAttributes.add(attr);
28
- }
29
- }
30
- }
31
- result.missingAttributes = Array.from(allMissingAttributes);
32
- }
33
- const missingFilterAttributes = new Set();
34
- const filters = policy.policy.definition.filters ?? [];
35
- for (const filter of filters) {
36
- collectMissingAttributesFromFilter(filter, attributeByName, missingFilterAttributes);
37
- }
38
- visitStructureFilters(policy.policy.definition.structure, (filter) => collectMissingAttributesFromFilter(filter, attributeByName, missingFilterAttributes), attributeByName);
39
- if (missingFilterAttributes.size > 0) {
40
- result.isValid = false;
41
- const missingList = Array.from(missingFilterAttributes).sort();
42
- result.errors.push(`Filters reference missing attributes: ${missingList.join(", ")}`);
43
- for (const attr of missingList) {
44
- if (!result.missingAttributes.includes(attr)) {
45
- result.missingAttributes.push(attr);
46
- }
47
- }
48
- }
49
- return result;
50
- }
51
- function validatePolicyStructure(structure, attributeByName) {
52
- if (!structure || typeof structure !== "object") {
53
- return { isValid: true, errors: [] };
54
- }
55
- const struct = structure;
56
- // Handle anyOf - at least one must be valid
57
- if (struct.anyOf && Array.isArray(struct.anyOf)) {
58
- for (const option of struct.anyOf) {
59
- const optionValidation = validatePolicyStructure(option, attributeByName);
60
- if (optionValidation.isValid) {
61
- // If any option is valid, the whole anyOf is valid
62
- return { isValid: true, errors: [] };
63
- }
64
- }
65
- // If no options are valid, collect all errors
66
- const allErrors = [];
67
- for (const option of struct.anyOf) {
68
- const optionValidation = validatePolicyStructure(option, attributeByName);
69
- allErrors.push(...optionValidation.errors);
70
- }
71
- return {
72
- isValid: false,
73
- errors: [
74
- `None of the anyOf options are satisfied. Issues: ${allErrors.join("; ")}`,
75
- ],
76
- };
77
- }
78
- // Handle allOf - all must be valid
79
- if (struct.allOf && Array.isArray(struct.allOf)) {
80
- const allErrors = [];
81
- for (const requirement of struct.allOf) {
82
- const reqValidation = validatePolicyStructure(requirement, attributeByName);
83
- if (!reqValidation.isValid) {
84
- allErrors.push(...reqValidation.errors);
85
- }
86
- }
87
- return allErrors.length > 0
88
- ? { isValid: false, errors: allErrors }
89
- : { isValid: true, errors: [] };
90
- }
91
- // Handle single field with attribute
92
- if (struct.field &&
93
- struct.field.type ===
94
- "attribute") {
95
- const attributeName = struct.field
96
- .attribute_name;
97
- const errors = [];
98
- // Check if attribute exists - we don't need to check mappings anymore
99
- // since we use company_data.<attribute_name> format
100
- if (!attributeByName.has(attributeName)) {
101
- errors.push(`Missing attributes: ${attributeName}`);
102
- }
103
- return errors.length > 0
104
- ? { isValid: false, errors }
105
- : { isValid: true, errors: [] };
106
- }
107
- // For other structures, recursively validate
108
- for (const value of Object.values(struct)) {
109
- if (typeof value === "object") {
110
- const childValidation = validatePolicyStructure(value, attributeByName);
111
- if (!childValidation.isValid) {
112
- return childValidation;
113
- }
114
- }
115
- }
116
- return { isValid: true, errors: [] };
117
- }
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) {
149
- if (!node || typeof node !== "object") {
150
- return;
151
- }
152
- if ("field" in node) {
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
- }
160
- }
161
- }
162
- return;
163
- }
164
- if ("anyOf" in node && Array.isArray(node.anyOf)) {
165
- // Only visit filters in satisfied branches
166
- for (const child of node.anyOf) {
167
- if (isBranchSatisfied(child, attributeByName)) {
168
- visitStructureFilters(child, visitor, attributeByName);
169
- }
170
- }
171
- }
172
- if ("allOf" in node && Array.isArray(node.allOf)) {
173
- // For allOf, visit all branches (they all must be satisfied)
174
- for (const child of node.allOf) {
175
- visitStructureFilters(child, visitor, attributeByName);
176
- }
177
- }
178
- }
179
- function collectMissingAttributesFromFilter(filter, attributesByName, missingAttributes) {
180
- visitFilterAttributes(filter, (attributeName) => {
181
- if (!attributesByName.has(attributeName)) {
182
- missingAttributes.add(attributeName);
183
- }
184
- });
185
- }
@@ -1,37 +0,0 @@
1
- import type { Attribute } from "../../attributes/types";
2
- import type { Dataset } from "../../datasets/types";
3
- import type { CollaborationPolicyType } from "../types";
4
- import type { PolicyMatchResult, PolicySqlFragments } from "./types";
5
- export declare function buildPolicySqlWithValidation(dataset: Dataset, policies: CollaborationPolicyType[], attributes: Attribute[]): PolicyMatchResult;
6
- /**
7
- * Categorizes collaboration policies into matching and non-matching groups based on dataset compatibility.
8
- *
9
- * This function validates each policy against the provided dataset and attributes to determine
10
- * whether the policy can be successfully applied. Policies are categorized as matching if they
11
- * have all required attributes available, or non-matching if they're missing required attributes
12
- * or mappings.
13
- *
14
- * @param policies - Array of collaboration policies to categorize
15
- * @param dataset - The dataset to validate policies against
16
- * @param attributes - Available attributes for validation
17
- * @returns Object containing matching policies, non-matching policies, and detailed skip information
18
- *
19
- * @example
20
- * ```typescript
21
- * const { matching, nonMatching, skippedDetails } = categorizePolicies(
22
- * allPolicies,
23
- * myDataset,
24
- * availableAttributes
25
- * );
26
- *
27
- * console.log(`${matching.length} policies can be applied`);
28
- * console.log(`${nonMatching.length} policies were skipped`);
29
- * skippedDetails.forEach(skip => console.log(`Skipped ${skip.name}: ${skip.reason}`));
30
- * ```
31
- */
32
- export declare function categorizePolicies(policies: CollaborationPolicyType[], dataset: Dataset, attributes: Attribute[]): {
33
- matching: CollaborationPolicyType[];
34
- nonMatching: CollaborationPolicyType[];
35
- skippedDetails: PolicyMatchResult["skippedPolicies"];
36
- };
37
- export declare function buildPolicySql(dataset: Dataset, policies: CollaborationPolicyType[], attributes: Attribute[]): PolicySqlFragments;