@ribbon-studios/js-utils 1.1.1 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CONTRIBUTING.md +1 -1
- package/README.md +110 -2
- package/dist/__tests__/rfetch.spec.d.ts +1 -0
- package/dist/index.cjs +92 -4
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +93 -5
- package/dist/promises/__tests__/retry.spec.d.ts +1 -0
- package/dist/promises/index.d.ts +1 -0
- package/dist/promises/retry.d.ts +8 -0
- package/dist/rfetch.d.ts +65 -0
- package/package.json +18 -15
package/CONTRIBUTING.md
CHANGED
package/README.md
CHANGED
|
@@ -19,6 +19,14 @@ Collection of generic javascript utilities curated by the Rainbow Cafe~
|
|
|
19
19
|
- [`assert`](#assert)
|
|
20
20
|
- [`assert.defined`](#assertdefined)
|
|
21
21
|
- [`never`](#never)
|
|
22
|
+
- [`retry`](#retry)
|
|
23
|
+
- [Fetch](#fetch)
|
|
24
|
+
- [`rfetch`](#rfetch)
|
|
25
|
+
- [`rfetch.get`](#rfetchget)
|
|
26
|
+
- [`rfetch.put`](#rfetchput)
|
|
27
|
+
- [`rfetch.post`](#rfetchpost)
|
|
28
|
+
- [`rfetch.patch`](#rfetchpatch)
|
|
29
|
+
- [`rfetch.remove`](#rfetchremove)
|
|
22
30
|
|
|
23
31
|
## Promises
|
|
24
32
|
|
|
@@ -96,6 +104,106 @@ const promise = never(); // Returns a promise that never resolves
|
|
|
96
104
|
const promise = never(Promise.resolve('hello')); // Returns a promise that never resolves
|
|
97
105
|
```
|
|
98
106
|
|
|
107
|
+
### `retry`
|
|
108
|
+
|
|
109
|
+
Retries a function `n` times until it resolves successfully.
|
|
110
|
+
This can be useful for requests that tend to be flaky.
|
|
111
|
+
|
|
112
|
+
```tsx
|
|
113
|
+
import { retry } from '@ribbon-studios/js-utils';
|
|
114
|
+
|
|
115
|
+
// Returns a promise that resolves when the request is successful or fails after its exceeded that maximum attempts.
|
|
116
|
+
const promise = retry(() => getMaps(), 5);
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Fetch
|
|
120
|
+
|
|
121
|
+
### `rfetch`
|
|
122
|
+
|
|
123
|
+
Lightweight wrapper around fetch that automatically handles:
|
|
124
|
+
|
|
125
|
+
- Query Params
|
|
126
|
+
- Form Data & JSON bodies
|
|
127
|
+
- JSON Responses (fallsback to text)
|
|
128
|
+
- Type Casting
|
|
129
|
+
- Errors
|
|
130
|
+
|
|
131
|
+
```tsx
|
|
132
|
+
import { rfetch, type RibbonFetchError } from '@ribbon-studios/js-utils';
|
|
133
|
+
|
|
134
|
+
try {
|
|
135
|
+
const response = await rfetch<MyExpectedResponse>('https://ribbonstudios.com', {
|
|
136
|
+
params: {
|
|
137
|
+
hello: 'world',
|
|
138
|
+
},
|
|
139
|
+
body: {
|
|
140
|
+
hallo: 'welt',
|
|
141
|
+
},
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
console.log(response);
|
|
145
|
+
// => MyExpectedResponse
|
|
146
|
+
} catch (error: RibbonFetchError<MyExpectedErrorResponse>) {
|
|
147
|
+
console.error(error);
|
|
148
|
+
// => { status: number; content: MyExpectedErrorResponse; }
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### `rfetch.get`
|
|
153
|
+
|
|
154
|
+
Shorthand for GET requests.
|
|
155
|
+
|
|
156
|
+
```tsx
|
|
157
|
+
import { rfetch, type RibbonFetchError } from '@ribbon-studios/js-utils';
|
|
158
|
+
|
|
159
|
+
// Shorthand for GET requests.
|
|
160
|
+
await rfetch.get<MyExpectedResponse>('https://ribbonstudios.com');
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### `rfetch.put`
|
|
164
|
+
|
|
165
|
+
Shorthand for PUT requests.
|
|
166
|
+
|
|
167
|
+
```tsx
|
|
168
|
+
import { rfetch, type RibbonFetchError } from '@ribbon-studios/js-utils';
|
|
169
|
+
|
|
170
|
+
// Shorthand for PUT requests.
|
|
171
|
+
await rfetch.put<MyExpectedResponse>('https://ribbonstudios.com');
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### `rfetch.post`
|
|
175
|
+
|
|
176
|
+
Shorthand for POST requests.
|
|
177
|
+
|
|
178
|
+
```tsx
|
|
179
|
+
import { rfetch, type RibbonFetchError } from '@ribbon-studios/js-utils';
|
|
180
|
+
|
|
181
|
+
// Shorthand for POST requests.
|
|
182
|
+
await rfetch.post<MyExpectedResponse>('https://ribbonstudios.com');
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### `rfetch.patch`
|
|
186
|
+
|
|
187
|
+
Shorthand for PATCH requests.
|
|
188
|
+
|
|
189
|
+
```tsx
|
|
190
|
+
import { rfetch, type RibbonFetchError } from '@ribbon-studios/js-utils';
|
|
191
|
+
|
|
192
|
+
// Shorthand for PATCH requests.
|
|
193
|
+
await rfetch.patch<MyExpectedResponse>('https://ribbonstudios.com');
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### `rfetch.remove`
|
|
197
|
+
|
|
198
|
+
Shorthand for DELETE requests.
|
|
199
|
+
|
|
200
|
+
```tsx
|
|
201
|
+
import { rfetch, type RibbonFetchError } from '@ribbon-studios/js-utils';
|
|
202
|
+
|
|
203
|
+
// Shorthand for DELETE requests.
|
|
204
|
+
await rfetch.remove<MyExpectedResponse>('https://ribbonstudios.com');
|
|
205
|
+
```
|
|
206
|
+
|
|
99
207
|
[_**Want to Contribute?**_](/CONTRIBUTING.md)
|
|
100
208
|
|
|
101
209
|
[npm-version-image]: https://img.shields.io/npm/v/@ribbon-studios/js-utils.svg
|
|
@@ -107,7 +215,7 @@ const promise = never(Promise.resolve('hello')); // Returns a promise that never
|
|
|
107
215
|
[coveralls-url]: https://coveralls.io/github/ribbon-studios/js-utils?branch=main
|
|
108
216
|
[code-style-image]: https://img.shields.io/badge/code%20style-prettier-ff69b4.svg
|
|
109
217
|
[code-style-url]: https://prettier.io
|
|
110
|
-
[maintainability-image]: https://img.shields.io/codeclimate/maintainability/ribbon-studios/
|
|
111
|
-
[maintainability-url]: https://codeclimate.com/github/ribbon-studios/
|
|
218
|
+
[maintainability-image]: https://img.shields.io/codeclimate/maintainability/ribbon-studios/js-utils
|
|
219
|
+
[maintainability-url]: https://codeclimate.com/github/ribbon-studios/js-utils/maintainability
|
|
112
220
|
[semantic-release-url]: https://github.com/semantic-release/semantic-release
|
|
113
221
|
[semantic-release-image]: https://img.shields.io/badge/%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/index.cjs
CHANGED
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
async function assert(p, predicate, message) {
|
|
4
4
|
const value = await p;
|
|
5
|
-
if (predicate(value))
|
|
6
|
-
return value;
|
|
5
|
+
if (predicate(value)) return value;
|
|
7
6
|
throw new Error(message ?? "Value does not satisfy predicate");
|
|
8
7
|
}
|
|
9
8
|
((assert2) => {
|
|
@@ -27,11 +26,100 @@ async function delay(promise, ms) {
|
|
|
27
26
|
delay2.fallback = fallback;
|
|
28
27
|
})(delay || (delay = {}));
|
|
29
28
|
async function never(p) {
|
|
30
|
-
if (p)
|
|
31
|
-
console.warn(`Promise is being called via "never", please ensure this doesn't get deployed!`, p);
|
|
29
|
+
if (p) console.warn(`Promise is being called via "never", please ensure this doesn't get deployed!`, p);
|
|
32
30
|
return new Promise(() => {
|
|
33
31
|
});
|
|
34
32
|
}
|
|
33
|
+
async function retry(fn, n) {
|
|
34
|
+
let attempts = 0;
|
|
35
|
+
while (true) {
|
|
36
|
+
try {
|
|
37
|
+
return await fn();
|
|
38
|
+
} catch (error) {
|
|
39
|
+
if (++attempts < n) continue;
|
|
40
|
+
throw error;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
async function rfetch(url, options) {
|
|
45
|
+
var _a, _b;
|
|
46
|
+
const { params, headers, body, ...internalOptions } = {
|
|
47
|
+
method: "GET",
|
|
48
|
+
headers: {},
|
|
49
|
+
...options
|
|
50
|
+
};
|
|
51
|
+
const internalURL = url instanceof URL ? url : new URL(url, url.startsWith("/") ? location.origin : void 0);
|
|
52
|
+
if (params) {
|
|
53
|
+
for (const [key, values] of Object.entries(params)) {
|
|
54
|
+
if (Array.isArray(values)) {
|
|
55
|
+
for (const value of values) {
|
|
56
|
+
internalURL.searchParams.append(key, value.toString());
|
|
57
|
+
}
|
|
58
|
+
} else {
|
|
59
|
+
internalURL.searchParams.append(key, values.toString());
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
let internalBody = void 0;
|
|
64
|
+
if (body) {
|
|
65
|
+
internalBody = body instanceof FormData ? body : JSON.stringify(body);
|
|
66
|
+
}
|
|
67
|
+
const response = await fetch(internalURL, {
|
|
68
|
+
...internalOptions,
|
|
69
|
+
headers: {
|
|
70
|
+
"Content-Type": internalBody instanceof FormData ? "application/x-www-form-urlencoded" : "application/json",
|
|
71
|
+
...headers
|
|
72
|
+
},
|
|
73
|
+
body: internalBody
|
|
74
|
+
});
|
|
75
|
+
const content = ((_b = (_a = response.headers.get("Content-Type")) == null ? void 0 : _a.toLowerCase()) == null ? void 0 : _b.includes("json")) ? await response.json() : await response.text();
|
|
76
|
+
if (response.ok) {
|
|
77
|
+
return content;
|
|
78
|
+
}
|
|
79
|
+
return Promise.reject({
|
|
80
|
+
status: response.status,
|
|
81
|
+
content
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
((rfetch2) => {
|
|
85
|
+
async function get(url, options) {
|
|
86
|
+
return rfetch2(url, {
|
|
87
|
+
...options,
|
|
88
|
+
method: "GET"
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
rfetch2.get = get;
|
|
92
|
+
async function put(url, options) {
|
|
93
|
+
return rfetch2(url, {
|
|
94
|
+
...options,
|
|
95
|
+
method: "PUT"
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
rfetch2.put = put;
|
|
99
|
+
async function post(url, options) {
|
|
100
|
+
return rfetch2(url, {
|
|
101
|
+
...options,
|
|
102
|
+
method: "POST"
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
rfetch2.post = post;
|
|
106
|
+
async function patch(url, options) {
|
|
107
|
+
return rfetch2(url, {
|
|
108
|
+
...options,
|
|
109
|
+
method: "PATCH"
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
rfetch2.patch = patch;
|
|
113
|
+
async function remove(url, options) {
|
|
114
|
+
return rfetch2(url, {
|
|
115
|
+
...options,
|
|
116
|
+
method: "DELETE"
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
rfetch2.remove = remove;
|
|
120
|
+
})(rfetch || (rfetch = {}));
|
|
35
121
|
exports.assert = assert;
|
|
36
122
|
exports.delay = delay;
|
|
37
123
|
exports.never = never;
|
|
124
|
+
exports.retry = retry;
|
|
125
|
+
exports.rfetch = rfetch;
|
package/dist/index.d.cts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
async function assert(p, predicate, message) {
|
|
2
2
|
const value = await p;
|
|
3
|
-
if (predicate(value))
|
|
4
|
-
return value;
|
|
3
|
+
if (predicate(value)) return value;
|
|
5
4
|
throw new Error(message ?? "Value does not satisfy predicate");
|
|
6
5
|
}
|
|
7
6
|
((assert2) => {
|
|
@@ -25,13 +24,102 @@ async function delay(promise, ms) {
|
|
|
25
24
|
delay2.fallback = fallback;
|
|
26
25
|
})(delay || (delay = {}));
|
|
27
26
|
async function never(p) {
|
|
28
|
-
if (p)
|
|
29
|
-
console.warn(`Promise is being called via "never", please ensure this doesn't get deployed!`, p);
|
|
27
|
+
if (p) console.warn(`Promise is being called via "never", please ensure this doesn't get deployed!`, p);
|
|
30
28
|
return new Promise(() => {
|
|
31
29
|
});
|
|
32
30
|
}
|
|
31
|
+
async function retry(fn, n) {
|
|
32
|
+
let attempts = 0;
|
|
33
|
+
while (true) {
|
|
34
|
+
try {
|
|
35
|
+
return await fn();
|
|
36
|
+
} catch (error) {
|
|
37
|
+
if (++attempts < n) continue;
|
|
38
|
+
throw error;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
async function rfetch(url, options) {
|
|
43
|
+
var _a, _b;
|
|
44
|
+
const { params, headers, body, ...internalOptions } = {
|
|
45
|
+
method: "GET",
|
|
46
|
+
headers: {},
|
|
47
|
+
...options
|
|
48
|
+
};
|
|
49
|
+
const internalURL = url instanceof URL ? url : new URL(url, url.startsWith("/") ? location.origin : void 0);
|
|
50
|
+
if (params) {
|
|
51
|
+
for (const [key, values] of Object.entries(params)) {
|
|
52
|
+
if (Array.isArray(values)) {
|
|
53
|
+
for (const value of values) {
|
|
54
|
+
internalURL.searchParams.append(key, value.toString());
|
|
55
|
+
}
|
|
56
|
+
} else {
|
|
57
|
+
internalURL.searchParams.append(key, values.toString());
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
let internalBody = void 0;
|
|
62
|
+
if (body) {
|
|
63
|
+
internalBody = body instanceof FormData ? body : JSON.stringify(body);
|
|
64
|
+
}
|
|
65
|
+
const response = await fetch(internalURL, {
|
|
66
|
+
...internalOptions,
|
|
67
|
+
headers: {
|
|
68
|
+
"Content-Type": internalBody instanceof FormData ? "application/x-www-form-urlencoded" : "application/json",
|
|
69
|
+
...headers
|
|
70
|
+
},
|
|
71
|
+
body: internalBody
|
|
72
|
+
});
|
|
73
|
+
const content = ((_b = (_a = response.headers.get("Content-Type")) == null ? void 0 : _a.toLowerCase()) == null ? void 0 : _b.includes("json")) ? await response.json() : await response.text();
|
|
74
|
+
if (response.ok) {
|
|
75
|
+
return content;
|
|
76
|
+
}
|
|
77
|
+
return Promise.reject({
|
|
78
|
+
status: response.status,
|
|
79
|
+
content
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
((rfetch2) => {
|
|
83
|
+
async function get(url, options) {
|
|
84
|
+
return rfetch2(url, {
|
|
85
|
+
...options,
|
|
86
|
+
method: "GET"
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
rfetch2.get = get;
|
|
90
|
+
async function put(url, options) {
|
|
91
|
+
return rfetch2(url, {
|
|
92
|
+
...options,
|
|
93
|
+
method: "PUT"
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
rfetch2.put = put;
|
|
97
|
+
async function post(url, options) {
|
|
98
|
+
return rfetch2(url, {
|
|
99
|
+
...options,
|
|
100
|
+
method: "POST"
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
rfetch2.post = post;
|
|
104
|
+
async function patch(url, options) {
|
|
105
|
+
return rfetch2(url, {
|
|
106
|
+
...options,
|
|
107
|
+
method: "PATCH"
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
rfetch2.patch = patch;
|
|
111
|
+
async function remove(url, options) {
|
|
112
|
+
return rfetch2(url, {
|
|
113
|
+
...options,
|
|
114
|
+
method: "DELETE"
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
rfetch2.remove = remove;
|
|
118
|
+
})(rfetch || (rfetch = {}));
|
|
33
119
|
export {
|
|
34
120
|
assert,
|
|
35
121
|
delay,
|
|
36
|
-
never
|
|
122
|
+
never,
|
|
123
|
+
retry,
|
|
124
|
+
rfetch
|
|
37
125
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/promises/index.d.ts
CHANGED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Attempts a request {@link n} times until it resolves.
|
|
3
|
+
*
|
|
4
|
+
* @param fn The function to invoke.
|
|
5
|
+
* @param n The maximum number of attempts
|
|
6
|
+
* @returns A resolved promise if it succeeds or the rejected promise if it exceeds {@link n}
|
|
7
|
+
*/
|
|
8
|
+
export declare function retry<T>(fn: () => Promise<T>, n: number): Promise<T>;
|
package/dist/rfetch.d.ts
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
type RibbonFetchParamType = string | number | boolean;
|
|
2
|
+
export type RibbonFetchOptions = {
|
|
3
|
+
method?: 'GET' | 'PUT' | 'POST' | 'PATCH' | 'DELETE';
|
|
4
|
+
params?: Record<string, RibbonFetchParamType | RibbonFetchParamType[]>;
|
|
5
|
+
body?: any;
|
|
6
|
+
headers?: HeadersInit;
|
|
7
|
+
} & Omit<RequestInit, 'body' | 'headers' | 'method'>;
|
|
8
|
+
export type RibbonFetchBasicOptions = Omit<RibbonFetchOptions, 'method' | 'body'>;
|
|
9
|
+
export type RibbonFetchBodyOptions = Omit<RibbonFetchOptions, 'method'>;
|
|
10
|
+
export type RibbonFetchError<R> = {
|
|
11
|
+
status: number;
|
|
12
|
+
content: R;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* A lightweight wrapper around fetch to simplify its usage.
|
|
16
|
+
*
|
|
17
|
+
* @param url The url you wish to fetch.
|
|
18
|
+
* @param options The request options.
|
|
19
|
+
* @returns The typed response or an error containing the `status` and the `content`
|
|
20
|
+
*/
|
|
21
|
+
export declare function rfetch<T = any>(url: string | URL, options?: RibbonFetchOptions): Promise<T>;
|
|
22
|
+
export declare namespace rfetch {
|
|
23
|
+
/**
|
|
24
|
+
* Shorthand method for a GET request
|
|
25
|
+
*
|
|
26
|
+
* @param url The url you wish to fetch.
|
|
27
|
+
* @param options The request options.
|
|
28
|
+
* @returns The typed response or an error containing the `status` and the `content`
|
|
29
|
+
*/
|
|
30
|
+
function get<T>(url: string | URL, options?: RibbonFetchBasicOptions): Promise<T>;
|
|
31
|
+
/**
|
|
32
|
+
* Shorthand method for a PUT request
|
|
33
|
+
*
|
|
34
|
+
* @param url The url you wish to fetch.
|
|
35
|
+
* @param options The request options.
|
|
36
|
+
* @returns The typed response or an error containing the `status` and the `content`
|
|
37
|
+
*/
|
|
38
|
+
function put<T>(url: string | URL, options?: RibbonFetchBodyOptions): Promise<T>;
|
|
39
|
+
/**
|
|
40
|
+
* Shorthand method for a POST request
|
|
41
|
+
*
|
|
42
|
+
* @param url The url you wish to fetch.
|
|
43
|
+
* @param options The request options.
|
|
44
|
+
* @returns The typed response or an error containing the `status` and the `content`
|
|
45
|
+
*/
|
|
46
|
+
function post<T>(url: string | URL, options?: RibbonFetchBodyOptions): Promise<T>;
|
|
47
|
+
/**
|
|
48
|
+
* Shorthand method for a PATCH request
|
|
49
|
+
*
|
|
50
|
+
* @param url The url you wish to fetch.
|
|
51
|
+
* @param options The request options.
|
|
52
|
+
* @returns The typed response or an error containing the `status` and the `content`
|
|
53
|
+
*/
|
|
54
|
+
function patch<T>(url: string | URL, options?: RibbonFetchBodyOptions): Promise<T>;
|
|
55
|
+
/**
|
|
56
|
+
* Shorthand method for a DELETE request
|
|
57
|
+
*
|
|
58
|
+
* @param url The url you wish to fetch.
|
|
59
|
+
* @param options The request options.
|
|
60
|
+
* @returns The typed response or an error containing the `status` and the `content`
|
|
61
|
+
* @note This is named `remove` purely because `delete` is a reserved key
|
|
62
|
+
*/
|
|
63
|
+
function remove<T>(url: string | URL, options?: RibbonFetchBodyOptions): Promise<T>;
|
|
64
|
+
}
|
|
65
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ribbon-studios/js-utils",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Collection of generic javascript utilities curated by the Rainbow Cafe~",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"source": "src/*.ts",
|
|
@@ -28,20 +28,23 @@
|
|
|
28
28
|
"build": "rm -rf dist && vite build"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
|
-
"@
|
|
32
|
-
"@
|
|
33
|
-
"@
|
|
34
|
-
"@
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
31
|
+
"@eslint/js": "^9.22.0",
|
|
32
|
+
"@types/chance": "^1.1.6",
|
|
33
|
+
"@types/node": "^22.13.10",
|
|
34
|
+
"@typescript-eslint/eslint-plugin": "^8.26.0",
|
|
35
|
+
"@typescript-eslint/parser": "^8.26.0",
|
|
36
|
+
"@vitest/coverage-v8": "^3.0.8",
|
|
37
|
+
"ajv": "^8.17.1",
|
|
38
|
+
"chance": "^1.1.12",
|
|
39
|
+
"eslint-plugin-unused-imports": "^4.1.4",
|
|
40
|
+
"happy-dom": "^17.4.1",
|
|
41
|
+
"jiti": "^2.4.2",
|
|
42
|
+
"typescript": "^5.8.2",
|
|
43
|
+
"typescript-eslint": "^8.26.0",
|
|
44
|
+
"vite": "^6.2.1",
|
|
45
|
+
"vite-plugin-dts": "^4.5.3",
|
|
46
|
+
"vite-plugin-lib-types": "^3.1.2",
|
|
47
|
+
"vitest": "^3.0.8",
|
|
45
48
|
"vitest-dom": "^0.1.1"
|
|
46
49
|
},
|
|
47
50
|
"publishConfig": {
|