tangled
alpha
login
or
join now
desertthunder.dev
/
inkfinite
web based infinite canvas
2
fork
atom
overview
issues
pulls
pipelines
feat: core math primitives
desertthunder.dev
1 month ago
afddf4bc
a1d68f68
+2213
-26
9 changed files
expand all
collapse all
unified
split
.vscode
settings.json
TODO.txt
eslint.config.js
package.json
packages
core
package.json
src
math.ts
tests
math.test.ts
pnpm-lock.yaml
pnpm-workspace.yaml
+10
-2
.vscode/settings.json
···
1
1
{
2
2
"[json]": { "editor.formatOnSave": true, "editor.defaultFormatter": "dprint.dprint" },
3
3
"[jsonc]": { "editor.formatOnSave": true, "editor.defaultFormatter": "dprint.dprint" },
4
4
-
"[javascript]": { "editor.formatOnSave": true, "editor.defaultFormatter": "dprint.dprint" },
5
5
-
"[typescript]": { "editor.formatOnSave": true, "editor.defaultFormatter": "dprint.dprint" }
4
4
+
"[javascript]": {
5
5
+
"editor.formatOnSave": true,
6
6
+
"editor.defaultFormatter": "dprint.dprint",
7
7
+
"editor.codeActionsOnSave": { "source.fixAll.eslint": "always" }
8
8
+
},
9
9
+
"[typescript]": {
10
10
+
"editor.formatOnSave": true,
11
11
+
"editor.defaultFormatter": "dprint.dprint",
12
12
+
"editor.codeActionsOnSave": { "source.fixAll.eslint": "always" }
13
13
+
}
6
14
}
+4
-6
TODO.txt
···
47
47
48
48
Goal: a correct, testable camera transform (world <-> screen).
49
49
50
50
-
Core primitives (/packages/core/src/math):
51
51
-
[ ] Define Vec2 { x, y } + helpers:
50
50
+
Core primitives (/packages/core/src/math.ts):
51
51
+
[x] Define Vec2 { x, y } + helpers:
52
52
- add, sub, mulScalar, len, normalize, dot
53
53
-
54
54
-
[ ] Define Box2 { min: Vec2, max: Vec2 }:
53
53
+
[x] Define Box2 { min: Vec2, max: Vec2 }:
55
54
- fromPoints, containsPoint, intersectsBox
56
56
-
57
57
-
[ ] Define Mat3 (2D affine) or equivalent:
55
55
+
[x] Define Mat3 (2D affine) or equivalent:
58
56
- identity
59
57
- translate(tx, ty)
60
58
- scale(sx, sy)
+15
eslint.config.js
···
1
1
+
// @ts-check
2
2
+
3
3
+
import eslint from "@eslint/js";
4
4
+
import eslintPluginUnicorn from "eslint-plugin-unicorn";
5
5
+
import { defineConfig } from "eslint/config";
6
6
+
import tseslint from "typescript-eslint";
7
7
+
8
8
+
export default defineConfig(
9
9
+
eslint.configs.recommended,
10
10
+
tseslint.configs.recommended,
11
11
+
eslintPluginUnicorn.configs.recommended,
12
12
+
[{
13
13
+
rules: { "unicorn/no-null": "off", "unicorn/prevent-abbreviations": ["error", { "replacements": { "i": false } }] },
14
14
+
}],
15
15
+
);
+16
-3
package.json
···
3
3
"version": "1.0.0",
4
4
"private": true,
5
5
"type": "module",
6
6
-
"workspaces": ["packages/*"],
6
6
+
"workspaces": [
7
7
+
"packages/*"
8
8
+
],
7
9
"scripts": {},
8
8
-
"devDependencies": { "dprint": "^0.50.2" },
9
9
-
"engines": { "node": ">=18.0.0", "pnpm": ">=8.0.0" },
10
10
+
"devDependencies": {
11
11
+
"@eslint/js": "^9.39.2",
12
12
+
"dprint": "^0.50.2",
13
13
+
"eslint": "^9.39.2",
14
14
+
"eslint-plugin-unicorn": "^62.0.0",
15
15
+
"globals": "^16.5.0",
16
16
+
"typescript": "^5.9.3",
17
17
+
"typescript-eslint": "^8.50.0"
18
18
+
},
19
19
+
"engines": {
20
20
+
"node": ">=18.0.0",
21
21
+
"pnpm": ">=8.0.0"
22
22
+
},
10
23
"packageManager": "pnpm@10.26.1"
11
24
}
+5
-15
packages/core/package.json
···
1
1
{
2
2
-
"name": "tsdown-starter",
2
2
+
"name": "inkfinite-core",
3
3
"type": "module",
4
4
"version": "0.0.0",
5
5
"description": "A starter for creating a TypeScript package.",
6
6
"author": "Author Name <author.name@mail.com>",
7
7
"license": "MIT",
8
8
"homepage": "https://github.com/author/library#readme",
9
9
-
"repository": {
10
10
-
"type": "git",
11
11
-
"url": "git+https://github.com/author/library.git"
12
12
-
},
13
13
-
"bugs": {
14
14
-
"url": "https://github.com/author/library/issues"
15
15
-
},
16
16
-
"exports": {
17
17
-
".": "./dist/index.mjs",
18
18
-
"./package.json": "./package.json"
19
19
-
},
9
9
+
"repository": { "type": "git", "url": "git+https://github.com/author/library.git" },
10
10
+
"bugs": { "url": "https://github.com/author/library/issues" },
11
11
+
"exports": { ".": "./dist/index.mjs", "./package.json": "./package.json" },
20
12
"main": "./dist/index.mjs",
21
13
"module": "./dist/index.mjs",
22
14
"types": "./dist/index.d.mts",
23
23
-
"files": [
24
24
-
"dist"
25
25
-
],
15
15
+
"files": ["dist"],
26
16
"scripts": {
27
17
"build": "tsdown",
28
18
"dev": "tsdown --watch",
+360
packages/core/src/math.ts
···
1
1
+
export type Vec2 = { x: number; y: number };
2
2
+
3
3
+
export const Vec2 = {
4
4
+
/**
5
5
+
* Add two vectors
6
6
+
*/
7
7
+
add(a: Vec2, b: Vec2): Vec2 {
8
8
+
return { x: a.x + b.x, y: a.y + b.y };
9
9
+
},
10
10
+
11
11
+
/**
12
12
+
* Subtract vector b from vector a
13
13
+
*/
14
14
+
sub(a: Vec2, b: Vec2): Vec2 {
15
15
+
return { x: a.x - b.x, y: a.y - b.y };
16
16
+
},
17
17
+
18
18
+
/**
19
19
+
* Multiply vector by scalar
20
20
+
*/
21
21
+
mulScalar(v: Vec2, s: number): Vec2 {
22
22
+
return { x: v.x * s, y: v.y * s };
23
23
+
},
24
24
+
25
25
+
/**
26
26
+
* Calculate length (magnitude) of vector
27
27
+
*/
28
28
+
len(v: Vec2): number {
29
29
+
return Math.hypot(v.x, v.y);
30
30
+
},
31
31
+
32
32
+
/**
33
33
+
* Calculate squared length (faster, no sqrt)
34
34
+
*/
35
35
+
lenSq(v: Vec2): number {
36
36
+
return v.x * v.x + v.y * v.y;
37
37
+
},
38
38
+
39
39
+
/**
40
40
+
* Normalize vector to unit length
41
41
+
* Returns zero vector if input length is zero
42
42
+
*/
43
43
+
normalize(v: Vec2): Vec2 {
44
44
+
const length = Vec2.len(v);
45
45
+
if (length === 0) {
46
46
+
return { x: 0, y: 0 };
47
47
+
}
48
48
+
return { x: v.x / length, y: v.y / length };
49
49
+
},
50
50
+
51
51
+
/**
52
52
+
* Calculate dot product of two vectors
53
53
+
*/
54
54
+
dot(a: Vec2, b: Vec2): number {
55
55
+
return a.x * b.x + a.y * b.y;
56
56
+
},
57
57
+
58
58
+
/**
59
59
+
* Calculate distance between two points
60
60
+
*/
61
61
+
dist(a: Vec2, b: Vec2): number {
62
62
+
return Vec2.len(Vec2.sub(a, b));
63
63
+
},
64
64
+
65
65
+
/**
66
66
+
* Calculate squared distance (faster, no sqrt)
67
67
+
*/
68
68
+
distSq(a: Vec2, b: Vec2): number {
69
69
+
return Vec2.lenSq(Vec2.sub(a, b));
70
70
+
},
71
71
+
72
72
+
/**
73
73
+
* Check if two vectors are approximately equal
74
74
+
*/
75
75
+
equals(a: Vec2, b: Vec2, epsilon = 1e-10): boolean {
76
76
+
return Math.abs(a.x - b.x) <= epsilon && Math.abs(a.y - b.y) <= epsilon;
77
77
+
},
78
78
+
79
79
+
/**
80
80
+
* Create a new vector
81
81
+
*/
82
82
+
create(x: number, y: number): Vec2 {
83
83
+
return { x, y };
84
84
+
},
85
85
+
86
86
+
/**
87
87
+
* Clone a vector
88
88
+
*/
89
89
+
clone(v: Vec2): Vec2 {
90
90
+
return { x: v.x, y: v.y };
91
91
+
},
92
92
+
};
93
93
+
94
94
+
export type Box2 = { min: Vec2; max: Vec2 };
95
95
+
96
96
+
export const Box2 = {
97
97
+
/**
98
98
+
* Create a bounding box from an array of points
99
99
+
*/
100
100
+
fromPoints(points: Vec2[]): Box2 {
101
101
+
if (points.length === 0) {
102
102
+
return { min: { x: 0, y: 0 }, max: { x: 0, y: 0 } };
103
103
+
}
104
104
+
105
105
+
let minX = points[0].x;
106
106
+
let minY = points[0].y;
107
107
+
let maxX = points[0].x;
108
108
+
let maxY = points[0].y;
109
109
+
110
110
+
for (let index = 1; index < points.length; index++) {
111
111
+
const p = points[index];
112
112
+
if (p.x < minX) minX = p.x;
113
113
+
if (p.y < minY) minY = p.y;
114
114
+
if (p.x > maxX) maxX = p.x;
115
115
+
if (p.y > maxY) maxY = p.y;
116
116
+
}
117
117
+
118
118
+
return { min: { x: minX, y: minY }, max: { x: maxX, y: maxY } };
119
119
+
},
120
120
+
121
121
+
/**
122
122
+
* Create a box from center and size
123
123
+
*/
124
124
+
fromCenterSize(center: Vec2, width: number, height: number): Box2 {
125
125
+
const halfW = width / 2;
126
126
+
const halfH = height / 2;
127
127
+
return { min: { x: center.x - halfW, y: center.y - halfH }, max: { x: center.x + halfW, y: center.y + halfH } };
128
128
+
},
129
129
+
130
130
+
/**
131
131
+
* Create a box from min/max coordinates
132
132
+
*/
133
133
+
create(minX: number, minY: number, maxX: number, maxY: number): Box2 {
134
134
+
return { min: { x: minX, y: minY }, max: { x: maxX, y: maxY } };
135
135
+
},
136
136
+
137
137
+
/**
138
138
+
* Check if a point is inside the box
139
139
+
*/
140
140
+
containsPoint(box: Box2, point: Vec2): boolean {
141
141
+
return (point.x >= box.min.x && point.x <= box.max.x && point.y >= box.min.y && point.y <= box.max.y);
142
142
+
},
143
143
+
144
144
+
/**
145
145
+
* Check if two boxes intersect
146
146
+
*/
147
147
+
intersectsBox(a: Box2, b: Box2): boolean {
148
148
+
return !(a.max.x < b.min.x || a.min.x > b.max.x || a.max.y < b.min.y || a.min.y > b.max.y);
149
149
+
},
150
150
+
151
151
+
/**
152
152
+
* Check if box a completely contains box b
153
153
+
*/
154
154
+
containsBox(a: Box2, b: Box2): boolean {
155
155
+
return (b.min.x >= a.min.x && b.max.x <= a.max.x && b.min.y >= a.min.y && b.max.y <= a.max.y);
156
156
+
},
157
157
+
158
158
+
/**
159
159
+
* Get the width of the box
160
160
+
*/
161
161
+
width(box: Box2): number {
162
162
+
return box.max.x - box.min.x;
163
163
+
},
164
164
+
165
165
+
/**
166
166
+
* Get the height of the box
167
167
+
*/
168
168
+
height(box: Box2): number {
169
169
+
return box.max.y - box.min.y;
170
170
+
},
171
171
+
172
172
+
/**
173
173
+
* Get the center point of the box
174
174
+
*/
175
175
+
center(box: Box2): Vec2 {
176
176
+
return { x: (box.min.x + box.max.x) / 2, y: (box.min.y + box.max.y) / 2 };
177
177
+
},
178
178
+
179
179
+
/**
180
180
+
* Get the area of the box
181
181
+
*/
182
182
+
area(box: Box2): number {
183
183
+
return Box2.width(box) * Box2.height(box);
184
184
+
},
185
185
+
186
186
+
/**
187
187
+
* Expand box to include a point
188
188
+
*/
189
189
+
expandToPoint(box: Box2, point: Vec2): Box2 {
190
190
+
return {
191
191
+
min: { x: Math.min(box.min.x, point.x), y: Math.min(box.min.y, point.y) },
192
192
+
max: { x: Math.max(box.max.x, point.x), y: Math.max(box.max.y, point.y) },
193
193
+
};
194
194
+
},
195
195
+
196
196
+
/**
197
197
+
* Clone a box
198
198
+
*/
199
199
+
clone(box: Box2): Box2 {
200
200
+
return { min: { ...box.min }, max: { ...box.max } };
201
201
+
},
202
202
+
};
203
203
+
204
204
+
/**
205
205
+
* 3x3 matrix stored in column-major order for 2D affine transforms
206
206
+
* Layout:
207
207
+
* [a c tx]
208
208
+
* [b d ty]
209
209
+
* [0 0 1]
210
210
+
*
211
211
+
* Stored as: [a, b, 0, c, d, 0, tx, ty, 1]
212
212
+
*/
213
213
+
export type Mat3 = [number, number, number, number, number, number, number, number, number];
214
214
+
215
215
+
export const Mat3 = {
216
216
+
/**
217
217
+
* Create an identity matrix
218
218
+
*/
219
219
+
identity(): Mat3 {
220
220
+
return [1, 0, 0, 0, 1, 0, 0, 0, 1];
221
221
+
},
222
222
+
223
223
+
/**
224
224
+
* Create a translation matrix
225
225
+
*/
226
226
+
translate(tx: number, ty: number): Mat3 {
227
227
+
return [1, 0, 0, 0, 1, 0, tx, ty, 1];
228
228
+
},
229
229
+
230
230
+
/**
231
231
+
* Create a scale matrix
232
232
+
*/
233
233
+
scale(sx: number, sy: number): Mat3 {
234
234
+
return [sx, 0, 0, 0, sy, 0, 0, 0, 1];
235
235
+
},
236
236
+
237
237
+
/**
238
238
+
* Create a rotation matrix
239
239
+
* @param theta - angle in radians
240
240
+
*/
241
241
+
rotate(theta: number): Mat3 {
242
242
+
const c = Math.cos(theta);
243
243
+
const s = Math.sin(theta);
244
244
+
return [c, s, 0, -s, c, 0, 0, 0, 1];
245
245
+
},
246
246
+
247
247
+
/**
248
248
+
* Multiply two matrices: result = a * b
249
249
+
* Order matters: transformations are applied right to left
250
250
+
*/
251
251
+
multiply(a: Mat3, b: Mat3): Mat3 {
252
252
+
const a00 = a[0], a01 = a[1], a02 = a[2];
253
253
+
const a10 = a[3], a11 = a[4], a12 = a[5];
254
254
+
const a20 = a[6], a21 = a[7], a22 = a[8];
255
255
+
256
256
+
const b00 = b[0], b01 = b[1], b02 = b[2];
257
257
+
const b10 = b[3], b11 = b[4], b12 = b[5];
258
258
+
const b20 = b[6], b21 = b[7], b22 = b[8];
259
259
+
260
260
+
return [
261
261
+
a00 * b00 + a10 * b01 + a20 * b02,
262
262
+
a01 * b00 + a11 * b01 + a21 * b02,
263
263
+
a02 * b00 + a12 * b01 + a22 * b02,
264
264
+
265
265
+
a00 * b10 + a10 * b11 + a20 * b12,
266
266
+
a01 * b10 + a11 * b11 + a21 * b12,
267
267
+
a02 * b10 + a12 * b11 + a22 * b12,
268
268
+
269
269
+
a00 * b20 + a10 * b21 + a20 * b22,
270
270
+
a01 * b20 + a11 * b21 + a21 * b22,
271
271
+
a02 * b20 + a12 * b21 + a22 * b22,
272
272
+
];
273
273
+
},
274
274
+
275
275
+
/**
276
276
+
* Transform a point by a matrix
277
277
+
*/
278
278
+
transformPoint(m: Mat3, p: Vec2): Vec2 {
279
279
+
const x = m[0] * p.x + m[3] * p.y + m[6];
280
280
+
const y = m[1] * p.x + m[4] * p.y + m[7];
281
281
+
return { x, y };
282
282
+
},
283
283
+
284
284
+
/**
285
285
+
* Invert a matrix
286
286
+
* Returns null if matrix is not invertible
287
287
+
*/
288
288
+
invert(m: Mat3): Mat3 | null {
289
289
+
const a00 = m[0], a01 = m[1], a02 = m[2];
290
290
+
const a10 = m[3], a11 = m[4], a12 = m[5];
291
291
+
const a20 = m[6], a21 = m[7], a22 = m[8];
292
292
+
293
293
+
const b01 = a22 * a11 - a12 * a21;
294
294
+
const b11 = -a22 * a10 + a12 * a20;
295
295
+
const b21 = a21 * a10 - a11 * a20;
296
296
+
297
297
+
const det = a00 * b01 + a01 * b11 + a02 * b21;
298
298
+
299
299
+
if (Math.abs(det) < 1e-10) {
300
300
+
return null;
301
301
+
}
302
302
+
303
303
+
const invDet = 1 / det;
304
304
+
305
305
+
return [
306
306
+
b01 * invDet,
307
307
+
(-a22 * a01 + a02 * a21) * invDet,
308
308
+
(a12 * a01 - a02 * a11) * invDet,
309
309
+
310
310
+
b11 * invDet,
311
311
+
(a22 * a00 - a02 * a20) * invDet,
312
312
+
(-a12 * a00 + a02 * a10) * invDet,
313
313
+
314
314
+
b21 * invDet,
315
315
+
(-a21 * a00 + a01 * a20) * invDet,
316
316
+
(a11 * a00 - a01 * a10) * invDet,
317
317
+
];
318
318
+
},
319
319
+
320
320
+
/**
321
321
+
* Get the determinant of a matrix
322
322
+
*/
323
323
+
determinant(m: Mat3): number {
324
324
+
const a00 = m[0], a01 = m[1], a02 = m[2];
325
325
+
const a10 = m[3], a11 = m[4], a12 = m[5];
326
326
+
const a20 = m[6], a21 = m[7], a22 = m[8];
327
327
+
328
328
+
return (a00 * (a22 * a11 - a12 * a21) + a01 * (-a22 * a10 + a12 * a20) + a02 * (a21 * a10 - a11 * a20));
329
329
+
},
330
330
+
331
331
+
/**
332
332
+
* Clone a matrix
333
333
+
*/
334
334
+
clone(m: Mat3): Mat3 {
335
335
+
return [...m] as Mat3;
336
336
+
},
337
337
+
338
338
+
/**
339
339
+
* Check if two matrices are approximately equal
340
340
+
*/
341
341
+
equals(a: Mat3, b: Mat3, epsilon = 1e-10): boolean {
342
342
+
for (let index = 0; index < 9; index++) {
343
343
+
if (Math.abs(a[index] - b[index]) >= epsilon) {
344
344
+
return false;
345
345
+
}
346
346
+
}
347
347
+
return true;
348
348
+
},
349
349
+
350
350
+
/**
351
351
+
* Create a combined transform matrix
352
352
+
* Applies in order: translate -> rotate -> scale
353
353
+
*/
354
354
+
fromTransform(tx: number, ty: number, rotation: number, sx: number, sy: number): Mat3 {
355
355
+
const c = Math.cos(rotation);
356
356
+
const s = Math.sin(rotation);
357
357
+
358
358
+
return [c * sx, s * sx, 0, -s * sy, c * sy, 0, tx, ty, 1];
359
359
+
},
360
360
+
};
+770
packages/core/tests/math.test.ts
···
1
1
+
import { describe, expect, it } from "vitest";
2
2
+
import { Box2, Mat3, Vec2 } from "../src/math";
3
3
+
4
4
+
describe("Vec2", () => {
5
5
+
describe("add", () => {
6
6
+
it.each([{
7
7
+
description: "should add two positive vectors",
8
8
+
a: { x: 1, y: 2 },
9
9
+
b: { x: 3, y: 4 },
10
10
+
expected: { x: 4, y: 6 },
11
11
+
}, {
12
12
+
description: "should handle negative values",
13
13
+
a: { x: -1, y: -2 },
14
14
+
b: { x: 3, y: 4 },
15
15
+
expected: { x: 2, y: 2 },
16
16
+
}, {
17
17
+
description: "should handle zero vectors",
18
18
+
a: { x: 0, y: 0 },
19
19
+
b: { x: 5, y: 10 },
20
20
+
expected: { x: 5, y: 10 },
21
21
+
}])("$description", ({ a, b, expected }) => {
22
22
+
expect(Vec2.add(a, b)).toEqual(expected);
23
23
+
});
24
24
+
25
25
+
it("should be commutative", () => {
26
26
+
const a = { x: 1, y: 2 };
27
27
+
const b = { x: 3, y: 4 };
28
28
+
expect(Vec2.add(a, b)).toEqual(Vec2.add(b, a));
29
29
+
});
30
30
+
});
31
31
+
32
32
+
describe("sub", () => {
33
33
+
it.each([{
34
34
+
description: "should subtract two vectors",
35
35
+
a: { x: 5, y: 7 },
36
36
+
b: { x: 2, y: 3 },
37
37
+
expected: { x: 3, y: 4 },
38
38
+
}, {
39
39
+
description: "should handle negative results",
40
40
+
a: { x: 1, y: 2 },
41
41
+
b: { x: 3, y: 4 },
42
42
+
expected: { x: -2, y: -2 },
43
43
+
}, {
44
44
+
description: "should handle zero vectors",
45
45
+
a: { x: 5, y: 10 },
46
46
+
b: { x: 0, y: 0 },
47
47
+
expected: { x: 5, y: 10 },
48
48
+
}])("$description", ({ a, b, expected }) => {
49
49
+
expect(Vec2.sub(a, b)).toEqual(expected);
50
50
+
});
51
51
+
52
52
+
it("should return zero vector when subtracting identical vectors", () => {
53
53
+
const a = { x: 5, y: 10 };
54
54
+
expect(Vec2.sub(a, a)).toEqual({ x: 0, y: 0 });
55
55
+
});
56
56
+
});
57
57
+
58
58
+
describe("mulScalar", () => {
59
59
+
it.each([
60
60
+
{ description: "should multiply by positive scalar", v: { x: 2, y: 3 }, scalar: 4, expected: { x: 8, y: 12 } },
61
61
+
{ description: "should multiply by negative scalar", v: { x: 2, y: 3 }, scalar: -2, expected: { x: -4, y: -6 } },
62
62
+
{ description: "should multiply by zero", v: { x: 5, y: 10 }, scalar: 0, expected: { x: 0, y: 0 } },
63
63
+
{ description: "should multiply by one (identity)", v: { x: 5, y: 10 }, scalar: 1, expected: { x: 5, y: 10 } },
64
64
+
{ description: "should handle fractional scalars", v: { x: 10, y: 20 }, scalar: 0.5, expected: { x: 5, y: 10 } },
65
65
+
])("$description", ({ v, scalar, expected }) => {
66
66
+
expect(Vec2.mulScalar(v, scalar)).toEqual(expected);
67
67
+
});
68
68
+
});
69
69
+
70
70
+
describe("len", () => {
71
71
+
it.each([
72
72
+
{ description: "should calculate length of 3-4-5 triangle", v: { x: 3, y: 4 }, expected: 5 },
73
73
+
{ description: "should return zero for zero vector", v: { x: 0, y: 0 }, expected: 0 },
74
74
+
{ description: "should handle negative components", v: { x: -3, y: -4 }, expected: 5 },
75
75
+
{ description: "should calculate length for unit vector X", v: { x: 1, y: 0 }, expected: 1 },
76
76
+
{ description: "should calculate length for unit vector Y", v: { x: 0, y: 1 }, expected: 1 },
77
77
+
])("$description", ({ v, expected }) => {
78
78
+
expect(Vec2.len(v)).toBe(expected);
79
79
+
});
80
80
+
81
81
+
it("should handle very small vectors", () => {
82
82
+
const v = { x: 1e-10, y: 1e-10 };
83
83
+
expect(Vec2.len(v)).toBeCloseTo(Math.sqrt(2) * 1e-10, 20);
84
84
+
});
85
85
+
});
86
86
+
87
87
+
describe("lenSq", () => {
88
88
+
it.each([{ description: "should calculate squared length", v: { x: 3, y: 4 }, expected: 25 }, {
89
89
+
description: "should return zero for zero vector",
90
90
+
v: { x: 0, y: 0 },
91
91
+
expected: 0,
92
92
+
}])("$description", ({ v, expected }) => {
93
93
+
expect(Vec2.lenSq(v)).toBe(expected);
94
94
+
});
95
95
+
96
96
+
it("should match len squared", () => {
97
97
+
const v = { x: 3, y: 4 };
98
98
+
expect(Vec2.lenSq(v)).toBe(Vec2.len(v) ** 2);
99
99
+
});
100
100
+
});
101
101
+
102
102
+
describe("normalize", () => {
103
103
+
it("should normalize vector to unit length", () => {
104
104
+
const v = { x: 3, y: 4 };
105
105
+
const result = Vec2.normalize(v);
106
106
+
expect(result.x).toBeCloseTo(0.6);
107
107
+
expect(result.y).toBeCloseTo(0.8);
108
108
+
expect(Vec2.len(result)).toBeCloseTo(1);
109
109
+
});
110
110
+
111
111
+
it("should handle zero vector (return zero)", () => {
112
112
+
const v = { x: 0, y: 0 };
113
113
+
expect(Vec2.normalize(v)).toEqual({ x: 0, y: 0 });
114
114
+
});
115
115
+
116
116
+
it("should handle already normalized vectors", () => {
117
117
+
const v = { x: 1, y: 0 };
118
118
+
const result = Vec2.normalize(v);
119
119
+
expect(result.x).toBeCloseTo(1);
120
120
+
expect(result.y).toBeCloseTo(0);
121
121
+
});
122
122
+
123
123
+
it("should handle negative components", () => {
124
124
+
const v = { x: -3, y: -4 };
125
125
+
const result = Vec2.normalize(v);
126
126
+
expect(result.x).toBeCloseTo(-0.6);
127
127
+
expect(result.y).toBeCloseTo(-0.8);
128
128
+
expect(Vec2.len(result)).toBeCloseTo(1);
129
129
+
});
130
130
+
131
131
+
it("should handle very small vectors", () => {
132
132
+
const v = { x: 1e-100, y: 1e-100 };
133
133
+
const result = Vec2.normalize(v);
134
134
+
const expectedX = 1 / Math.sqrt(2);
135
135
+
expect(result.x).toBeCloseTo(expectedX, 5);
136
136
+
expect(result.y).toBeCloseTo(expectedX, 5);
137
137
+
});
138
138
+
});
139
139
+
140
140
+
describe("dot", () => {
141
141
+
it.each([
142
142
+
{ description: "should calculate dot product", a: { x: 2, y: 3 }, b: { x: 4, y: 5 }, expected: 23 },
143
143
+
{
144
144
+
description: "should return zero for perpendicular vectors",
145
145
+
a: { x: 1, y: 0 },
146
146
+
b: { x: 0, y: 1 },
147
147
+
expected: 0,
148
148
+
},
149
149
+
{ description: "should handle negative values", a: { x: 2, y: 3 }, b: { x: -4, y: -5 }, expected: -23 },
150
150
+
{ description: "should return zero with zero vector", a: { x: 5, y: 10 }, b: { x: 0, y: 0 }, expected: 0 },
151
151
+
{
152
152
+
description: "should calculate dot product of parallel vectors",
153
153
+
a: { x: 2, y: 3 },
154
154
+
b: { x: 4, y: 6 },
155
155
+
expected: 26,
156
156
+
},
157
157
+
])("$description", ({ a, b, expected }) => {
158
158
+
expect(Vec2.dot(a, b)).toBe(expected);
159
159
+
});
160
160
+
161
161
+
it("should be commutative", () => {
162
162
+
const a = { x: 2, y: 3 };
163
163
+
const b = { x: 4, y: 5 };
164
164
+
expect(Vec2.dot(a, b)).toBe(Vec2.dot(b, a));
165
165
+
});
166
166
+
});
167
167
+
168
168
+
describe("dist and distSq", () => {
169
169
+
it.each([{
170
170
+
description: "should calculate distance between two points",
171
171
+
a: { x: 0, y: 0 },
172
172
+
b: { x: 3, y: 4 },
173
173
+
expectedDist: 5,
174
174
+
expectedDistSq: 25,
175
175
+
}, {
176
176
+
description: "should return zero for identical points",
177
177
+
a: { x: 5, y: 10 },
178
178
+
b: { x: 5, y: 10 },
179
179
+
expectedDist: 0,
180
180
+
expectedDistSq: 0,
181
181
+
}, {
182
182
+
description: "should handle negative coordinates",
183
183
+
a: { x: -3, y: -4 },
184
184
+
b: { x: 0, y: 0 },
185
185
+
expectedDist: 5,
186
186
+
expectedDistSq: 25,
187
187
+
}])("$description", ({ a, b, expectedDist, expectedDistSq }) => {
188
188
+
expect(Vec2.dist(a, b)).toBe(expectedDist);
189
189
+
expect(Vec2.distSq(a, b)).toBe(expectedDistSq);
190
190
+
});
191
191
+
192
192
+
it("should be symmetric", () => {
193
193
+
const a = { x: 1, y: 2 };
194
194
+
const b = { x: 4, y: 6 };
195
195
+
expect(Vec2.dist(a, b)).toBe(Vec2.dist(b, a));
196
196
+
});
197
197
+
198
198
+
it("distSq should match dist squared", () => {
199
199
+
const a = { x: 1, y: 2 };
200
200
+
const b = { x: 4, y: 6 };
201
201
+
expect(Vec2.distSq(a, b)).toBe(Vec2.dist(a, b) ** 2);
202
202
+
});
203
203
+
});
204
204
+
205
205
+
describe("equals", () => {
206
206
+
it.each([{
207
207
+
description: "should return true for identical vectors",
208
208
+
a: { x: 1.5, y: 2.5 },
209
209
+
b: { x: 1.5, y: 2.5 },
210
210
+
expected: true,
211
211
+
}, {
212
212
+
description: "should return false for different vectors",
213
213
+
a: { x: 1, y: 2 },
214
214
+
b: { x: 3, y: 4 },
215
215
+
expected: false,
216
216
+
}])("$description", ({ a, b, expected }) => {
217
217
+
expect(Vec2.equals(a, b)).toBe(expected);
218
218
+
});
219
219
+
220
220
+
it("should use epsilon for floating point comparison", () => {
221
221
+
const a = { x: 1 + 5e-11, y: 2 + 5e-11 };
222
222
+
const b = { x: 1, y: 2 };
223
223
+
expect(Vec2.equals(a, b)).toBe(true);
224
224
+
});
225
225
+
226
226
+
it("should allow custom epsilon", () => {
227
227
+
const a = { x: 1.001, y: 2.001 };
228
228
+
const b = { x: 1, y: 2 };
229
229
+
expect(Vec2.equals(a, b, 0.01)).toBe(true);
230
230
+
expect(Vec2.equals(a, b, 0.0001)).toBe(false);
231
231
+
});
232
232
+
});
233
233
+
234
234
+
describe("create and clone", () => {
235
235
+
it("should create a vector", () => {
236
236
+
expect(Vec2.create(3, 4)).toEqual({ x: 3, y: 4 });
237
237
+
});
238
238
+
239
239
+
it("should clone a vector", () => {
240
240
+
const original = { x: 5, y: 10 };
241
241
+
const cloned = Vec2.clone(original);
242
242
+
expect(cloned).toEqual(original);
243
243
+
expect(cloned).not.toBe(original);
244
244
+
});
245
245
+
});
246
246
+
});
247
247
+
248
248
+
describe("Box2", () => {
249
249
+
describe("fromPoints", () => {
250
250
+
it.each([
251
251
+
{
252
252
+
description: "should create box from multiple points",
253
253
+
points: [{ x: 1, y: 2 }, { x: 5, y: 8 }, { x: 3, y: 4 }],
254
254
+
expected: { min: { x: 1, y: 2 }, max: { x: 5, y: 8 } },
255
255
+
},
256
256
+
{
257
257
+
description: "should handle single point",
258
258
+
points: [{ x: 3, y: 4 }],
259
259
+
expected: { min: { x: 3, y: 4 }, max: { x: 3, y: 4 } },
260
260
+
},
261
261
+
{ description: "should handle empty array", points: [], expected: { min: { x: 0, y: 0 }, max: { x: 0, y: 0 } } },
262
262
+
{
263
263
+
description: "should handle negative coordinates",
264
264
+
points: [{ x: -5, y: -3 }, { x: 2, y: 4 }, { x: -1, y: 0 }],
265
265
+
expected: { min: { x: -5, y: -3 }, max: { x: 2, y: 4 } },
266
266
+
},
267
267
+
])("$description", ({ points, expected }) => {
268
268
+
expect(Box2.fromPoints(points)).toEqual(expected);
269
269
+
});
270
270
+
271
271
+
it("should handle points in any order", () => {
272
272
+
const points1 = [{ x: 0, y: 0 }, { x: 10, y: 10 }];
273
273
+
const points2 = [{ x: 10, y: 10 }, { x: 0, y: 0 }];
274
274
+
expect(Box2.fromPoints(points1)).toEqual(Box2.fromPoints(points2));
275
275
+
});
276
276
+
});
277
277
+
278
278
+
describe("fromCenterSize", () => {
279
279
+
it("should create box from center and size", () => {
280
280
+
const center = { x: 5, y: 5 };
281
281
+
const box = Box2.fromCenterSize(center, 10, 6);
282
282
+
expect(box).toEqual({ min: { x: 0, y: 2 }, max: { x: 10, y: 8 } });
283
283
+
});
284
284
+
285
285
+
it("should handle zero size", () => {
286
286
+
const center = { x: 5, y: 5 };
287
287
+
const box = Box2.fromCenterSize(center, 0, 0);
288
288
+
expect(box).toEqual({ min: { x: 5, y: 5 }, max: { x: 5, y: 5 } });
289
289
+
});
290
290
+
291
291
+
it("should handle odd dimensions", () => {
292
292
+
const center = { x: 0, y: 0 };
293
293
+
const box = Box2.fromCenterSize(center, 5, 3);
294
294
+
expect(box.min.x).toBeCloseTo(-2.5);
295
295
+
expect(box.min.y).toBeCloseTo(-1.5);
296
296
+
expect(box.max.x).toBeCloseTo(2.5);
297
297
+
expect(box.max.y).toBeCloseTo(1.5);
298
298
+
});
299
299
+
});
300
300
+
301
301
+
describe("create", () => {
302
302
+
it("should create box from coordinates", () => {
303
303
+
expect(Box2.create(0, 0, 10, 10)).toEqual({ min: { x: 0, y: 0 }, max: { x: 10, y: 10 } });
304
304
+
});
305
305
+
});
306
306
+
307
307
+
describe("containsPoint", () => {
308
308
+
const box = Box2.create(0, 0, 10, 10);
309
309
+
310
310
+
it.each([
311
311
+
{ description: "point inside box", point: { x: 5, y: 5 }, expected: true },
312
312
+
{ description: "point on left edge", point: { x: 0, y: 5 }, expected: true },
313
313
+
{ description: "point on right edge", point: { x: 10, y: 5 }, expected: true },
314
314
+
{ description: "point on top edge", point: { x: 5, y: 0 }, expected: true },
315
315
+
{ description: "point on bottom edge", point: { x: 5, y: 10 }, expected: true },
316
316
+
{ description: "top-left corner", point: { x: 0, y: 0 }, expected: true },
317
317
+
{ description: "bottom-right corner", point: { x: 10, y: 10 }, expected: true },
318
318
+
{ description: "point left of box", point: { x: -1, y: 5 }, expected: false },
319
319
+
{ description: "point right of box", point: { x: 11, y: 5 }, expected: false },
320
320
+
{ description: "point above box", point: { x: 5, y: -1 }, expected: false },
321
321
+
{ description: "point below box", point: { x: 5, y: 11 }, expected: false },
322
322
+
])("should handle $description", ({ point, expected }) => {
323
323
+
expect(Box2.containsPoint(box, point)).toBe(expected);
324
324
+
});
325
325
+
326
326
+
it("should handle negative coordinates", () => {
327
327
+
const negBox = Box2.create(-10, -10, 10, 10);
328
328
+
expect(Box2.containsPoint(negBox, { x: 0, y: 0 })).toBe(true);
329
329
+
expect(Box2.containsPoint(negBox, { x: -5, y: -5 })).toBe(true);
330
330
+
expect(Box2.containsPoint(negBox, { x: -11, y: 0 })).toBe(false);
331
331
+
});
332
332
+
333
333
+
it("should handle zero-size box", () => {
334
334
+
const pointBox = Box2.create(5, 5, 5, 5);
335
335
+
expect(Box2.containsPoint(pointBox, { x: 5, y: 5 })).toBe(true);
336
336
+
expect(Box2.containsPoint(pointBox, { x: 5.1, y: 5 })).toBe(false);
337
337
+
});
338
338
+
});
339
339
+
340
340
+
describe("intersectsBox", () => {
341
341
+
it.each([{
342
342
+
description: "overlapping boxes",
343
343
+
a: Box2.create(0, 0, 10, 10),
344
344
+
b: Box2.create(5, 5, 15, 15),
345
345
+
expected: true,
346
346
+
}, {
347
347
+
description: "boxes touching at edge",
348
348
+
a: Box2.create(0, 0, 10, 10),
349
349
+
b: Box2.create(10, 0, 20, 10),
350
350
+
expected: true,
351
351
+
}, {
352
352
+
description: "one box contains another",
353
353
+
a: Box2.create(0, 0, 10, 10),
354
354
+
b: Box2.create(2, 2, 8, 8),
355
355
+
expected: true,
356
356
+
}, {
357
357
+
description: "non-overlapping boxes",
358
358
+
a: Box2.create(0, 0, 10, 10),
359
359
+
b: Box2.create(11, 11, 20, 20),
360
360
+
expected: false,
361
361
+
}, {
362
362
+
description: "boxes separated horizontally",
363
363
+
a: Box2.create(0, 0, 10, 10),
364
364
+
b: Box2.create(11, 0, 20, 10),
365
365
+
expected: false,
366
366
+
}, {
367
367
+
description: "boxes separated vertically",
368
368
+
a: Box2.create(0, 0, 10, 10),
369
369
+
b: Box2.create(0, 11, 10, 20),
370
370
+
expected: false,
371
371
+
}])("should handle $description", ({ a, b, expected }) => {
372
372
+
expect(Box2.intersectsBox(a, b)).toBe(expected);
373
373
+
});
374
374
+
375
375
+
it("should handle negative coordinates", () => {
376
376
+
const a = Box2.create(-10, -10, 0, 0);
377
377
+
const b = Box2.create(-5, -5, 5, 5);
378
378
+
expect(Box2.intersectsBox(a, b)).toBe(true);
379
379
+
});
380
380
+
381
381
+
it("should be symmetric", () => {
382
382
+
const a = Box2.create(0, 0, 10, 10);
383
383
+
const b = Box2.create(5, 5, 15, 15);
384
384
+
expect(Box2.intersectsBox(a, b)).toBe(Box2.intersectsBox(b, a));
385
385
+
});
386
386
+
});
387
387
+
388
388
+
describe("containsBox", () => {
389
389
+
it.each([
390
390
+
{ description: "a contains b", a: Box2.create(0, 0, 10, 10), b: Box2.create(2, 2, 8, 8), expected: true },
391
391
+
{
392
392
+
description: "b contains a (should be false)",
393
393
+
a: Box2.create(2, 2, 8, 8),
394
394
+
b: Box2.create(0, 0, 10, 10),
395
395
+
expected: false,
396
396
+
},
397
397
+
{ description: "identical boxes", a: Box2.create(0, 0, 10, 10), b: Box2.create(0, 0, 10, 10), expected: true },
398
398
+
{
399
399
+
description: "overlapping but not contained",
400
400
+
a: Box2.create(0, 0, 10, 10),
401
401
+
b: Box2.create(5, 5, 15, 15),
402
402
+
expected: false,
403
403
+
},
404
404
+
{
405
405
+
description: "boxes just touching",
406
406
+
a: Box2.create(0, 0, 10, 10),
407
407
+
b: Box2.create(10, 0, 20, 10),
408
408
+
expected: false,
409
409
+
},
410
410
+
])("should handle $description", ({ a, b, expected }) => {
411
411
+
expect(Box2.containsBox(a, b)).toBe(expected);
412
412
+
});
413
413
+
});
414
414
+
415
415
+
describe("width, height, center, area", () => {
416
416
+
it.each([{
417
417
+
description: "standard box",
418
418
+
box: Box2.create(0, 0, 10, 5),
419
419
+
width: 10,
420
420
+
height: 5,
421
421
+
center: { x: 5, y: 2.5 },
422
422
+
area: 50,
423
423
+
}, {
424
424
+
description: "zero-width box",
425
425
+
box: Box2.create(5, 5, 5, 10),
426
426
+
width: 0,
427
427
+
height: 5,
428
428
+
center: { x: 5, y: 7.5 },
429
429
+
area: 0,
430
430
+
}, {
431
431
+
description: "negative coordinate box",
432
432
+
box: Box2.create(-10, -5, 10, 5),
433
433
+
width: 20,
434
434
+
height: 10,
435
435
+
center: { x: 0, y: 0 },
436
436
+
area: 200,
437
437
+
}, {
438
438
+
description: "zero-size box",
439
439
+
box: Box2.create(5, 5, 5, 5),
440
440
+
width: 0,
441
441
+
height: 0,
442
442
+
center: { x: 5, y: 5 },
443
443
+
area: 0,
444
444
+
}])("should calculate properties for $description", ({ box, width, height, center, area }) => {
445
445
+
expect(Box2.width(box)).toBe(width);
446
446
+
expect(Box2.height(box)).toBe(height);
447
447
+
expect(Box2.center(box)).toEqual(center);
448
448
+
expect(Box2.area(box)).toBe(area);
449
449
+
});
450
450
+
});
451
451
+
452
452
+
describe("expandToPoint", () => {
453
453
+
it.each([{
454
454
+
description: "expand to point outside (right)",
455
455
+
box: Box2.create(0, 0, 10, 10),
456
456
+
point: { x: 15, y: 5 },
457
457
+
expected: { min: { x: 0, y: 0 }, max: { x: 15, y: 10 } },
458
458
+
}, {
459
459
+
description: "point inside (no change)",
460
460
+
box: Box2.create(0, 0, 10, 10),
461
461
+
point: { x: 5, y: 5 },
462
462
+
expected: { min: { x: 0, y: 0 }, max: { x: 10, y: 10 } },
463
463
+
}, {
464
464
+
description: "expand in multiple directions",
465
465
+
box: Box2.create(5, 5, 10, 10),
466
466
+
point: { x: 0, y: 15 },
467
467
+
expected: { min: { x: 0, y: 5 }, max: { x: 10, y: 15 } },
468
468
+
}, {
469
469
+
description: "expand to negative coordinates",
470
470
+
box: Box2.create(0, 0, 10, 10),
471
471
+
point: { x: -5, y: -5 },
472
472
+
expected: { min: { x: -5, y: -5 }, max: { x: 10, y: 10 } },
473
473
+
}])("should $description", ({ box, point, expected }) => {
474
474
+
expect(Box2.expandToPoint(box, point)).toEqual(expected);
475
475
+
});
476
476
+
});
477
477
+
478
478
+
describe("clone", () => {
479
479
+
it("should create a copy of the box", () => {
480
480
+
const box = Box2.create(0, 0, 10, 10);
481
481
+
const cloned = Box2.clone(box);
482
482
+
expect(cloned).toEqual(box);
483
483
+
expect(cloned).not.toBe(box);
484
484
+
expect(cloned.min).not.toBe(box.min);
485
485
+
expect(cloned.max).not.toBe(box.max);
486
486
+
});
487
487
+
});
488
488
+
});
489
489
+
490
490
+
describe("Mat3", () => {
491
491
+
describe("identity", () => {
492
492
+
it("should create identity matrix", () => {
493
493
+
expect(Mat3.identity()).toEqual([1, 0, 0, 0, 1, 0, 0, 0, 1]);
494
494
+
});
495
495
+
496
496
+
it("should not transform points", () => {
497
497
+
const m = Mat3.identity();
498
498
+
const p = { x: 5, y: 10 };
499
499
+
expect(Mat3.transformPoint(m, p)).toEqual(p);
500
500
+
});
501
501
+
});
502
502
+
503
503
+
describe("translate", () => {
504
504
+
it.each([{ description: "positive translation", tx: 5, ty: 10, point: { x: 0, y: 0 }, expected: { x: 5, y: 10 } }, {
505
505
+
description: "negative translation",
506
506
+
tx: -5,
507
507
+
ty: -10,
508
508
+
point: { x: 5, y: 10 },
509
509
+
expected: { x: 0, y: 0 },
510
510
+
}, {
511
511
+
description: "zero translation (identity)",
512
512
+
tx: 0,
513
513
+
ty: 0,
514
514
+
point: { x: 5, y: 10 },
515
515
+
expected: { x: 5, y: 10 },
516
516
+
}])("should handle $description", ({ tx, ty, point, expected }) => {
517
517
+
const m = Mat3.translate(tx, ty);
518
518
+
expect(Mat3.transformPoint(m, point)).toEqual(expected);
519
519
+
});
520
520
+
521
521
+
it("should create correct matrix structure", () => {
522
522
+
expect(Mat3.translate(5, 10)).toEqual([1, 0, 0, 0, 1, 0, 5, 10, 1]);
523
523
+
});
524
524
+
});
525
525
+
526
526
+
describe("scale", () => {
527
527
+
it.each([
528
528
+
{ description: "non-uniform scale", sx: 2, sy: 3, point: { x: 5, y: 10 }, expected: { x: 10, y: 30 } },
529
529
+
{ description: "uniform scale", sx: 2, sy: 2, point: { x: 5, y: 10 }, expected: { x: 10, y: 20 } },
530
530
+
{ description: "scale by 1 (identity)", sx: 1, sy: 1, point: { x: 5, y: 10 }, expected: { x: 5, y: 10 } },
531
531
+
{ description: "scale by 0 (collapse)", sx: 0, sy: 0, point: { x: 5, y: 10 }, expected: { x: 0, y: 0 } },
532
532
+
])("should handle $description", ({ sx, sy, point, expected }) => {
533
533
+
const m = Mat3.scale(sx, sy);
534
534
+
expect(Mat3.transformPoint(m, point)).toEqual(expected);
535
535
+
});
536
536
+
537
537
+
it("should handle negative scale (flip)", () => {
538
538
+
const m = Mat3.scale(-1, 1);
539
539
+
const result = Mat3.transformPoint(m, { x: 5, y: 10 });
540
540
+
expect(result).toEqual({ x: -5, y: 10 });
541
541
+
});
542
542
+
});
543
543
+
544
544
+
describe("rotate", () => {
545
545
+
it.each([
546
546
+
{
547
547
+
description: "90 degrees counterclockwise",
548
548
+
angle: Math.PI / 2,
549
549
+
point: { x: 1, y: 0 },
550
550
+
expected: { x: 0, y: 1 },
551
551
+
},
552
552
+
{ description: "180 degrees", angle: Math.PI, point: { x: 1, y: 0 }, expected: { x: -1, y: 0 } },
553
553
+
{ description: "zero rotation", angle: 0, point: { x: 5, y: 10 }, expected: { x: 5, y: 10 } },
554
554
+
{
555
555
+
description: "360 degrees (full rotation)",
556
556
+
angle: 2 * Math.PI,
557
557
+
point: { x: 5, y: 10 },
558
558
+
expected: { x: 5, y: 10 },
559
559
+
},
560
560
+
{ description: "-90 degrees (clockwise)", angle: -Math.PI / 2, point: { x: 1, y: 0 }, expected: { x: 0, y: -1 } },
561
561
+
])("should handle $description", ({ angle, point, expected }) => {
562
562
+
const m = Mat3.rotate(angle);
563
563
+
const result = Mat3.transformPoint(m, point);
564
564
+
expect(result.x).toBeCloseTo(expected.x, 10);
565
565
+
expect(result.y).toBeCloseTo(expected.y, 10);
566
566
+
});
567
567
+
});
568
568
+
569
569
+
describe("multiply", () => {
570
570
+
it("should combine translations", () => {
571
571
+
const a = Mat3.translate(5, 0);
572
572
+
const b = Mat3.translate(0, 10);
573
573
+
const result = Mat3.multiply(a, b);
574
574
+
const transformed = Mat3.transformPoint(result, { x: 0, y: 0 });
575
575
+
expect(transformed).toEqual({ x: 5, y: 10 });
576
576
+
});
577
577
+
578
578
+
it("should apply transforms right to left", () => {
579
579
+
const translate = Mat3.translate(10, 0);
580
580
+
const scale = Mat3.scale(2, 1);
581
581
+
const result = Mat3.multiply(translate, scale);
582
582
+
const transformed = Mat3.transformPoint(result, { x: 5, y: 0 });
583
583
+
expect(transformed.x).toBeCloseTo(20);
584
584
+
});
585
585
+
586
586
+
it("should handle identity multiplication", () => {
587
587
+
const m = Mat3.translate(5, 10);
588
588
+
const identity = Mat3.identity();
589
589
+
expect(Mat3.equals(Mat3.multiply(m, identity), m)).toBe(true);
590
590
+
expect(Mat3.equals(Mat3.multiply(identity, m), m)).toBe(true);
591
591
+
});
592
592
+
593
593
+
it("should be associative", () => {
594
594
+
const a = Mat3.translate(1, 2);
595
595
+
const b = Mat3.scale(2, 3);
596
596
+
const c = Mat3.rotate(Math.PI / 4);
597
597
+
const result1 = Mat3.multiply(Mat3.multiply(a, b), c);
598
598
+
const result2 = Mat3.multiply(a, Mat3.multiply(b, c));
599
599
+
expect(Mat3.equals(result1, result2)).toBe(true);
600
600
+
});
601
601
+
602
602
+
it("should not be commutative", () => {
603
603
+
const a = Mat3.translate(10, 0);
604
604
+
const b = Mat3.scale(2, 1);
605
605
+
const result1 = Mat3.multiply(a, b);
606
606
+
const result2 = Mat3.multiply(b, a);
607
607
+
expect(Mat3.equals(result1, result2)).toBe(false);
608
608
+
});
609
609
+
});
610
610
+
611
611
+
describe("transformPoint", () => {
612
612
+
it("should transform through combined transforms", () => {
613
613
+
const m = Mat3.multiply(Mat3.translate(10, 20), Mat3.multiply(Mat3.rotate(Math.PI / 2), Mat3.scale(2, 2)));
614
614
+
const result = Mat3.transformPoint(m, { x: 1, y: 0 });
615
615
+
expect(result.x).toBeCloseTo(10);
616
616
+
expect(result.y).toBeCloseTo(22);
617
617
+
});
618
618
+
619
619
+
it("should handle origin point", () => {
620
620
+
const m = Mat3.translate(5, 10);
621
621
+
expect(Mat3.transformPoint(m, { x: 0, y: 0 })).toEqual({ x: 5, y: 10 });
622
622
+
});
623
623
+
});
624
624
+
625
625
+
describe("invert", () => {
626
626
+
it.each([{ description: "translation", matrix: Mat3.translate(5, 10) }, {
627
627
+
description: "scale",
628
628
+
matrix: Mat3.scale(2, 3),
629
629
+
}, { description: "rotation", matrix: Mat3.rotate(Math.PI / 3) }])("should invert $description", ({ matrix }) => {
630
630
+
const inv = Mat3.invert(matrix);
631
631
+
expect(inv).not.toBeNull();
632
632
+
633
633
+
const p = { x: 10, y: 20 };
634
634
+
const transformed = Mat3.transformPoint(matrix, p);
635
635
+
const restored = Mat3.transformPoint(inv!, transformed);
636
636
+
637
637
+
expect(restored.x).toBeCloseTo(p.x);
638
638
+
expect(restored.y).toBeCloseTo(p.y);
639
639
+
});
640
640
+
641
641
+
it("should invert identity to identity", () => {
642
642
+
const m = Mat3.identity();
643
643
+
const inv = Mat3.invert(m);
644
644
+
expect(inv).not.toBeNull();
645
645
+
expect(Mat3.equals(inv!, m)).toBe(true);
646
646
+
});
647
647
+
648
648
+
it("should return null for non-invertible matrix", () => {
649
649
+
const m = Mat3.scale(0, 0);
650
650
+
expect(Mat3.invert(m)).toBeNull();
651
651
+
});
652
652
+
653
653
+
it("should satisfy M * M^-1 = I", () => {
654
654
+
const m = Mat3.multiply(Mat3.translate(5, 10), Mat3.multiply(Mat3.rotate(0.5), Mat3.scale(2, 3)));
655
655
+
const inv = Mat3.invert(m);
656
656
+
expect(inv).not.toBeNull();
657
657
+
658
658
+
const identity = Mat3.multiply(m, inv!);
659
659
+
expect(Mat3.equals(identity, Mat3.identity(), 1e-10)).toBe(true);
660
660
+
});
661
661
+
});
662
662
+
663
663
+
describe("determinant", () => {
664
664
+
it.each([
665
665
+
{ description: "identity", matrix: Mat3.identity(), expected: 1 },
666
666
+
{ description: "translation", matrix: Mat3.translate(5, 10), expected: 1 },
667
667
+
{ description: "scale 2x3", matrix: Mat3.scale(2, 3), expected: 6 },
668
668
+
{ description: "rotation", matrix: Mat3.rotate(Math.PI / 4), expected: 1 },
669
669
+
{ description: "singular matrix", matrix: Mat3.scale(0, 5), expected: 0 },
670
670
+
{ description: "reflection", matrix: Mat3.scale(-1, 1), expected: -1 },
671
671
+
])("should calculate determinant for $description", ({ matrix, expected }) => {
672
672
+
expect(Mat3.determinant(matrix)).toBeCloseTo(expected, 10);
673
673
+
});
674
674
+
});
675
675
+
676
676
+
describe("clone and equals", () => {
677
677
+
it("should clone matrix", () => {
678
678
+
const m = Mat3.translate(5, 10);
679
679
+
const cloned = Mat3.clone(m);
680
680
+
expect(cloned).toEqual(m);
681
681
+
expect(cloned).not.toBe(m);
682
682
+
});
683
683
+
684
684
+
it.each([
685
685
+
{ description: "identical matrices", a: Mat3.translate(5, 10), b: Mat3.translate(5, 10), expected: true },
686
686
+
{ description: "different matrices", a: Mat3.translate(5, 10), b: Mat3.translate(10, 5), expected: false },
687
687
+
])("should compare $description", ({ a, b, expected }) => {
688
688
+
expect(Mat3.equals(a, b)).toBe(expected);
689
689
+
});
690
690
+
691
691
+
it("should use epsilon for floating point comparison", () => {
692
692
+
const a = Mat3.rotate(Math.PI / 4);
693
693
+
const b = Mat3.clone(a);
694
694
+
b[0] += 1e-15;
695
695
+
expect(Mat3.equals(a, b)).toBe(true);
696
696
+
});
697
697
+
698
698
+
it("should allow custom epsilon", () => {
699
699
+
const a = Mat3.identity();
700
700
+
const b = Mat3.identity();
701
701
+
b[0] = 1.001;
702
702
+
expect(Mat3.equals(a, b, 0.01)).toBe(true);
703
703
+
expect(Mat3.equals(a, b, 0.0001)).toBe(false);
704
704
+
});
705
705
+
});
706
706
+
707
707
+
describe("fromTransform", () => {
708
708
+
it("should create combined transform matrix", () => {
709
709
+
const m = Mat3.fromTransform(10, 20, 0, 1, 1);
710
710
+
const expected = Mat3.translate(10, 20);
711
711
+
expect(Mat3.equals(m, expected)).toBe(true);
712
712
+
});
713
713
+
714
714
+
it("should handle all transforms", () => {
715
715
+
const tx = 10, ty = 20;
716
716
+
const rotation = Math.PI / 4;
717
717
+
const sx = 2, sy = 3;
718
718
+
719
719
+
const m = Mat3.fromTransform(tx, ty, rotation, sx, sy);
720
720
+
const p = { x: 1, y: 0 };
721
721
+
const result = Mat3.transformPoint(m, p);
722
722
+
723
723
+
const scaled = { x: 2, y: 0 };
724
724
+
const rotated = { x: scaled.x * Math.cos(rotation), y: scaled.x * Math.sin(rotation) };
725
725
+
const translated = { x: rotated.x + tx, y: rotated.y + ty };
726
726
+
727
727
+
expect(result.x).toBeCloseTo(translated.x);
728
728
+
expect(result.y).toBeCloseTo(translated.y);
729
729
+
});
730
730
+
731
731
+
it("should match manual composition", () => {
732
732
+
const tx = 5, ty = 10;
733
733
+
const rotation = Math.PI / 6;
734
734
+
const sx = 2, sy = 3;
735
735
+
736
736
+
const m1 = Mat3.fromTransform(tx, ty, rotation, sx, sy);
737
737
+
const m2 = Mat3.multiply(Mat3.translate(tx, ty), Mat3.multiply(Mat3.rotate(rotation), Mat3.scale(sx, sy)));
738
738
+
739
739
+
expect(Mat3.equals(m1, m2, 1e-10)).toBe(true);
740
740
+
});
741
741
+
});
742
742
+
743
743
+
describe("edge cases and numerical stability", () => {
744
744
+
it.each([{
745
745
+
description: "very large values",
746
746
+
matrix: Mat3.translate(1e10, 1e10),
747
747
+
point: { x: 0, y: 0 },
748
748
+
expected: { x: 1e10, y: 1e10 },
749
749
+
}, {
750
750
+
description: "very small values",
751
751
+
matrix: Mat3.scale(1e-10, 1e-10),
752
752
+
point: { x: 1e10, y: 1e10 },
753
753
+
expected: { x: 1, y: 1 },
754
754
+
}])("should handle $description", ({ matrix, point, expected }) => {
755
755
+
const result = Mat3.transformPoint(matrix, point);
756
756
+
expect(result.x).toBeCloseTo(expected.x);
757
757
+
expect(result.y).toBeCloseTo(expected.y);
758
758
+
});
759
759
+
760
760
+
it("should handle accumulated rotations", () => {
761
761
+
let m = Mat3.identity();
762
762
+
for (let i = 0; i < 100; i++) {
763
763
+
m = Mat3.multiply(m, Mat3.rotate((2 * Math.PI) / 100));
764
764
+
}
765
765
+
const result = Mat3.transformPoint(m, { x: 1, y: 0 });
766
766
+
expect(result.x).toBeCloseTo(1, 5);
767
767
+
expect(result.y).toBeCloseTo(0, 5);
768
768
+
});
769
769
+
});
770
770
+
});
+1032
pnpm-lock.yaml
···
8
8
9
9
.:
10
10
devDependencies:
11
11
+
'@eslint/js':
12
12
+
specifier: ^9.39.2
13
13
+
version: 9.39.2
11
14
dprint:
12
15
specifier: ^0.50.2
13
16
version: 0.50.2
17
17
+
eslint:
18
18
+
specifier: ^9.39.2
19
19
+
version: 9.39.2(jiti@2.6.1)
20
20
+
eslint-plugin-unicorn:
21
21
+
specifier: ^62.0.0
22
22
+
version: 62.0.0(eslint@9.39.2(jiti@2.6.1))
23
23
+
globals:
24
24
+
specifier: ^16.5.0
25
25
+
version: 16.5.0
26
26
+
typescript:
27
27
+
specifier: ^5.9.3
28
28
+
version: 5.9.3
29
29
+
typescript-eslint:
30
30
+
specifier: ^8.50.0
31
31
+
version: 8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
14
32
15
33
packages/core:
16
34
devDependencies:
···
281
299
cpu: [x64]
282
300
os: [win32]
283
301
302
302
+
'@eslint-community/eslint-utils@4.9.0':
303
303
+
resolution: {integrity: sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==}
304
304
+
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
305
305
+
peerDependencies:
306
306
+
eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
307
307
+
308
308
+
'@eslint-community/regexpp@4.12.2':
309
309
+
resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==}
310
310
+
engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
311
311
+
312
312
+
'@eslint/config-array@0.21.1':
313
313
+
resolution: {integrity: sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==}
314
314
+
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
315
315
+
316
316
+
'@eslint/config-helpers@0.4.2':
317
317
+
resolution: {integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==}
318
318
+
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
319
319
+
320
320
+
'@eslint/core@0.17.0':
321
321
+
resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==}
322
322
+
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
323
323
+
324
324
+
'@eslint/eslintrc@3.3.3':
325
325
+
resolution: {integrity: sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==}
326
326
+
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
327
327
+
328
328
+
'@eslint/js@9.39.2':
329
329
+
resolution: {integrity: sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==}
330
330
+
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
331
331
+
332
332
+
'@eslint/object-schema@2.1.7':
333
333
+
resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==}
334
334
+
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
335
335
+
336
336
+
'@eslint/plugin-kit@0.4.1':
337
337
+
resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==}
338
338
+
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
339
339
+
340
340
+
'@humanfs/core@0.19.1':
341
341
+
resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==}
342
342
+
engines: {node: '>=18.18.0'}
343
343
+
344
344
+
'@humanfs/node@0.16.7':
345
345
+
resolution: {integrity: sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==}
346
346
+
engines: {node: '>=18.18.0'}
347
347
+
348
348
+
'@humanwhocodes/module-importer@1.0.1':
349
349
+
resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==}
350
350
+
engines: {node: '>=12.22'}
351
351
+
352
352
+
'@humanwhocodes/retry@0.4.3':
353
353
+
resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==}
354
354
+
engines: {node: '>=18.18'}
355
355
+
284
356
'@jridgewell/gen-mapping@0.3.13':
285
357
resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==}
286
358
···
508
580
'@types/estree@1.0.8':
509
581
resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==}
510
582
583
583
+
'@types/json-schema@7.0.15':
584
584
+
resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
585
585
+
511
586
'@types/node@25.0.3':
512
587
resolution: {integrity: sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA==}
513
588
589
589
+
'@typescript-eslint/eslint-plugin@8.50.0':
590
590
+
resolution: {integrity: sha512-O7QnmOXYKVtPrfYzMolrCTfkezCJS9+ljLdKW/+DCvRsc3UAz+sbH6Xcsv7p30+0OwUbeWfUDAQE0vpabZ3QLg==}
591
591
+
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
592
592
+
peerDependencies:
593
593
+
'@typescript-eslint/parser': ^8.50.0
594
594
+
eslint: ^8.57.0 || ^9.0.0
595
595
+
typescript: '>=4.8.4 <6.0.0'
596
596
+
597
597
+
'@typescript-eslint/parser@8.50.0':
598
598
+
resolution: {integrity: sha512-6/cmF2piao+f6wSxUsJLZjck7OQsYyRtcOZS02k7XINSNlz93v6emM8WutDQSXnroG2xwYlEVHJI+cPA7CPM3Q==}
599
599
+
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
600
600
+
peerDependencies:
601
601
+
eslint: ^8.57.0 || ^9.0.0
602
602
+
typescript: '>=4.8.4 <6.0.0'
603
603
+
604
604
+
'@typescript-eslint/project-service@8.50.0':
605
605
+
resolution: {integrity: sha512-Cg/nQcL1BcoTijEWyx4mkVC56r8dj44bFDvBdygifuS20f3OZCHmFbjF34DPSi07kwlFvqfv/xOLnJ5DquxSGQ==}
606
606
+
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
607
607
+
peerDependencies:
608
608
+
typescript: '>=4.8.4 <6.0.0'
609
609
+
610
610
+
'@typescript-eslint/scope-manager@8.50.0':
611
611
+
resolution: {integrity: sha512-xCwfuCZjhIqy7+HKxBLrDVT5q/iq7XBVBXLn57RTIIpelLtEIZHXAF/Upa3+gaCpeV1NNS5Z9A+ID6jn50VD4A==}
612
612
+
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
613
613
+
614
614
+
'@typescript-eslint/tsconfig-utils@8.50.0':
615
615
+
resolution: {integrity: sha512-vxd3G/ybKTSlm31MOA96gqvrRGv9RJ7LGtZCn2Vrc5htA0zCDvcMqUkifcjrWNNKXHUU3WCkYOzzVSFBd0wa2w==}
616
616
+
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
617
617
+
peerDependencies:
618
618
+
typescript: '>=4.8.4 <6.0.0'
619
619
+
620
620
+
'@typescript-eslint/type-utils@8.50.0':
621
621
+
resolution: {integrity: sha512-7OciHT2lKCewR0mFoBrvZJ4AXTMe/sYOe87289WAViOocEmDjjv8MvIOT2XESuKj9jp8u3SZYUSh89QA4S1kQw==}
622
622
+
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
623
623
+
peerDependencies:
624
624
+
eslint: ^8.57.0 || ^9.0.0
625
625
+
typescript: '>=4.8.4 <6.0.0'
626
626
+
627
627
+
'@typescript-eslint/types@8.50.0':
628
628
+
resolution: {integrity: sha512-iX1mgmGrXdANhhITbpp2QQM2fGehBse9LbTf0sidWK6yg/NE+uhV5dfU1g6EYPlcReYmkE9QLPq/2irKAmtS9w==}
629
629
+
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
630
630
+
631
631
+
'@typescript-eslint/typescript-estree@8.50.0':
632
632
+
resolution: {integrity: sha512-W7SVAGBR/IX7zm1t70Yujpbk+zdPq/u4soeFSknWFdXIFuWsBGBOUu/Tn/I6KHSKvSh91OiMuaSnYp3mtPt5IQ==}
633
633
+
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
634
634
+
peerDependencies:
635
635
+
typescript: '>=4.8.4 <6.0.0'
636
636
+
637
637
+
'@typescript-eslint/utils@8.50.0':
638
638
+
resolution: {integrity: sha512-87KgUXET09CRjGCi2Ejxy3PULXna63/bMYv72tCAlDJC3Yqwln0HiFJ3VJMst2+mEtNtZu5oFvX4qJGjKsnAgg==}
639
639
+
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
640
640
+
peerDependencies:
641
641
+
eslint: ^8.57.0 || ^9.0.0
642
642
+
typescript: '>=4.8.4 <6.0.0'
643
643
+
644
644
+
'@typescript-eslint/visitor-keys@8.50.0':
645
645
+
resolution: {integrity: sha512-Xzmnb58+Db78gT/CCj/PVCvK+zxbnsw6F+O1oheYszJbBSdEjVhQi3C/Xttzxgi/GLmpvOggRs1RFpiJ8+c34Q==}
646
646
+
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
647
647
+
514
648
'@vitest/expect@4.0.16':
515
649
resolution: {integrity: sha512-eshqULT2It7McaJkQGLkPjPjNph+uevROGuIMJdG3V+0BSR2w9u6J9Lwu+E8cK5TETlfou8GRijhafIMhXsimA==}
516
650
···
540
674
'@vitest/utils@4.0.16':
541
675
resolution: {integrity: sha512-h8z9yYhV3e1LEfaQ3zdypIrnAg/9hguReGZoS7Gl0aBG5xgA410zBqECqmaF/+RkTggRsfnzc1XaAHA6bmUufA==}
542
676
677
677
+
acorn-jsx@5.3.2:
678
678
+
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
679
679
+
peerDependencies:
680
680
+
acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
681
681
+
682
682
+
acorn@8.15.0:
683
683
+
resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==}
684
684
+
engines: {node: '>=0.4.0'}
685
685
+
hasBin: true
686
686
+
687
687
+
ajv@6.12.6:
688
688
+
resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
689
689
+
690
690
+
ansi-styles@4.3.0:
691
691
+
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
692
692
+
engines: {node: '>=8'}
693
693
+
543
694
ansis@4.2.0:
544
695
resolution: {integrity: sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==}
545
696
engines: {node: '>=14'}
697
697
+
698
698
+
argparse@2.0.1:
699
699
+
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
546
700
547
701
args-tokenizer@0.3.0:
548
702
resolution: {integrity: sha512-xXAd7G2Mll5W8uo37GETpQ2VrE84M181Z7ugHFGQnJZ50M2mbOv0osSZ9VsSgPfJQ+LVG0prSi0th+ELMsno7Q==}
···
555
709
resolution: {integrity: sha512-m1Q/RaVOnTp9JxPX+F+Zn7IcLYMzM8kZofDImfsKZd8MbR+ikdOzTeztStWqfrqIxZnYWryyI9ePm3NGjnZgGw==}
556
710
engines: {node: '>=20.19.0'}
557
711
712
712
+
balanced-match@1.0.2:
713
713
+
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
714
714
+
715
715
+
baseline-browser-mapping@2.9.11:
716
716
+
resolution: {integrity: sha512-Sg0xJUNDU1sJNGdfGWhVHX0kkZ+HWcvmVymJbj6NSgZZmW/8S9Y2HQ5euytnIgakgxN6papOAWiwDo1ctFDcoQ==}
717
717
+
hasBin: true
718
718
+
558
719
birpc@4.0.0:
559
720
resolution: {integrity: sha512-LShSxJP0KTmd101b6DRyGBj57LZxSDYWKitQNW/mi8GRMvZb078Uf9+pveax1DrVL89vm7mWe+TovdI/UDOuPw==}
560
721
722
722
+
brace-expansion@1.1.12:
723
723
+
resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==}
724
724
+
725
725
+
brace-expansion@2.0.2:
726
726
+
resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==}
727
727
+
728
728
+
browserslist@4.28.1:
729
729
+
resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==}
730
730
+
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
731
731
+
hasBin: true
732
732
+
733
733
+
builtin-modules@5.0.0:
734
734
+
resolution: {integrity: sha512-bkXY9WsVpY7CvMhKSR6pZilZu9Ln5WDrKVBUXf2S443etkmEO4V58heTecXcUIsNsi4Rx8JUO4NfX1IcQl4deg==}
735
735
+
engines: {node: '>=18.20'}
736
736
+
561
737
bumpp@10.3.2:
562
738
resolution: {integrity: sha512-yUUkVx5zpTywLNX97MlrqtpanI7eMMwFwLntWR2EBVDw3/Pm3aRIzCoDEGHATLIiHK9PuJC7xWI4XNWqXItSPg==}
563
739
engines: {node: '>=18'}
···
575
751
resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
576
752
engines: {node: '>=8'}
577
753
754
754
+
callsites@3.1.0:
755
755
+
resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
756
756
+
engines: {node: '>=6'}
757
757
+
758
758
+
caniuse-lite@1.0.30001761:
759
759
+
resolution: {integrity: sha512-JF9ptu1vP2coz98+5051jZ4PwQgd2ni8A+gYSN7EA7dPKIMf0pDlSUxhdmVOaV3/fYK5uWBkgSXJaRLr4+3A6g==}
760
760
+
578
761
chai@6.2.1:
579
762
resolution: {integrity: sha512-p4Z49OGG5W/WBCPSS/dH3jQ73kD6tiMmUM+bckNK6Jr5JHMG3k9bg/BvKR8lKmtVBKmOiuVaV2ws8s9oSbwysg==}
580
763
engines: {node: '>=18'}
581
764
765
765
+
chalk@4.1.2:
766
766
+
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
767
767
+
engines: {node: '>=10'}
768
768
+
769
769
+
change-case@5.4.4:
770
770
+
resolution: {integrity: sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w==}
771
771
+
582
772
chokidar@5.0.0:
583
773
resolution: {integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==}
584
774
engines: {node: '>= 20.19.0'}
775
775
+
776
776
+
ci-info@4.3.1:
777
777
+
resolution: {integrity: sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==}
778
778
+
engines: {node: '>=8'}
585
779
586
780
citty@0.1.6:
587
781
resolution: {integrity: sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==}
588
782
783
783
+
clean-regexp@1.0.0:
784
784
+
resolution: {integrity: sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==}
785
785
+
engines: {node: '>=4'}
786
786
+
787
787
+
color-convert@2.0.1:
788
788
+
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
789
789
+
engines: {node: '>=7.0.0'}
790
790
+
791
791
+
color-name@1.1.4:
792
792
+
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
793
793
+
794
794
+
concat-map@0.0.1:
795
795
+
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
796
796
+
589
797
confbox@0.2.2:
590
798
resolution: {integrity: sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==}
591
799
···
593
801
resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==}
594
802
engines: {node: ^14.18.0 || >=16.10.0}
595
803
804
804
+
core-js-compat@3.47.0:
805
805
+
resolution: {integrity: sha512-IGfuznZ/n7Kp9+nypamBhvwdwLsW6KC8IOaURw2doAK5e98AG3acVLdh0woOnEqCfUtS+Vu882JE4k/DAm3ItQ==}
806
806
+
807
807
+
cross-spawn@7.0.6:
808
808
+
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
809
809
+
engines: {node: '>= 8'}
810
810
+
811
811
+
debug@4.4.3:
812
812
+
resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
813
813
+
engines: {node: '>=6.0'}
814
814
+
peerDependencies:
815
815
+
supports-color: '*'
816
816
+
peerDependenciesMeta:
817
817
+
supports-color:
818
818
+
optional: true
819
819
+
820
820
+
deep-is@0.1.4:
821
821
+
resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
822
822
+
596
823
defu@6.1.4:
597
824
resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==}
598
825
···
616
843
oxc-resolver:
617
844
optional: true
618
845
846
846
+
electron-to-chromium@1.5.267:
847
847
+
resolution: {integrity: sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==}
848
848
+
619
849
empathic@2.0.0:
620
850
resolution: {integrity: sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==}
621
851
engines: {node: '>=14'}
···
632
862
resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
633
863
engines: {node: '>=6'}
634
864
865
865
+
escape-string-regexp@1.0.5:
866
866
+
resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==}
867
867
+
engines: {node: '>=0.8.0'}
868
868
+
869
869
+
escape-string-regexp@4.0.0:
870
870
+
resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
871
871
+
engines: {node: '>=10'}
872
872
+
873
873
+
eslint-plugin-unicorn@62.0.0:
874
874
+
resolution: {integrity: sha512-HIlIkGLkvf29YEiS/ImuDZQbP12gWyx5i3C6XrRxMvVdqMroCI9qoVYCoIl17ChN+U89pn9sVwLxhIWj5nEc7g==}
875
875
+
engines: {node: ^20.10.0 || >=21.0.0}
876
876
+
peerDependencies:
877
877
+
eslint: '>=9.38.0'
878
878
+
879
879
+
eslint-scope@8.4.0:
880
880
+
resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==}
881
881
+
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
882
882
+
883
883
+
eslint-visitor-keys@3.4.3:
884
884
+
resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==}
885
885
+
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
886
886
+
887
887
+
eslint-visitor-keys@4.2.1:
888
888
+
resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==}
889
889
+
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
890
890
+
891
891
+
eslint@9.39.2:
892
892
+
resolution: {integrity: sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==}
893
893
+
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
894
894
+
hasBin: true
895
895
+
peerDependencies:
896
896
+
jiti: '*'
897
897
+
peerDependenciesMeta:
898
898
+
jiti:
899
899
+
optional: true
900
900
+
901
901
+
espree@10.4.0:
902
902
+
resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==}
903
903
+
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
904
904
+
905
905
+
esquery@1.6.0:
906
906
+
resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==}
907
907
+
engines: {node: '>=0.10'}
908
908
+
909
909
+
esrecurse@4.3.0:
910
910
+
resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==}
911
911
+
engines: {node: '>=4.0'}
912
912
+
913
913
+
estraverse@5.3.0:
914
914
+
resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==}
915
915
+
engines: {node: '>=4.0'}
916
916
+
635
917
estree-walker@3.0.3:
636
918
resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==}
637
919
920
920
+
esutils@2.0.3:
921
921
+
resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
922
922
+
engines: {node: '>=0.10.0'}
923
923
+
638
924
expect-type@1.3.0:
639
925
resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==}
640
926
engines: {node: '>=12.0.0'}
···
642
928
exsolve@1.0.8:
643
929
resolution: {integrity: sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==}
644
930
931
931
+
fast-deep-equal@3.1.3:
932
932
+
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
933
933
+
934
934
+
fast-json-stable-stringify@2.1.0:
935
935
+
resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
936
936
+
937
937
+
fast-levenshtein@2.0.6:
938
938
+
resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==}
939
939
+
645
940
fdir@6.5.0:
646
941
resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==}
647
942
engines: {node: '>=12.0.0'}
···
651
946
picomatch:
652
947
optional: true
653
948
949
949
+
file-entry-cache@8.0.0:
950
950
+
resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==}
951
951
+
engines: {node: '>=16.0.0'}
952
952
+
953
953
+
find-up-simple@1.0.1:
954
954
+
resolution: {integrity: sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==}
955
955
+
engines: {node: '>=18'}
956
956
+
957
957
+
find-up@5.0.0:
958
958
+
resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
959
959
+
engines: {node: '>=10'}
960
960
+
961
961
+
flat-cache@4.0.1:
962
962
+
resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==}
963
963
+
engines: {node: '>=16'}
964
964
+
965
965
+
flatted@3.3.3:
966
966
+
resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==}
967
967
+
654
968
fsevents@2.3.3:
655
969
resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
656
970
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
···
663
977
resolution: {integrity: sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==}
664
978
hasBin: true
665
979
980
980
+
glob-parent@6.0.2:
981
981
+
resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
982
982
+
engines: {node: '>=10.13.0'}
983
983
+
984
984
+
globals@14.0.0:
985
985
+
resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==}
986
986
+
engines: {node: '>=18'}
987
987
+
988
988
+
globals@16.5.0:
989
989
+
resolution: {integrity: sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==}
990
990
+
engines: {node: '>=18'}
991
991
+
992
992
+
has-flag@4.0.0:
993
993
+
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
994
994
+
engines: {node: '>=8'}
995
995
+
666
996
hookable@5.5.3:
667
997
resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==}
668
998
999
999
+
ignore@5.3.2:
1000
1000
+
resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
1001
1001
+
engines: {node: '>= 4'}
1002
1002
+
1003
1003
+
ignore@7.0.5:
1004
1004
+
resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==}
1005
1005
+
engines: {node: '>= 4'}
1006
1006
+
1007
1007
+
import-fresh@3.3.1:
1008
1008
+
resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==}
1009
1009
+
engines: {node: '>=6'}
1010
1010
+
669
1011
import-without-cache@0.2.4:
670
1012
resolution: {integrity: sha512-b/Ke0y4n26ffQhkLvgBxV/NVO/QEE6AZlrMj8DYuxBWNAAu4iMQWZTFWzKcCTEmv7VQ0ae0j8KwrlGzSy8sYQQ==}
671
1013
engines: {node: '>=20.19.0'}
672
1014
1015
1015
+
imurmurhash@0.1.4:
1016
1016
+
resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
1017
1017
+
engines: {node: '>=0.8.19'}
1018
1018
+
1019
1019
+
indent-string@5.0.0:
1020
1020
+
resolution: {integrity: sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==}
1021
1021
+
engines: {node: '>=12'}
1022
1022
+
1023
1023
+
is-builtin-module@5.0.0:
1024
1024
+
resolution: {integrity: sha512-f4RqJKBUe5rQkJ2eJEJBXSticB3hGbN9j0yxxMQFqIW89Jp9WYFtzfTcRlstDKVUTRzSOTLKRfO9vIztenwtxA==}
1025
1025
+
engines: {node: '>=18.20'}
1026
1026
+
1027
1027
+
is-extglob@2.1.1:
1028
1028
+
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
1029
1029
+
engines: {node: '>=0.10.0'}
1030
1030
+
1031
1031
+
is-glob@4.0.3:
1032
1032
+
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
1033
1033
+
engines: {node: '>=0.10.0'}
1034
1034
+
1035
1035
+
isexe@2.0.0:
1036
1036
+
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
1037
1037
+
673
1038
jiti@2.6.1:
674
1039
resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==}
675
1040
hasBin: true
676
1041
1042
1042
+
js-yaml@4.1.1:
1043
1043
+
resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==}
1044
1044
+
hasBin: true
1045
1045
+
677
1046
jsesc@3.1.0:
678
1047
resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==}
679
1048
engines: {node: '>=6'}
680
1049
hasBin: true
681
1050
1051
1051
+
json-buffer@3.0.1:
1052
1052
+
resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
1053
1053
+
1054
1054
+
json-schema-traverse@0.4.1:
1055
1055
+
resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
1056
1056
+
1057
1057
+
json-stable-stringify-without-jsonify@1.0.1:
1058
1058
+
resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==}
1059
1059
+
682
1060
jsonc-parser@3.3.1:
683
1061
resolution: {integrity: sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==}
684
1062
1063
1063
+
keyv@4.5.4:
1064
1064
+
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
1065
1065
+
1066
1066
+
levn@0.4.1:
1067
1067
+
resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
1068
1068
+
engines: {node: '>= 0.8.0'}
1069
1069
+
1070
1070
+
locate-path@6.0.0:
1071
1071
+
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
1072
1072
+
engines: {node: '>=10'}
1073
1073
+
1074
1074
+
lodash.merge@4.6.2:
1075
1075
+
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
1076
1076
+
685
1077
magic-string@0.30.21:
686
1078
resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
687
1079
1080
1080
+
minimatch@3.1.2:
1081
1081
+
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
1082
1082
+
1083
1083
+
minimatch@9.0.5:
1084
1084
+
resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==}
1085
1085
+
engines: {node: '>=16 || 14 >=14.17'}
1086
1086
+
1087
1087
+
ms@2.1.3:
1088
1088
+
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
1089
1089
+
688
1090
nanoid@3.3.11:
689
1091
resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==}
690
1092
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
691
1093
hasBin: true
692
1094
1095
1095
+
natural-compare@1.4.0:
1096
1096
+
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
1097
1097
+
693
1098
node-fetch-native@1.6.7:
694
1099
resolution: {integrity: sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==}
1100
1100
+
1101
1101
+
node-releases@2.0.27:
1102
1102
+
resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==}
695
1103
696
1104
nypm@0.6.2:
697
1105
resolution: {integrity: sha512-7eM+hpOtrKrBDCh7Ypu2lJ9Z7PNZBdi/8AT3AX8xoCj43BBVHD0hPSTEvMtkMpfs8FCqBGhxB+uToIQimA111g==}
···
703
1111
704
1112
ohash@2.0.11:
705
1113
resolution: {integrity: sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==}
1114
1114
+
1115
1115
+
optionator@0.9.4:
1116
1116
+
resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
1117
1117
+
engines: {node: '>= 0.8.0'}
1118
1118
+
1119
1119
+
p-limit@3.1.0:
1120
1120
+
resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==}
1121
1121
+
engines: {node: '>=10'}
1122
1122
+
1123
1123
+
p-locate@5.0.0:
1124
1124
+
resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
1125
1125
+
engines: {node: '>=10'}
706
1126
707
1127
package-manager-detector@1.6.0:
708
1128
resolution: {integrity: sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==}
709
1129
1130
1130
+
parent-module@1.0.1:
1131
1131
+
resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
1132
1132
+
engines: {node: '>=6'}
1133
1133
+
1134
1134
+
path-exists@4.0.0:
1135
1135
+
resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
1136
1136
+
engines: {node: '>=8'}
1137
1137
+
1138
1138
+
path-key@3.1.1:
1139
1139
+
resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
1140
1140
+
engines: {node: '>=8'}
1141
1141
+
710
1142
pathe@2.0.3:
711
1143
resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
712
1144
···
722
1154
723
1155
pkg-types@2.3.0:
724
1156
resolution: {integrity: sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==}
1157
1157
+
1158
1158
+
pluralize@8.0.0:
1159
1159
+
resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==}
1160
1160
+
engines: {node: '>=4'}
725
1161
726
1162
postcss@8.5.6:
727
1163
resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==}
728
1164
engines: {node: ^10 || ^12 || >=14}
729
1165
1166
1166
+
prelude-ls@1.2.1:
1167
1167
+
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
1168
1168
+
engines: {node: '>= 0.8.0'}
1169
1169
+
1170
1170
+
punycode@2.3.1:
1171
1171
+
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
1172
1172
+
engines: {node: '>=6'}
1173
1173
+
730
1174
quansync@1.0.0:
731
1175
resolution: {integrity: sha512-5xZacEEufv3HSTPQuchrvV6soaiACMFnq1H8wkVioctoH3TRha9Sz66lOxRwPK/qZj7HPiSveih9yAyh98gvqA==}
732
1176
···
737
1181
resolution: {integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==}
738
1182
engines: {node: '>= 20.19.0'}
739
1183
1184
1184
+
regexp-tree@0.1.27:
1185
1185
+
resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==}
1186
1186
+
hasBin: true
1187
1187
+
1188
1188
+
regjsparser@0.13.0:
1189
1189
+
resolution: {integrity: sha512-NZQZdC5wOE/H3UT28fVGL+ikOZcEzfMGk/c3iN9UGxzWHMa1op7274oyiUVrAG4B2EuFhus8SvkaYnhvW92p9Q==}
1190
1190
+
hasBin: true
1191
1191
+
1192
1192
+
resolve-from@4.0.0:
1193
1193
+
resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
1194
1194
+
engines: {node: '>=4'}
1195
1195
+
740
1196
resolve-pkg-maps@1.0.0:
741
1197
resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==}
742
1198
···
774
1230
engines: {node: '>=10'}
775
1231
hasBin: true
776
1232
1233
1233
+
shebang-command@2.0.0:
1234
1234
+
resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
1235
1235
+
engines: {node: '>=8'}
1236
1236
+
1237
1237
+
shebang-regex@3.0.0:
1238
1238
+
resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
1239
1239
+
engines: {node: '>=8'}
1240
1240
+
777
1241
siginfo@2.0.0:
778
1242
resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==}
779
1243
···
787
1251
std-env@3.10.0:
788
1252
resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==}
789
1253
1254
1254
+
strip-indent@4.1.1:
1255
1255
+
resolution: {integrity: sha512-SlyRoSkdh1dYP0PzclLE7r0M9sgbFKKMFXpFRUMNuKhQSbC6VQIGzq3E0qsfvGJaUFJPGv6Ws1NZ/haTAjfbMA==}
1256
1256
+
engines: {node: '>=12'}
1257
1257
+
1258
1258
+
strip-json-comments@3.1.1:
1259
1259
+
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
1260
1260
+
engines: {node: '>=8'}
1261
1261
+
1262
1262
+
supports-color@7.2.0:
1263
1263
+
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
1264
1264
+
engines: {node: '>=8'}
1265
1265
+
790
1266
tinybench@2.9.0:
791
1267
resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==}
792
1268
···
806
1282
resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==}
807
1283
hasBin: true
808
1284
1285
1285
+
ts-api-utils@2.1.0:
1286
1286
+
resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==}
1287
1287
+
engines: {node: '>=18.12'}
1288
1288
+
peerDependencies:
1289
1289
+
typescript: '>=4.8.4'
1290
1290
+
809
1291
tsdown@0.18.1:
810
1292
resolution: {integrity: sha512-na4MdVA8QS9Zw++0KovGpjvw1BY5WvoCWcE4Aw0dyfff9nWK8BPzniQEVs+apGUg3DHaYMDfs+XiFaDDgqDDzQ==}
811
1293
engines: {node: '>=20.19.0'}
···
834
1316
tslib@2.8.1:
835
1317
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
836
1318
1319
1319
+
type-check@0.4.0:
1320
1320
+
resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
1321
1321
+
engines: {node: '>= 0.8.0'}
1322
1322
+
1323
1323
+
typescript-eslint@8.50.0:
1324
1324
+
resolution: {integrity: sha512-Q1/6yNUmCpH94fbgMUMg2/BSAr/6U7GBk61kZTv1/asghQOWOjTlp9K8mixS5NcJmm2creY+UFfGeW/+OcA64A==}
1325
1325
+
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
1326
1326
+
peerDependencies:
1327
1327
+
eslint: ^8.57.0 || ^9.0.0
1328
1328
+
typescript: '>=4.8.4 <6.0.0'
1329
1329
+
837
1330
typescript@5.9.3:
838
1331
resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
839
1332
engines: {node: '>=14.17'}
···
854
1347
peerDependenciesMeta:
855
1348
synckit:
856
1349
optional: true
1350
1350
+
1351
1351
+
update-browserslist-db@1.2.3:
1352
1352
+
resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==}
1353
1353
+
hasBin: true
1354
1354
+
peerDependencies:
1355
1355
+
browserslist: '>= 4.21.0'
1356
1356
+
1357
1357
+
uri-js@4.4.1:
1358
1358
+
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
857
1359
858
1360
vite@7.3.0:
859
1361
resolution: {integrity: sha512-dZwN5L1VlUBewiP6H9s2+B3e3Jg96D0vzN+Ry73sOefebhYr9f94wwkMNN/9ouoU8pV1BqA1d1zGk8928cx0rg==}
···
929
1431
jsdom:
930
1432
optional: true
931
1433
1434
1434
+
which@2.0.2:
1435
1435
+
resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
1436
1436
+
engines: {node: '>= 8'}
1437
1437
+
hasBin: true
1438
1438
+
932
1439
why-is-node-running@2.3.0:
933
1440
resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==}
934
1441
engines: {node: '>=8'}
935
1442
hasBin: true
936
1443
1444
1444
+
word-wrap@1.2.5:
1445
1445
+
resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
1446
1446
+
engines: {node: '>=0.10.0'}
1447
1447
+
937
1448
yaml@2.8.2:
938
1449
resolution: {integrity: sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==}
939
1450
engines: {node: '>= 14.6'}
940
1451
hasBin: true
1452
1452
+
1453
1453
+
yocto-queue@0.1.0:
1454
1454
+
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
1455
1455
+
engines: {node: '>=10'}
941
1456
942
1457
snapshots:
943
1458
···
1083
1598
'@esbuild/win32-x64@0.27.2':
1084
1599
optional: true
1085
1600
1601
1601
+
'@eslint-community/eslint-utils@4.9.0(eslint@9.39.2(jiti@2.6.1))':
1602
1602
+
dependencies:
1603
1603
+
eslint: 9.39.2(jiti@2.6.1)
1604
1604
+
eslint-visitor-keys: 3.4.3
1605
1605
+
1606
1606
+
'@eslint-community/regexpp@4.12.2': {}
1607
1607
+
1608
1608
+
'@eslint/config-array@0.21.1':
1609
1609
+
dependencies:
1610
1610
+
'@eslint/object-schema': 2.1.7
1611
1611
+
debug: 4.4.3
1612
1612
+
minimatch: 3.1.2
1613
1613
+
transitivePeerDependencies:
1614
1614
+
- supports-color
1615
1615
+
1616
1616
+
'@eslint/config-helpers@0.4.2':
1617
1617
+
dependencies:
1618
1618
+
'@eslint/core': 0.17.0
1619
1619
+
1620
1620
+
'@eslint/core@0.17.0':
1621
1621
+
dependencies:
1622
1622
+
'@types/json-schema': 7.0.15
1623
1623
+
1624
1624
+
'@eslint/eslintrc@3.3.3':
1625
1625
+
dependencies:
1626
1626
+
ajv: 6.12.6
1627
1627
+
debug: 4.4.3
1628
1628
+
espree: 10.4.0
1629
1629
+
globals: 14.0.0
1630
1630
+
ignore: 5.3.2
1631
1631
+
import-fresh: 3.3.1
1632
1632
+
js-yaml: 4.1.1
1633
1633
+
minimatch: 3.1.2
1634
1634
+
strip-json-comments: 3.1.1
1635
1635
+
transitivePeerDependencies:
1636
1636
+
- supports-color
1637
1637
+
1638
1638
+
'@eslint/js@9.39.2': {}
1639
1639
+
1640
1640
+
'@eslint/object-schema@2.1.7': {}
1641
1641
+
1642
1642
+
'@eslint/plugin-kit@0.4.1':
1643
1643
+
dependencies:
1644
1644
+
'@eslint/core': 0.17.0
1645
1645
+
levn: 0.4.1
1646
1646
+
1647
1647
+
'@humanfs/core@0.19.1': {}
1648
1648
+
1649
1649
+
'@humanfs/node@0.16.7':
1650
1650
+
dependencies:
1651
1651
+
'@humanfs/core': 0.19.1
1652
1652
+
'@humanwhocodes/retry': 0.4.3
1653
1653
+
1654
1654
+
'@humanwhocodes/module-importer@1.0.1': {}
1655
1655
+
1656
1656
+
'@humanwhocodes/retry@0.4.3': {}
1657
1657
+
1086
1658
'@jridgewell/gen-mapping@0.3.13':
1087
1659
dependencies:
1088
1660
'@jridgewell/sourcemap-codec': 1.5.5
···
1235
1807
1236
1808
'@types/estree@1.0.8': {}
1237
1809
1810
1810
+
'@types/json-schema@7.0.15': {}
1811
1811
+
1238
1812
'@types/node@25.0.3':
1239
1813
dependencies:
1240
1814
undici-types: 7.16.0
1241
1815
1816
1816
+
'@typescript-eslint/eslint-plugin@8.50.0(@typescript-eslint/parser@8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)':
1817
1817
+
dependencies:
1818
1818
+
'@eslint-community/regexpp': 4.12.2
1819
1819
+
'@typescript-eslint/parser': 8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
1820
1820
+
'@typescript-eslint/scope-manager': 8.50.0
1821
1821
+
'@typescript-eslint/type-utils': 8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
1822
1822
+
'@typescript-eslint/utils': 8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
1823
1823
+
'@typescript-eslint/visitor-keys': 8.50.0
1824
1824
+
eslint: 9.39.2(jiti@2.6.1)
1825
1825
+
ignore: 7.0.5
1826
1826
+
natural-compare: 1.4.0
1827
1827
+
ts-api-utils: 2.1.0(typescript@5.9.3)
1828
1828
+
typescript: 5.9.3
1829
1829
+
transitivePeerDependencies:
1830
1830
+
- supports-color
1831
1831
+
1832
1832
+
'@typescript-eslint/parser@8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)':
1833
1833
+
dependencies:
1834
1834
+
'@typescript-eslint/scope-manager': 8.50.0
1835
1835
+
'@typescript-eslint/types': 8.50.0
1836
1836
+
'@typescript-eslint/typescript-estree': 8.50.0(typescript@5.9.3)
1837
1837
+
'@typescript-eslint/visitor-keys': 8.50.0
1838
1838
+
debug: 4.4.3
1839
1839
+
eslint: 9.39.2(jiti@2.6.1)
1840
1840
+
typescript: 5.9.3
1841
1841
+
transitivePeerDependencies:
1842
1842
+
- supports-color
1843
1843
+
1844
1844
+
'@typescript-eslint/project-service@8.50.0(typescript@5.9.3)':
1845
1845
+
dependencies:
1846
1846
+
'@typescript-eslint/tsconfig-utils': 8.50.0(typescript@5.9.3)
1847
1847
+
'@typescript-eslint/types': 8.50.0
1848
1848
+
debug: 4.4.3
1849
1849
+
typescript: 5.9.3
1850
1850
+
transitivePeerDependencies:
1851
1851
+
- supports-color
1852
1852
+
1853
1853
+
'@typescript-eslint/scope-manager@8.50.0':
1854
1854
+
dependencies:
1855
1855
+
'@typescript-eslint/types': 8.50.0
1856
1856
+
'@typescript-eslint/visitor-keys': 8.50.0
1857
1857
+
1858
1858
+
'@typescript-eslint/tsconfig-utils@8.50.0(typescript@5.9.3)':
1859
1859
+
dependencies:
1860
1860
+
typescript: 5.9.3
1861
1861
+
1862
1862
+
'@typescript-eslint/type-utils@8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)':
1863
1863
+
dependencies:
1864
1864
+
'@typescript-eslint/types': 8.50.0
1865
1865
+
'@typescript-eslint/typescript-estree': 8.50.0(typescript@5.9.3)
1866
1866
+
'@typescript-eslint/utils': 8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
1867
1867
+
debug: 4.4.3
1868
1868
+
eslint: 9.39.2(jiti@2.6.1)
1869
1869
+
ts-api-utils: 2.1.0(typescript@5.9.3)
1870
1870
+
typescript: 5.9.3
1871
1871
+
transitivePeerDependencies:
1872
1872
+
- supports-color
1873
1873
+
1874
1874
+
'@typescript-eslint/types@8.50.0': {}
1875
1875
+
1876
1876
+
'@typescript-eslint/typescript-estree@8.50.0(typescript@5.9.3)':
1877
1877
+
dependencies:
1878
1878
+
'@typescript-eslint/project-service': 8.50.0(typescript@5.9.3)
1879
1879
+
'@typescript-eslint/tsconfig-utils': 8.50.0(typescript@5.9.3)
1880
1880
+
'@typescript-eslint/types': 8.50.0
1881
1881
+
'@typescript-eslint/visitor-keys': 8.50.0
1882
1882
+
debug: 4.4.3
1883
1883
+
minimatch: 9.0.5
1884
1884
+
semver: 7.7.3
1885
1885
+
tinyglobby: 0.2.15
1886
1886
+
ts-api-utils: 2.1.0(typescript@5.9.3)
1887
1887
+
typescript: 5.9.3
1888
1888
+
transitivePeerDependencies:
1889
1889
+
- supports-color
1890
1890
+
1891
1891
+
'@typescript-eslint/utils@8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)':
1892
1892
+
dependencies:
1893
1893
+
'@eslint-community/eslint-utils': 4.9.0(eslint@9.39.2(jiti@2.6.1))
1894
1894
+
'@typescript-eslint/scope-manager': 8.50.0
1895
1895
+
'@typescript-eslint/types': 8.50.0
1896
1896
+
'@typescript-eslint/typescript-estree': 8.50.0(typescript@5.9.3)
1897
1897
+
eslint: 9.39.2(jiti@2.6.1)
1898
1898
+
typescript: 5.9.3
1899
1899
+
transitivePeerDependencies:
1900
1900
+
- supports-color
1901
1901
+
1902
1902
+
'@typescript-eslint/visitor-keys@8.50.0':
1903
1903
+
dependencies:
1904
1904
+
'@typescript-eslint/types': 8.50.0
1905
1905
+
eslint-visitor-keys: 4.2.1
1906
1906
+
1242
1907
'@vitest/expect@4.0.16':
1243
1908
dependencies:
1244
1909
'@standard-schema/spec': 1.1.0
···
1278
1943
'@vitest/pretty-format': 4.0.16
1279
1944
tinyrainbow: 3.0.3
1280
1945
1946
1946
+
acorn-jsx@5.3.2(acorn@8.15.0):
1947
1947
+
dependencies:
1948
1948
+
acorn: 8.15.0
1949
1949
+
1950
1950
+
acorn@8.15.0: {}
1951
1951
+
1952
1952
+
ajv@6.12.6:
1953
1953
+
dependencies:
1954
1954
+
fast-deep-equal: 3.1.3
1955
1955
+
fast-json-stable-stringify: 2.1.0
1956
1956
+
json-schema-traverse: 0.4.1
1957
1957
+
uri-js: 4.4.1
1958
1958
+
1959
1959
+
ansi-styles@4.3.0:
1960
1960
+
dependencies:
1961
1961
+
color-convert: 2.0.1
1962
1962
+
1281
1963
ansis@4.2.0: {}
1964
1964
+
1965
1965
+
argparse@2.0.1: {}
1282
1966
1283
1967
args-tokenizer@0.3.0: {}
1284
1968
···
1289
1973
'@babel/parser': 7.28.5
1290
1974
pathe: 2.0.3
1291
1975
1976
1976
+
balanced-match@1.0.2: {}
1977
1977
+
1978
1978
+
baseline-browser-mapping@2.9.11: {}
1979
1979
+
1292
1980
birpc@4.0.0: {}
1293
1981
1982
1982
+
brace-expansion@1.1.12:
1983
1983
+
dependencies:
1984
1984
+
balanced-match: 1.0.2
1985
1985
+
concat-map: 0.0.1
1986
1986
+
1987
1987
+
brace-expansion@2.0.2:
1988
1988
+
dependencies:
1989
1989
+
balanced-match: 1.0.2
1990
1990
+
1991
1991
+
browserslist@4.28.1:
1992
1992
+
dependencies:
1993
1993
+
baseline-browser-mapping: 2.9.11
1994
1994
+
caniuse-lite: 1.0.30001761
1995
1995
+
electron-to-chromium: 1.5.267
1996
1996
+
node-releases: 2.0.27
1997
1997
+
update-browserslist-db: 1.2.3(browserslist@4.28.1)
1998
1998
+
1999
1999
+
builtin-modules@5.0.0: {}
2000
2000
+
1294
2001
bumpp@10.3.2:
1295
2002
dependencies:
1296
2003
ansis: 4.2.0
···
1324
2031
1325
2032
cac@6.7.14: {}
1326
2033
2034
2034
+
callsites@3.1.0: {}
2035
2035
+
2036
2036
+
caniuse-lite@1.0.30001761: {}
2037
2037
+
1327
2038
chai@6.2.1: {}
2039
2039
+
2040
2040
+
chalk@4.1.2:
2041
2041
+
dependencies:
2042
2042
+
ansi-styles: 4.3.0
2043
2043
+
supports-color: 7.2.0
2044
2044
+
2045
2045
+
change-case@5.4.4: {}
1328
2046
1329
2047
chokidar@5.0.0:
1330
2048
dependencies:
1331
2049
readdirp: 5.0.0
1332
2050
2051
2051
+
ci-info@4.3.1: {}
2052
2052
+
1333
2053
citty@0.1.6:
1334
2054
dependencies:
1335
2055
consola: 3.4.2
1336
2056
2057
2057
+
clean-regexp@1.0.0:
2058
2058
+
dependencies:
2059
2059
+
escape-string-regexp: 1.0.5
2060
2060
+
2061
2061
+
color-convert@2.0.1:
2062
2062
+
dependencies:
2063
2063
+
color-name: 1.1.4
2064
2064
+
2065
2065
+
color-name@1.1.4: {}
2066
2066
+
2067
2067
+
concat-map@0.0.1: {}
2068
2068
+
1337
2069
confbox@0.2.2: {}
1338
2070
1339
2071
consola@3.4.2: {}
1340
2072
2073
2073
+
core-js-compat@3.47.0:
2074
2074
+
dependencies:
2075
2075
+
browserslist: 4.28.1
2076
2076
+
2077
2077
+
cross-spawn@7.0.6:
2078
2078
+
dependencies:
2079
2079
+
path-key: 3.1.1
2080
2080
+
shebang-command: 2.0.0
2081
2081
+
which: 2.0.2
2082
2082
+
2083
2083
+
debug@4.4.3:
2084
2084
+
dependencies:
2085
2085
+
ms: 2.1.3
2086
2086
+
2087
2087
+
deep-is@0.1.4: {}
2088
2088
+
1341
2089
defu@6.1.4: {}
1342
2090
1343
2091
destr@2.0.5: {}
···
1357
2105
'@dprint/win32-x64': 0.50.2
1358
2106
1359
2107
dts-resolver@2.1.3: {}
2108
2108
+
2109
2109
+
electron-to-chromium@1.5.267: {}
1360
2110
1361
2111
empathic@2.0.0: {}
1362
2112
···
1393
2143
1394
2144
escalade@3.2.0: {}
1395
2145
2146
2146
+
escape-string-regexp@1.0.5: {}
2147
2147
+
2148
2148
+
escape-string-regexp@4.0.0: {}
2149
2149
+
2150
2150
+
eslint-plugin-unicorn@62.0.0(eslint@9.39.2(jiti@2.6.1)):
2151
2151
+
dependencies:
2152
2152
+
'@babel/helper-validator-identifier': 7.28.5
2153
2153
+
'@eslint-community/eslint-utils': 4.9.0(eslint@9.39.2(jiti@2.6.1))
2154
2154
+
'@eslint/plugin-kit': 0.4.1
2155
2155
+
change-case: 5.4.4
2156
2156
+
ci-info: 4.3.1
2157
2157
+
clean-regexp: 1.0.0
2158
2158
+
core-js-compat: 3.47.0
2159
2159
+
eslint: 9.39.2(jiti@2.6.1)
2160
2160
+
esquery: 1.6.0
2161
2161
+
find-up-simple: 1.0.1
2162
2162
+
globals: 16.5.0
2163
2163
+
indent-string: 5.0.0
2164
2164
+
is-builtin-module: 5.0.0
2165
2165
+
jsesc: 3.1.0
2166
2166
+
pluralize: 8.0.0
2167
2167
+
regexp-tree: 0.1.27
2168
2168
+
regjsparser: 0.13.0
2169
2169
+
semver: 7.7.3
2170
2170
+
strip-indent: 4.1.1
2171
2171
+
2172
2172
+
eslint-scope@8.4.0:
2173
2173
+
dependencies:
2174
2174
+
esrecurse: 4.3.0
2175
2175
+
estraverse: 5.3.0
2176
2176
+
2177
2177
+
eslint-visitor-keys@3.4.3: {}
2178
2178
+
2179
2179
+
eslint-visitor-keys@4.2.1: {}
2180
2180
+
2181
2181
+
eslint@9.39.2(jiti@2.6.1):
2182
2182
+
dependencies:
2183
2183
+
'@eslint-community/eslint-utils': 4.9.0(eslint@9.39.2(jiti@2.6.1))
2184
2184
+
'@eslint-community/regexpp': 4.12.2
2185
2185
+
'@eslint/config-array': 0.21.1
2186
2186
+
'@eslint/config-helpers': 0.4.2
2187
2187
+
'@eslint/core': 0.17.0
2188
2188
+
'@eslint/eslintrc': 3.3.3
2189
2189
+
'@eslint/js': 9.39.2
2190
2190
+
'@eslint/plugin-kit': 0.4.1
2191
2191
+
'@humanfs/node': 0.16.7
2192
2192
+
'@humanwhocodes/module-importer': 1.0.1
2193
2193
+
'@humanwhocodes/retry': 0.4.3
2194
2194
+
'@types/estree': 1.0.8
2195
2195
+
ajv: 6.12.6
2196
2196
+
chalk: 4.1.2
2197
2197
+
cross-spawn: 7.0.6
2198
2198
+
debug: 4.4.3
2199
2199
+
escape-string-regexp: 4.0.0
2200
2200
+
eslint-scope: 8.4.0
2201
2201
+
eslint-visitor-keys: 4.2.1
2202
2202
+
espree: 10.4.0
2203
2203
+
esquery: 1.6.0
2204
2204
+
esutils: 2.0.3
2205
2205
+
fast-deep-equal: 3.1.3
2206
2206
+
file-entry-cache: 8.0.0
2207
2207
+
find-up: 5.0.0
2208
2208
+
glob-parent: 6.0.2
2209
2209
+
ignore: 5.3.2
2210
2210
+
imurmurhash: 0.1.4
2211
2211
+
is-glob: 4.0.3
2212
2212
+
json-stable-stringify-without-jsonify: 1.0.1
2213
2213
+
lodash.merge: 4.6.2
2214
2214
+
minimatch: 3.1.2
2215
2215
+
natural-compare: 1.4.0
2216
2216
+
optionator: 0.9.4
2217
2217
+
optionalDependencies:
2218
2218
+
jiti: 2.6.1
2219
2219
+
transitivePeerDependencies:
2220
2220
+
- supports-color
2221
2221
+
2222
2222
+
espree@10.4.0:
2223
2223
+
dependencies:
2224
2224
+
acorn: 8.15.0
2225
2225
+
acorn-jsx: 5.3.2(acorn@8.15.0)
2226
2226
+
eslint-visitor-keys: 4.2.1
2227
2227
+
2228
2228
+
esquery@1.6.0:
2229
2229
+
dependencies:
2230
2230
+
estraverse: 5.3.0
2231
2231
+
2232
2232
+
esrecurse@4.3.0:
2233
2233
+
dependencies:
2234
2234
+
estraverse: 5.3.0
2235
2235
+
2236
2236
+
estraverse@5.3.0: {}
2237
2237
+
1396
2238
estree-walker@3.0.3:
1397
2239
dependencies:
1398
2240
'@types/estree': 1.0.8
1399
2241
2242
2242
+
esutils@2.0.3: {}
2243
2243
+
1400
2244
expect-type@1.3.0: {}
1401
2245
1402
2246
exsolve@1.0.8: {}
1403
2247
2248
2248
+
fast-deep-equal@3.1.3: {}
2249
2249
+
2250
2250
+
fast-json-stable-stringify@2.1.0: {}
2251
2251
+
2252
2252
+
fast-levenshtein@2.0.6: {}
2253
2253
+
1404
2254
fdir@6.5.0(picomatch@4.0.3):
1405
2255
optionalDependencies:
1406
2256
picomatch: 4.0.3
1407
2257
2258
2258
+
file-entry-cache@8.0.0:
2259
2259
+
dependencies:
2260
2260
+
flat-cache: 4.0.1
2261
2261
+
2262
2262
+
find-up-simple@1.0.1: {}
2263
2263
+
2264
2264
+
find-up@5.0.0:
2265
2265
+
dependencies:
2266
2266
+
locate-path: 6.0.0
2267
2267
+
path-exists: 4.0.0
2268
2268
+
2269
2269
+
flat-cache@4.0.1:
2270
2270
+
dependencies:
2271
2271
+
flatted: 3.3.3
2272
2272
+
keyv: 4.5.4
2273
2273
+
2274
2274
+
flatted@3.3.3: {}
2275
2275
+
1408
2276
fsevents@2.3.3:
1409
2277
optional: true
1410
2278
···
1421
2289
nypm: 0.6.2
1422
2290
pathe: 2.0.3
1423
2291
2292
2292
+
glob-parent@6.0.2:
2293
2293
+
dependencies:
2294
2294
+
is-glob: 4.0.3
2295
2295
+
2296
2296
+
globals@14.0.0: {}
2297
2297
+
2298
2298
+
globals@16.5.0: {}
2299
2299
+
2300
2300
+
has-flag@4.0.0: {}
2301
2301
+
1424
2302
hookable@5.5.3: {}
2303
2303
+
2304
2304
+
ignore@5.3.2: {}
2305
2305
+
2306
2306
+
ignore@7.0.5: {}
2307
2307
+
2308
2308
+
import-fresh@3.3.1:
2309
2309
+
dependencies:
2310
2310
+
parent-module: 1.0.1
2311
2311
+
resolve-from: 4.0.0
1425
2312
1426
2313
import-without-cache@0.2.4: {}
2314
2314
+
2315
2315
+
imurmurhash@0.1.4: {}
2316
2316
+
2317
2317
+
indent-string@5.0.0: {}
2318
2318
+
2319
2319
+
is-builtin-module@5.0.0:
2320
2320
+
dependencies:
2321
2321
+
builtin-modules: 5.0.0
2322
2322
+
2323
2323
+
is-extglob@2.1.1: {}
2324
2324
+
2325
2325
+
is-glob@4.0.3:
2326
2326
+
dependencies:
2327
2327
+
is-extglob: 2.1.1
2328
2328
+
2329
2329
+
isexe@2.0.0: {}
1427
2330
1428
2331
jiti@2.6.1: {}
1429
2332
2333
2333
+
js-yaml@4.1.1:
2334
2334
+
dependencies:
2335
2335
+
argparse: 2.0.1
2336
2336
+
1430
2337
jsesc@3.1.0: {}
1431
2338
2339
2339
+
json-buffer@3.0.1: {}
2340
2340
+
2341
2341
+
json-schema-traverse@0.4.1: {}
2342
2342
+
2343
2343
+
json-stable-stringify-without-jsonify@1.0.1: {}
2344
2344
+
1432
2345
jsonc-parser@3.3.1: {}
1433
2346
2347
2347
+
keyv@4.5.4:
2348
2348
+
dependencies:
2349
2349
+
json-buffer: 3.0.1
2350
2350
+
2351
2351
+
levn@0.4.1:
2352
2352
+
dependencies:
2353
2353
+
prelude-ls: 1.2.1
2354
2354
+
type-check: 0.4.0
2355
2355
+
2356
2356
+
locate-path@6.0.0:
2357
2357
+
dependencies:
2358
2358
+
p-locate: 5.0.0
2359
2359
+
2360
2360
+
lodash.merge@4.6.2: {}
2361
2361
+
1434
2362
magic-string@0.30.21:
1435
2363
dependencies:
1436
2364
'@jridgewell/sourcemap-codec': 1.5.5
1437
2365
2366
2366
+
minimatch@3.1.2:
2367
2367
+
dependencies:
2368
2368
+
brace-expansion: 1.1.12
2369
2369
+
2370
2370
+
minimatch@9.0.5:
2371
2371
+
dependencies:
2372
2372
+
brace-expansion: 2.0.2
2373
2373
+
2374
2374
+
ms@2.1.3: {}
2375
2375
+
1438
2376
nanoid@3.3.11: {}
1439
2377
2378
2378
+
natural-compare@1.4.0: {}
2379
2379
+
1440
2380
node-fetch-native@1.6.7: {}
2381
2381
+
2382
2382
+
node-releases@2.0.27: {}
1441
2383
1442
2384
nypm@0.6.2:
1443
2385
dependencies:
···
1451
2393
1452
2394
ohash@2.0.11: {}
1453
2395
2396
2396
+
optionator@0.9.4:
2397
2397
+
dependencies:
2398
2398
+
deep-is: 0.1.4
2399
2399
+
fast-levenshtein: 2.0.6
2400
2400
+
levn: 0.4.1
2401
2401
+
prelude-ls: 1.2.1
2402
2402
+
type-check: 0.4.0
2403
2403
+
word-wrap: 1.2.5
2404
2404
+
2405
2405
+
p-limit@3.1.0:
2406
2406
+
dependencies:
2407
2407
+
yocto-queue: 0.1.0
2408
2408
+
2409
2409
+
p-locate@5.0.0:
2410
2410
+
dependencies:
2411
2411
+
p-limit: 3.1.0
2412
2412
+
1454
2413
package-manager-detector@1.6.0: {}
1455
2414
2415
2415
+
parent-module@1.0.1:
2416
2416
+
dependencies:
2417
2417
+
callsites: 3.1.0
2418
2418
+
2419
2419
+
path-exists@4.0.0: {}
2420
2420
+
2421
2421
+
path-key@3.1.1: {}
2422
2422
+
1456
2423
pathe@2.0.3: {}
1457
2424
1458
2425
perfect-debounce@2.0.0: {}
···
1467
2434
exsolve: 1.0.8
1468
2435
pathe: 2.0.3
1469
2436
2437
2437
+
pluralize@8.0.0: {}
2438
2438
+
1470
2439
postcss@8.5.6:
1471
2440
dependencies:
1472
2441
nanoid: 3.3.11
1473
2442
picocolors: 1.1.1
1474
2443
source-map-js: 1.2.1
1475
2444
2445
2445
+
prelude-ls@1.2.1: {}
2446
2446
+
2447
2447
+
punycode@2.3.1: {}
2448
2448
+
1476
2449
quansync@1.0.0: {}
1477
2450
1478
2451
rc9@2.1.2:
···
1481
2454
destr: 2.0.5
1482
2455
1483
2456
readdirp@5.0.0: {}
2457
2457
+
2458
2458
+
regexp-tree@0.1.27: {}
2459
2459
+
2460
2460
+
regjsparser@0.13.0:
2461
2461
+
dependencies:
2462
2462
+
jsesc: 3.1.0
2463
2463
+
2464
2464
+
resolve-from@4.0.0: {}
1484
2465
1485
2466
resolve-pkg-maps@1.0.0: {}
1486
2467
···
1549
2530
1550
2531
semver@7.7.3: {}
1551
2532
2533
2533
+
shebang-command@2.0.0:
2534
2534
+
dependencies:
2535
2535
+
shebang-regex: 3.0.0
2536
2536
+
2537
2537
+
shebang-regex@3.0.0: {}
2538
2538
+
1552
2539
siginfo@2.0.0: {}
1553
2540
1554
2541
source-map-js@1.2.1: {}
···
1557
2544
1558
2545
std-env@3.10.0: {}
1559
2546
2547
2547
+
strip-indent@4.1.1: {}
2548
2548
+
2549
2549
+
strip-json-comments@3.1.1: {}
2550
2550
+
2551
2551
+
supports-color@7.2.0:
2552
2552
+
dependencies:
2553
2553
+
has-flag: 4.0.0
2554
2554
+
1560
2555
tinybench@2.9.0: {}
1561
2556
1562
2557
tinyexec@1.0.2: {}
···
1569
2564
tinyrainbow@3.0.3: {}
1570
2565
1571
2566
tree-kill@1.2.2: {}
2567
2567
+
2568
2568
+
ts-api-utils@2.1.0(typescript@5.9.3):
2569
2569
+
dependencies:
2570
2570
+
typescript: 5.9.3
1572
2571
1573
2572
tsdown@0.18.1(typescript@5.9.3):
1574
2573
dependencies:
···
1600
2599
tslib@2.8.1:
1601
2600
optional: true
1602
2601
2602
2602
+
type-check@0.4.0:
2603
2603
+
dependencies:
2604
2604
+
prelude-ls: 1.2.1
2605
2605
+
2606
2606
+
typescript-eslint@8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3):
2607
2607
+
dependencies:
2608
2608
+
'@typescript-eslint/eslint-plugin': 8.50.0(@typescript-eslint/parser@8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
2609
2609
+
'@typescript-eslint/parser': 8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
2610
2610
+
'@typescript-eslint/typescript-estree': 8.50.0(typescript@5.9.3)
2611
2611
+
'@typescript-eslint/utils': 8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
2612
2612
+
eslint: 9.39.2(jiti@2.6.1)
2613
2613
+
typescript: 5.9.3
2614
2614
+
transitivePeerDependencies:
2615
2615
+
- supports-color
2616
2616
+
1603
2617
typescript@5.9.3: {}
1604
2618
1605
2619
unconfig-core@7.4.2:
···
1612
2626
unrun@0.2.20:
1613
2627
dependencies:
1614
2628
rolldown: 1.0.0-beta.55
2629
2629
+
2630
2630
+
update-browserslist-db@1.2.3(browserslist@4.28.1):
2631
2631
+
dependencies:
2632
2632
+
browserslist: 4.28.1
2633
2633
+
escalade: 3.2.0
2634
2634
+
picocolors: 1.1.1
2635
2635
+
2636
2636
+
uri-js@4.4.1:
2637
2637
+
dependencies:
2638
2638
+
punycode: 2.3.1
1615
2639
1616
2640
vite@7.3.0(@types/node@25.0.3)(jiti@2.6.1)(yaml@2.8.2):
1617
2641
dependencies:
···
1664
2688
- tsx
1665
2689
- yaml
1666
2690
2691
2691
+
which@2.0.2:
2692
2692
+
dependencies:
2693
2693
+
isexe: 2.0.0
2694
2694
+
1667
2695
why-is-node-running@2.3.0:
1668
2696
dependencies:
1669
2697
siginfo: 2.0.0
1670
2698
stackback: 0.0.2
1671
2699
2700
2700
+
word-wrap@1.2.5: {}
2701
2701
+
1672
2702
yaml@2.8.2: {}
2703
2703
+
2704
2704
+
yocto-queue@0.1.0: {}
+1
pnpm-workspace.yaml
···
2
2
- packages/*
3
3
4
4
onlyBuiltDependencies:
5
5
+
- dprint
5
6
- esbuild