@synnaxlabs/x 0.47.0 → 0.49.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 +7 -105
- package/dist/src/deep/join.d.ts.map +1 -0
- package/dist/src/deep/path.d.ts +1 -1
- package/dist/src/deep/path.d.ts.map +1 -1
- package/dist/src/destructor/destructor.d.ts +7 -0
- package/dist/src/destructor/destructor.d.ts.map +1 -0
- package/dist/src/destructor/index.d.ts +2 -0
- package/dist/src/destructor/index.d.ts.map +1 -0
- package/dist/src/index.d.ts +5 -10
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/math/constants.d.ts +1 -0
- package/dist/src/math/constants.d.ts.map +1 -1
- package/dist/src/migrate/migrate.d.ts +4 -4
- package/dist/src/migrate/migrate.d.ts.map +1 -1
- package/dist/src/narrow/index.d.ts +2 -0
- package/dist/src/narrow/index.d.ts.map +1 -0
- package/dist/src/narrow/narrow.d.ts +4 -0
- package/dist/src/narrow/narrow.d.ts.map +1 -0
- package/dist/src/narrow/narrow.spec.d.ts +2 -0
- package/dist/src/narrow/narrow.spec.d.ts.map +1 -0
- package/dist/src/numeric/numeric.d.ts +0 -1
- package/dist/src/numeric/numeric.d.ts.map +1 -1
- package/dist/src/observe/observe.d.ts +4 -4
- package/dist/src/observe/observe.d.ts.map +1 -1
- package/dist/src/optional/index.d.ts +2 -0
- package/dist/src/optional/index.d.ts.map +1 -0
- package/dist/src/optional/optional.d.ts.map +1 -0
- package/dist/src/scheduler/index.d.ts +2 -0
- package/dist/src/scheduler/index.d.ts.map +1 -0
- package/dist/src/{flush.d.ts → scheduler/scheduler.d.ts} +1 -1
- package/dist/src/scheduler/scheduler.d.ts.map +1 -0
- package/dist/src/scheduler/scheduler.spec.d.ts +2 -0
- package/dist/src/scheduler/scheduler.spec.d.ts.map +1 -0
- package/dist/src/shallow/copy.d.ts +2 -0
- package/dist/src/shallow/copy.d.ts.map +1 -0
- package/dist/src/shallow/copy.spec.d.ts +2 -0
- package/dist/src/shallow/copy.spec.d.ts.map +1 -0
- package/dist/src/shallow/index.d.ts +2 -0
- package/dist/src/shallow/index.d.ts.map +1 -0
- package/dist/src/spatial/base.d.ts +5 -38
- package/dist/src/spatial/base.d.ts.map +1 -1
- package/dist/src/spatial/direction/direction.d.ts +2 -1
- package/dist/src/spatial/direction/direction.d.ts.map +1 -1
- package/dist/src/spatial/external.d.ts +2 -1
- package/dist/src/spatial/external.d.ts.map +1 -1
- package/dist/src/spatial/location/location.d.ts +2 -2
- package/dist/src/spatial/location/location.d.ts.map +1 -1
- package/dist/src/spatial/sticky/index.d.ts +2 -0
- package/dist/src/spatial/sticky/index.d.ts.map +1 -0
- package/dist/src/spatial/sticky/sticky.d.ts +74 -0
- package/dist/src/spatial/sticky/sticky.d.ts.map +1 -0
- package/dist/src/spatial/sticky/sticky.spec.d.ts +2 -0
- package/dist/src/spatial/sticky/sticky.spec.d.ts.map +1 -0
- package/dist/src/spatial/xy/xy.d.ts +10 -2
- package/dist/src/spatial/xy/xy.d.ts.map +1 -1
- package/dist/src/status/status.d.ts +2 -2
- package/dist/src/status/status.d.ts.map +1 -1
- package/dist/src/telem/series.d.ts +4 -4
- package/dist/src/telem/series.d.ts.map +1 -1
- package/dist/src/telem/telem.d.ts +14 -1
- package/dist/src/telem/telem.d.ts.map +1 -1
- package/dist/src/types/index.d.ts +2 -0
- package/dist/src/types/index.d.ts.map +1 -0
- package/dist/src/zod/external.d.ts +1 -0
- package/dist/src/zod/external.d.ts.map +1 -1
- package/dist/src/zod/schemas.d.ts +3 -0
- package/dist/src/zod/schemas.d.ts.map +1 -0
- package/dist/src/zod/schemas.spec.d.ts +2 -0
- package/dist/src/zod/schemas.spec.d.ts.map +1 -0
- package/dist/x.cjs +12 -0
- package/dist/x.js +5521 -0
- package/package.json +12 -150
- package/src/binary/codec.ts +2 -2
- package/src/deep/merge.ts +3 -3
- package/src/deep/path.ts +1 -1
- package/src/{destructor.ts → destructor/destructor.ts} +1 -1
- package/src/{invert.ts → destructor/index.ts} +1 -1
- package/src/index.ts +5 -10
- package/src/math/constants.ts +1 -0
- package/src/migrate/migrate.spec.ts +238 -0
- package/src/migrate/migrate.ts +67 -7
- package/src/{mock → narrow}/index.ts +1 -1
- package/src/narrow/narrow.spec.ts +70 -0
- package/src/{identity.ts → narrow/narrow.ts} +6 -0
- package/src/numeric/numeric.ts +0 -5
- package/src/observe/observe.ts +4 -4
- package/src/{replace.ts → optional/index.ts} +1 -1
- package/src/scheduler/index.ts +10 -0
- package/src/scheduler/scheduler.spec.ts +82 -0
- package/src/shallow/copy.spec.ts +141 -0
- package/src/{shallowCopy.ts → shallow/copy.ts} +1 -1
- package/src/shallow/index.ts +10 -0
- package/src/spatial/base.ts +6 -15
- package/src/spatial/direction/direction.ts +2 -0
- package/src/spatial/external.ts +2 -1
- package/src/spatial/location/location.spec.ts +16 -0
- package/src/spatial/location/location.ts +7 -7
- package/src/spatial/sticky/index.ts +10 -0
- package/src/spatial/sticky/sticky.spec.ts +584 -0
- package/src/spatial/sticky/sticky.ts +98 -0
- package/src/spatial/xy/xy.spec.ts +55 -0
- package/src/spatial/xy/xy.ts +27 -2
- package/src/status/status.ts +5 -5
- package/src/telem/series.ts +5 -6
- package/src/telem/telem.spec.ts +87 -28
- package/src/telem/telem.ts +49 -9
- package/src/{clamp → types}/index.ts +1 -1
- package/src/zod/external.ts +1 -0
- package/src/zod/schemas.spec.ts +51 -0
- package/src/zod/schemas.ts +14 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/vite.config.ts +1 -36
- package/dist/array.cjs +0 -1
- package/dist/array.js +0 -4
- package/dist/base-DRybODwJ.js +0 -42
- package/dist/base-KIBsp6TI.cjs +0 -1
- package/dist/binary.cjs +0 -1
- package/dist/binary.js +0 -4
- package/dist/bounds-4BWKPqaP.js +0 -183
- package/dist/bounds-C2TKFgVk.cjs +0 -1
- package/dist/bounds.cjs +0 -1
- package/dist/bounds.js +0 -4
- package/dist/box-BXWXSkKu.js +0 -203
- package/dist/box-rH3ggwXk.cjs +0 -1
- package/dist/box.cjs +0 -1
- package/dist/box.js +0 -4
- package/dist/caseconv.cjs +0 -1
- package/dist/caseconv.js +0 -4
- package/dist/change-C-YELKx6.cjs +0 -1
- package/dist/change-DLl6DccR.js +0 -12
- package/dist/change.cjs +0 -1
- package/dist/change.js +0 -4
- package/dist/compare-Bnx9CdjS.js +0 -119
- package/dist/compare-GPoFaKRW.cjs +0 -1
- package/dist/compare.cjs +0 -1
- package/dist/compare.js +0 -36
- package/dist/debounce.cjs +0 -1
- package/dist/debounce.js +0 -17
- package/dist/deep.cjs +0 -1
- package/dist/deep.js +0 -247
- package/dist/destructor.cjs +0 -1
- package/dist/destructor.js +0 -1
- package/dist/dimensions-Cg5Owbwn.cjs +0 -1
- package/dist/dimensions-DC0uLPwn.js +0 -43
- package/dist/dimensions.cjs +0 -1
- package/dist/dimensions.js +0 -4
- package/dist/direction-C_b4tfRN.js +0 -19
- package/dist/direction-DqQB9M37.cjs +0 -1
- package/dist/direction.cjs +0 -1
- package/dist/direction.js +0 -4
- package/dist/external-2YWy569j.js +0 -23
- package/dist/external-B6edOwoQ.cjs +0 -1
- package/dist/external-B80i4ymZ.js +0 -29
- package/dist/external-B9AAGv50.cjs +0 -1
- package/dist/external-BYuXBYJh.js +0 -40
- package/dist/external-BxmTQZ6m.cjs +0 -1
- package/dist/external-DLiGrXn7.cjs +0 -1
- package/dist/external-Du5qzfYv.js +0 -35
- package/dist/get-CtJEJIC_.js +0 -82
- package/dist/get-D2VRwUw4.cjs +0 -1
- package/dist/identity.cjs +0 -1
- package/dist/identity.js +0 -4
- package/dist/index-Bfvg0v-N.cjs +0 -3
- package/dist/index-Bv029kh3.js +0 -19
- package/dist/index-CqisIWWC.cjs +0 -1
- package/dist/index-CyNZHQFw.cjs +0 -1
- package/dist/index-qmkoZBNO.js +0 -57
- package/dist/index-yz34Wc2p.js +0 -92
- package/dist/index.cjs +0 -5
- package/dist/index.js +0 -985
- package/dist/kv.cjs +0 -1
- package/dist/kv.js +0 -4
- package/dist/link.cjs +0 -1
- package/dist/link.js +0 -10
- package/dist/location-0qDBiCqP.cjs +0 -1
- package/dist/location-BIzpxczO.js +0 -95
- package/dist/location.cjs +0 -1
- package/dist/location.js +0 -4
- package/dist/observe.cjs +0 -1
- package/dist/observe.js +0 -48
- package/dist/record-BwjIgrpU.cjs +0 -1
- package/dist/record-tSFQKmdG.js +0 -19
- package/dist/record.cjs +0 -1
- package/dist/record.js +0 -4
- package/dist/runtime.cjs +0 -1
- package/dist/runtime.js +0 -4
- package/dist/scale-BXy1w8R_.cjs +0 -1
- package/dist/scale-DJCMZbfU.js +0 -228
- package/dist/scale.cjs +0 -1
- package/dist/scale.js +0 -4
- package/dist/series-Bh0pHoUF.cjs +0 -6
- package/dist/series-Cf8rT2IX.js +0 -2810
- package/dist/spatial-DnsaOypA.js +0 -11
- package/dist/spatial-DrxzaD5U.cjs +0 -1
- package/dist/spatial.cjs +0 -1
- package/dist/spatial.js +0 -18
- package/dist/src/clamp/index.d.ts +0 -2
- package/dist/src/clamp/index.d.ts.map +0 -1
- package/dist/src/destructor.d.ts +0 -7
- package/dist/src/destructor.d.ts.map +0 -1
- package/dist/src/flush.d.ts.map +0 -1
- package/dist/src/identity.d.ts +0 -3
- package/dist/src/identity.d.ts.map +0 -1
- package/dist/src/invert.d.ts +0 -2
- package/dist/src/invert.d.ts.map +0 -1
- package/dist/src/join.d.ts.map +0 -1
- package/dist/src/mock/index.d.ts +0 -2
- package/dist/src/mock/index.d.ts.map +0 -1
- package/dist/src/optional.d.ts.map +0 -1
- package/dist/src/renderable.d.ts +0 -5
- package/dist/src/renderable.d.ts.map +0 -1
- package/dist/src/replace.d.ts +0 -2
- package/dist/src/replace.d.ts.map +0 -1
- package/dist/src/shallowCopy.d.ts +0 -2
- package/dist/src/shallowCopy.d.ts.map +0 -1
- package/dist/src/telem/generate.d.ts +0 -3
- package/dist/src/telem/generate.d.ts.map +0 -1
- package/dist/src/transform.d.ts +0 -6
- package/dist/src/transform.d.ts.map +0 -1
- package/dist/src/undefined.d.ts +0 -2
- package/dist/src/undefined.d.ts.map +0 -1
- package/dist/telem.cjs +0 -1
- package/dist/telem.js +0 -18
- package/dist/unique.cjs +0 -1
- package/dist/unique.js +0 -4
- package/dist/url.cjs +0 -1
- package/dist/url.js +0 -51
- package/dist/worker.cjs +0 -1
- package/dist/worker.js +0 -43
- package/dist/xy-C-MUIjVs.cjs +0 -1
- package/dist/xy-DnrCAZaw.js +0 -154
- package/dist/xy.cjs +0 -1
- package/dist/xy.js +0 -4
- package/dist/zod.cjs +0 -1
- package/dist/zod.js +0 -4
- package/src/renderable.ts +0 -20
- package/src/telem/generate.ts +0 -17
- package/src/transform.ts +0 -17
- package/src/undefined.ts +0 -14
- /package/dist/src/{join.d.ts → deep/join.d.ts} +0 -0
- /package/dist/src/{optional.d.ts → optional/optional.d.ts} +0 -0
- /package/src/{join.ts → deep/join.ts} +0 -0
- /package/src/{optional.ts → optional/optional.ts} +0 -0
- /package/src/{flush.ts → scheduler/scheduler.ts} +0 -0
|
@@ -268,4 +268,59 @@ describe("XY", () => {
|
|
|
268
268
|
expect(result).toEqual({ x: 7, y: 17 });
|
|
269
269
|
});
|
|
270
270
|
});
|
|
271
|
+
|
|
272
|
+
describe("set", () => {
|
|
273
|
+
it("should set x coordinate to target value", () => {
|
|
274
|
+
expect(xy.set([5, 10], "x", 20)).toEqual({ x: 20, y: 10 });
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
it("should set y coordinate to target value", () => {
|
|
278
|
+
expect(xy.set([5, 10], "y", 20)).toEqual({ x: 5, y: 20 });
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
it("should accept crude directions like locations", () => {
|
|
282
|
+
expect(xy.set([5, 10], "left", 20)).toEqual({ x: 20, y: 10 });
|
|
283
|
+
expect(xy.set([5, 10], "right", 20)).toEqual({ x: 20, y: 10 });
|
|
284
|
+
expect(xy.set([5, 10], "top", 20)).toEqual({ x: 5, y: 20 });
|
|
285
|
+
expect(xy.set([5, 10], "bottom", 20)).toEqual({ x: 5, y: 20 });
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
it("should work with different coordinate input formats", () => {
|
|
289
|
+
expect(xy.set({ width: 5, height: 10 }, "x", 15)).toEqual({ x: 15, y: 10 });
|
|
290
|
+
expect(xy.set({ x: 3, y: 4 }, "y", 8)).toEqual({ x: 3, y: 8 });
|
|
291
|
+
});
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
describe("rotate", () => {
|
|
295
|
+
it("should rotate a point 90 degrees clockwise around the origin", () => {
|
|
296
|
+
const point = { x: 1, y: 0 };
|
|
297
|
+
const center = { x: 0, y: 0 };
|
|
298
|
+
const result = xy.rotate(point, center, "clockwise");
|
|
299
|
+
expect(result.x).toBeCloseTo(0);
|
|
300
|
+
expect(result.y).toBeCloseTo(1);
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
it("should rotate a point 90 degrees counterclockwise around the origin", () => {
|
|
304
|
+
const point = { x: 1, y: 0 };
|
|
305
|
+
const center = { x: 0, y: 0 };
|
|
306
|
+
const result = xy.rotate(point, center, "counterclockwise");
|
|
307
|
+
expect(result.x).toBeCloseTo(0);
|
|
308
|
+
expect(result.y).toBeCloseTo(-1);
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
it("should rotate a point around a non-origin center", () => {
|
|
312
|
+
const point = { x: 2, y: 1 };
|
|
313
|
+
const center = { x: 1, y: 1 };
|
|
314
|
+
const result = xy.rotate(point, center, "clockwise");
|
|
315
|
+
expect(result.x).toBeCloseTo(1);
|
|
316
|
+
expect(result.y).toBeCloseTo(2);
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
it("should return the same point when rotating around itself", () => {
|
|
320
|
+
const point = { x: 5, y: 5 };
|
|
321
|
+
const result = xy.rotate(point, point, "clockwise");
|
|
322
|
+
expect(result.x).toBeCloseTo(5);
|
|
323
|
+
expect(result.y).toBeCloseTo(5);
|
|
324
|
+
});
|
|
325
|
+
});
|
|
271
326
|
});
|
package/src/spatial/xy/xy.ts
CHANGED
|
@@ -10,8 +10,10 @@
|
|
|
10
10
|
import { z } from "zod";
|
|
11
11
|
|
|
12
12
|
import {
|
|
13
|
+
type AngularDirection,
|
|
13
14
|
type ClientXY,
|
|
14
15
|
clientXY,
|
|
16
|
+
type CrudeDirection,
|
|
15
17
|
dimensions,
|
|
16
18
|
type Direction,
|
|
17
19
|
type NumberCouple,
|
|
@@ -20,6 +22,7 @@ import {
|
|
|
20
22
|
type XY,
|
|
21
23
|
xy,
|
|
22
24
|
} from "@/spatial/base";
|
|
25
|
+
import { direction as dir } from "@/spatial/direction";
|
|
23
26
|
import { type location } from "@/spatial/location";
|
|
24
27
|
|
|
25
28
|
export { type ClientXY as Client, clientXY, type XY, xy };
|
|
@@ -139,9 +142,10 @@ export const translate: Translate = (a, b, v, ...cb): XY => {
|
|
|
139
142
|
* @returns the given coordinate the given direction set to the given value.
|
|
140
143
|
* @example set({ x: 1, y: 2 }, "x", 3) // { x: 3, y: 2 }
|
|
141
144
|
*/
|
|
142
|
-
export const set = (c: Crude, direction:
|
|
145
|
+
export const set = (c: Crude, direction: CrudeDirection, value: number): XY => {
|
|
143
146
|
const xy = construct(c);
|
|
144
|
-
|
|
147
|
+
const d = dir.construct(direction);
|
|
148
|
+
if (d === "x") return { x: value, y: xy.y };
|
|
145
149
|
return { x: xy.x, y: value };
|
|
146
150
|
};
|
|
147
151
|
|
|
@@ -328,3 +332,24 @@ export const reciprocal = (a: Crude): XY => {
|
|
|
328
332
|
const xy = construct(a);
|
|
329
333
|
return { x: 1 / xy.x, y: 1 / xy.y };
|
|
330
334
|
};
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Rotates a point 90 degrees around a center point.
|
|
338
|
+
* @param point - The point to rotate.
|
|
339
|
+
* @param center - The center point to rotate around.
|
|
340
|
+
* @param dir - The direction to rotate (clockwise or counterclockwise).
|
|
341
|
+
* @returns The rotated point.
|
|
342
|
+
*/
|
|
343
|
+
export const rotate = (point: Crude, center: Crude, dir: AngularDirection): XY => {
|
|
344
|
+
const p = construct(point);
|
|
345
|
+
const c = construct(center);
|
|
346
|
+
const angle = dir === "clockwise" ? Math.PI / 2 : -Math.PI / 2;
|
|
347
|
+
const relativeX = p.x - c.x;
|
|
348
|
+
const relativeY = p.y - c.y;
|
|
349
|
+
const rotatedX = relativeX * Math.cos(angle) - relativeY * Math.sin(angle);
|
|
350
|
+
const rotatedY = relativeX * Math.sin(angle) + relativeY * Math.cos(angle);
|
|
351
|
+
return {
|
|
352
|
+
x: rotatedX + c.x,
|
|
353
|
+
y: rotatedY + c.y,
|
|
354
|
+
};
|
|
355
|
+
};
|
package/src/status/status.ts
CHANGED
|
@@ -12,7 +12,7 @@ import { z } from "zod";
|
|
|
12
12
|
import { array } from "@/array";
|
|
13
13
|
import { id } from "@/id";
|
|
14
14
|
import { label } from "@/label";
|
|
15
|
-
import { type
|
|
15
|
+
import { type optional } from "@/optional";
|
|
16
16
|
import { TimeStamp } from "@/telem";
|
|
17
17
|
|
|
18
18
|
export const variantZ = z.enum([
|
|
@@ -75,10 +75,10 @@ type Base<V extends Variant> = {
|
|
|
75
75
|
export type Status<DetailsSchema = z.ZodNever, V extends Variant = Variant> = Base<V> &
|
|
76
76
|
([DetailsSchema] extends [z.ZodNever] ? {} : { details: z.output<DetailsSchema> });
|
|
77
77
|
|
|
78
|
-
export type Crude<
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
> &
|
|
78
|
+
export type Crude<
|
|
79
|
+
DetailsSchema = z.ZodNever,
|
|
80
|
+
V extends Variant = Variant,
|
|
81
|
+
> = optional.Optional<Base<V>, "key" | "time" | "name"> &
|
|
82
82
|
([DetailsSchema] extends [z.ZodNever] ? {} : { details: z.output<DetailsSchema> });
|
|
83
83
|
|
|
84
84
|
export const exceptionDetailsSchema = z.object({
|
package/src/telem/series.ts
CHANGED
|
@@ -14,7 +14,7 @@ import { caseconv } from "@/caseconv";
|
|
|
14
14
|
import { compare } from "@/compare";
|
|
15
15
|
import { id } from "@/id";
|
|
16
16
|
import { instance } from "@/instance";
|
|
17
|
-
import {
|
|
17
|
+
import { math } from "@/math";
|
|
18
18
|
import { bounds } from "@/spatial";
|
|
19
19
|
import {
|
|
20
20
|
type GLBufferController,
|
|
@@ -22,7 +22,6 @@ import {
|
|
|
22
22
|
glBufferUsageZ,
|
|
23
23
|
} from "@/telem/gl";
|
|
24
24
|
import {
|
|
25
|
-
addSamples,
|
|
26
25
|
convertDataType,
|
|
27
26
|
type CrudeDataType,
|
|
28
27
|
type CrudeTimeStamp,
|
|
@@ -200,7 +199,7 @@ export class Series<T extends TelemValue = TelemValue>
|
|
|
200
199
|
z.instanceof(ArrayBuffer),
|
|
201
200
|
z.instanceof(Uint8Array),
|
|
202
201
|
]),
|
|
203
|
-
glBufferUsage: glBufferUsageZ.
|
|
202
|
+
glBufferUsage: glBufferUsageZ.default("static").optional(),
|
|
204
203
|
});
|
|
205
204
|
|
|
206
205
|
/**
|
|
@@ -635,7 +634,7 @@ export class Series<T extends TelemValue = TelemValue>
|
|
|
635
634
|
throw new Error("cannot calculate maximum on a variable length data type");
|
|
636
635
|
if (this.writePos === 0) return -Infinity;
|
|
637
636
|
this.cachedMax ??= this.calcRawMax();
|
|
638
|
-
return
|
|
637
|
+
return math.add(this.cachedMax, this.sampleOffset);
|
|
639
638
|
}
|
|
640
639
|
|
|
641
640
|
private calcRawMin(): math.Numeric {
|
|
@@ -661,7 +660,7 @@ export class Series<T extends TelemValue = TelemValue>
|
|
|
661
660
|
throw new Error("cannot calculate minimum on a variable length data type");
|
|
662
661
|
if (this.writePos === 0) return Infinity;
|
|
663
662
|
this.cachedMin ??= this.calcRawMin();
|
|
664
|
-
return
|
|
663
|
+
return math.add(this.cachedMin, this.sampleOffset);
|
|
665
664
|
}
|
|
666
665
|
|
|
667
666
|
/** @returns the bounds of the series. */
|
|
@@ -726,7 +725,7 @@ export class Series<T extends TelemValue = TelemValue>
|
|
|
726
725
|
if (required === true) throw new Error(`[series] - no value at index ${index}`);
|
|
727
726
|
return undefined;
|
|
728
727
|
}
|
|
729
|
-
return
|
|
728
|
+
return math.add(v, this.sampleOffset) as T;
|
|
730
729
|
}
|
|
731
730
|
|
|
732
731
|
private atUUID(index: number, required: boolean): string | undefined {
|
package/src/telem/telem.spec.ts
CHANGED
|
@@ -11,7 +11,6 @@ import { describe, expect, it, test } from "vitest";
|
|
|
11
11
|
|
|
12
12
|
import { binary } from "@/binary";
|
|
13
13
|
import {
|
|
14
|
-
addSamples,
|
|
15
14
|
type CrudeDataType,
|
|
16
15
|
DataType,
|
|
17
16
|
Density,
|
|
@@ -98,6 +97,55 @@ describe("TimeStamp", () => {
|
|
|
98
97
|
).toBe(true);
|
|
99
98
|
});
|
|
100
99
|
|
|
100
|
+
describe("datetime-local format parsing", () => {
|
|
101
|
+
test("should parse as UTC by default", () => {
|
|
102
|
+
const ts = new TimeStamp("2025-11-03T17:44:45.500");
|
|
103
|
+
const utcTS = new TimeStamp("2025-11-03T17:44:45.500Z");
|
|
104
|
+
|
|
105
|
+
expect(ts.valueOf()).toEqual(utcTS.valueOf());
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
test("should handle 1-digit milliseconds with default UTC", () => {
|
|
109
|
+
const ts = new TimeStamp("2025-11-03T17:44:45.5");
|
|
110
|
+
expect(ts.millisecond).toBe(500);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
test("should handle 1-digit milliseconds with local", () => {
|
|
114
|
+
const ts = new TimeStamp("2025-11-03T17:44:45.5", "local");
|
|
115
|
+
expect(ts.millisecond).toBe(500);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
test("should handle 2-digit milliseconds", () => {
|
|
119
|
+
const ts = new TimeStamp("2025-11-03T17:44:45.50");
|
|
120
|
+
expect(ts.millisecond).toBe(500);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
test("should handle 3-digit milliseconds", () => {
|
|
124
|
+
const ts = new TimeStamp("2025-11-03T17:44:45.809");
|
|
125
|
+
expect(ts.millisecond).toBe(809);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
test("should handle 810 milliseconds", () => {
|
|
129
|
+
const ts = new TimeStamp("2025-11-03T17:44:45.810");
|
|
130
|
+
expect(ts.millisecond).toBeGreaterThanOrEqual(809);
|
|
131
|
+
expect(ts.millisecond).toBeLessThanOrEqual(810);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
test("should handle datetime without milliseconds", () => {
|
|
135
|
+
const ts = new TimeStamp("2025-11-03T17:44:45");
|
|
136
|
+
expect(ts.millisecond).toBe(0);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
test("should round-trip when using local tzInfo", () => {
|
|
140
|
+
const input = "2025-11-03T17:44:45.809";
|
|
141
|
+
const ts1 = new TimeStamp(input, "local");
|
|
142
|
+
const output = ts1.toString("ISO", "local").slice(0, -1);
|
|
143
|
+
const ts2 = new TimeStamp(output, "local");
|
|
144
|
+
|
|
145
|
+
expect(ts1.valueOf()).toEqual(ts2.valueOf());
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
|
|
101
149
|
test("construct from date", () => {
|
|
102
150
|
const ts = new TimeStamp([2021, 1, 1], "UTC");
|
|
103
151
|
expect(ts.date().getUTCFullYear()).toEqual(2021);
|
|
@@ -734,6 +782,44 @@ describe("TimeStamp", () => {
|
|
|
734
782
|
});
|
|
735
783
|
});
|
|
736
784
|
});
|
|
785
|
+
|
|
786
|
+
describe("formatBySpan", () => {
|
|
787
|
+
test("should return 'shortDate' for spans >= 30 days", () => {
|
|
788
|
+
const ts = new TimeStamp([2022, 12, 15], "UTC");
|
|
789
|
+
const span = TimeSpan.days(30);
|
|
790
|
+
expect(ts.formatBySpan(span)).toBe("shortDate");
|
|
791
|
+
});
|
|
792
|
+
|
|
793
|
+
test("should return 'dateTime' for spans >= 1 day", () => {
|
|
794
|
+
const ts = new TimeStamp([2022, 12, 15], "UTC");
|
|
795
|
+
const span = TimeSpan.days(1);
|
|
796
|
+
expect(ts.formatBySpan(span)).toBe("dateTime");
|
|
797
|
+
});
|
|
798
|
+
|
|
799
|
+
test("should return 'time' for spans >= 1 hour", () => {
|
|
800
|
+
const ts = new TimeStamp([2022, 12, 15], "UTC");
|
|
801
|
+
const span = TimeSpan.hours(1);
|
|
802
|
+
expect(ts.formatBySpan(span)).toBe("time");
|
|
803
|
+
});
|
|
804
|
+
|
|
805
|
+
test("should return 'preciseTime' for spans >= 1 second", () => {
|
|
806
|
+
const ts = new TimeStamp([2022, 12, 15], "UTC");
|
|
807
|
+
const span = TimeSpan.seconds(1);
|
|
808
|
+
expect(ts.formatBySpan(span)).toBe("preciseTime");
|
|
809
|
+
});
|
|
810
|
+
|
|
811
|
+
test("should return 'ISOTime' for spans < 1 second", () => {
|
|
812
|
+
const ts = new TimeStamp([2022, 12, 15], "UTC");
|
|
813
|
+
const span = TimeSpan.milliseconds(500);
|
|
814
|
+
expect(ts.formatBySpan(span)).toBe("ISOTime");
|
|
815
|
+
});
|
|
816
|
+
|
|
817
|
+
test("should work with very small spans", () => {
|
|
818
|
+
const ts = new TimeStamp([2022, 12, 15], "UTC");
|
|
819
|
+
const span = TimeSpan.microseconds(100);
|
|
820
|
+
expect(ts.formatBySpan(span)).toBe("ISOTime");
|
|
821
|
+
});
|
|
822
|
+
});
|
|
737
823
|
});
|
|
738
824
|
|
|
739
825
|
describe("TimeSpan", () => {
|
|
@@ -1935,30 +2021,3 @@ describe("Size", () => {
|
|
|
1935
2021
|
});
|
|
1936
2022
|
});
|
|
1937
2023
|
});
|
|
1938
|
-
|
|
1939
|
-
describe("addSamples", () => {
|
|
1940
|
-
test("adds two numbers", () => {
|
|
1941
|
-
expect(addSamples(1, 2)).toBe(3);
|
|
1942
|
-
expect(addSamples(1.5, 2.5)).toBe(4);
|
|
1943
|
-
expect(addSamples(-1, 1)).toBe(0);
|
|
1944
|
-
});
|
|
1945
|
-
|
|
1946
|
-
test("adds two bigints", () => {
|
|
1947
|
-
expect(addSamples(1n, 2n)).toBe(3n);
|
|
1948
|
-
expect(addSamples(-1n, 1n)).toBe(0n);
|
|
1949
|
-
expect(addSamples(9007199254740991n, 1n)).toBe(9007199254740992n);
|
|
1950
|
-
});
|
|
1951
|
-
|
|
1952
|
-
test("handles mixed numeric types", () => {
|
|
1953
|
-
expect(addSamples(1, 2n)).toBe(3);
|
|
1954
|
-
expect(addSamples(2n, 1)).toBe(3);
|
|
1955
|
-
expect(addSamples(1.5, 2n)).toBe(3.5);
|
|
1956
|
-
expect(addSamples(2n, 1.5)).toBe(3.5);
|
|
1957
|
-
});
|
|
1958
|
-
|
|
1959
|
-
test("handles edge cases", () => {
|
|
1960
|
-
expect(addSamples(0, 0)).toBe(0);
|
|
1961
|
-
expect(addSamples(Number.MAX_SAFE_INTEGER, 1)).toBe(Number.MAX_SAFE_INTEGER + 1);
|
|
1962
|
-
expect(addSamples(Number.MIN_SAFE_INTEGER, -1)).toBe(Number.MIN_SAFE_INTEGER - 1);
|
|
1963
|
-
});
|
|
1964
|
-
});
|
package/src/telem/telem.ts
CHANGED
|
@@ -154,6 +154,32 @@ export class TimeStamp
|
|
|
154
154
|
private static parseDateTimeString(str: string, tzInfo: TZInfo = "UTC"): bigint {
|
|
155
155
|
if (!str.includes("/") && !str.includes("-"))
|
|
156
156
|
return TimeStamp.parseTimeString(str, tzInfo);
|
|
157
|
+
|
|
158
|
+
const isDateTimeLocal =
|
|
159
|
+
str.match(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{1,3})?$/) != null;
|
|
160
|
+
|
|
161
|
+
if (isDateTimeLocal) {
|
|
162
|
+
let datePart = str;
|
|
163
|
+
let ms = 0;
|
|
164
|
+
|
|
165
|
+
if (str.includes(".")) {
|
|
166
|
+
const parts = str.split(".");
|
|
167
|
+
datePart = parts[0];
|
|
168
|
+
const msPart = parts[1] || "0";
|
|
169
|
+
ms = parseInt(msPart.padEnd(3, "0").slice(0, 3));
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const d =
|
|
173
|
+
tzInfo === "local"
|
|
174
|
+
? new Date(datePart.replace("T", " "))
|
|
175
|
+
: new Date(`${datePart}Z`);
|
|
176
|
+
|
|
177
|
+
const baseBigInt = BigInt(d.getTime()) * TimeStamp.MILLISECOND.valueOf();
|
|
178
|
+
const msBigInt = BigInt(ms) * TimeStamp.MILLISECOND.valueOf();
|
|
179
|
+
|
|
180
|
+
return baseBigInt + msBigInt;
|
|
181
|
+
}
|
|
182
|
+
|
|
157
183
|
const d = new Date(str);
|
|
158
184
|
// Essential to note that this makes the date midnight in UTC! Not local!
|
|
159
185
|
// As a result, we need to add the tzInfo offset back in.
|
|
@@ -560,6 +586,28 @@ export class TimeStamp
|
|
|
560
586
|
return this.sub(this.remainder(span));
|
|
561
587
|
}
|
|
562
588
|
|
|
589
|
+
/**
|
|
590
|
+
* Determines the appropriate string format based on the span magnitude.
|
|
591
|
+
*
|
|
592
|
+
* @param span - The span that provides context for format selection
|
|
593
|
+
* @returns The appropriate TimeStampStringFormat
|
|
594
|
+
*
|
|
595
|
+
* Rules:
|
|
596
|
+
* - For spans >= 30 days: "shortDate" (e.g., "Nov 5")
|
|
597
|
+
* - For spans >= 1 day: "dateTime" (e.g., "Nov 5 14:23:45")
|
|
598
|
+
* - For spans >= 1 hour: "time" (e.g., "14:23:45")
|
|
599
|
+
* - For spans >= 1 second: "preciseTime" (e.g., "14:23:45.123")
|
|
600
|
+
* - For spans < 1 second: "ISOTime" (full precision time)
|
|
601
|
+
*/
|
|
602
|
+
formatBySpan(span: TimeSpan): TimeStampStringFormat {
|
|
603
|
+
if (span.greaterThanOrEqual(TimeSpan.days(30))) return "shortDate";
|
|
604
|
+
if (span.greaterThanOrEqual(TimeSpan.DAY)) return "dateTime";
|
|
605
|
+
if (span.greaterThanOrEqual(TimeSpan.HOUR)) return "time";
|
|
606
|
+
if (span.greaterThanOrEqual(TimeSpan.SECOND)) return "preciseTime";
|
|
607
|
+
|
|
608
|
+
return "ISOTime";
|
|
609
|
+
}
|
|
610
|
+
|
|
563
611
|
/**
|
|
564
612
|
* @returns A new TimeStamp representing the current time in UTC. It's important to
|
|
565
613
|
* note that this TimeStamp is only accurate to the millisecond level (that's the best
|
|
@@ -2250,13 +2298,5 @@ export const convertDataType = (
|
|
|
2250
2298
|
if (source.usesBigInt && !target.usesBigInt) return Number(value) - Number(offset);
|
|
2251
2299
|
if (!source.usesBigInt && target.usesBigInt)
|
|
2252
2300
|
return BigInt(value.valueOf()) - BigInt(offset.valueOf());
|
|
2253
|
-
return
|
|
2254
|
-
};
|
|
2255
|
-
|
|
2256
|
-
export const addSamples = (a: math.Numeric, b: math.Numeric): math.Numeric => {
|
|
2257
|
-
if (b == 0) return a;
|
|
2258
|
-
if (a == 0) return b;
|
|
2259
|
-
if (typeof a === "bigint" && typeof b === "bigint") return a + b;
|
|
2260
|
-
if (typeof a === "number" && typeof b === "number") return a + b;
|
|
2261
|
-
return Number(a) + Number(b);
|
|
2301
|
+
return math.sub(value, offset);
|
|
2262
2302
|
};
|
package/src/zod/external.ts
CHANGED
|
@@ -0,0 +1,51 @@
|
|
|
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 { zod } from "@/zod";
|
|
13
|
+
|
|
14
|
+
describe("zod", () => {
|
|
15
|
+
describe("uint12", () => {
|
|
16
|
+
describe("success", () => {
|
|
17
|
+
interface Spec {
|
|
18
|
+
input: number;
|
|
19
|
+
expected: number;
|
|
20
|
+
}
|
|
21
|
+
const specs: Spec[] = [
|
|
22
|
+
{ input: 0, expected: 0 },
|
|
23
|
+
{ input: 1, expected: 1 },
|
|
24
|
+
{ input: 2 ** 12 - 1, expected: 2 ** 12 - 1 },
|
|
25
|
+
];
|
|
26
|
+
specs.forEach(({ input, expected }) => {
|
|
27
|
+
it(`should parse ${input} as ${expected}`, () => {
|
|
28
|
+
const result = zod.uint12.parse(input);
|
|
29
|
+
expect(result).toBe(expected);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
describe("failure", () => {
|
|
34
|
+
interface Spec {
|
|
35
|
+
input: unknown;
|
|
36
|
+
expected: string;
|
|
37
|
+
}
|
|
38
|
+
const specs: Spec[] = [
|
|
39
|
+
{ input: -1, expected: "Too small: expected number to be >=0" },
|
|
40
|
+
{ input: 2 ** 12, expected: "Too big: expected number to be <=4095" },
|
|
41
|
+
{ input: "1", expected: "Invalid input: expected number, received string" },
|
|
42
|
+
{ input: 1.5, expected: "Invalid input: expected int, received number" },
|
|
43
|
+
];
|
|
44
|
+
specs.forEach(({ input, expected }) => {
|
|
45
|
+
it(`should throw for ${String(input)}`, () => {
|
|
46
|
+
expect(() => zod.uint12.parse(input)).toThrow(expected);
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
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 { z } from "zod";
|
|
11
|
+
|
|
12
|
+
import { MAX_UINT12 } from "@/math/constants";
|
|
13
|
+
|
|
14
|
+
export const uint12 = z.int().min(0).max(MAX_UINT12);
|