@narrative.io/data-collaboration-sdk-ts 2.64.1 → 2.66.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 (34) hide show
  1. package/README.md +137 -1
  2. package/build/collaboration-policy/core/filter-builder.d.ts +3 -0
  3. package/build/collaboration-policy/core/filter-builder.js +90 -0
  4. package/build/collaboration-policy/core/filter-utils.d.ts +6 -0
  5. package/build/collaboration-policy/core/filter-utils.js +49 -0
  6. package/build/collaboration-policy/core/policy-traverser.d.ts +4 -0
  7. package/build/collaboration-policy/core/policy-traverser.js +100 -0
  8. package/build/collaboration-policy/core/policy-validator.d.ts +11 -0
  9. package/build/collaboration-policy/core/policy-validator.js +148 -0
  10. package/build/collaboration-policy/core/sql-builder.d.ts +37 -0
  11. package/build/collaboration-policy/core/sql-builder.js +173 -0
  12. package/build/collaboration-policy/core/types.d.ts +24 -0
  13. package/build/collaboration-policy/core/types.js +1 -0
  14. package/build/collaboration-policy/index.d.ts +4 -0
  15. package/build/collaboration-policy/index.js +3 -0
  16. package/build/collaboration-policy/scripts/generate-policy-schema.d.ts +2 -0
  17. package/build/collaboration-policy/scripts/generate-policy-schema.js +4 -0
  18. package/build/collaboration-policy/types/collaboration-policy.d.ts +697 -0
  19. package/build/collaboration-policy/types/collaboration-policy.js +262 -0
  20. package/build/collaboration-policy/types/index.d.ts +2 -0
  21. package/build/collaboration-policy/types/index.js +1 -0
  22. package/build/collaboration-policy/useCollaborationPolicy.d.ts +8 -0
  23. package/build/collaboration-policy/useCollaborationPolicy.js +14 -0
  24. package/build/collaboration-policy/utils/path-helpers.d.ts +4 -0
  25. package/build/collaboration-policy/utils/path-helpers.js +39 -0
  26. package/build/collaboration-policy/utils/sql-helpers.d.ts +5 -0
  27. package/build/collaboration-policy/utils/sql-helpers.js +65 -0
  28. package/build/index.d.ts +1 -0
  29. package/build/index.js +1 -0
  30. package/build/jobs/types.d.ts +7 -0
  31. package/build/nql/AstParser.js +5 -4
  32. package/build/nql/NqlBuilder.js +1 -1
  33. package/build/nql/types.d.ts +13 -0
  34. package/package.json +16 -12
@@ -0,0 +1,262 @@
1
+ import * as z from "zod/v4";
2
+ /** Branded types */
3
+ const CollaborationPolicyIdentifier = z
4
+ .string()
5
+ .regex(/^[a-zA-Z0-9_-]+$/)
6
+ .brand("CollaborationPolicyId")
7
+ .meta({
8
+ id: "collaboration_policy_identifier",
9
+ });
10
+ /** Refresh Schedule Schema */
11
+ const RefreshScheduleSchema = z
12
+ .object({
13
+ max: z.union([
14
+ z.enum(["@hourly", "@daily", "@weekly", "@monthly", "@once"]),
15
+ z
16
+ .string()
17
+ .regex(/^([0-5]?[0-9]|\*) ([01]?[0-9]|2[0-3]|\*) ([0-2]?[0-9]|3[01]|\*) ([0]?[1-9]|1[0-2]|\*) ([0-6]|\*)$/, "Invalid cron expression"),
18
+ ]),
19
+ })
20
+ .strict()
21
+ .meta({
22
+ id: "refresh_schedule",
23
+ });
24
+ const CollaborationPolicyDefinitionMetadataSchema = z
25
+ .object({
26
+ tags: z.array(z.string().regex(/^[a-zA-Z0-9_-]+$/)).optional(),
27
+ refresh_schedule: RefreshScheduleSchema.optional(),
28
+ })
29
+ .meta({ id: "metadata" });
30
+ const JsonPointerSchema = z
31
+ .string()
32
+ .regex(/^(#\/|\/).+/, 'JSON Pointer must start with "/" or "#/".')
33
+ .meta({ id: "json-pointer" });
34
+ /** Path can be dot-style or JSON Pointer */
35
+ const PathSchema = z
36
+ .union([
37
+ z
38
+ .object({
39
+ dot: z.string().min(1, "Dot path cannot be empty"),
40
+ })
41
+ .strict(),
42
+ z
43
+ .object({
44
+ pointer: JsonPointerSchema,
45
+ })
46
+ .strict(),
47
+ ])
48
+ .meta({ id: "path" });
49
+ /** ---------------------------
50
+ * Base + contextual variants
51
+ * --------------------------*/
52
+ /**
53
+ * BaseAttributeRef:
54
+ * - supports either `attribute_name` (by name) OR `attribute` (by pointer), not both
55
+ * - includes both `additional_required_properties` and `path` (context will prune)
56
+ */
57
+ const BaseAttributeRef = z
58
+ .object({
59
+ type: z.literal("attribute").meta({ id: "field_type" }),
60
+ // Choose ONE of these identifiers:
61
+ attribute_name: z.string().meta({ id: "attribute_name" }),
62
+ // Context-specific fields (trim in the derived schemas):
63
+ additional_required_properties: z
64
+ .array(PathSchema)
65
+ .optional()
66
+ .meta({ id: "additional_required_properties" }),
67
+ path: PathSchema.optional(),
68
+ })
69
+ .strict()
70
+ .meta({ id: "attribute_reference" });
71
+ /**
72
+ * StructureAttributeRef:
73
+ * - used in your “structure” (the logical tree)
74
+ * - allows: attribute_name + additional_required_properties
75
+ * - forbids: path, attribute (pointer)
76
+ * Example target:
77
+ * field: {
78
+ * type: "attribute",
79
+ * attribute_name: "sha256_hashed_email",
80
+ * additional_required_properties: [{ dot: "type" }],
81
+ * }
82
+ */
83
+ const StructureAttributeRef = BaseAttributeRef.omit({
84
+ path: true,
85
+ }).meta({ id: "structure_attribute_reference" });
86
+ /**
87
+ * FilterAttributeRef:
88
+ * - used inside filters
89
+ * - allows: attribute (pointer) + optional path
90
+ * - forbids: additional_required_properties, attribute_name
91
+ * Example target:
92
+ * left: {
93
+ * type: "attribute",
94
+ * attribute: "https://api.narrative.io/attributes/iso_3166_1_country",
95
+ * path: { dot: "value" },
96
+ * }
97
+ */
98
+ const FilterAttributeRef = BaseAttributeRef.omit({
99
+ additional_required_properties: true,
100
+ }).meta({ id: "filter_attribute_reference" });
101
+ // Now Expression can reference Filter without a lazy;
102
+ // the recursive bits inside Filter are handled by getters.
103
+ const Expression = z
104
+ .union([
105
+ z
106
+ .string()
107
+ .refine((s) => !s.startsWith("https://api.narrative.io/attributes/"), "String expression cannot be a JSON pointer; use { type:'attribute', attribute: ... }"),
108
+ z.number(),
109
+ z.boolean(),
110
+ FilterAttributeRef,
111
+ ])
112
+ .meta({ id: "expression" });
113
+ const FilterAndOr = z
114
+ .object({
115
+ op: z.enum(["and", "or"]),
116
+ stage: z.literal("generation").default("generation"),
117
+ name: z.string().optional(),
118
+ required: z.boolean().default(true),
119
+ get args() {
120
+ return z.array(Expression).min(2);
121
+ },
122
+ })
123
+ .strict();
124
+ const FilterNot = z
125
+ .object({
126
+ op: z.literal("not"),
127
+ stage: z.literal("generation").default("generation"),
128
+ name: z.string().optional(),
129
+ required: z.boolean().default(true),
130
+ get args() {
131
+ return z.array(Expression).length(1);
132
+ },
133
+ })
134
+ .strict();
135
+ const FilterIsNull = z
136
+ .object({
137
+ op: z.enum(["is_null", "is_not_null"]),
138
+ stage: z.literal("generation").default("generation"),
139
+ name: z.string().optional(),
140
+ required: z.boolean().default(true),
141
+ get left() {
142
+ return Expression;
143
+ },
144
+ })
145
+ .strict();
146
+ const FilterIn = z
147
+ .object({
148
+ op: z.enum(["in", "not in"]),
149
+ stage: z.literal("generation").default("generation"),
150
+ name: z.string().optional(),
151
+ required: z.boolean().default(true),
152
+ get left() {
153
+ return Expression;
154
+ },
155
+ get right() {
156
+ return z.array(Expression).min(1);
157
+ },
158
+ })
159
+ .strict();
160
+ const FilterCompare = z
161
+ .object({
162
+ op: z.enum(["=", "<>", ">", ">=", "<", "<=", "like", "not like"]),
163
+ stage: z.literal("generation").default("generation"),
164
+ name: z.string().optional(),
165
+ required: z.boolean().default(true),
166
+ get left() {
167
+ return Expression;
168
+ },
169
+ get right() {
170
+ return Expression;
171
+ },
172
+ })
173
+ .strict();
174
+ const FilterBetween = z
175
+ .object({
176
+ op: z.literal("between"),
177
+ stage: z.literal("generation").default("generation"),
178
+ name: z.string().optional(),
179
+ required: z.boolean().default(true),
180
+ get operand() {
181
+ return Expression;
182
+ },
183
+ get lower() {
184
+ return Expression;
185
+ },
186
+ get upper() {
187
+ return Expression;
188
+ },
189
+ })
190
+ .strict();
191
+ const Filter = z
192
+ .union([
193
+ FilterAndOr,
194
+ FilterNot,
195
+ FilterIsNull,
196
+ FilterIn,
197
+ FilterCompare,
198
+ FilterBetween,
199
+ ])
200
+ .meta({ id: "filter" });
201
+ const logicalTree = (leaf) => {
202
+ const NodeSchema = z.lazy(() => z
203
+ .union([
204
+ z
205
+ .object({
206
+ anyOf: z
207
+ .array(z.union([leaf, NodeSchema]))
208
+ .min(1)
209
+ .meta({ id: "any_of" }),
210
+ })
211
+ .strict()
212
+ .meta({ id: "any_of_object" }),
213
+ z
214
+ .object({
215
+ allOf: z
216
+ .array(z.union([leaf, NodeSchema]))
217
+ .min(1)
218
+ .meta({ id: "all_of" }),
219
+ })
220
+ .strict()
221
+ .meta({ id: "all_of_object" }),
222
+ ])
223
+ .meta({ id: "logical_node" }));
224
+ // Top-level can be a leaf T or a logical node.
225
+ return z.union([leaf, NodeSchema]).meta({ id: "logical_tree" });
226
+ };
227
+ const ExtendedAttribute = z
228
+ .object({
229
+ field: StructureAttributeRef,
230
+ filters: z.array(Filter).optional(),
231
+ })
232
+ .meta({ id: "extended_attribute" });
233
+ const CollaborationPolicyDefinitionShape = z
234
+ .object({
235
+ id: CollaborationPolicyIdentifier,
236
+ structure: logicalTree(ExtendedAttribute).meta({ id: "structure" }),
237
+ filters: z.array(Filter).optional(),
238
+ })
239
+ .meta({ id: "shape" });
240
+ const CollaborationPolicyDefinition = z
241
+ .object({
242
+ metadata: CollaborationPolicyDefinitionMetadataSchema,
243
+ definition: CollaborationPolicyDefinitionShape,
244
+ })
245
+ .meta({ id: "policy_definition" });
246
+ const CollaborationPolicy = z
247
+ .object({
248
+ name: CollaborationPolicyIdentifier,
249
+ description: z.string().max(2000).optional(),
250
+ display_name: z.string().max(255),
251
+ policy: CollaborationPolicyDefinition,
252
+ })
253
+ .meta({ id: "policy" });
254
+ // Export the schema for validation
255
+ export { CollaborationPolicy };
256
+ export function buildCollaborationPolicyJsonSchema(options = {}) {
257
+ const override = (options ?? {});
258
+ return z.toJSONSchema(CollaborationPolicy, {
259
+ reused: "ref",
260
+ ...override,
261
+ });
262
+ }
@@ -0,0 +1,2 @@
1
+ export type { CollaborationPolicyInput, CollaborationPolicyType, } from "./collaboration-policy";
2
+ export { buildCollaborationPolicyJsonSchema, CollaborationPolicy, } from "./collaboration-policy";
@@ -0,0 +1 @@
1
+ export { buildCollaborationPolicyJsonSchema, CollaborationPolicy, } from "./collaboration-policy";
@@ -0,0 +1,8 @@
1
+ import type { Attribute } from "../attributes/types";
2
+ import type { Dataset } from "../datasets/types";
3
+ import type { PolicySqlFragments } from "./core/types";
4
+ import type { CollaborationPolicyType } from "./types";
5
+ export default function useCollaborationPolicy(): {
6
+ getEligibleConnectorsPolicies: (dataset: Dataset, policies: CollaborationPolicyType[], attributes: Attribute[]) => CollaborationPolicyType[];
7
+ buildPolicySqlFragments: (dataset: Dataset, policies: CollaborationPolicyType[], attributes: Attribute[]) => PolicySqlFragments;
8
+ };
@@ -0,0 +1,14 @@
1
+ import { buildPolicySql, categorizePolicies } from "./core/sql-builder";
2
+ export default function useCollaborationPolicy() {
3
+ const getEligibleConnectorsPolicies = (dataset, policies, attributes) => {
4
+ const { matching } = categorizePolicies(policies, dataset, attributes);
5
+ return matching;
6
+ };
7
+ const buildPolicySqlFragments = (dataset, policies, attributes) => {
8
+ return buildPolicySql(dataset, policies, attributes);
9
+ };
10
+ return {
11
+ getEligibleConnectorsPolicies,
12
+ buildPolicySqlFragments,
13
+ };
14
+ }
@@ -0,0 +1,4 @@
1
+ import type { Attribute } from "../../attributes/types";
2
+ import type { AttributePathIndex, PathValue } from "../core/types";
3
+ export declare function markAttributePath(index: AttributePathIndex, attribute: Attribute, path: string): void;
4
+ export declare function normalizePathValue(path?: PathValue): string;
@@ -0,0 +1,39 @@
1
+ export function markAttributePath(index, attribute, path) {
2
+ const attributePaths = index.get(attribute.name) ?? new Set();
3
+ // Use the provided path, even if it's an empty string (which represents the root attribute)
4
+ const normalized = path !== undefined && path !== null
5
+ ? path
6
+ : determineDefaultPath(attribute);
7
+ attributePaths.add(normalized);
8
+ index.set(attribute.name, attributePaths);
9
+ }
10
+ function determineDefaultPath(attribute) {
11
+ if (attribute.type === "object" && "properties" in attribute) {
12
+ const properties = attribute.properties ?? {};
13
+ if ("value" in properties) {
14
+ return "value";
15
+ }
16
+ const [firstKey] = Object.keys(properties);
17
+ if (firstKey) {
18
+ return firstKey;
19
+ }
20
+ }
21
+ return "";
22
+ }
23
+ export function normalizePathValue(path) {
24
+ if (!path) {
25
+ return "";
26
+ }
27
+ if ("dot" in path) {
28
+ return path.dot;
29
+ }
30
+ const pointer = path.pointer;
31
+ let trimmed = pointer.startsWith("#/") ? pointer.slice(2) : pointer;
32
+ if (trimmed.startsWith("/")) {
33
+ trimmed = trimmed.slice(1);
34
+ }
35
+ const parts = trimmed
36
+ .split("/")
37
+ .map((segment) => segment.replace(/~1/g, "/").replace(/~0/g, "~"));
38
+ return parts.join(".");
39
+ }
@@ -0,0 +1,5 @@
1
+ import type { Attribute } from "../../attributes/types";
2
+ export declare function resolveAttributeExpression(attribute: Attribute, path: string, datasetName: string): string;
3
+ export declare function buildSelectAlias(attributeName: string, path: string): string;
4
+ export declare function buildPolicyWhereGroups(policyWhereClauses: string[][]): string[];
5
+ export declare function formatWhereClause(policyWhereClauses: string[][]): string;
@@ -0,0 +1,65 @@
1
+ export function resolveAttributeExpression(attribute, path, datasetName) {
2
+ // Use standardized company_data format with proper SQL identifier quoting
3
+ const quotedDatasetName = quoteIdentifier(datasetName);
4
+ const quotedRosettaStone = quoteIdentifier("_rosetta_stone");
5
+ const quotedAttributeName = quoteIdentifier(attribute.name);
6
+ const basePath = `company_data.${quotedDatasetName}.${quotedRosettaStone}.${quotedAttributeName}`;
7
+ if (!path) {
8
+ return basePath;
9
+ }
10
+ // Handle different path formats and quote each path segment
11
+ let pathSegments;
12
+ if (path.includes(".")) {
13
+ // Already dot notation (e.g., "some.nested.path")
14
+ pathSegments = path.split(".");
15
+ }
16
+ else if (path.includes("/")) {
17
+ // JSON pointer format was normalized but still has slashes
18
+ // This shouldn't happen after normalizePathValue, but handle it just in case
19
+ pathSegments = path.split("/");
20
+ }
21
+ else {
22
+ // Simple property name (e.g., "value", "type")
23
+ pathSegments = [path];
24
+ }
25
+ // Quote each path segment and join with dots
26
+ const quotedPathSegments = pathSegments
27
+ .filter((segment) => segment.length > 0)
28
+ .map((segment) => quoteIdentifier(segment));
29
+ return `${basePath}.${quotedPathSegments.join(".")}`;
30
+ }
31
+ export function buildSelectAlias(attributeName, path) {
32
+ if (!path) {
33
+ return quoteIdentifier(attributeName);
34
+ }
35
+ const suffix = path.replace(/[^a-zA-Z0-9]+/g, "_");
36
+ return quoteIdentifier(`${attributeName}_${suffix}`);
37
+ }
38
+ export function buildPolicyWhereGroups(policyWhereClauses) {
39
+ const groups = [];
40
+ for (const clauses of policyWhereClauses) {
41
+ if (clauses.length === 0) {
42
+ continue;
43
+ }
44
+ const firstClause = clauses[0];
45
+ if (firstClause === undefined) {
46
+ continue;
47
+ }
48
+ groups.push(clauses.length === 1 ? firstClause : `(${clauses.join(" AND ")})`);
49
+ }
50
+ return groups;
51
+ }
52
+ export function formatWhereClause(policyWhereClauses) {
53
+ const groups = buildPolicyWhereGroups(policyWhereClauses);
54
+ if (groups.length === 0) {
55
+ return "";
56
+ }
57
+ if (groups.length === 1) {
58
+ return `\nWHERE\n ${groups[0]}`;
59
+ }
60
+ return `\nWHERE\n ${groups.join(" OR\n ")}`;
61
+ }
62
+ function quoteIdentifier(identifier) {
63
+ const safe = identifier.replace(/"/g, "");
64
+ return `"${safe}"`;
65
+ }
package/build/index.d.ts CHANGED
@@ -5,6 +5,7 @@ export type { App } from "./apps";
5
5
  export * from "./attributes";
6
6
  export * from "./authentication";
7
7
  export * from "./base-api";
8
+ export * from "./collaboration-policy";
8
9
  export * from "./company-info";
9
10
  export * from "./connections";
10
11
  export * from "./contracts";
package/build/index.js CHANGED
@@ -5,6 +5,7 @@ export { resources } from "./access-tokens/types";
5
5
  export * from "./attributes";
6
6
  export * from "./authentication";
7
7
  export * from "./base-api";
8
+ export * from "./collaboration-policy";
8
9
  export * from "./company-info";
9
10
  export * from "./connections";
10
11
  export * from "./contracts";
@@ -58,6 +58,13 @@ export interface MaterializedViewInput {
58
58
  budget: NqlBudget;
59
59
  dataset_id: number;
60
60
  stats_enabled: boolean;
61
+ chunk_metadata?: {
62
+ batch_id: string;
63
+ chunk_sequence: {
64
+ number: number;
65
+ of: number;
66
+ };
67
+ };
61
68
  }
62
69
  export interface MaterializedViewOutput {
63
70
  success: {
@@ -196,8 +196,8 @@ function parseColumnRef(n) {
196
196
  return attrRef;
197
197
  }
198
198
  if (n.schema === "company_data" &&
199
- !Number.isNaN(Number.parseInt(n.table))) {
200
- const datasetId = Number.parseInt(n.table);
199
+ !Number.isNaN(Number.parseInt(n.table, 10))) {
200
+ const datasetId = Number.parseInt(n.table, 10);
201
201
  const datasetColumnRef = {
202
202
  type: "dataset_column_ref",
203
203
  as: n.as,
@@ -442,8 +442,9 @@ function parseTable(n) {
442
442
  };
443
443
  return table;
444
444
  }
445
- if (n.schema === "company_data" && !Number.isNaN(Number.parseInt(n.table))) {
446
- const datasetId = Number.parseInt(n.table);
445
+ if (n.schema === "company_data" &&
446
+ !Number.isNaN(Number.parseInt(n.table, 10))) {
447
+ const datasetId = Number.parseInt(n.table, 10);
447
448
  const table = {
448
449
  type: "dataset",
449
450
  as: n.as,
@@ -331,7 +331,7 @@ function compileLit(value, valueType, as, aliasParens) {
331
331
  break;
332
332
  }
333
333
  case "long":
334
- valueNql = `${Number.parseInt(value)}`;
334
+ valueNql = `${Number.parseInt(value, 10)}`;
335
335
  break;
336
336
  case "double":
337
337
  valueNql = `${Number.parseFloat(value)}`;
@@ -293,6 +293,18 @@ export declare const NqlObj: z.ZodObject<{
293
293
  join: z.ZodUndefined;
294
294
  }, z.core.$strip>;
295
295
  export type Nql = z.infer<typeof NqlObj>;
296
+ export interface RelatedJob {
297
+ id: string;
298
+ number: number;
299
+ idempotency_key: string;
300
+ state: string;
301
+ compiled_select: string;
302
+ }
303
+ export interface BatchInfo {
304
+ batch_id: string;
305
+ batch_size: number;
306
+ related_jobs: RelatedJob[];
307
+ }
296
308
  export interface NqlResult {
297
309
  id: string;
298
310
  company_id: number;
@@ -318,6 +330,7 @@ export interface NqlResult {
318
330
  };
319
331
  state: string;
320
332
  updated_at: string;
333
+ chunking_context?: BatchInfo;
321
334
  }
322
335
  export type NqlMappingErrors = Record<number, string>;
323
336
  export interface NqlCompileResult {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@narrative.io/data-collaboration-sdk-ts",
3
- "version": "2.64.1",
3
+ "version": "2.66.0",
4
4
  "main": "build/index.js",
5
5
  "repository": "github:narrative-io/data-collaboration-sdk-ts",
6
6
  "source": "src/index.ts",
@@ -14,27 +14,31 @@
14
14
  "preversion": "npm run lint",
15
15
  "version": "npm run && git add -A src",
16
16
  "postversion": "git push && git push --tags",
17
- "test": "jest --coverage"
17
+ "test": "jest --coverage",
18
+ "dev": "tsc -w",
19
+ "check:built": "node scripts/ensureBuild.js",
20
+ "link:global": "npm run check:built && npm link",
21
+ "pack:dist": "npm run check:built && npm pack"
18
22
  },
19
23
  "keywords": [],
20
24
  "author": "",
21
25
  "license": "ISC",
22
26
  "devDependencies": {
23
- "@babel/core": "7.28.0",
24
- "@babel/preset-env": "7.28.0",
27
+ "@babel/core": "7.28.4",
28
+ "@babel/preset-env": "7.28.3",
25
29
  "@babel/preset-typescript": "7.27.1",
26
- "@biomejs/biome": "2.1.4",
27
- "@commitlint/cli": "19.8.1",
28
- "@commitlint/config-conventional": "19.8.1",
30
+ "@biomejs/biome": "2.2.5",
31
+ "@commitlint/cli": "20.1.0",
32
+ "@commitlint/config-conventional": "20.0.0",
29
33
  "@types/jest": "30.0.0",
30
- "babel-jest": "30.0.5",
31
- "jest": "30.0.5",
32
- "lefthook": "1.12.2",
33
- "ts-jest": "29.4.1"
34
+ "babel-jest": "30.2.0",
35
+ "jest": "30.2.0",
36
+ "lefthook": "1.13.6",
37
+ "ts-jest": "29.4.4"
34
38
  },
35
39
  "dependencies": {
36
40
  "mande": "2.0.9",
37
- "zod": "4.0.17",
41
+ "zod": "4.1.11",
38
42
  "bignumber.js": "9.3.1"
39
43
  },
40
44
  "overrides": {