@synnaxlabs/x 0.44.1 → 0.44.3
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 +19 -19
- package/dist/bounds-8OC_obRs.js +186 -0
- package/dist/bounds-CRK04jp7.cjs +1 -0
- package/dist/bounds.cjs +1 -1
- package/dist/bounds.js +1 -1
- package/dist/compare.cjs +1 -1
- package/dist/compare.js +1 -1
- package/dist/deep.cjs +1 -1
- package/dist/deep.js +56 -46
- package/dist/{external-BFgJjMcS.js → external-BM_NS5yM.js} +6 -6
- package/dist/external-E3ErJeeM.cjs +1 -0
- package/dist/{index-PNh31WTW.js → index-CBMHFqs4.js} +34 -33
- package/dist/index-DOJlZHqJ.cjs +1 -0
- package/dist/index.cjs +3 -3
- package/dist/index.js +235 -229
- package/dist/path-Blh4wJuA.js +110 -0
- package/dist/path-CPSfCjde.cjs +1 -0
- package/dist/{scale-C6qKDbRb.cjs → scale-C3fEtXxW.cjs} +1 -1
- package/dist/{scale-EWNUk-bn.js → scale-Db1Gunj0.js} +1 -1
- package/dist/scale.cjs +1 -1
- package/dist/scale.js +1 -1
- package/dist/series-BcF7A8Je.cjs +6 -0
- package/dist/{series-Bn5y1tD1.js → series-Cl3Vh_u-.js} +588 -471
- package/dist/spatial.cjs +1 -1
- package/dist/spatial.js +2 -2
- package/dist/src/breaker/breaker.d.ts +2 -1
- package/dist/src/breaker/breaker.d.ts.map +1 -1
- package/dist/src/deep/copy.d.ts.map +1 -1
- package/dist/src/deep/path.d.ts +1 -0
- package/dist/src/deep/path.d.ts.map +1 -1
- package/dist/src/id/id.d.ts +3 -1
- package/dist/src/id/id.d.ts.map +1 -1
- package/dist/src/math/math.d.ts +2 -1
- package/dist/src/math/math.d.ts.map +1 -1
- package/dist/src/observe/observe.d.ts +1 -0
- package/dist/src/observe/observe.d.ts.map +1 -1
- package/dist/src/primitive/primitive.d.ts +13 -1
- package/dist/src/primitive/primitive.d.ts.map +1 -1
- package/dist/src/status/status.d.ts +1 -0
- package/dist/src/status/status.d.ts.map +1 -1
- package/dist/src/strings/strings.d.ts +1 -1
- package/dist/src/strings/strings.d.ts.map +1 -1
- package/dist/src/telem/series.d.ts +7 -0
- package/dist/src/telem/series.d.ts.map +1 -1
- package/dist/src/telem/telem.d.ts +78 -1
- package/dist/src/telem/telem.d.ts.map +1 -1
- package/dist/src/zod/util.d.ts.map +1 -1
- package/dist/telem.cjs +1 -1
- package/dist/telem.js +1 -1
- package/dist/zod.cjs +1 -1
- package/dist/zod.js +1 -1
- package/package.json +1 -1
- package/src/breaker/breaker.ts +4 -0
- package/src/deep/copy.ts +12 -1
- package/src/deep/path.spec.ts +41 -0
- package/src/deep/path.ts +19 -2
- package/src/id/id.ts +8 -4
- package/src/math/math.spec.ts +20 -0
- package/src/math/math.ts +32 -29
- package/src/observe/observe.ts +2 -0
- package/src/primitive/primitive.spec.ts +7 -4
- package/src/primitive/primitive.ts +17 -1
- package/src/spatial/bounds/bounds.ts +1 -1
- package/src/status/status.ts +11 -0
- package/src/strings/strings.spec.ts +3 -0
- package/src/strings/strings.ts +2 -1
- package/src/telem/series.spec.ts +543 -2
- package/src/telem/series.ts +28 -9
- package/src/telem/telem.spec.ts +556 -0
- package/src/telem/telem.ts +118 -5
- package/src/testutil/testutil.spec.ts +6 -3
- package/src/zod/util.ts +5 -3
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/bounds-D6e9xoHt.cjs +0 -1
- package/dist/bounds-Dj9nG39I.js +0 -174
- package/dist/external-mffsMzJx.cjs +0 -1
- package/dist/index-B1m2qvBT.cjs +0 -1
- package/dist/path-BXdMenka.js +0 -101
- package/dist/path-st_E5-LJ.cjs +0 -1
- package/dist/series-CYAhDD6B.cjs +0 -6
package/src/deep/path.ts
CHANGED
|
@@ -126,6 +126,16 @@ const defaultGetter = (obj: record.Unknown, key: string): unknown => {
|
|
|
126
126
|
return undefined;
|
|
127
127
|
};
|
|
128
128
|
|
|
129
|
+
export const resolvePath = <T = record.Unknown>(path: string, obj: T): string => {
|
|
130
|
+
const parts = path.split(".");
|
|
131
|
+
parts.forEach((part, i) => {
|
|
132
|
+
obj = defaultGetter(obj as record.Unknown, part) as T;
|
|
133
|
+
if (obj != null && typeof obj === "object" && "key" in obj)
|
|
134
|
+
parts[i] = obj.key as string;
|
|
135
|
+
});
|
|
136
|
+
return parts.join(".");
|
|
137
|
+
};
|
|
138
|
+
|
|
129
139
|
/**
|
|
130
140
|
* Gets the value at the given path on the object. If the path does not exist
|
|
131
141
|
* and the optional flag is set to true, null will be returned. If the path does
|
|
@@ -158,6 +168,12 @@ export const get = (<V = record.Unknown, T = record.Unknown>(
|
|
|
158
168
|
return result as V;
|
|
159
169
|
}) as Get;
|
|
160
170
|
|
|
171
|
+
const getIndex = (part: string): number | null => {
|
|
172
|
+
// in order to be considered an index, all characters must be numbers
|
|
173
|
+
for (const char of part) if (isNaN(parseInt(char))) return null;
|
|
174
|
+
return parseInt(part);
|
|
175
|
+
};
|
|
176
|
+
|
|
161
177
|
/**
|
|
162
178
|
* Sets the value at the given path on the object. If the parents of the deep path
|
|
163
179
|
* do not exist, new objects will be created.
|
|
@@ -180,8 +196,9 @@ export const set = <V>(obj: V, path: string, value: unknown): void => {
|
|
|
180
196
|
return;
|
|
181
197
|
}
|
|
182
198
|
if (result.length === 0) return;
|
|
183
|
-
const index =
|
|
184
|
-
|
|
199
|
+
const index = getIndex(parts[parts.length - 1]);
|
|
200
|
+
// If we can't parse an index, try to interpret it as an object key.
|
|
201
|
+
if (index == null) {
|
|
185
202
|
const first = result[0];
|
|
186
203
|
if (typeof first === "object" && "key" in first) {
|
|
187
204
|
const objIndex = result.findIndex((o) => o.key === parts[parts.length - 1]);
|
package/src/id/id.ts
CHANGED
|
@@ -9,15 +9,19 @@
|
|
|
9
9
|
|
|
10
10
|
import { customAlphabet } from "nanoid/non-secure";
|
|
11
11
|
|
|
12
|
-
const
|
|
12
|
+
const ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
|
13
|
+
const ALPHANUMERIC = `0123456789${ALPHABET}`;
|
|
13
14
|
|
|
14
15
|
export const LENGTH = 11;
|
|
15
16
|
|
|
16
|
-
const
|
|
17
|
+
const createPrefix = customAlphabet(ALPHABET, 1);
|
|
18
|
+
const createInternal = customAlphabet(ALPHANUMERIC, LENGTH - 1);
|
|
17
19
|
|
|
18
20
|
/**
|
|
19
|
-
* Creates a unique alphanumeric string of length 11.
|
|
21
|
+
* Creates a unique alphanumeric string of length 11. The returned id always begins
|
|
22
|
+
* with a letter to disambiguate from values that can be potentially interpreted as
|
|
23
|
+
* numbers.
|
|
20
24
|
*
|
|
21
25
|
* @returns {string} A unique alphanumeric string.
|
|
22
26
|
*/
|
|
23
|
-
export const create = (): string => createInternal()
|
|
27
|
+
export const create = (): string => `${createPrefix()}${createInternal()}`;
|
package/src/math/math.spec.ts
CHANGED
|
@@ -73,6 +73,10 @@ describe("math", () => {
|
|
|
73
73
|
it("should return false if a bigint and a number are not equal", () => {
|
|
74
74
|
expect(math.equal(1n, 2)).toBe(false);
|
|
75
75
|
});
|
|
76
|
+
it("should handle bigint a and decimal b correctly", () => {
|
|
77
|
+
expect(math.equal(5n, 5.5)).toBe(false);
|
|
78
|
+
expect(math.equal(5n, 5.0)).toBe(true);
|
|
79
|
+
});
|
|
76
80
|
});
|
|
77
81
|
describe("roundToNearestMagnitude", () => {
|
|
78
82
|
it("should round to the nearest magnitude of 10", () => {
|
|
@@ -94,6 +98,10 @@ describe("math", () => {
|
|
|
94
98
|
it("should return the minimum of a bigint and a number", () => {
|
|
95
99
|
expect(math.min(1n, 2)).toBe(1n);
|
|
96
100
|
});
|
|
101
|
+
it("should handle bigint a and decimal b correctly", () => {
|
|
102
|
+
expect(math.min(10n, 5.5)).toBe(6n);
|
|
103
|
+
expect(math.min(3n, 7.8)).toBe(3n);
|
|
104
|
+
});
|
|
97
105
|
});
|
|
98
106
|
describe("max", () => {
|
|
99
107
|
it("should return the maximum of two numbers", () => {
|
|
@@ -108,6 +116,10 @@ describe("math", () => {
|
|
|
108
116
|
it("should return the maximum of a bigint and a number", () => {
|
|
109
117
|
expect(math.max(1n, 2)).toBe(2n);
|
|
110
118
|
});
|
|
119
|
+
it("should handle bigint a and decimal b correctly", () => {
|
|
120
|
+
expect(math.max(3n, 5.5)).toBe(6n);
|
|
121
|
+
expect(math.max(10n, 7.8)).toBe(10n);
|
|
122
|
+
});
|
|
111
123
|
});
|
|
112
124
|
describe("abs", () => {
|
|
113
125
|
it("should return the absolute value of a number", () => {
|
|
@@ -130,6 +142,10 @@ describe("math", () => {
|
|
|
130
142
|
it("should multiply a bigint and a number", () => {
|
|
131
143
|
expect(math.mult(1n, 2)).toBe(2n);
|
|
132
144
|
});
|
|
145
|
+
it("should handle bigint a and decimal b correctly", () => {
|
|
146
|
+
expect(math.mult(3n, 2.5)).toBe(8n);
|
|
147
|
+
expect(math.mult(4n, 0.5)).toBe(2n);
|
|
148
|
+
});
|
|
133
149
|
});
|
|
134
150
|
|
|
135
151
|
describe("div", () => {
|
|
@@ -145,5 +161,9 @@ describe("math", () => {
|
|
|
145
161
|
it("should divide a bigint and a number", () => {
|
|
146
162
|
expect(math.div(2n, 1)).toBe(2n);
|
|
147
163
|
});
|
|
164
|
+
it("should handle bigint a and decimal b correctly", () => {
|
|
165
|
+
expect(math.div(10n, 2.5)).toBe(4n);
|
|
166
|
+
expect(math.div(8n, 0.5)).toBe(16n);
|
|
167
|
+
});
|
|
148
168
|
});
|
|
149
169
|
});
|
package/src/math/math.ts
CHANGED
|
@@ -10,27 +10,38 @@
|
|
|
10
10
|
/** A numeric value is either a a number, or a bigint. */
|
|
11
11
|
export type Numeric = number | bigint;
|
|
12
12
|
|
|
13
|
+
const multiCoercedOp =
|
|
14
|
+
(func: (a: number, b: number) => Numeric) =>
|
|
15
|
+
<V extends Numeric>(a: V, b: Numeric): V => {
|
|
16
|
+
if (typeof a === "bigint") {
|
|
17
|
+
if (isInteger(b))
|
|
18
|
+
return func(a as unknown as number, BigInt(b) as unknown as number) as V;
|
|
19
|
+
const res = func(Number(a), Number(b)) as number;
|
|
20
|
+
if (typeof res === "number") return BigInt(Math.round(res)) as V;
|
|
21
|
+
return res;
|
|
22
|
+
}
|
|
23
|
+
return func(Number(a), Number(b)) as V;
|
|
24
|
+
};
|
|
25
|
+
|
|
13
26
|
/**
|
|
14
27
|
* @returns the product of a and b, coercing b to the type of a if necessary. */
|
|
15
|
-
export const sub =
|
|
16
|
-
if (typeof a === "bigint") return (a - BigInt(b)) as V;
|
|
17
|
-
return (a - Number(b)) as V;
|
|
18
|
-
};
|
|
28
|
+
export const sub = multiCoercedOp((a, b) => a - b);
|
|
19
29
|
|
|
20
30
|
/** @returns the sum of a and b, coercing b to the type of a if necessary. */
|
|
21
|
-
export const add =
|
|
22
|
-
if (typeof a === "bigint") return (a + BigInt(b)) as V;
|
|
23
|
-
return ((a as unknown as number) + Number(b)) as V;
|
|
24
|
-
};
|
|
31
|
+
export const add = multiCoercedOp((a, b) => a + b);
|
|
25
32
|
|
|
26
33
|
/** @returns true if a is close to b within epsilon. */
|
|
27
34
|
export const closeTo = (a: number, b: number, epsilon = 0.0001): boolean =>
|
|
28
35
|
Math.abs(a - b) < epsilon;
|
|
29
36
|
|
|
30
37
|
/** @returns true if a is equal to b, coercing b to the type of a if necessary. */
|
|
31
|
-
export const equal =
|
|
32
|
-
|
|
33
|
-
|
|
38
|
+
export const equal = (a: Numeric, b: Numeric): boolean => {
|
|
39
|
+
const aIsBigInt = typeof a === "bigint";
|
|
40
|
+
const bIsBigInt = typeof b === "bigint";
|
|
41
|
+
if (aIsBigInt && bIsBigInt) return a === b;
|
|
42
|
+
if (aIsBigInt && isInteger(b)) return a === BigInt(b);
|
|
43
|
+
if (bIsBigInt && isInteger(a)) return b === BigInt(a);
|
|
44
|
+
return a === b;
|
|
34
45
|
};
|
|
35
46
|
|
|
36
47
|
/**
|
|
@@ -45,32 +56,24 @@ export const roundToNearestMagnitude = (num: number): number => {
|
|
|
45
56
|
};
|
|
46
57
|
|
|
47
58
|
/** @returns the minimum of a and b, coercing b to the type of a if necessary. */
|
|
48
|
-
export const min =
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
59
|
+
export const min = multiCoercedOp((a, b) => (a <= b ? a : b));
|
|
60
|
+
|
|
61
|
+
export const isInteger = (a: Numeric): boolean => {
|
|
62
|
+
if (typeof a === "bigint") return true;
|
|
63
|
+
return Number.isInteger(a);
|
|
52
64
|
};
|
|
53
65
|
|
|
54
66
|
/** @returns the maximum of a and b, coercing b to the type of a if necessary. */
|
|
55
|
-
export const max =
|
|
56
|
-
if (typeof a === "bigint") return (a >= b ? a : BigInt(b)) as V;
|
|
57
|
-
return (a >= b ? a : Number(b)) as V;
|
|
58
|
-
};
|
|
67
|
+
export const max = multiCoercedOp((a, b) => (a >= b ? a : b));
|
|
59
68
|
|
|
60
69
|
/** @returns the absolute value of a. */
|
|
61
70
|
export const abs = <V extends Numeric>(a: V): V => {
|
|
62
|
-
if (a
|
|
63
|
-
return a;
|
|
71
|
+
if (typeof a === "bigint") return (a < 0n ? -a : a) as V;
|
|
72
|
+
return (a < 0 ? -a : a) as V;
|
|
64
73
|
};
|
|
65
74
|
|
|
66
75
|
/** @returns the multiplication of a and b, coercing b to the type of a if necessary. */
|
|
67
|
-
export const mult =
|
|
68
|
-
if (typeof a === "bigint") return (a * BigInt(b)) as V;
|
|
69
|
-
return (a * Number(b)) as V;
|
|
70
|
-
};
|
|
76
|
+
export const mult = multiCoercedOp((a, b) => a * b);
|
|
71
77
|
|
|
72
78
|
/** @returns the division of a and b, coercing b to the type of a if necessary. */
|
|
73
|
-
export const div =
|
|
74
|
-
if (typeof a === "bigint") return (a / BigInt(b)) as V;
|
|
75
|
-
return (a / Number(b)) as V;
|
|
76
|
-
};
|
|
79
|
+
export const div = multiCoercedOp((a, b) => a / b);
|
package/src/observe/observe.ts
CHANGED
|
@@ -12,6 +12,8 @@ import { type Destructor } from "@/destructor";
|
|
|
12
12
|
/** Handler is called when the value of an Observable changes. */
|
|
13
13
|
export type Handler<T> = (value: T) => void;
|
|
14
14
|
|
|
15
|
+
export type AsyncHandler<T> = (value: T) => Promise<void>;
|
|
16
|
+
|
|
15
17
|
/** A generic interface for an entity whose value can be observed when it changes. */
|
|
16
18
|
export interface Observable<T> {
|
|
17
19
|
/**
|
|
@@ -7,11 +7,12 @@
|
|
|
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 { describe, expect, it } from "vitest";
|
|
10
|
+
import { describe, expect, it, test } from "vitest";
|
|
11
11
|
import { z } from "zod";
|
|
12
12
|
|
|
13
13
|
import { binary } from "@/binary";
|
|
14
14
|
import { primitive } from "@/primitive";
|
|
15
|
+
import { testutil } from "@/testutil";
|
|
15
16
|
|
|
16
17
|
class ExampleStringer implements primitive.Stringer {
|
|
17
18
|
readonly value: string;
|
|
@@ -25,7 +26,7 @@ class ExampleStringer implements primitive.Stringer {
|
|
|
25
26
|
}
|
|
26
27
|
|
|
27
28
|
describe("primitive", () => {
|
|
28
|
-
describe("isZero", () => {
|
|
29
|
+
describe("isZero and isNonZero", () => {
|
|
29
30
|
interface Spec {
|
|
30
31
|
value: primitive.Value;
|
|
31
32
|
expected: boolean;
|
|
@@ -42,10 +43,12 @@ describe("primitive", () => {
|
|
|
42
43
|
{ value: new ExampleStringer("cat"), expected: false },
|
|
43
44
|
];
|
|
44
45
|
SPECS.forEach(({ value, expected }) => {
|
|
45
|
-
|
|
46
|
-
it(`should return ${expected} for ${value} ${typeof value}`, () => {
|
|
46
|
+
test(`isZero should return ${expected} for ${testutil.toString(value)}`, () => {
|
|
47
47
|
expect(primitive.isZero(value)).toEqual(expected);
|
|
48
48
|
});
|
|
49
|
+
test(`isNonZero should return ${!expected} for ${testutil.toString(value)}`, () => {
|
|
50
|
+
expect(primitive.isNonZero(value)).toEqual(!expected);
|
|
51
|
+
});
|
|
49
52
|
});
|
|
50
53
|
});
|
|
51
54
|
|
|
@@ -52,6 +52,16 @@ export interface Stringer {
|
|
|
52
52
|
export const isStringer = (value: unknown): boolean =>
|
|
53
53
|
value != null && typeof value === "object" && "toString" in value;
|
|
54
54
|
|
|
55
|
+
/**
|
|
56
|
+
* Type representing zero values for each primitive type
|
|
57
|
+
*/
|
|
58
|
+
export type ZeroValue = "" | 0 | 0n | false | null | undefined;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Type representing non-zero values for each primitive type
|
|
62
|
+
*/
|
|
63
|
+
export type NonZeroValue = Exclude<Value, ZeroValue>;
|
|
64
|
+
|
|
55
65
|
/**
|
|
56
66
|
* @returns true if the given primitive is the zero value for its type.
|
|
57
67
|
* For strings value == ""
|
|
@@ -61,7 +71,7 @@ export const isStringer = (value: unknown): boolean =>
|
|
|
61
71
|
* For objects value == null
|
|
62
72
|
* For undefined returns true
|
|
63
73
|
*/
|
|
64
|
-
export const isZero = <V extends Value>(value: V):
|
|
74
|
+
export const isZero = <V extends Value>(value: V): value is V & ZeroValue => {
|
|
65
75
|
if (isStringer(value)) return value?.toString().length === 0;
|
|
66
76
|
switch (typeof value) {
|
|
67
77
|
case "string":
|
|
@@ -80,3 +90,9 @@ export const isZero = <V extends Value>(value: V): boolean => {
|
|
|
80
90
|
return false;
|
|
81
91
|
}
|
|
82
92
|
};
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Type predicate function that narrows to non-zero values
|
|
96
|
+
*/
|
|
97
|
+
export const isNonZero = <V extends Value>(value: V): value is V & NonZeroValue =>
|
|
98
|
+
!isZero(value);
|
|
@@ -615,7 +615,7 @@ export const traverse = <T extends numeric.Value = number>(
|
|
|
615
615
|
currentPosition,
|
|
616
616
|
dir > 0 ? moveDist : -moveDist,
|
|
617
617
|
) as T;
|
|
618
|
-
remainingDist = math.sub(remainingDist, dir > 0 ? moveDist : -moveDist);
|
|
618
|
+
remainingDist = math.sub<T>(remainingDist, dir > 0 ? moveDist : -moveDist);
|
|
619
619
|
|
|
620
620
|
// If we've exhausted the distance, return the current position
|
|
621
621
|
if (math.equal(remainingDist, 0)) return currentPosition as T;
|
package/src/status/status.ts
CHANGED
|
@@ -89,3 +89,14 @@ export const create = <D = undefined, V extends Variant = Variant>(
|
|
|
89
89
|
time: TimeStamp.now(),
|
|
90
90
|
...spec,
|
|
91
91
|
}) as unknown as Status<D, V>;
|
|
92
|
+
|
|
93
|
+
export const filterVariant = (
|
|
94
|
+
variant: Variant,
|
|
95
|
+
only: Variant | Variant[] = [],
|
|
96
|
+
): Variant | undefined => {
|
|
97
|
+
if (Array.isArray(only)) {
|
|
98
|
+
if (only.includes(variant)) return variant;
|
|
99
|
+
return undefined;
|
|
100
|
+
}
|
|
101
|
+
return only === variant ? variant : undefined;
|
|
102
|
+
};
|
|
@@ -15,6 +15,9 @@ describe("naturalLanguageJoin", () => {
|
|
|
15
15
|
it("should return an empty string for an empty array", () =>
|
|
16
16
|
expect(strings.naturalLanguageJoin([])).toBe(""));
|
|
17
17
|
|
|
18
|
+
it("should return the string for a single string", () =>
|
|
19
|
+
expect(strings.naturalLanguageJoin("apple")).toBe("apple"));
|
|
20
|
+
|
|
18
21
|
it("should return the zeroLength string for an empty array if provided", () =>
|
|
19
22
|
expect(strings.naturalLanguageJoin([], "No items")).toBe("No items"));
|
|
20
23
|
|
package/src/strings/strings.ts
CHANGED
|
@@ -24,9 +24,10 @@
|
|
|
24
24
|
* ```
|
|
25
25
|
*/
|
|
26
26
|
export const naturalLanguageJoin = (
|
|
27
|
-
strings: string[],
|
|
27
|
+
strings: string | string[],
|
|
28
28
|
zeroLength: string = "",
|
|
29
29
|
): string => {
|
|
30
|
+
if (typeof strings === "string") return strings;
|
|
30
31
|
const length = strings.length;
|
|
31
32
|
if (length === 0) return zeroLength;
|
|
32
33
|
if (length === 1) return strings[0];
|