@audio-ui/utils 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build$colon$pkg.log +15 -0
- package/CHANGELOG.md +7 -0
- package/README.md +3 -0
- package/package.json +44 -0
- package/src/geom.ts +335 -0
- package/src/index.ts +3 -0
- package/src/math.ts +34 -0
- package/src/std.ts +49 -0
- package/tsconfig.json +7 -0
- package/tsup.config.ts +11 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
|
|
2
|
+
[0m[2m[35m$[0m [2m[1mtsup[0m
|
|
3
|
+
[34mCLI[39m Building entry: {"index":"src/index.ts"}
|
|
4
|
+
[34mCLI[39m Using tsconfig: tsconfig.json
|
|
5
|
+
[34mCLI[39m tsup v8.5.1
|
|
6
|
+
[34mCLI[39m Using tsup config: /Users/lucienloua/Desktop/audio-ui/packages/utils/tsup.config.ts
|
|
7
|
+
[34mCLI[39m Target: es2022
|
|
8
|
+
[34mCLI[39m Cleaning output folder
|
|
9
|
+
[34mESM[39m Build start
|
|
10
|
+
[32mESM[39m [1mdist/index.js [22m[32m9.31 KB[39m
|
|
11
|
+
[32mESM[39m [1mdist/index.js.map [22m[32m20.40 KB[39m
|
|
12
|
+
[32mESM[39m ⚡️ Build success in 18ms
|
|
13
|
+
DTS Build start
|
|
14
|
+
DTS ⚡️ Build success in 1684ms
|
|
15
|
+
DTS dist/index.d.ts 5.34 KB
|
package/CHANGELOG.md
ADDED
package/README.md
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@audio-ui/utils",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "A collection of utility functions for Audio UI.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"module": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"type": "module",
|
|
9
|
+
"publishConfig": {
|
|
10
|
+
"access": "public"
|
|
11
|
+
},
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "git+https://github.com/ouestlabs/audio-ui.git",
|
|
15
|
+
"directory": "packages/utils"
|
|
16
|
+
},
|
|
17
|
+
"homepage": "https://github.com/ouestlabs/audio-ui/tree/main/packages/utils",
|
|
18
|
+
"bugs": {
|
|
19
|
+
"url": "https://github.com/ouestlabs/audio-ui/issues"
|
|
20
|
+
},
|
|
21
|
+
"keywords": [
|
|
22
|
+
"audio-ui",
|
|
23
|
+
"utils"
|
|
24
|
+
],
|
|
25
|
+
"exports": {
|
|
26
|
+
".": {
|
|
27
|
+
"types": "./dist/index.d.ts",
|
|
28
|
+
"import": "./dist/index.js"
|
|
29
|
+
},
|
|
30
|
+
"./dom": {
|
|
31
|
+
"types": "./dist/dom/index.d.ts",
|
|
32
|
+
"import": "./dist/dom/index.js"
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"scripts": {
|
|
36
|
+
"build:pkg": "tsup",
|
|
37
|
+
"dev": "tsup --watch"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@audio-ui/typescript": "workspace:*",
|
|
41
|
+
"@types/bun": "latest",
|
|
42
|
+
"tsup": "^8.5.0"
|
|
43
|
+
}
|
|
44
|
+
}
|
package/src/geom.ts
ADDED
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
import { clamp } from "./math";
|
|
2
|
+
import { type int, Unhandled } from "./std";
|
|
3
|
+
|
|
4
|
+
export type Point = { x: number; y: number };
|
|
5
|
+
export type Circle = Point & { r: number };
|
|
6
|
+
export type Size = { width: number; height: number };
|
|
7
|
+
export type Rect = Point & Size;
|
|
8
|
+
export type Padding = [number, number, number, number];
|
|
9
|
+
export type Client = { clientX: number; clientY: number };
|
|
10
|
+
|
|
11
|
+
export enum Axis {
|
|
12
|
+
T = 0,
|
|
13
|
+
R = 1,
|
|
14
|
+
B = 2,
|
|
15
|
+
L = 3,
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export enum Corner {
|
|
19
|
+
TL = 0,
|
|
20
|
+
TR = 1,
|
|
21
|
+
BR = 2,
|
|
22
|
+
BL = 3,
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export namespace Geom {
|
|
26
|
+
export const outerTangentPoints = (a: Circle, b: Circle): [Point, Point] => {
|
|
27
|
+
const dx = b.x - a.x;
|
|
28
|
+
const dy = b.y - a.y;
|
|
29
|
+
const angle =
|
|
30
|
+
Math.atan2(dy, dx) +
|
|
31
|
+
Math.acos((a.r - b.r) / Math.sqrt(dx * dx + dy * dy));
|
|
32
|
+
const cs = Math.cos(angle);
|
|
33
|
+
const sn = Math.sin(angle);
|
|
34
|
+
return [
|
|
35
|
+
{ x: a.x + a.r * cs, y: a.y + a.r * sn },
|
|
36
|
+
{ x: b.x + b.r * cs, y: b.y + b.r * sn },
|
|
37
|
+
];
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export namespace Point {
|
|
42
|
+
export const zero = (): Point => ({ x: 0, y: 0 });
|
|
43
|
+
export const create = (x: number, y: number): Point => ({ x, y });
|
|
44
|
+
export const clone = (point: Point): Point => ({ ...point });
|
|
45
|
+
export const floor = (point: Point): Point => ({
|
|
46
|
+
x: Math.floor(point.x),
|
|
47
|
+
y: Math.floor(point.y),
|
|
48
|
+
});
|
|
49
|
+
export const length = (point: Point): number =>
|
|
50
|
+
Math.sqrt(point.x * point.x + point.y * point.y);
|
|
51
|
+
export const distance = (a: Point, b: Point): number =>
|
|
52
|
+
Math.sqrt((b.x - a.x) ** 2 + (b.y - a.y) ** 2);
|
|
53
|
+
export const add = (a: Point, b: Point): Point => ({
|
|
54
|
+
x: a.x + b.x,
|
|
55
|
+
y: a.y + b.y,
|
|
56
|
+
});
|
|
57
|
+
export const subtract = (a: Point, b: Point): Point => ({
|
|
58
|
+
x: a.x - b.x,
|
|
59
|
+
y: a.y - b.y,
|
|
60
|
+
});
|
|
61
|
+
export const scaleBy = (point: Point, scale: number): Point => ({
|
|
62
|
+
x: point.x * scale,
|
|
63
|
+
y: point.y * scale,
|
|
64
|
+
});
|
|
65
|
+
export const scaleTo = (point: Point, scale: number): Point => {
|
|
66
|
+
const multiplier = scale / length(point);
|
|
67
|
+
return { x: point.x * multiplier, y: point.y * multiplier };
|
|
68
|
+
};
|
|
69
|
+
export const fromClient = (object: {
|
|
70
|
+
clientX: number;
|
|
71
|
+
clientY: number;
|
|
72
|
+
}): Point => ({
|
|
73
|
+
x: object.clientX,
|
|
74
|
+
y: object.clientY,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export namespace Rect {
|
|
79
|
+
export const Empty: Readonly<Rect> = Object.freeze({
|
|
80
|
+
x: 0,
|
|
81
|
+
y: 0,
|
|
82
|
+
width: 0,
|
|
83
|
+
height: 0,
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
export const corners = (rectangle: Rect): Array<Point> => {
|
|
87
|
+
const x0 = rectangle.x;
|
|
88
|
+
const y0 = rectangle.y;
|
|
89
|
+
const x1 = x0 + rectangle.width;
|
|
90
|
+
const y1 = y0 + rectangle.height;
|
|
91
|
+
return [
|
|
92
|
+
{ x: x0, y: y0 },
|
|
93
|
+
{ x: x1, y: y0 },
|
|
94
|
+
{ x: x1, y: y1 },
|
|
95
|
+
{ x: x0, y: y1 },
|
|
96
|
+
];
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
export const inflate = (rect: Rect, amount: number): Rect => ({
|
|
100
|
+
x: rect.x - amount,
|
|
101
|
+
y: rect.y - amount,
|
|
102
|
+
width: rect.width + amount * 2.0,
|
|
103
|
+
height: rect.height + amount * 2.0,
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
export const contains = (outer: Rect, inner: Rect): boolean => {
|
|
107
|
+
const topLeftInside = inner.x >= outer.x && inner.y >= outer.y;
|
|
108
|
+
const bottomRightInside =
|
|
109
|
+
inner.x + inner.width <= outer.x + outer.width &&
|
|
110
|
+
inner.y + inner.height <= outer.y + outer.height;
|
|
111
|
+
return topLeftInside && bottomRightInside;
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
export const isPointInside = (point: Point, rect: Rect): boolean =>
|
|
115
|
+
point.x >= rect.x &&
|
|
116
|
+
point.x <= rect.x + rect.width &&
|
|
117
|
+
point.y >= rect.y &&
|
|
118
|
+
point.y <= rect.y + rect.height;
|
|
119
|
+
|
|
120
|
+
export const intersect = (a: Rect, b: Rect): boolean => {
|
|
121
|
+
const xMin = Math.max(a.x, b.x);
|
|
122
|
+
const xMax = Math.min(a.x + a.width, b.x + b.width);
|
|
123
|
+
const yMax = Math.min(a.y + a.height, b.y + b.height);
|
|
124
|
+
const yMin = Math.max(a.y, b.y);
|
|
125
|
+
return xMax > xMin && yMax > yMin;
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
export const axis = (rectangle: Rect, axisValue: Axis): number => {
|
|
129
|
+
switch (axisValue) {
|
|
130
|
+
case Axis.T:
|
|
131
|
+
return rectangle.y;
|
|
132
|
+
case Axis.R:
|
|
133
|
+
return rectangle.x + rectangle.width;
|
|
134
|
+
case Axis.B:
|
|
135
|
+
return rectangle.y + rectangle.height;
|
|
136
|
+
case Axis.L:
|
|
137
|
+
return rectangle.x;
|
|
138
|
+
default:
|
|
139
|
+
return Unhandled(axisValue);
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
export const corner = (rectangle: Rect, cornerValue: Corner): Point => {
|
|
144
|
+
switch (cornerValue) {
|
|
145
|
+
case Corner.TL:
|
|
146
|
+
return { x: rectangle.x, y: rectangle.y };
|
|
147
|
+
case Corner.TR:
|
|
148
|
+
return { x: rectangle.x + rectangle.width, y: rectangle.y };
|
|
149
|
+
case Corner.BR:
|
|
150
|
+
return {
|
|
151
|
+
x: rectangle.x + rectangle.width,
|
|
152
|
+
y: rectangle.y + rectangle.height,
|
|
153
|
+
};
|
|
154
|
+
case Corner.BL:
|
|
155
|
+
return { x: rectangle.x, y: rectangle.y + rectangle.height };
|
|
156
|
+
default:
|
|
157
|
+
return Unhandled(cornerValue);
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
export const center = (rectangle: Rect): Point => ({
|
|
162
|
+
x: rectangle.x + rectangle.width * 0.5,
|
|
163
|
+
y: rectangle.y + rectangle.height * 0.5,
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
export const isEmpty = (rectangle: Rect): boolean =>
|
|
167
|
+
rectangle.width === 0 || rectangle.height === 0;
|
|
168
|
+
|
|
169
|
+
export const union = (a: Rect, b: Readonly<Rect>): void => {
|
|
170
|
+
if (Rect.isEmpty(a)) {
|
|
171
|
+
if (!Rect.isEmpty(b)) {
|
|
172
|
+
a.x = b.x;
|
|
173
|
+
a.y = b.y;
|
|
174
|
+
a.width = b.width;
|
|
175
|
+
a.height = b.height;
|
|
176
|
+
}
|
|
177
|
+
} else if (!Rect.isEmpty(b)) {
|
|
178
|
+
const bx = b.x;
|
|
179
|
+
const by = b.y;
|
|
180
|
+
const ux = Math.min(a.x, bx);
|
|
181
|
+
const uy = Math.min(a.y, by);
|
|
182
|
+
a.width = Math.max(a.x + a.width, bx + b.width) - ux;
|
|
183
|
+
a.height = Math.max(a.y + a.height, by + b.height) - uy;
|
|
184
|
+
a.x = ux;
|
|
185
|
+
a.y = uy;
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export interface AABB {
|
|
191
|
+
xMin: number;
|
|
192
|
+
xMax: number;
|
|
193
|
+
yMin: number;
|
|
194
|
+
yMax: number;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
export namespace AABB {
|
|
198
|
+
export const width = (aabb: AABB): number => aabb.xMax - aabb.xMin;
|
|
199
|
+
export const height = (aabb: AABB): number => aabb.yMax - aabb.yMin;
|
|
200
|
+
|
|
201
|
+
export const from = (aabb: AABB, that: AABB): void => {
|
|
202
|
+
aabb.xMin = that.xMin;
|
|
203
|
+
aabb.xMax = that.xMax;
|
|
204
|
+
aabb.yMin = that.yMin;
|
|
205
|
+
aabb.yMax = that.yMax;
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
export const extend = (aabb: AABB, offset: number): void => {
|
|
209
|
+
aabb.xMin -= offset;
|
|
210
|
+
aabb.yMin -= offset;
|
|
211
|
+
aabb.xMax += offset;
|
|
212
|
+
aabb.yMax += offset;
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
export const padding = (
|
|
216
|
+
aabb: AABB,
|
|
217
|
+
[top, right, bottom, left]: Readonly<Padding>
|
|
218
|
+
): AABB => {
|
|
219
|
+
aabb.xMin += left;
|
|
220
|
+
aabb.yMin += top;
|
|
221
|
+
aabb.xMax -= right;
|
|
222
|
+
aabb.yMax -= bottom;
|
|
223
|
+
return aabb;
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
export const intersectPoint = (aabb: AABB, point: Point): boolean =>
|
|
227
|
+
aabb.xMin <= point.x &&
|
|
228
|
+
point.x < aabb.xMax &&
|
|
229
|
+
aabb.yMin <= point.y &&
|
|
230
|
+
point.y < aabb.yMax;
|
|
231
|
+
|
|
232
|
+
export const intersectThat = (aabb: AABB, that: AABB): boolean =>
|
|
233
|
+
that.xMin < aabb.xMax &&
|
|
234
|
+
that.xMax > aabb.xMin &&
|
|
235
|
+
that.yMin < aabb.yMax &&
|
|
236
|
+
that.yMax > aabb.yMin;
|
|
237
|
+
|
|
238
|
+
export const center = (aabb: AABB): Point => ({
|
|
239
|
+
x: (aabb.xMin + aabb.xMax) * 0.5,
|
|
240
|
+
y: (aabb.yMin + aabb.yMax) * 0.5,
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
export namespace Padding {
|
|
245
|
+
export const Identity: Readonly<Padding> = Object.freeze([
|
|
246
|
+
0.0, 0.0, 0.0, 0.0,
|
|
247
|
+
]);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
export namespace CohenSutherland {
|
|
251
|
+
export const intersects = (
|
|
252
|
+
xMin: number,
|
|
253
|
+
xMax: number,
|
|
254
|
+
yMin: number,
|
|
255
|
+
yMax: number,
|
|
256
|
+
x0: number,
|
|
257
|
+
y0: number,
|
|
258
|
+
x1: number,
|
|
259
|
+
y1: number
|
|
260
|
+
): boolean => {
|
|
261
|
+
const c0 = code(xMin, xMax, yMin, yMax, x0, y0);
|
|
262
|
+
const c1 = code(xMin, xMax, yMin, yMax, x1, y1);
|
|
263
|
+
if ((c0 | c1) === 0) {
|
|
264
|
+
return false;
|
|
265
|
+
}
|
|
266
|
+
if ((c0 & c1) !== 0) {
|
|
267
|
+
return false;
|
|
268
|
+
}
|
|
269
|
+
const s = sign(x0, y0, x1, y1, xMin, yMin);
|
|
270
|
+
return (
|
|
271
|
+
s !== sign(x0, y0, x1, y1, xMax, yMin) ||
|
|
272
|
+
s !== sign(x0, y0, x1, y1, xMax, yMax) ||
|
|
273
|
+
s !== sign(x0, y0, x1, y1, xMin, yMax)
|
|
274
|
+
);
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
const code = (
|
|
278
|
+
xMin: number,
|
|
279
|
+
xMax: number,
|
|
280
|
+
yMin: number,
|
|
281
|
+
yMax: number,
|
|
282
|
+
x: number,
|
|
283
|
+
y: number
|
|
284
|
+
): int => {
|
|
285
|
+
let codeValue = 0;
|
|
286
|
+
if (x <= xMin) {
|
|
287
|
+
codeValue |= 1;
|
|
288
|
+
} else if (x >= xMax) {
|
|
289
|
+
codeValue |= 2;
|
|
290
|
+
}
|
|
291
|
+
if (y <= yMin) {
|
|
292
|
+
codeValue |= 8;
|
|
293
|
+
} else if (y >= yMax) {
|
|
294
|
+
codeValue |= 4;
|
|
295
|
+
}
|
|
296
|
+
return codeValue;
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
const sign = (
|
|
300
|
+
x0: number,
|
|
301
|
+
y0: number,
|
|
302
|
+
x1: number,
|
|
303
|
+
y1: number,
|
|
304
|
+
x2: number,
|
|
305
|
+
y2: number
|
|
306
|
+
): boolean => (x1 - x0) * (y2 - y0) - (x2 - x0) * (y1 - y0) >= 0;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
export interface ValueAxis {
|
|
310
|
+
valueToAxis(value: number): number;
|
|
311
|
+
axisToValue(axis: number): number;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
export namespace ValueAxis {
|
|
315
|
+
export const Identity: ValueAxis = {
|
|
316
|
+
valueToAxis: (value: number): number => value,
|
|
317
|
+
axisToValue: (axis: number): number => axis,
|
|
318
|
+
};
|
|
319
|
+
|
|
320
|
+
export const toClamped = (
|
|
321
|
+
valueAxis: ValueAxis,
|
|
322
|
+
min: number,
|
|
323
|
+
max: number
|
|
324
|
+
): ValueAxis => ({
|
|
325
|
+
valueToAxis: (value: number): number =>
|
|
326
|
+
valueAxis.valueToAxis(clamp(value, min, max)),
|
|
327
|
+
axisToValue: (axis: number): number =>
|
|
328
|
+
clamp(valueAxis.axisToValue(axis), min, max),
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
export const createClamped = (min: number, max: number): ValueAxis => ({
|
|
332
|
+
valueToAxis: (value: number): number => clamp(value, min, max),
|
|
333
|
+
axisToValue: (axis: number): number => clamp(axis, min, max),
|
|
334
|
+
});
|
|
335
|
+
}
|
package/src/index.ts
ADDED
package/src/math.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { int, unitValue } from "./std";
|
|
2
|
+
|
|
3
|
+
export const TAU = Math.PI * 2.0;
|
|
4
|
+
export const PI_HALF = Math.PI / 2.0;
|
|
5
|
+
export const PI_QUART = Math.PI / 4.0;
|
|
6
|
+
export const INVERSE_SQRT_2 = 1.0 / Math.sqrt(2.0);
|
|
7
|
+
|
|
8
|
+
export const clamp = (value: number, min: number, max: number): number =>
|
|
9
|
+
Math.max(min, Math.min(value, max));
|
|
10
|
+
export const clampUnit = (value: number): unitValue =>
|
|
11
|
+
Math.max(0.0, Math.min(value, 1.0));
|
|
12
|
+
export const squashUnit = (value: unitValue, margin: unitValue): unitValue =>
|
|
13
|
+
margin + (1.0 - 2.0 * margin) * Math.max(0.0, Math.min(value, 1.0));
|
|
14
|
+
export const quantizeFloor = (value: number, interval: number): number =>
|
|
15
|
+
Math.floor(value / interval) * interval;
|
|
16
|
+
export const quantizeCeil = (value: number, interval: number): number =>
|
|
17
|
+
Math.ceil(value / interval) * interval;
|
|
18
|
+
export const quantizeRound = (value: number, interval: number): number =>
|
|
19
|
+
Math.round(value / interval) * interval;
|
|
20
|
+
export const linear = (y1: number, y2: number, mu: number): number =>
|
|
21
|
+
y1 + (y2 - y1) * mu;
|
|
22
|
+
export const exponential = (y1: number, y2: number, mu: number): number =>
|
|
23
|
+
y1 * (y2 / y1) ** mu;
|
|
24
|
+
export const cosine = (y1: number, y2: number, mu: number): number => {
|
|
25
|
+
const mu2 = (1.0 - Math.cos(mu * Math.PI)) * 0.5;
|
|
26
|
+
return y1 * (1.0 - mu2) + y2 * mu2;
|
|
27
|
+
};
|
|
28
|
+
export const mod = (value: number, range: number): number =>
|
|
29
|
+
fract(value / range) * range;
|
|
30
|
+
export const fract = (value: number): number => value - Math.floor(value);
|
|
31
|
+
export const nextPowOf2 = (n: int): int =>
|
|
32
|
+
2 ** Math.ceil(Math.log(n) / Math.log(2));
|
|
33
|
+
export const radToDeg = (rad: number): number => (rad * 180.0) / Math.PI;
|
|
34
|
+
export const degToRad = (deg: number): number => (deg / 180.0) * Math.PI;
|
package/src/std.ts
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export type int = number;
|
|
2
|
+
export type unitValue = number; // 0...1
|
|
3
|
+
export type Optional<T> = T | undefined;
|
|
4
|
+
export type Nullable<T> = T | null;
|
|
5
|
+
export type Maybe<T> = T | undefined | null;
|
|
6
|
+
export type ValueOrProvider<T> = T | (() => T);
|
|
7
|
+
export type Procedure<T> = (value: T) => void;
|
|
8
|
+
export type Func<U, T> = (value: U) => T;
|
|
9
|
+
export type AnyFunc = (...args: any[]) => any;
|
|
10
|
+
export type AssertType<T> = (value: unknown) => value is T;
|
|
11
|
+
export type Exec = () => void;
|
|
12
|
+
|
|
13
|
+
export const isDefined = <T>(value: Maybe<T>): value is T =>
|
|
14
|
+
value !== undefined && value !== null;
|
|
15
|
+
|
|
16
|
+
export const isUndefined = (value: unknown): value is undefined =>
|
|
17
|
+
value === undefined;
|
|
18
|
+
|
|
19
|
+
export const isNotUndefined = <T>(value: Optional<T>): value is T =>
|
|
20
|
+
value !== undefined;
|
|
21
|
+
|
|
22
|
+
export const asDefined = <T>(
|
|
23
|
+
value: Maybe<T>,
|
|
24
|
+
fail: ValueOrProvider<string> = "asDefined failed"
|
|
25
|
+
): T =>
|
|
26
|
+
value === null || value === undefined ? panic(getOrProvide(fail)) : value;
|
|
27
|
+
|
|
28
|
+
export const Unhandled = <R>(empty: never): R => {
|
|
29
|
+
throw new Error(`Unhandled ${empty}`);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const panic = (issue?: string | Error | unknown): never => {
|
|
33
|
+
throw typeof issue === "string" ? new Error(issue) : issue;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export const getOrProvide = <T>(value: ValueOrProvider<T>): T =>
|
|
37
|
+
value instanceof Function ? value() : value;
|
|
38
|
+
|
|
39
|
+
export const EmptyExec: Exec = (): void => {
|
|
40
|
+
// no-op
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export const EmptyProcedure: Procedure<any> = (_: any): void => {
|
|
44
|
+
// no-op
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export function assertType<T>(_value: unknown): asserts _value is T {
|
|
48
|
+
// no-op
|
|
49
|
+
}
|
package/tsconfig.json
ADDED