@synnaxlabs/x 0.46.2 → 0.47.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 +17 -17
- 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 +206 -201
- package/dist/{scale-BBWhTUqJ.js → scale-DJCMZbfU.js} +1 -1
- package/dist/scale.js +1 -1
- package/dist/series-Bh0pHoUF.cjs +6 -0
- package/dist/{series-Clbw-fZI.js → series-Cf8rT2IX.js} +7 -7
- 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/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/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 +4 -4
- 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/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/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";
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
import { describe, expect, it, test } from "vitest";
|
|
11
11
|
|
|
12
12
|
import { type numeric } from "@/numeric";
|
|
13
|
-
import
|
|
13
|
+
import { bounds } from "@/spatial/bounds";
|
|
14
14
|
import { testutil } from "@/testutil";
|
|
15
15
|
|
|
16
16
|
describe("Bounds", () => {
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
// License, use of this software will be governed by the Apache License, Version 2.0,
|
|
8
8
|
// included in the file licenses/APL.txt.
|
|
9
9
|
|
|
10
|
-
import {
|
|
10
|
+
import { abs, add, equal as mathEqual, min as mathMin, sub } from "@/math/math";
|
|
11
11
|
import { type numeric } from "@/numeric";
|
|
12
12
|
import { type Bounds, bounds, type CrudeBounds } from "@/spatial/base";
|
|
13
13
|
|
|
@@ -479,7 +479,7 @@ export const buildInsertionPlan = <T extends numeric.Value>(
|
|
|
479
479
|
}
|
|
480
480
|
let deleteInBetween = upper.index - lower.index;
|
|
481
481
|
let insertInto = lower.index;
|
|
482
|
-
let removeBefore =
|
|
482
|
+
let removeBefore = sub(Number(span(_bounds[lower.index])), lower.position);
|
|
483
483
|
// If we're overlapping with the previous bound, we need to slice out one less
|
|
484
484
|
// and insert one further up.
|
|
485
485
|
if (lower.position !== 0) {
|
|
@@ -596,7 +596,7 @@ export const traverse = <T extends numeric.Value = number>(
|
|
|
596
596
|
let remainingDist = dist;
|
|
597
597
|
let currentPosition = start as number | bigint;
|
|
598
598
|
|
|
599
|
-
while (
|
|
599
|
+
while (mathEqual(remainingDist, 0) === false) {
|
|
600
600
|
// Find the bound we're currently in or adjacent to
|
|
601
601
|
const index = _bounds.findIndex((b) => {
|
|
602
602
|
if (dir > 0) return currentPosition >= b.lower && currentPosition < b.upper;
|
|
@@ -606,19 +606,16 @@ export const traverse = <T extends numeric.Value = number>(
|
|
|
606
606
|
if (index !== -1) {
|
|
607
607
|
const b = _bounds[index];
|
|
608
608
|
let distanceInBound: T;
|
|
609
|
-
if (dir > 0) distanceInBound =
|
|
610
|
-
else distanceInBound =
|
|
609
|
+
if (dir > 0) distanceInBound = sub(b.upper, currentPosition);
|
|
610
|
+
else distanceInBound = sub(currentPosition, b.lower) as T;
|
|
611
611
|
|
|
612
612
|
if (distanceInBound > (0 as T)) {
|
|
613
|
-
const moveDist =
|
|
614
|
-
currentPosition =
|
|
615
|
-
|
|
616
|
-
dir > 0 ? moveDist : -moveDist,
|
|
617
|
-
) as T;
|
|
618
|
-
remainingDist = math.sub<T>(remainingDist, dir > 0 ? moveDist : -moveDist);
|
|
613
|
+
const moveDist = mathMin(abs(remainingDist), distanceInBound);
|
|
614
|
+
currentPosition = add(currentPosition, dir > 0 ? moveDist : -moveDist) as T;
|
|
615
|
+
remainingDist = sub<T>(remainingDist, dir > 0 ? moveDist : -moveDist);
|
|
619
616
|
|
|
620
617
|
// If we've exhausted the distance, return the current position
|
|
621
|
-
if (
|
|
618
|
+
if (mathEqual(remainingDist, 0)) return currentPosition as T;
|
|
622
619
|
continue;
|
|
623
620
|
}
|
|
624
621
|
}
|
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
|
|
10
10
|
import { describe, expect, it, test } from "vitest";
|
|
11
11
|
|
|
12
|
-
import
|
|
13
|
-
import
|
|
14
|
-
import type
|
|
12
|
+
import { box } from "@/spatial/box";
|
|
13
|
+
import { location } from "@/spatial/location";
|
|
14
|
+
import { type xy } from "@/spatial/xy";
|
|
15
15
|
|
|
16
16
|
describe("Box", () => {
|
|
17
17
|
describe("construction", () => {
|
package/src/spatial/box/box.ts
CHANGED
|
@@ -9,11 +9,11 @@
|
|
|
9
9
|
|
|
10
10
|
import { z } from "zod";
|
|
11
11
|
|
|
12
|
-
import type
|
|
13
|
-
import type
|
|
14
|
-
import
|
|
15
|
-
import
|
|
16
|
-
import
|
|
12
|
+
import { type bounds } from "@/spatial/bounds";
|
|
13
|
+
import { type dimensions } from "@/spatial/dimensions";
|
|
14
|
+
import { direction } from "@/spatial/direction";
|
|
15
|
+
import { location } from "@/spatial/location";
|
|
16
|
+
import { xy } from "@/spatial/xy";
|
|
17
17
|
|
|
18
18
|
const cssPos = z.union([z.number(), z.string()]);
|
|
19
19
|
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
import { describe, expect, it, test } from "vitest";
|
|
11
11
|
|
|
12
|
-
import
|
|
12
|
+
import { box } from "@/spatial/box";
|
|
13
13
|
import { Scale, XY } from "@/spatial/scale/scale";
|
|
14
14
|
|
|
15
15
|
type ScaleSpec = [name: string, scale: Scale<number>, i: number, o: number];
|
|
@@ -11,12 +11,12 @@ import { z } from "zod";
|
|
|
11
11
|
|
|
12
12
|
import { clamp } from "@/clamp/clamp";
|
|
13
13
|
import { type numeric } from "@/numeric";
|
|
14
|
-
import
|
|
14
|
+
import { bounds } from "@/spatial/bounds";
|
|
15
|
+
import { box } from "@/spatial/box";
|
|
15
16
|
import { type Box, isBox } from "@/spatial/box/box";
|
|
16
|
-
import
|
|
17
|
-
import
|
|
18
|
-
import
|
|
19
|
-
import * as xy from "@/spatial/xy/xy";
|
|
17
|
+
import { type dimensions } from "@/spatial/dimensions";
|
|
18
|
+
import { location } from "@/spatial/location";
|
|
19
|
+
import { xy } from "@/spatial/xy";
|
|
20
20
|
|
|
21
21
|
export const crudeXYTransform = z.object({ offset: xy.crudeZ, scale: xy.crudeZ });
|
|
22
22
|
export type XYTransformT = z.infer<typeof crudeXYTransform>;
|
|
@@ -449,7 +449,7 @@ export class XY {
|
|
|
449
449
|
return new XY().magnify(xy);
|
|
450
450
|
}
|
|
451
451
|
|
|
452
|
-
static scale(box:
|
|
452
|
+
static scale(box: dimensions.Dimensions | Box): XY {
|
|
453
453
|
return new XY().scale(box);
|
|
454
454
|
}
|
|
455
455
|
|
|
@@ -484,7 +484,7 @@ export class XY {
|
|
|
484
484
|
return next;
|
|
485
485
|
}
|
|
486
486
|
|
|
487
|
-
scale(b: Box |
|
|
487
|
+
scale(b: Box | dimensions.Dimensions): XY {
|
|
488
488
|
const next = this.copy();
|
|
489
489
|
if (isBox(b)) {
|
|
490
490
|
const prevRoot = this.currRoot;
|
package/tsconfig.json
CHANGED