@synnaxlabs/x 0.36.0 → 0.38.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 +41 -37
- package/dist/binary.cjs +1 -1
- package/dist/binary.js +1 -1
- package/dist/box-BZ6d2d5A.cjs +1 -0
- package/dist/box-Cto-5Uxu.js +201 -0
- package/dist/box.cjs +1 -1
- package/dist/box.js +1 -1
- package/dist/caseconv.cjs +1 -1
- package/dist/caseconv.js +1 -1
- package/dist/compare.cjs +1 -1
- package/dist/compare.js +1 -1
- package/dist/external-C-dNgNQw.cjs +1 -0
- package/dist/external-Cax-LfQW.cjs +1 -0
- package/dist/external-DqPrWKvU.js +47 -0
- package/dist/external-vFGUdZf6.js +30 -0
- package/dist/index-BG3Scw3G.cjs +1 -0
- package/dist/{index-HQonyH7n.js → index-BVC_8Cg9.js} +1 -1
- package/dist/index-BfDeGfej.js +41 -0
- package/dist/{index-CYxQwEdX.cjs → index-CnclyYpG.cjs} +1 -1
- package/dist/index-D4NCYiQB.js +19 -0
- package/dist/index-Dd8DLyMx.cjs +1 -0
- package/dist/{index-BBa2mWG1.js → index-OHIRoCei.js} +1 -1
- package/dist/index-udOjA9d-.cjs +1 -0
- package/dist/index.cjs +2 -2
- package/dist/index.js +126 -124
- package/dist/kv.cjs +1 -1
- package/dist/kv.js +2 -2
- package/dist/link.cjs +1 -0
- package/dist/link.js +10 -0
- package/dist/{location-DLP2ZS0o.cjs → location-BIet4Mig.cjs} +1 -1
- package/dist/{location-Cn1ByVTZ.js → location-C5Ot4MVG.js} +1 -1
- package/dist/location.cjs +1 -1
- package/dist/location.js +1 -1
- package/dist/position-CvSNZkSD.cjs +1 -0
- package/dist/position-GeF1oEYk.js +85 -0
- package/dist/position.cjs +1 -1
- package/dist/position.js +1 -1
- package/dist/runtime.cjs +1 -1
- package/dist/runtime.js +1 -1
- package/dist/{scale-BI4wJF3b.cjs → scale-BTgf0Mr-.cjs} +1 -1
- package/dist/{scale-rZ1YKDFy.js → scale-Dh1UNRoC.js} +3 -3
- package/dist/scale.cjs +1 -1
- package/dist/scale.js +1 -1
- package/dist/series-BMhEEJZL.cjs +11 -0
- package/dist/{series-CnEQe1dh.js → series-DxDIugLj.js} +296 -286
- package/dist/spatial.cjs +1 -1
- package/dist/spatial.js +5 -5
- package/dist/src/breaker/breaker.d.ts +1 -1
- package/dist/src/breaker/breaker.d.ts.map +1 -1
- package/dist/src/caseconv/caseconv.d.ts +12 -6
- package/dist/src/caseconv/caseconv.d.ts.map +1 -1
- package/dist/src/deep/path.d.ts.map +1 -1
- package/dist/src/index.d.ts +2 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/kv/external.d.ts +3 -0
- package/dist/src/kv/external.d.ts.map +1 -0
- package/dist/src/kv/index.d.ts +1 -1
- package/dist/src/kv/index.d.ts.map +1 -1
- package/dist/src/kv/mock.d.ts +24 -0
- package/dist/src/kv/mock.d.ts.map +1 -0
- package/dist/src/kv/mock.spec.d.ts +2 -0
- package/dist/src/kv/mock.spec.d.ts.map +1 -0
- package/dist/src/kv/types.d.ts +18 -18
- package/dist/src/kv/types.d.ts.map +1 -1
- package/dist/src/link/index.d.ts +2 -0
- package/dist/src/link/index.d.ts.map +1 -0
- package/dist/src/link/link.d.ts +2 -0
- package/dist/src/link/link.d.ts.map +1 -0
- package/dist/src/link/link.spec.d.ts +2 -0
- package/dist/src/link/link.spec.d.ts.map +1 -0
- package/dist/src/runtime/os.d.ts +1 -1
- package/dist/src/runtime/os.d.ts.map +1 -1
- package/dist/src/sleep/sleep.d.ts.map +1 -1
- package/dist/src/telem/index.d.ts +1 -1
- package/dist/src/telem/index.d.ts.map +1 -1
- package/dist/src/telem/series.d.ts +1 -0
- package/dist/src/telem/series.d.ts.map +1 -1
- package/dist/src/telem/telem.d.ts +2 -0
- package/dist/src/telem/telem.d.ts.map +1 -1
- package/dist/src/unique/index.d.ts +2 -0
- package/dist/src/unique/index.d.ts.map +1 -0
- package/dist/src/unique/unique.d.ts +42 -0
- package/dist/src/unique/unique.d.ts.map +1 -0
- package/dist/src/unique/unique.spec.d.ts +2 -0
- package/dist/src/unique/unique.spec.d.ts.map +1 -0
- package/dist/src/zodutil/index.d.ts.map +1 -1
- package/dist/src/zodutil/zodutil.d.ts +1 -16
- package/dist/src/zodutil/zodutil.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 +2 -2
- package/dist/url.cjs +1 -1
- package/dist/url.js +5 -5
- package/dist/{xy-LADI2wVU.cjs → xy-Budz-qz-.cjs} +1 -1
- package/dist/{xy-DQdccWlc.js → xy-DxjPL2DZ.js} +4 -4
- package/dist/xy.cjs +1 -1
- package/dist/xy.js +1 -1
- package/dist/zodutil-BfrF8jE3.js +23 -0
- package/dist/zodutil-DFJyyQd2.cjs +1 -0
- package/dist/zodutil.cjs +1 -1
- package/dist/zodutil.js +1 -1
- package/package.json +8 -10
- package/src/breaker/breaker.spec.ts +3 -4
- package/src/breaker/breaker.ts +3 -2
- package/src/caseconv/caseconv.spec.ts +20 -20
- package/src/caseconv/caseconv.ts +34 -5
- package/src/compare/compare.ts +2 -2
- package/src/deep/path.ts +1 -1
- package/src/index.ts +2 -1
- package/src/{unique.ts → kv/external.ts} +2 -1
- package/src/kv/index.ts +1 -1
- package/src/kv/mock.spec.ts +101 -0
- package/src/kv/mock.ts +58 -0
- package/src/kv/types.ts +22 -28
- package/src/link/index.ts +10 -0
- package/src/link/link.spec.ts +68 -0
- package/src/link/link.ts +21 -0
- package/src/runtime/os.ts +18 -2
- package/src/sleep/sleep.ts +1 -1
- package/src/telem/index.ts +1 -1
- package/src/telem/series.spec.ts +21 -0
- package/src/telem/series.ts +15 -9
- package/src/telem/telem.ts +34 -10
- package/src/unique/index.ts +10 -0
- package/src/unique/unique.spec.ts +192 -0
- package/src/unique/unique.ts +67 -0
- package/src/zodutil/index.ts +1 -1
- package/src/zodutil/zodutil.ts +1 -29
- package/tsconfig.tsbuildinfo +1 -1
- package/vite.config.ts +6 -8
- package/dist/box-BpSX4si6.cjs +0 -1
- package/dist/box-CYXc9-qp.js +0 -201
- package/dist/external-B3XSLDq5.cjs +0 -1
- package/dist/external-sVtvYJS6.js +0 -23
- package/dist/index-YsO0EMN8.cjs +0 -1
- package/dist/index-eue4dSQX.js +0 -45
- package/dist/index-h-QAL9T1.cjs +0 -1
- package/dist/position-DJXB-pDS.js +0 -85
- package/dist/position-JCN6-sJC.cjs +0 -1
- package/dist/series-BN9CILsQ.cjs +0 -11
- package/dist/src/unique.d.ts +0 -2
- package/dist/src/unique.d.ts.map +0 -1
- package/dist/types-BpAJW2TM.js +0 -11
- package/dist/types-zRwnQ1hc.cjs +0 -1
- package/dist/zodutil-BRjUdYAv.cjs +0 -1
- package/dist/zodutil-DI4gVZkT.js +0 -27
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";const O=require("zod"),i=require("./base-B48bPNx5.cjs"),z=O.z.union([O.z.number(),i.xy,i.numberCouple,i.dimensions,i.signedDimensions,i.clientXY]),s=(t,n)=>{if(typeof t=="string"){if(n===void 0)throw new Error("The y coordinate must be given.");return t==="x"?{x:n,y:0}:{x:0,y:n}}return typeof t=="number"?{x:t,y:n??t}:Array.isArray(t)?{x:t[0],y:t[1]}:"signedWidth"in t?{x:t.signedWidth,y:t.signedHeight}:"clientX"in t?{x:t.clientX,y:t.clientY}:"width"in t?{x:t.width,y:t.height}:{x:t.x,y:t.y}},u=Object.freeze({x:0,y:0}),P=Object.freeze({x:1,y:1}),
|
|
1
|
+
"use strict";const O=require("zod"),i=require("./base-B48bPNx5.cjs"),z=O.z.union([O.z.number(),i.xy,i.numberCouple,i.dimensions,i.signedDimensions,i.clientXY]),s=(t,n)=>{if(typeof t=="string"){if(n===void 0)throw new Error("The y coordinate must be given.");return t==="x"?{x:n,y:0}:{x:0,y:n}}return typeof t=="number"?{x:t,y:n??t}:Array.isArray(t)?{x:t[0],y:t[1]}:"signedWidth"in t?{x:t.signedWidth,y:t.signedHeight}:"clientX"in t?{x:t.clientX,y:t.clientY}:"width"in t?{x:t.width,y:t.height}:{x:t.x,y:t.y}},u=Object.freeze({x:0,y:0}),P=Object.freeze({x:1,y:1}),E=Object.freeze({x:1/0,y:1/0}),I=Object.freeze({x:NaN,y:NaN}),g=(t,n,e=0)=>{const r=s(t),o=s(n);return e===0?r.x===o.x&&r.y===o.y:Math.abs(r.x-o.x)<=e&&Math.abs(r.y-o.y)<=e},Z=t=>g(t,u),h=(t,n,e)=>{const r=s(t),o=s(n,e);return{x:r.x*o.x,y:r.y*o.y}},_=(t,n)=>{const e=s(t);return{x:e.x+n,y:e.y}},j=(t,n)=>{const e=s(t);return{x:e.x,y:e.y+n}},p=(t,n,e,...r)=>typeof n=="string"&&typeof e=="number"?n==="x"?_(t,e):j(t,e):[t,n,e??u,...r].reduce((o,y)=>{const c=s(y);return{x:o.x+c.x,y:o.y+c.y}},u),v=(t,n,e)=>{const r=s(t);return n==="x"?{x:e,y:r.y}:{x:r.x,y:e}},w=(t,n)=>{const e=s(t),r=s(n);return Math.sqrt((e.x-r.x)**2+(e.y-r.y)**2)},A=(t,n)=>{const e=s(t),r=s(n);return{x:r.x-e.x,y:r.y-e.y}},T=t=>{const n=s(t);return Number.isNaN(n.x)||Number.isNaN(n.y)},H=t=>{const n=s(t);return Number.isFinite(n.x)&&Number.isFinite(n.y)},R=t=>{const n=s(t);return[n.x,n.y]},S=t=>{const n=s(t);return{left:n.x,top:n.y}},F=(t,n=0)=>{const e=s(t);return{x:Number(e.x.toFixed(n)),y:Number(e.y.toFixed(n))}},m=(t,n)=>{const e=s(t),r=s(n);return{x:e.x-r.x,y:e.y-r.y}},d=t=>{const n=s(t),e=Math.hypot(n.x,n.y);return e===0?{x:0,y:0}:{x:-n.y/e,y:n.x/e}},X=t=>{const n=s(t),e=Math.hypot(n.x,n.y);return e===0?{x:0,y:0}:{x:n.x/e,y:n.y/e}},Y=(...t)=>{const n=t.reduce((e,r)=>p(e,r),u);return h(n,1/t.length)},W=(t,n)=>{const e=[];for(let r=0;r<t.length;r++){const o=t[r];let y,c,b,x;if(r===0){const a=t[r+1],l=m(a,o);c=d(l),b=c,x=n}else if(r===t.length-1){const a=t[r-1],l=m(o,a);y=d(l),b=y,x=n}else{const a=t[r-1],l=t[r+1],f=m(o,a),N=m(l,o);y=d(f),c=d(N);const q=Math.acos((f.x*N.x+f.y*N.y)/(Math.hypot(f.x,f.y)*Math.hypot(N.x,N.y))),M=Math.sin(q/2);M===0?x=n:x=n/M,b=X(Y(y,c))}e.push(h(b,x))}return e},C=Object.freeze(Object.defineProperty({__proto__:null,INFINITY:E,NAN:I,ONE:P,ZERO:u,average:Y,calculateMiters:W,clientXY:i.clientXY,construct:s,couple:R,crudeZ:z,css:S,distance:w,equals:g,isFinite:H,isNan:T,isZero:Z,normal:d,normalize:X,scale:h,set:v,sub:m,translate:p,translateX:_,translateY:j,translation:A,truncate:F,xy:i.xy},Symbol.toStringTag,{value:"Module"}));exports.ONE=P;exports.ZERO=u;exports.construct=s;exports.crudeZ=z;exports.equals=g;exports.translate=p;exports.truncate=F;exports.xy=C;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { z as h } from "zod";
|
|
2
|
-
import { x as p, n as
|
|
2
|
+
import { x as p, n as v, d as w, s as A, i as M } from "./base-DnZzEvvz.js";
|
|
3
3
|
const X = h.union([
|
|
4
4
|
h.number(),
|
|
5
5
|
p,
|
|
6
|
-
|
|
6
|
+
v,
|
|
7
7
|
w,
|
|
8
8
|
A,
|
|
9
9
|
M
|
|
@@ -78,9 +78,9 @@ const X = h.union([
|
|
|
78
78
|
} else {
|
|
79
79
|
const x = t[r - 1], u = t[r + 1], a = f(o, x), l = f(u, o);
|
|
80
80
|
i = m(a), c = m(l);
|
|
81
|
-
const
|
|
81
|
+
const I = Math.acos(
|
|
82
82
|
(a.x * l.x + a.y * l.y) / (Math.hypot(a.x, a.y) * Math.hypot(l.x, l.y))
|
|
83
|
-
), g = Math.sin(
|
|
83
|
+
), g = Math.sin(I / 2);
|
|
84
84
|
g === 0 ? y = n : y = n / g, b = j(F(i, c));
|
|
85
85
|
}
|
|
86
86
|
e.push(d(b, y));
|
package/dist/xy.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./xy-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./xy-Budz-qz-.cjs");exports.xy=e.xy;
|
package/dist/xy.js
CHANGED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { z as s } from "zod";
|
|
2
|
+
import { t as l, g } from "./path-DD6ytXzr.js";
|
|
3
|
+
const c = (e) => l(e, (t, r, n) => {
|
|
4
|
+
const i = r === n.length - 1, u = !isNaN(parseInt(t)), a = !isNaN(parseInt(n[r + 1]));
|
|
5
|
+
return u && (t = "element"), i || a ? t : [t, "shape"];
|
|
6
|
+
}), o = (e, t) => {
|
|
7
|
+
if (e == null) return null;
|
|
8
|
+
const r = e[t];
|
|
9
|
+
return r == null && typeof e == "object" && "sourceType" in e ? e.sourceType()[t] : r;
|
|
10
|
+
}, m = (e, t, r) => g(
|
|
11
|
+
o(e, "shape"),
|
|
12
|
+
c(t),
|
|
13
|
+
{ ...r, getter: o }
|
|
14
|
+
), f = s.bigint().or(s.string().transform(BigInt)), y = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
15
|
+
__proto__: null,
|
|
16
|
+
bigInt: f,
|
|
17
|
+
getFieldSchema: m,
|
|
18
|
+
getFieldSchemaPath: c
|
|
19
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
20
|
+
export {
|
|
21
|
+
f as b,
|
|
22
|
+
y as z
|
|
23
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";const s=require("zod"),c=require("./path-1tZLZ4AN.cjs"),i=e=>c.transformPath(e,(t,n,r)=>{const l=n===r.length-1,a=!isNaN(parseInt(t)),g=!isNaN(parseInt(r[n+1]));return a&&(t="element"),l||g?t:[t,"shape"]}),o=(e,t)=>{if(e==null)return null;const n=e[t];return n==null&&typeof e=="object"&&"sourceType"in e?e.sourceType()[t]:n},f=(e,t,n)=>c.get(o(e,"shape"),i(t),{...n,getter:o}),u=s.z.bigint().or(s.z.string().transform(BigInt)),p=Object.freeze(Object.defineProperty({__proto__:null,bigInt:u,getFieldSchema:f,getFieldSchemaPath:i},Symbol.toStringTag,{value:"Module"}));exports.bigInt=u;exports.zodutil=p;
|
package/dist/zodutil.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("./zodutil-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("./zodutil-DFJyyQd2.cjs");exports.zodutil=t.zodutil;
|
package/dist/zodutil.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@synnaxlabs/x",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.38.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Common Utilities for Synnax Labs",
|
|
6
6
|
"repository": "https://github.com/synnaxlabs/synnax/tree/main/x/go",
|
|
@@ -13,19 +13,18 @@
|
|
|
13
13
|
"control systems"
|
|
14
14
|
],
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"nanoid": "^5.0.
|
|
16
|
+
"nanoid": "^5.0.9",
|
|
17
17
|
"zod": "^3.24.1"
|
|
18
18
|
},
|
|
19
19
|
"devDependencies": {
|
|
20
|
-
"@types/node": "^22.
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"vite": "^6.0.3",
|
|
20
|
+
"@types/node": "^22.10.6",
|
|
21
|
+
"eslint": "^9.18.0",
|
|
22
|
+
"typescript": "^5.7.3",
|
|
23
|
+
"vite": "^6.0.7",
|
|
25
24
|
"vitest": "^2.1.8",
|
|
26
25
|
"@synnaxlabs/tsconfig": "0.0.2",
|
|
27
|
-
"
|
|
28
|
-
"
|
|
26
|
+
"@synnaxlabs/vite-plugin": "0.0.1",
|
|
27
|
+
"eslint-config-synnaxlabs": "0.0.1"
|
|
29
28
|
},
|
|
30
29
|
"main": "./dist/index.cjs",
|
|
31
30
|
"module": "./dist/index.js",
|
|
@@ -180,7 +179,6 @@
|
|
|
180
179
|
"scripts": {
|
|
181
180
|
"build": "tsc --noEmit && vite build",
|
|
182
181
|
"test": "vitest",
|
|
183
|
-
"cov": "vitest --coverage",
|
|
184
182
|
"lint": "eslint --cache",
|
|
185
183
|
"fix": "eslint --cache --fix"
|
|
186
184
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { describe,
|
|
1
|
+
import { describe, expect, it, vi } from "vitest";
|
|
2
|
+
|
|
2
3
|
import { breaker } from "@/breaker";
|
|
3
4
|
import { TimeSpan } from "@/telem";
|
|
4
5
|
|
|
@@ -52,9 +53,7 @@ describe("breaker", () => {
|
|
|
52
53
|
const brk = breaker.create();
|
|
53
54
|
let attempts = 0;
|
|
54
55
|
|
|
55
|
-
while (await brk())
|
|
56
|
-
attempts++;
|
|
57
|
-
}
|
|
56
|
+
while (await brk()) attempts++;
|
|
58
57
|
|
|
59
58
|
expect(attempts).toBe(5); // Default maxRetries is 5
|
|
60
59
|
});
|
package/src/breaker/breaker.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { sleep } from "@/sleep";
|
|
2
|
-
import { CrudeTimeSpan, TimeSpan } from "@/telem";
|
|
3
1
|
import { z } from "zod";
|
|
4
2
|
|
|
3
|
+
import { sleep } from "@/sleep";
|
|
4
|
+
import { type CrudeTimeSpan, TimeSpan } from "@/telem";
|
|
5
|
+
|
|
5
6
|
export const breakerConfig = z.object({
|
|
6
7
|
interval: TimeSpan.z.optional(),
|
|
7
8
|
maxRetries: z.number().optional(),
|
|
@@ -51,16 +51,8 @@ describe("caseconv", () => {
|
|
|
51
51
|
[{ fooBar: 1 }, { bazQux: 2 }],
|
|
52
52
|
],
|
|
53
53
|
[
|
|
54
|
-
{
|
|
55
|
-
|
|
56
|
-
time_stamp: 123,
|
|
57
|
-
value: [1, 2, 3],
|
|
58
|
-
},
|
|
59
|
-
{
|
|
60
|
-
channelKey: "test",
|
|
61
|
-
timeStamp: 123,
|
|
62
|
-
value: [1, 2, 3],
|
|
63
|
-
},
|
|
54
|
+
{ channel_key: "test", time_stamp: 123, value: [1, 2, 3] },
|
|
55
|
+
{ channelKey: "test", timeStamp: 123, value: [1, 2, 3] },
|
|
64
56
|
],
|
|
65
57
|
];
|
|
66
58
|
SPECS.forEach(([input, expected], i) => {
|
|
@@ -108,16 +100,8 @@ describe("caseconv", () => {
|
|
|
108
100
|
[{ foo_bar: 1 }, { baz_qux: 2 }],
|
|
109
101
|
],
|
|
110
102
|
[
|
|
111
|
-
{
|
|
112
|
-
|
|
113
|
-
timeStamp: 123,
|
|
114
|
-
value: [1, 2, 3],
|
|
115
|
-
},
|
|
116
|
-
{
|
|
117
|
-
channel_key: "test",
|
|
118
|
-
time_stamp: 123,
|
|
119
|
-
value: [1, 2, 3],
|
|
120
|
-
},
|
|
103
|
+
{ channelKey: "test", timeStamp: 123, value: [1, 2, 3] },
|
|
104
|
+
{ channel_key: "test", time_stamp: 123, value: [1, 2, 3] },
|
|
121
105
|
],
|
|
122
106
|
];
|
|
123
107
|
SPECS.forEach(([input, expected], i) => {
|
|
@@ -127,4 +111,20 @@ describe("caseconv", () => {
|
|
|
127
111
|
});
|
|
128
112
|
});
|
|
129
113
|
});
|
|
114
|
+
describe("toKebab", () => {
|
|
115
|
+
const SPECS: [string, string][] = [
|
|
116
|
+
["fooBar", "foo-bar"],
|
|
117
|
+
["fooBarBaz", "foo-bar-baz"],
|
|
118
|
+
["foo bar", "foo-bar"],
|
|
119
|
+
["foo bar baz", "foo-bar-baz"],
|
|
120
|
+
["foo.bar", "foo.bar"],
|
|
121
|
+
["foo.bar.baz", "foo.bar.baz"],
|
|
122
|
+
["Foo Bar", "foo-bar"],
|
|
123
|
+
];
|
|
124
|
+
SPECS.forEach(([input, expected]) => {
|
|
125
|
+
it(`should convert ${input} to ${expected}`, () => {
|
|
126
|
+
expect(caseconv.toKebab(input)).toBe(expected);
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
130
|
});
|
package/src/caseconv/caseconv.ts
CHANGED
|
@@ -77,6 +77,13 @@ const camelToSnakeStr = (str: string): string =>
|
|
|
77
77
|
// Don't convert the first character and don't convert a character that is after a
|
|
78
78
|
// non-alphanumeric character
|
|
79
79
|
str.replace(/([a-z0-9])([A-Z])/g, (_, p1, p2) => `${p1}_${p2.toLowerCase()}`);
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Converts a camelCase string to snake_case.
|
|
83
|
+
*
|
|
84
|
+
* @param str - The string to convert
|
|
85
|
+
* @returns The converted string in snake_case
|
|
86
|
+
*/
|
|
80
87
|
export const camelToSnake = createConverter(camelToSnakeStr);
|
|
81
88
|
|
|
82
89
|
/**
|
|
@@ -109,22 +116,44 @@ export interface Options {
|
|
|
109
116
|
/**
|
|
110
117
|
* Default options for convert function. This option is not recursive.
|
|
111
118
|
*/
|
|
112
|
-
|
|
119
|
+
const defaultOptions: Options = {
|
|
113
120
|
recursive: true,
|
|
114
121
|
recursiveInArray: true,
|
|
115
122
|
keepTypesOnRecursion: [Number, String, Uint8Array],
|
|
116
123
|
};
|
|
117
124
|
|
|
118
|
-
|
|
125
|
+
const validateOptions = (opt: Options = defaultOptions): Options => {
|
|
119
126
|
if (opt.recursive == null) opt = defaultOptions;
|
|
120
127
|
else opt.recursiveInArray ??= false;
|
|
121
128
|
return opt;
|
|
122
129
|
};
|
|
123
130
|
|
|
124
|
-
|
|
131
|
+
const isArrayObject = (obj: any): boolean => obj != null && Array.isArray(obj);
|
|
125
132
|
|
|
126
|
-
|
|
133
|
+
const isValidObject = (obj: any): boolean =>
|
|
127
134
|
obj != null && typeof obj === "object" && !Array.isArray(obj);
|
|
128
135
|
|
|
129
|
-
|
|
136
|
+
const belongToTypes = (obj: any, types?: any[]): boolean =>
|
|
130
137
|
(types || []).some((Type) => obj instanceof Type);
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Converts a string to kebab-case.
|
|
141
|
+
* Handles spaces, camelCase, and uppercase characters.
|
|
142
|
+
*
|
|
143
|
+
* @param str - The string to convert
|
|
144
|
+
* @returns The converted string in kebab-case
|
|
145
|
+
*/
|
|
146
|
+
const toKebabStr = (str: string): string =>
|
|
147
|
+
str
|
|
148
|
+
.replace(/\s+/g, "-")
|
|
149
|
+
.replace(/([a-z0-9])([A-Z])/g, (_, p1, p2) => `${p1}-${p2.toLowerCase()}`)
|
|
150
|
+
.toLowerCase();
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Converts a string to kebab-case.
|
|
154
|
+
* Handles spaces, camelCase, and uppercase characters.
|
|
155
|
+
*
|
|
156
|
+
* @param str - The string to convert
|
|
157
|
+
* @returns The converted string in kebab-case
|
|
158
|
+
*/
|
|
159
|
+
export const toKebab = createConverter(toKebabStr);
|
package/src/compare/compare.ts
CHANGED
|
@@ -99,8 +99,8 @@ export const uniqueUnorderedPrimitiveArrays = <T extends Primitive>(
|
|
|
99
99
|
a: readonly T[] | T[],
|
|
100
100
|
b: readonly T[] | T[],
|
|
101
101
|
): number => {
|
|
102
|
-
const uniqueA = unique(a);
|
|
103
|
-
const uniqueB = unique(b);
|
|
102
|
+
const uniqueA = unique.unique(a);
|
|
103
|
+
const uniqueB = unique.unique(b);
|
|
104
104
|
return unorderedPrimitiveArrays(uniqueA, uniqueB);
|
|
105
105
|
};
|
|
106
106
|
|
package/src/deep/path.ts
CHANGED
|
@@ -146,7 +146,7 @@ export const get = (<V = unknown, T = UnknownRecord>(
|
|
|
146
146
|
result = v as UnknownRecord;
|
|
147
147
|
}
|
|
148
148
|
return result as V;
|
|
149
|
-
}) as
|
|
149
|
+
}) as Get;
|
|
150
150
|
|
|
151
151
|
/**
|
|
152
152
|
* Sets the value at the given path on the object. If the parents of the deep path
|
package/src/index.ts
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
// included in the file licenses/APL.txt.
|
|
9
9
|
|
|
10
10
|
export * from "@/binary";
|
|
11
|
+
export * from "@/breaker";
|
|
11
12
|
export * from "@/caseconv";
|
|
12
13
|
export * from "@/change";
|
|
13
14
|
export * from "@/clamp/clamp";
|
|
@@ -21,6 +22,7 @@ export * from "@/id";
|
|
|
21
22
|
export * from "@/identity";
|
|
22
23
|
export * from "@/invert";
|
|
23
24
|
export * from "@/kv";
|
|
25
|
+
export * from "@/link";
|
|
24
26
|
export * from "@/math";
|
|
25
27
|
export * from "@/migrate";
|
|
26
28
|
export * from "@/observe";
|
|
@@ -41,4 +43,3 @@ export * from "@/unique";
|
|
|
41
43
|
export * from "@/url";
|
|
42
44
|
export * from "@/worker";
|
|
43
45
|
export * from "@/zodutil";
|
|
44
|
-
export * from "@/breaker";
|
|
@@ -7,4 +7,5 @@
|
|
|
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
|
-
export
|
|
10
|
+
export * from "@/kv/mock";
|
|
11
|
+
export * from "@/kv/types";
|
package/src/kv/index.ts
CHANGED
|
@@ -0,0 +1,101 @@
|
|
|
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 { beforeEach, describe, expect, it } from "vitest";
|
|
11
|
+
|
|
12
|
+
import { kv } from "@/kv";
|
|
13
|
+
|
|
14
|
+
describe("MockAsync", () => {
|
|
15
|
+
let db: kv.MockAsync;
|
|
16
|
+
|
|
17
|
+
beforeEach(() => {
|
|
18
|
+
db = new kv.MockAsync();
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it("should set and get values", async () => {
|
|
22
|
+
await db.set("key", "value");
|
|
23
|
+
expect(await db.get("key")).toBe("value");
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it("should return null for non-existent keys", async () => {
|
|
27
|
+
expect(await db.get("non-existent")).toBeNull();
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("should delete values", async () => {
|
|
31
|
+
await db.set("key", "value");
|
|
32
|
+
await db.delete("key");
|
|
33
|
+
expect(await db.get("key")).toBeNull();
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it("should return correct length", async () => {
|
|
37
|
+
expect(await db.length()).toBe(0);
|
|
38
|
+
await db.set("key1", "value1");
|
|
39
|
+
await db.set("key2", "value2");
|
|
40
|
+
expect(await db.length()).toBe(2);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it("should clear all values", async () => {
|
|
44
|
+
await db.set("key1", "value1");
|
|
45
|
+
await db.set("key2", "value2");
|
|
46
|
+
await db.clear();
|
|
47
|
+
expect(await db.length()).toBe(0);
|
|
48
|
+
expect(await db.get("key1")).toBeNull();
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it("should handle different value types", async () => {
|
|
52
|
+
const number = 42;
|
|
53
|
+
const object = { test: "value" };
|
|
54
|
+
const array = [1, 2, 3];
|
|
55
|
+
|
|
56
|
+
await db.set("number", number);
|
|
57
|
+
await db.set("object", object);
|
|
58
|
+
await db.set("array", array);
|
|
59
|
+
|
|
60
|
+
expect(await db.get("number")).toBe(number);
|
|
61
|
+
expect(await db.get("object")).toEqual(object);
|
|
62
|
+
expect(await db.get("array")).toEqual(array);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
describe("MockSync", () => {
|
|
67
|
+
let db: kv.MockSync;
|
|
68
|
+
|
|
69
|
+
beforeEach(() => {
|
|
70
|
+
db = new kv.MockSync();
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it("should set and get values", () => {
|
|
74
|
+
db.set("key", "value");
|
|
75
|
+
expect(db.get("key")).toBe("value");
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it("should return null for non-existent keys", () => {
|
|
79
|
+
expect(db.get("non-existent")).toBeNull();
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it("should delete values", () => {
|
|
83
|
+
db.set("key", "value");
|
|
84
|
+
db.delete("key");
|
|
85
|
+
expect(db.get("key")).toBeNull();
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it("should handle different value types", () => {
|
|
89
|
+
const number = 42;
|
|
90
|
+
const object = { test: "value" };
|
|
91
|
+
const array = [1, 2, 3];
|
|
92
|
+
|
|
93
|
+
db.set("number", number);
|
|
94
|
+
db.set("object", object);
|
|
95
|
+
db.set("array", array);
|
|
96
|
+
|
|
97
|
+
expect(db.get("number")).toBe(number);
|
|
98
|
+
expect(db.get("object")).toEqual(object);
|
|
99
|
+
expect(db.get("array")).toEqual(array);
|
|
100
|
+
});
|
|
101
|
+
});
|
package/src/kv/mock.ts
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// Copyright 2024 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 Async, type KV } from "@/kv/types";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* A mock implementation of an async key-value store that keeps all data in a map
|
|
14
|
+
* in memory.
|
|
15
|
+
*/
|
|
16
|
+
export class MockAsync implements Async {
|
|
17
|
+
readonly store: Map<string, unknown> = new Map();
|
|
18
|
+
|
|
19
|
+
async get<V>(key: string): Promise<V | null> {
|
|
20
|
+
return (this.store.get(key) as V) ?? null;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async set<V>(key: string, value: V): Promise<void> {
|
|
24
|
+
this.store.set(key, value);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async delete(key: string): Promise<void> {
|
|
28
|
+
this.store.delete(key);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async length(): Promise<number> {
|
|
32
|
+
return this.store.size;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async clear(): Promise<void> {
|
|
36
|
+
this.store.clear();
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* A mock implementation of a sync key-value store that keeps all data in a map
|
|
42
|
+
* in memory.
|
|
43
|
+
*/
|
|
44
|
+
export class MockSync implements KV {
|
|
45
|
+
readonly store: Map<string, unknown> = new Map();
|
|
46
|
+
|
|
47
|
+
get<V>(key: string): V | null {
|
|
48
|
+
return (this.store.get(key) as V) ?? null;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
set<V>(key: string, value: V): void {
|
|
52
|
+
this.store.set(key, value);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
delete(key: string): void {
|
|
56
|
+
this.store.delete(key);
|
|
57
|
+
}
|
|
58
|
+
}
|
package/src/kv/types.ts
CHANGED
|
@@ -9,57 +9,51 @@
|
|
|
9
9
|
|
|
10
10
|
import { z } from "zod";
|
|
11
11
|
|
|
12
|
-
export interface
|
|
13
|
-
extends Reader<K, V>,
|
|
14
|
-
Writer<WK, WV>,
|
|
15
|
-
Deleter<D> {}
|
|
16
|
-
|
|
17
|
-
export interface Reader<K = string, V = string> {
|
|
12
|
+
export interface Reader<V = unknown> {
|
|
18
13
|
/** @returns the value for a given key, or null if the key is not present. */
|
|
19
|
-
get: (key:
|
|
14
|
+
get: (key: string) => V | null;
|
|
20
15
|
}
|
|
21
16
|
|
|
22
|
-
export interface Writer<
|
|
17
|
+
export interface Writer<V = unknown> {
|
|
23
18
|
/** Sets a key-value pair in the store. */
|
|
24
|
-
set: (key:
|
|
19
|
+
set: (key: string, value: V) => void;
|
|
25
20
|
}
|
|
26
21
|
|
|
27
|
-
export interface Deleter
|
|
22
|
+
export interface Deleter {
|
|
28
23
|
/** Deletes a key-value pair from the store. */
|
|
29
|
-
delete: (key:
|
|
24
|
+
delete: (key: string) => void;
|
|
30
25
|
}
|
|
31
26
|
|
|
32
|
-
|
|
33
|
-
export interface Async<K = string, V = string, WK = K, WV = V, D = K>
|
|
34
|
-
extends AsyncReader<K, V>,
|
|
35
|
-
AsyncWriter<WK, WV>,
|
|
36
|
-
AsyncDeleter<D> {}
|
|
27
|
+
export interface KV<R = unknown, W = R> extends Reader<R>, Writer<W>, Deleter {}
|
|
37
28
|
|
|
38
29
|
/** A readable key-value store. */
|
|
39
|
-
export interface AsyncReader<
|
|
30
|
+
export interface AsyncReader<V = unknown> {
|
|
40
31
|
/** Get the value for a given key. */
|
|
41
|
-
get: (key:
|
|
32
|
+
get: (key: string) => Promise<V | null>;
|
|
42
33
|
}
|
|
43
34
|
|
|
44
35
|
/** A writable key-value store. */
|
|
45
|
-
export interface AsyncWriter<
|
|
36
|
+
export interface AsyncWriter<V = unknown> {
|
|
46
37
|
/** Sets a key-value pair in the store. The value must be serializable. */
|
|
47
|
-
set: (key:
|
|
38
|
+
set: (key: string, value: V) => Promise<void>;
|
|
48
39
|
}
|
|
49
40
|
|
|
50
41
|
/** A key-value store that can delete key-value pairs. */
|
|
51
|
-
export interface AsyncDeleter
|
|
42
|
+
export interface AsyncDeleter {
|
|
52
43
|
/** Deletes a key-value pair from the store. */
|
|
53
|
-
delete: (key:
|
|
44
|
+
delete: (key: string) => Promise<void>;
|
|
54
45
|
}
|
|
55
46
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
47
|
+
/** A read-writable key-value store. */
|
|
48
|
+
export interface Async<R = unknown, W = R>
|
|
49
|
+
extends AsyncReader<R>,
|
|
50
|
+
AsyncWriter<W>,
|
|
51
|
+
AsyncDeleter {}
|
|
52
|
+
|
|
53
|
+
export const stringPairZ = z.object({ key: z.string(), value: z.string() });
|
|
60
54
|
|
|
61
55
|
/** A general purpose key-value pair. */
|
|
62
|
-
export interface Pair<
|
|
63
|
-
key:
|
|
56
|
+
export interface Pair<V = unknown> {
|
|
57
|
+
key: string;
|
|
64
58
|
value: V;
|
|
65
59
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// Copyright 2024 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 link from "@/link/link";
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// Copyright 2024 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 { is } from "@/link/link";
|
|
13
|
+
|
|
14
|
+
describe("is", () => {
|
|
15
|
+
// Valid IRIs
|
|
16
|
+
it("should return true for a simple HTTP URL", () => {
|
|
17
|
+
expect(is("http://example.com")).toBe(true);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it("should return true for an HTTP URL with a port", () => {
|
|
21
|
+
expect(is("http://example.com:8080")).toBe(true);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it("should return true for an HTTPS URL with path, query, and fragment", () => {
|
|
25
|
+
expect(is("https://example.com/path?query=param#fragment")).toBe(true);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it("should return true for an IRI with IPv4", () => {
|
|
29
|
+
expect(is("http://192.168.1.1")).toBe(true);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it("should return true for an IRI with percent-encoded spaces", () => {
|
|
33
|
+
expect(is("http://example.com/path%20with%20spaces")).toBe(true);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it("should return true for an IRI with query and fragment", () => {
|
|
37
|
+
expect(is("http://example.com/path?query=123#section")).toBe(true);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// Invalid IRIs
|
|
41
|
+
it("should return false for a URL with invalid characters", () => {
|
|
42
|
+
expect(is("http://example.com/invalid|character")).toBe(false);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it("should return false for a scheme with spaces", () => {
|
|
46
|
+
expect(is("ht tp://example.com")).toBe(false);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it("should return false for a URL with a missing host", () => {
|
|
50
|
+
expect(is("http://")).toBe(false);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it("should return false for a URL with an unsupported scheme", () => {
|
|
54
|
+
expect(is("xyz://example.com")).toBe(false);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it("should return false for an IPv6 with double colons", () => {
|
|
58
|
+
expect(is("http://[2001:db8:::1]")).toBe(false);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it("should return false for a scheme with a trailing colon", () => {
|
|
62
|
+
expect(is("http:/example.com")).toBe(false);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it("should return false for a fragment with spaces", () => {
|
|
66
|
+
expect(is("http://example.com#invalid fragment")).toBe(false);
|
|
67
|
+
});
|
|
68
|
+
});
|