@synnaxlabs/x 0.46.2 → 0.48.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/.turbo/turbo-build.log +18 -18
- package/dist/{bounds-DeUXrllt.js → bounds-4BWKPqaP.js} +1 -4
- package/dist/bounds.js +1 -1
- package/dist/{index-C452Pas0.js → compare-Bnx9CdjS.js} +37 -47
- package/dist/compare-GPoFaKRW.cjs +1 -0
- package/dist/compare.cjs +1 -1
- package/dist/compare.js +34 -2
- package/dist/eslint.config.d.ts +3 -0
- package/dist/eslint.config.d.ts.map +1 -0
- package/dist/{index-D4NCYiQB.js → index-Bv029kh3.js} +2 -2
- package/dist/{index-udOjA9d-.cjs → index-CqisIWWC.cjs} +1 -1
- package/dist/index.cjs +3 -3
- package/dist/index.js +489 -465
- package/dist/{scale-BBWhTUqJ.js → scale-DJCMZbfU.js} +1 -1
- package/dist/scale.js +1 -1
- package/dist/series-B7l2au4y.cjs +6 -0
- package/dist/{series-Clbw-fZI.js → series-TpAaBlEg.js} +172 -145
- package/dist/spatial.js +2 -2
- package/dist/src/array/nullable.d.ts.map +1 -1
- package/dist/src/compare/binary.d.ts +25 -0
- package/dist/src/compare/binary.d.ts.map +1 -0
- package/dist/src/compare/binary.spec.d.ts +2 -0
- package/dist/src/compare/binary.spec.d.ts.map +1 -0
- package/dist/src/compare/external.d.ts +3 -0
- package/dist/src/compare/external.d.ts.map +1 -0
- package/dist/src/compare/index.d.ts +1 -1
- package/dist/src/compare/index.d.ts.map +1 -1
- package/dist/src/csv/csv.d.ts +11 -0
- package/dist/src/csv/csv.d.ts.map +1 -0
- package/dist/src/csv/csv.spec.d.ts +2 -0
- package/dist/src/csv/csv.spec.d.ts.map +1 -0
- package/dist/src/csv/index.d.ts +2 -0
- package/dist/src/csv/index.d.ts.map +1 -0
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/migrate/migrate.d.ts +1 -1
- package/dist/src/migrate/migrate.d.ts.map +1 -1
- package/dist/src/spatial/bounds/bounds.d.ts.map +1 -1
- package/dist/src/spatial/box/box.d.ts +5 -5
- package/dist/src/spatial/box/box.d.ts.map +1 -1
- package/dist/src/spatial/scale/scale.d.ts +6 -6
- package/dist/src/spatial/scale/scale.d.ts.map +1 -1
- package/dist/src/telem/telem.d.ts +14 -0
- package/dist/src/telem/telem.d.ts.map +1 -1
- package/dist/telem.cjs +1 -1
- package/dist/telem.js +1 -1
- package/dist/unique.cjs +1 -1
- package/dist/unique.js +1 -1
- package/package.json +9 -9
- package/src/array/nullable.ts +9 -0
- package/src/compare/binary.spec.ts +308 -0
- package/src/compare/binary.ts +50 -0
- package/src/compare/external.ts +11 -0
- package/src/compare/index.ts +1 -1
- package/src/csv/csv.spec.ts +28 -0
- package/src/csv/csv.ts +26 -0
- package/src/csv/index.ts +10 -0
- package/src/index.ts +1 -0
- package/src/jsonrpc/jsonrpc.spec.ts +9 -0
- package/src/math/round.spec.ts +2 -1
- package/src/migrate/migrate.spec.ts +238 -0
- package/src/migrate/migrate.ts +62 -4
- package/src/spatial/bounds/bounds.spec.ts +1 -1
- package/src/spatial/bounds/bounds.ts +9 -12
- package/src/spatial/box/box.spec.ts +3 -3
- package/src/spatial/box/box.ts +5 -5
- package/src/spatial/dimensions/dimensions.spec.ts +1 -1
- package/src/spatial/direction/direction.spec.ts +1 -1
- package/src/spatial/location/location.spec.ts +1 -1
- package/src/spatial/scale/scale.spec.ts +1 -1
- package/src/spatial/scale/scale.ts +7 -7
- package/src/telem/telem.spec.ts +87 -0
- package/src/telem/telem.ts +48 -0
- package/tsconfig.json +1 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/index-xaxa1hoa.cjs +0 -1
- package/dist/series-B2zqvP8A.cjs +0 -6
- /package/{eslint.config.js → eslint.config.ts} +0 -0
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
// Copyright 2025 Synnax Labs, Inc.
|
|
2
|
+
//
|
|
3
|
+
// Use of this software is governed by the Business Source License included in the file
|
|
4
|
+
// licenses/BSL.txt.
|
|
5
|
+
//
|
|
6
|
+
// As of the Change Date specified in that file, in accordance with the Business Source
|
|
7
|
+
// License, use of this software will be governed by the Apache License, Version 2.0,
|
|
8
|
+
// included in the file licenses/APL.txt.
|
|
9
|
+
|
|
10
|
+
import { describe, expect, it } from "vitest";
|
|
11
|
+
|
|
12
|
+
import { insert, search } from "@/compare/binary";
|
|
13
|
+
|
|
14
|
+
describe("compare", () => {
|
|
15
|
+
describe("search", () => {
|
|
16
|
+
describe("number arrays", () => {
|
|
17
|
+
interface Spec {
|
|
18
|
+
name: string;
|
|
19
|
+
array: number[];
|
|
20
|
+
value: number;
|
|
21
|
+
expected: number;
|
|
22
|
+
}
|
|
23
|
+
const SPECS: Spec[] = [
|
|
24
|
+
{
|
|
25
|
+
name: "finds element at start",
|
|
26
|
+
array: [1, 2, 3, 4, 5],
|
|
27
|
+
value: 1,
|
|
28
|
+
expected: 0,
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
name: "finds element in middle",
|
|
32
|
+
array: [1, 2, 3, 4, 5],
|
|
33
|
+
value: 3,
|
|
34
|
+
expected: 2,
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
name: "finds element at end",
|
|
38
|
+
array: [1, 2, 3, 4, 5],
|
|
39
|
+
value: 5,
|
|
40
|
+
expected: 4,
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: "returns insertion point for missing element (start)",
|
|
44
|
+
array: [2, 4, 6, 8],
|
|
45
|
+
value: 1,
|
|
46
|
+
expected: 0,
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
name: "returns insertion point for missing element (middle)",
|
|
50
|
+
array: [1, 3, 5, 7],
|
|
51
|
+
value: 4,
|
|
52
|
+
expected: 2,
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
name: "returns insertion point for missing element (end)",
|
|
56
|
+
array: [1, 2, 3, 4],
|
|
57
|
+
value: 5,
|
|
58
|
+
expected: 4,
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
name: "handles empty array",
|
|
62
|
+
array: [],
|
|
63
|
+
value: 1,
|
|
64
|
+
expected: 0,
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
name: "handles single element array (found)",
|
|
68
|
+
array: [5],
|
|
69
|
+
value: 5,
|
|
70
|
+
expected: 0,
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
name: "handles single element array (not found, before)",
|
|
74
|
+
array: [5],
|
|
75
|
+
value: 3,
|
|
76
|
+
expected: 0,
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
name: "handles single element array (not found, after)",
|
|
80
|
+
array: [5],
|
|
81
|
+
value: 7,
|
|
82
|
+
expected: 1,
|
|
83
|
+
},
|
|
84
|
+
];
|
|
85
|
+
SPECS.forEach((spec) => {
|
|
86
|
+
it(spec.name, () => {
|
|
87
|
+
expect(search(spec.array, spec.value)).toBe(spec.expected);
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
describe("string arrays", () => {
|
|
93
|
+
interface Spec {
|
|
94
|
+
name: string;
|
|
95
|
+
array: string[];
|
|
96
|
+
value: string;
|
|
97
|
+
expected: number;
|
|
98
|
+
}
|
|
99
|
+
const SPECS: Spec[] = [
|
|
100
|
+
{
|
|
101
|
+
name: "finds string element",
|
|
102
|
+
array: ["apple", "banana", "cherry", "date"],
|
|
103
|
+
value: "cherry",
|
|
104
|
+
expected: 2,
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
name: "returns insertion point for missing string",
|
|
108
|
+
array: ["apple", "banana", "date"],
|
|
109
|
+
value: "cherry",
|
|
110
|
+
expected: 2,
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
name: "handles not found string",
|
|
114
|
+
array: ["apple", "banana", "date"],
|
|
115
|
+
value: "cherry",
|
|
116
|
+
expected: 2,
|
|
117
|
+
},
|
|
118
|
+
];
|
|
119
|
+
SPECS.forEach((spec) => {
|
|
120
|
+
it(spec.name, () => {
|
|
121
|
+
expect(search(spec.array, spec.value)).toBe(spec.expected);
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
describe("custom comparator", () => {
|
|
127
|
+
interface Item {
|
|
128
|
+
id: number;
|
|
129
|
+
name: string;
|
|
130
|
+
}
|
|
131
|
+
interface Spec {
|
|
132
|
+
name: string;
|
|
133
|
+
array: Item[];
|
|
134
|
+
value: Item;
|
|
135
|
+
expected: number;
|
|
136
|
+
}
|
|
137
|
+
const SPECS: Spec[] = [
|
|
138
|
+
{
|
|
139
|
+
name: "finds element with custom comparator",
|
|
140
|
+
array: [
|
|
141
|
+
{ id: 1, name: "a" },
|
|
142
|
+
{ id: 2, name: "b" },
|
|
143
|
+
{ id: 3, name: "c" },
|
|
144
|
+
],
|
|
145
|
+
value: { id: 2, name: "b" },
|
|
146
|
+
expected: 1,
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
name: "returns insertion point with custom comparator",
|
|
150
|
+
array: [
|
|
151
|
+
{ id: 1, name: "a" },
|
|
152
|
+
{ id: 3, name: "c" },
|
|
153
|
+
{ id: 5, name: "e" },
|
|
154
|
+
],
|
|
155
|
+
value: { id: 4, name: "d" },
|
|
156
|
+
expected: 2,
|
|
157
|
+
},
|
|
158
|
+
];
|
|
159
|
+
SPECS.forEach((spec) => {
|
|
160
|
+
it(spec.name, () => {
|
|
161
|
+
const comparator = (a: Item, b: Item) => a.id - b.id;
|
|
162
|
+
expect(search(spec.array, spec.value, comparator)).toBe(spec.expected);
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
describe("insert", () => {
|
|
169
|
+
describe("number arrays", () => {
|
|
170
|
+
interface Spec {
|
|
171
|
+
name: string;
|
|
172
|
+
array: number[];
|
|
173
|
+
value: number;
|
|
174
|
+
expected: number[];
|
|
175
|
+
}
|
|
176
|
+
const SPECS: Spec[] = [
|
|
177
|
+
{
|
|
178
|
+
name: "inserts into empty array",
|
|
179
|
+
array: [],
|
|
180
|
+
value: 5,
|
|
181
|
+
expected: [5],
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
name: "inserts at beginning",
|
|
185
|
+
array: [2, 3, 4],
|
|
186
|
+
value: 1,
|
|
187
|
+
expected: [1, 2, 3, 4],
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
name: "inserts in middle",
|
|
191
|
+
array: [1, 2, 4, 5],
|
|
192
|
+
value: 3,
|
|
193
|
+
expected: [1, 2, 3, 4, 5],
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
name: "inserts at end",
|
|
197
|
+
array: [1, 2, 3],
|
|
198
|
+
value: 4,
|
|
199
|
+
expected: [1, 2, 3, 4],
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
name: "inserts duplicate value",
|
|
203
|
+
array: [1, 2, 3, 4],
|
|
204
|
+
value: 2,
|
|
205
|
+
expected: [1, 2, 2, 3, 4],
|
|
206
|
+
},
|
|
207
|
+
];
|
|
208
|
+
SPECS.forEach((spec) => {
|
|
209
|
+
it(spec.name, () => {
|
|
210
|
+
const arr = [...spec.array];
|
|
211
|
+
insert(arr, spec.value);
|
|
212
|
+
expect(arr).toEqual(spec.expected);
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
describe("string arrays", () => {
|
|
218
|
+
interface Spec {
|
|
219
|
+
name: string;
|
|
220
|
+
array: string[];
|
|
221
|
+
value: string;
|
|
222
|
+
expected: string[];
|
|
223
|
+
}
|
|
224
|
+
const SPECS: Spec[] = [
|
|
225
|
+
{
|
|
226
|
+
name: "inserts string in correct position",
|
|
227
|
+
array: ["apple", "banana", "date"],
|
|
228
|
+
value: "cherry",
|
|
229
|
+
expected: ["apple", "banana", "cherry", "date"],
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
name: "inserts at beginning of string array",
|
|
233
|
+
array: ["banana", "cherry"],
|
|
234
|
+
value: "apple",
|
|
235
|
+
expected: ["apple", "banana", "cherry"],
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
name: "handles not found string",
|
|
239
|
+
array: ["apple", "banana", "date"],
|
|
240
|
+
value: "cherry",
|
|
241
|
+
expected: ["apple", "banana", "cherry", "date"],
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
name: "handles empty array",
|
|
245
|
+
array: [],
|
|
246
|
+
value: "cherry",
|
|
247
|
+
expected: ["cherry"],
|
|
248
|
+
},
|
|
249
|
+
];
|
|
250
|
+
SPECS.forEach((spec) => {
|
|
251
|
+
it(spec.name, () => {
|
|
252
|
+
const arr = [...spec.array];
|
|
253
|
+
insert(arr, spec.value);
|
|
254
|
+
expect(arr).toEqual(spec.expected);
|
|
255
|
+
});
|
|
256
|
+
});
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
describe("custom comparator", () => {
|
|
260
|
+
interface Item {
|
|
261
|
+
id: number;
|
|
262
|
+
name: string;
|
|
263
|
+
}
|
|
264
|
+
interface Spec {
|
|
265
|
+
name: string;
|
|
266
|
+
array: Item[];
|
|
267
|
+
value: Item;
|
|
268
|
+
expected: Item[];
|
|
269
|
+
}
|
|
270
|
+
const SPECS: Spec[] = [
|
|
271
|
+
{
|
|
272
|
+
name: "inserts with custom comparator",
|
|
273
|
+
array: [
|
|
274
|
+
{ id: 1, name: "a" },
|
|
275
|
+
{ id: 3, name: "c" },
|
|
276
|
+
],
|
|
277
|
+
value: { id: 2, name: "b" },
|
|
278
|
+
expected: [
|
|
279
|
+
{ id: 1, name: "a" },
|
|
280
|
+
{ id: 2, name: "b" },
|
|
281
|
+
{ id: 3, name: "c" },
|
|
282
|
+
],
|
|
283
|
+
},
|
|
284
|
+
{
|
|
285
|
+
name: "maintains sort order with custom comparator",
|
|
286
|
+
array: [
|
|
287
|
+
{ id: 5, name: "e" },
|
|
288
|
+
{ id: 10, name: "j" },
|
|
289
|
+
],
|
|
290
|
+
value: { id: 7, name: "g" },
|
|
291
|
+
expected: [
|
|
292
|
+
{ id: 5, name: "e" },
|
|
293
|
+
{ id: 7, name: "g" },
|
|
294
|
+
{ id: 10, name: "j" },
|
|
295
|
+
],
|
|
296
|
+
},
|
|
297
|
+
];
|
|
298
|
+
SPECS.forEach((spec) => {
|
|
299
|
+
it(spec.name, () => {
|
|
300
|
+
const arr = [...spec.array];
|
|
301
|
+
const comparator = (a: Item, b: Item) => a.id - b.id;
|
|
302
|
+
insert(arr, spec.value, comparator);
|
|
303
|
+
expect(arr).toEqual(spec.expected);
|
|
304
|
+
});
|
|
305
|
+
});
|
|
306
|
+
});
|
|
307
|
+
});
|
|
308
|
+
});
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// Copyright 2025 Synnax Labs, Inc.
|
|
2
|
+
//
|
|
3
|
+
// Use of this software is governed by the Business Source License included in the file
|
|
4
|
+
// licenses/BSL.txt.
|
|
5
|
+
//
|
|
6
|
+
// As of the Change Date specified in that file, in accordance with the Business Source
|
|
7
|
+
// License, use of this software will be governed by the Apache License, Version 2.0,
|
|
8
|
+
// included in the file licenses/APL.txt.
|
|
9
|
+
|
|
10
|
+
import { type Comparator, newF } from "@/compare/compare";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Performs a binary search on the given array. If the array is not sorted, or the
|
|
14
|
+
* comparator does not correctly order the values, the behavior of this function is
|
|
15
|
+
* undefined. If the value is not found, the index of the first element greater than the
|
|
16
|
+
* value is returned. If the value is greater than all elements in the array, the length
|
|
17
|
+
* of the array is returned.
|
|
18
|
+
*
|
|
19
|
+
* @param array - The array to search.
|
|
20
|
+
* @param value - The value to search for.
|
|
21
|
+
* @param comparator - The comparator to use.
|
|
22
|
+
* @returns The index of the value in the array.
|
|
23
|
+
*/
|
|
24
|
+
export const search = <T>(array: T[], value: T, comparator?: Comparator<T>): number => {
|
|
25
|
+
let left = 0;
|
|
26
|
+
let right = array.length;
|
|
27
|
+
const cf = comparator ?? newF(value);
|
|
28
|
+
while (left < right) {
|
|
29
|
+
const mid = Math.floor((left + right) / 2);
|
|
30
|
+
const cmp = cf(array[mid], value);
|
|
31
|
+
if (cmp === 0) return mid;
|
|
32
|
+
if (cmp < 0) left = mid + 1;
|
|
33
|
+
else right = mid;
|
|
34
|
+
}
|
|
35
|
+
return left;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Inserts a value into the given sorted array and maintains the sort order of the
|
|
40
|
+
* array. If the array is not sorted, or the comparator does not correctly order the
|
|
41
|
+
* values, the behavior of this function is undefined.
|
|
42
|
+
*
|
|
43
|
+
* @param array - The array to insert the value into.
|
|
44
|
+
* @param value - The value to insert.
|
|
45
|
+
* @param comparator - The comparator to use.
|
|
46
|
+
*/
|
|
47
|
+
export const insert = <T>(array: T[], value: T, comparator?: Comparator<T>): void => {
|
|
48
|
+
const idx = search(array, value, comparator);
|
|
49
|
+
array.splice(idx, 0, value);
|
|
50
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// Copyright 2025 Synnax Labs, Inc.
|
|
2
|
+
//
|
|
3
|
+
// Use of this software is governed by the Business Source License included in the file
|
|
4
|
+
// licenses/BSL.txt.
|
|
5
|
+
//
|
|
6
|
+
// As of the Change Date specified in that file, in accordance with the Business Source
|
|
7
|
+
// License, use of this software will be governed by the Apache License, Version 2.0,
|
|
8
|
+
// included in the file licenses/APL.txt.
|
|
9
|
+
|
|
10
|
+
export * from "@/compare/binary";
|
|
11
|
+
export * from "@/compare/compare";
|
package/src/compare/index.ts
CHANGED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// Copyright 2025 Synnax Labs, Inc.
|
|
2
|
+
//
|
|
3
|
+
// Use of this software is governed by the Business Source License included in the file
|
|
4
|
+
// licenses/BSL.txt.
|
|
5
|
+
//
|
|
6
|
+
// As of the Change Date specified in that file, in accordance with the Business Source
|
|
7
|
+
// License, use of this software will be governed by the Apache License, Version 2.0,
|
|
8
|
+
// included in the file licenses/APL.txt.
|
|
9
|
+
|
|
10
|
+
import { describe, expect, it } from "vitest";
|
|
11
|
+
|
|
12
|
+
import { csv } from "@/csv";
|
|
13
|
+
|
|
14
|
+
describe("csv", () => {
|
|
15
|
+
describe("maybeEscapeField", () => {
|
|
16
|
+
it("shouldn't escape fields without special characters", () => {
|
|
17
|
+
expect(csv.maybeEscapeField("hello")).toBe("hello");
|
|
18
|
+
expect(csv.maybeEscapeField("123")).toBe("123");
|
|
19
|
+
expect(csv.maybeEscapeField("Call me Ishmael")).toBe("Call me Ishmael");
|
|
20
|
+
});
|
|
21
|
+
it("should escape fields with special characters", () => {
|
|
22
|
+
expect(csv.maybeEscapeField("hello,world")).toBe('"hello,world"');
|
|
23
|
+
expect(csv.maybeEscapeField("hello\nworld")).toBe('"hello\nworld"');
|
|
24
|
+
expect(csv.maybeEscapeField("hello\r\nworld")).toBe('"hello\r\nworld"');
|
|
25
|
+
expect(csv.maybeEscapeField('"hello"')).toBe('"""hello"""');
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
});
|
package/src/csv/csv.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// Copyright 2025 Synnax Labs, Inc.
|
|
2
|
+
//
|
|
3
|
+
// Use of this software is governed by the Business Source License included in the file
|
|
4
|
+
// licenses/BSL.txt.
|
|
5
|
+
//
|
|
6
|
+
// As of the Change Date specified in that file, in accordance with the Business Source
|
|
7
|
+
// License, use of this software will be governed by the Apache License, Version 2.0,
|
|
8
|
+
// included in the file licenses/APL.txt.
|
|
9
|
+
|
|
10
|
+
const regex = /[",\n]/;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Escapes a CSV field by wrapping it in double quotes if it contains a comma, double
|
|
14
|
+
* quote, or newline. Also escapes any internal double quotes by doubling them. For
|
|
15
|
+
* example, the field foo"bar,baz becomes "foo""bar,baz"
|
|
16
|
+
*
|
|
17
|
+
* @param field - The string field to potentially escape for CSV output.
|
|
18
|
+
* @returns The escaped CSV-safe field.
|
|
19
|
+
*/
|
|
20
|
+
export const maybeEscapeField = (field: string): string => {
|
|
21
|
+
if (!regex.test(field)) return field;
|
|
22
|
+
const escaped = field.replace(/"/g, '""');
|
|
23
|
+
return `"${escaped}"`;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export type RecordDelimiter = "\r\n" | "\n";
|
package/src/csv/index.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// Copyright 2025 Synnax Labs, Inc.
|
|
2
|
+
//
|
|
3
|
+
// Use of this software is governed by the Business Source License included in the file
|
|
4
|
+
// licenses/BSL.txt.
|
|
5
|
+
//
|
|
6
|
+
// As of the Change Date specified in that file, in accordance with the Business Source
|
|
7
|
+
// License, use of this software will be governed by the Apache License, Version 2.0,
|
|
8
|
+
// included in the file licenses/APL.txt.
|
|
9
|
+
|
|
10
|
+
export * as csv from "@/csv/csv";
|
package/src/index.ts
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
// Copyright 2025 Synnax Labs, Inc.
|
|
2
|
+
//
|
|
3
|
+
// Use of this software is governed by the Business Source License included in the file
|
|
4
|
+
// licenses/BSL.txt.
|
|
5
|
+
//
|
|
6
|
+
// As of the Change Date specified in that file, in accordance with the Business Source
|
|
7
|
+
// License, use of this software will be governed by the Apache License, Version 2.0,
|
|
8
|
+
// included in the file licenses/APL.txt.
|
|
9
|
+
|
|
1
10
|
import { describe, expect, it } from "vitest";
|
|
2
11
|
|
|
3
12
|
import { jsonRPC } from "@/jsonrpc";
|
package/src/math/round.spec.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/* eslint-disable no-loss-of-precision */
|
|
2
1
|
// Copyright 2025 Synnax Labs, Inc.
|
|
3
2
|
//
|
|
4
3
|
// Use of this software is governed by the Business Source License included in the file
|
|
@@ -8,6 +7,8 @@
|
|
|
8
7
|
// License, use of this software will be governed by the Apache License, Version 2.0,
|
|
9
8
|
// included in the file licenses/APL.txt.
|
|
10
9
|
|
|
10
|
+
/* eslint-disable no-loss-of-precision */
|
|
11
|
+
|
|
11
12
|
import { describe, expect, it } from "vitest";
|
|
12
13
|
|
|
13
14
|
import { math } from "@/math";
|