@dungarees/random 0.11.4

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/fake.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ import type { RandomBackend } from './type.ts';
2
+ export type FakeRandomBackend = {
3
+ backend: RandomBackend;
4
+ integerRequests: Array<[number, number]>;
5
+ stringRequests: number[];
6
+ };
7
+ export declare const createFakeRandomBackend: () => FakeRandomBackend;
package/fake.js ADDED
@@ -0,0 +1,22 @@
1
+ // Returns the top of the range and a repeated letter, so a test can name the value it expects
2
+ // rather than reading it back out of the subject.
3
+ export const createFakeRandomBackend = () => {
4
+ const integerRequests = [];
5
+ const stringRequests = [];
6
+ const FIRST_LETTER_CHAR_CODE = 97;
7
+ return {
8
+ backend: {
9
+ generateInteger: (min, max) => {
10
+ integerRequests.push([min, max]);
11
+ return max;
12
+ },
13
+ generateString: (length) => {
14
+ const letter = String.fromCharCode(FIRST_LETTER_CHAR_CODE + stringRequests.length);
15
+ stringRequests.push(length);
16
+ return letter.repeat(length);
17
+ },
18
+ },
19
+ integerRequests,
20
+ stringRequests,
21
+ };
22
+ };
@@ -0,0 +1,2 @@
1
+ import type { RandomBackend } from './type.ts';
2
+ export declare const createNodeCryptoBackend: () => RandomBackend;
package/node-crypto.js ADDED
@@ -0,0 +1,10 @@
1
+ import { randomBytes, randomInt } from 'node:crypto';
2
+ export const createNodeCryptoBackend = () => ({
3
+ // randomInt takes an exclusive upper bound, and the service's range is inclusive.
4
+ generateInteger: (min, max) => randomInt(min, max + 1),
5
+ generateString: (length) => {
6
+ // Each byte renders as two hex characters, so an odd length needs one byte more than half.
7
+ const hex = randomBytes(Math.ceil(length / 2)).toString('hex');
8
+ return hex.slice(0, length);
9
+ },
10
+ });
package/package.json ADDED
@@ -0,0 +1,450 @@
1
+ {
2
+ "name": "@dungarees/random",
3
+ "engines": {
4
+ "node": ">=25.0.0"
5
+ },
6
+ "scripts": {
7
+ "type-check": "tsc --noEmit"
8
+ },
9
+ "type": "module",
10
+ "dependencies": {
11
+ "@dungarees/core": "*"
12
+ },
13
+ "devDependencies": {
14
+ "typescript": "^5.9.3",
15
+ "vitest": "^3.0.2"
16
+ },
17
+ "author": "info@productkind.com",
18
+ "license": "MIT",
19
+ "version": "0.11.4",
20
+ "exports": {
21
+ "./fake.ts": {
22
+ "import": "./fake.js",
23
+ "types": "./fake.d.ts"
24
+ },
25
+ "./node-crypto.ts": {
26
+ "import": "./node-crypto.js",
27
+ "types": "./node-crypto.d.ts"
28
+ },
29
+ "./node_modules/typescript/lib/lib.d.ts": {
30
+ "import": "./node_modules/typescript/lib/lib.d.js",
31
+ "types": "./node_modules/typescript/lib/lib.d.d.ts"
32
+ },
33
+ "./node_modules/typescript/lib/lib.decorators.d.ts": {
34
+ "import": "./node_modules/typescript/lib/lib.decorators.d.js",
35
+ "types": "./node_modules/typescript/lib/lib.decorators.d.d.ts"
36
+ },
37
+ "./node_modules/typescript/lib/lib.decorators.legacy.d.ts": {
38
+ "import": "./node_modules/typescript/lib/lib.decorators.legacy.d.js",
39
+ "types": "./node_modules/typescript/lib/lib.decorators.legacy.d.d.ts"
40
+ },
41
+ "./node_modules/typescript/lib/lib.dom.asynciterable.d.ts": {
42
+ "import": "./node_modules/typescript/lib/lib.dom.asynciterable.d.js",
43
+ "types": "./node_modules/typescript/lib/lib.dom.asynciterable.d.d.ts"
44
+ },
45
+ "./node_modules/typescript/lib/lib.dom.d.ts": {
46
+ "import": "./node_modules/typescript/lib/lib.dom.d.js",
47
+ "types": "./node_modules/typescript/lib/lib.dom.d.d.ts"
48
+ },
49
+ "./node_modules/typescript/lib/lib.dom.iterable.d.ts": {
50
+ "import": "./node_modules/typescript/lib/lib.dom.iterable.d.js",
51
+ "types": "./node_modules/typescript/lib/lib.dom.iterable.d.d.ts"
52
+ },
53
+ "./node_modules/typescript/lib/lib.es2015.collection.d.ts": {
54
+ "import": "./node_modules/typescript/lib/lib.es2015.collection.d.js",
55
+ "types": "./node_modules/typescript/lib/lib.es2015.collection.d.d.ts"
56
+ },
57
+ "./node_modules/typescript/lib/lib.es2015.core.d.ts": {
58
+ "import": "./node_modules/typescript/lib/lib.es2015.core.d.js",
59
+ "types": "./node_modules/typescript/lib/lib.es2015.core.d.d.ts"
60
+ },
61
+ "./node_modules/typescript/lib/lib.es2015.d.ts": {
62
+ "import": "./node_modules/typescript/lib/lib.es2015.d.js",
63
+ "types": "./node_modules/typescript/lib/lib.es2015.d.d.ts"
64
+ },
65
+ "./node_modules/typescript/lib/lib.es2015.generator.d.ts": {
66
+ "import": "./node_modules/typescript/lib/lib.es2015.generator.d.js",
67
+ "types": "./node_modules/typescript/lib/lib.es2015.generator.d.d.ts"
68
+ },
69
+ "./node_modules/typescript/lib/lib.es2015.iterable.d.ts": {
70
+ "import": "./node_modules/typescript/lib/lib.es2015.iterable.d.js",
71
+ "types": "./node_modules/typescript/lib/lib.es2015.iterable.d.d.ts"
72
+ },
73
+ "./node_modules/typescript/lib/lib.es2015.promise.d.ts": {
74
+ "import": "./node_modules/typescript/lib/lib.es2015.promise.d.js",
75
+ "types": "./node_modules/typescript/lib/lib.es2015.promise.d.d.ts"
76
+ },
77
+ "./node_modules/typescript/lib/lib.es2015.proxy.d.ts": {
78
+ "import": "./node_modules/typescript/lib/lib.es2015.proxy.d.js",
79
+ "types": "./node_modules/typescript/lib/lib.es2015.proxy.d.d.ts"
80
+ },
81
+ "./node_modules/typescript/lib/lib.es2015.reflect.d.ts": {
82
+ "import": "./node_modules/typescript/lib/lib.es2015.reflect.d.js",
83
+ "types": "./node_modules/typescript/lib/lib.es2015.reflect.d.d.ts"
84
+ },
85
+ "./node_modules/typescript/lib/lib.es2015.symbol.d.ts": {
86
+ "import": "./node_modules/typescript/lib/lib.es2015.symbol.d.js",
87
+ "types": "./node_modules/typescript/lib/lib.es2015.symbol.d.d.ts"
88
+ },
89
+ "./node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts": {
90
+ "import": "./node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.js",
91
+ "types": "./node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.d.ts"
92
+ },
93
+ "./node_modules/typescript/lib/lib.es2016.array.include.d.ts": {
94
+ "import": "./node_modules/typescript/lib/lib.es2016.array.include.d.js",
95
+ "types": "./node_modules/typescript/lib/lib.es2016.array.include.d.d.ts"
96
+ },
97
+ "./node_modules/typescript/lib/lib.es2016.d.ts": {
98
+ "import": "./node_modules/typescript/lib/lib.es2016.d.js",
99
+ "types": "./node_modules/typescript/lib/lib.es2016.d.d.ts"
100
+ },
101
+ "./node_modules/typescript/lib/lib.es2016.full.d.ts": {
102
+ "import": "./node_modules/typescript/lib/lib.es2016.full.d.js",
103
+ "types": "./node_modules/typescript/lib/lib.es2016.full.d.d.ts"
104
+ },
105
+ "./node_modules/typescript/lib/lib.es2016.intl.d.ts": {
106
+ "import": "./node_modules/typescript/lib/lib.es2016.intl.d.js",
107
+ "types": "./node_modules/typescript/lib/lib.es2016.intl.d.d.ts"
108
+ },
109
+ "./node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts": {
110
+ "import": "./node_modules/typescript/lib/lib.es2017.arraybuffer.d.js",
111
+ "types": "./node_modules/typescript/lib/lib.es2017.arraybuffer.d.d.ts"
112
+ },
113
+ "./node_modules/typescript/lib/lib.es2017.d.ts": {
114
+ "import": "./node_modules/typescript/lib/lib.es2017.d.js",
115
+ "types": "./node_modules/typescript/lib/lib.es2017.d.d.ts"
116
+ },
117
+ "./node_modules/typescript/lib/lib.es2017.date.d.ts": {
118
+ "import": "./node_modules/typescript/lib/lib.es2017.date.d.js",
119
+ "types": "./node_modules/typescript/lib/lib.es2017.date.d.d.ts"
120
+ },
121
+ "./node_modules/typescript/lib/lib.es2017.full.d.ts": {
122
+ "import": "./node_modules/typescript/lib/lib.es2017.full.d.js",
123
+ "types": "./node_modules/typescript/lib/lib.es2017.full.d.d.ts"
124
+ },
125
+ "./node_modules/typescript/lib/lib.es2017.intl.d.ts": {
126
+ "import": "./node_modules/typescript/lib/lib.es2017.intl.d.js",
127
+ "types": "./node_modules/typescript/lib/lib.es2017.intl.d.d.ts"
128
+ },
129
+ "./node_modules/typescript/lib/lib.es2017.object.d.ts": {
130
+ "import": "./node_modules/typescript/lib/lib.es2017.object.d.js",
131
+ "types": "./node_modules/typescript/lib/lib.es2017.object.d.d.ts"
132
+ },
133
+ "./node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts": {
134
+ "import": "./node_modules/typescript/lib/lib.es2017.sharedmemory.d.js",
135
+ "types": "./node_modules/typescript/lib/lib.es2017.sharedmemory.d.d.ts"
136
+ },
137
+ "./node_modules/typescript/lib/lib.es2017.string.d.ts": {
138
+ "import": "./node_modules/typescript/lib/lib.es2017.string.d.js",
139
+ "types": "./node_modules/typescript/lib/lib.es2017.string.d.d.ts"
140
+ },
141
+ "./node_modules/typescript/lib/lib.es2017.typedarrays.d.ts": {
142
+ "import": "./node_modules/typescript/lib/lib.es2017.typedarrays.d.js",
143
+ "types": "./node_modules/typescript/lib/lib.es2017.typedarrays.d.d.ts"
144
+ },
145
+ "./node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts": {
146
+ "import": "./node_modules/typescript/lib/lib.es2018.asyncgenerator.d.js",
147
+ "types": "./node_modules/typescript/lib/lib.es2018.asyncgenerator.d.d.ts"
148
+ },
149
+ "./node_modules/typescript/lib/lib.es2018.asynciterable.d.ts": {
150
+ "import": "./node_modules/typescript/lib/lib.es2018.asynciterable.d.js",
151
+ "types": "./node_modules/typescript/lib/lib.es2018.asynciterable.d.d.ts"
152
+ },
153
+ "./node_modules/typescript/lib/lib.es2018.d.ts": {
154
+ "import": "./node_modules/typescript/lib/lib.es2018.d.js",
155
+ "types": "./node_modules/typescript/lib/lib.es2018.d.d.ts"
156
+ },
157
+ "./node_modules/typescript/lib/lib.es2018.full.d.ts": {
158
+ "import": "./node_modules/typescript/lib/lib.es2018.full.d.js",
159
+ "types": "./node_modules/typescript/lib/lib.es2018.full.d.d.ts"
160
+ },
161
+ "./node_modules/typescript/lib/lib.es2018.intl.d.ts": {
162
+ "import": "./node_modules/typescript/lib/lib.es2018.intl.d.js",
163
+ "types": "./node_modules/typescript/lib/lib.es2018.intl.d.d.ts"
164
+ },
165
+ "./node_modules/typescript/lib/lib.es2018.promise.d.ts": {
166
+ "import": "./node_modules/typescript/lib/lib.es2018.promise.d.js",
167
+ "types": "./node_modules/typescript/lib/lib.es2018.promise.d.d.ts"
168
+ },
169
+ "./node_modules/typescript/lib/lib.es2018.regexp.d.ts": {
170
+ "import": "./node_modules/typescript/lib/lib.es2018.regexp.d.js",
171
+ "types": "./node_modules/typescript/lib/lib.es2018.regexp.d.d.ts"
172
+ },
173
+ "./node_modules/typescript/lib/lib.es2019.array.d.ts": {
174
+ "import": "./node_modules/typescript/lib/lib.es2019.array.d.js",
175
+ "types": "./node_modules/typescript/lib/lib.es2019.array.d.d.ts"
176
+ },
177
+ "./node_modules/typescript/lib/lib.es2019.d.ts": {
178
+ "import": "./node_modules/typescript/lib/lib.es2019.d.js",
179
+ "types": "./node_modules/typescript/lib/lib.es2019.d.d.ts"
180
+ },
181
+ "./node_modules/typescript/lib/lib.es2019.full.d.ts": {
182
+ "import": "./node_modules/typescript/lib/lib.es2019.full.d.js",
183
+ "types": "./node_modules/typescript/lib/lib.es2019.full.d.d.ts"
184
+ },
185
+ "./node_modules/typescript/lib/lib.es2019.intl.d.ts": {
186
+ "import": "./node_modules/typescript/lib/lib.es2019.intl.d.js",
187
+ "types": "./node_modules/typescript/lib/lib.es2019.intl.d.d.ts"
188
+ },
189
+ "./node_modules/typescript/lib/lib.es2019.object.d.ts": {
190
+ "import": "./node_modules/typescript/lib/lib.es2019.object.d.js",
191
+ "types": "./node_modules/typescript/lib/lib.es2019.object.d.d.ts"
192
+ },
193
+ "./node_modules/typescript/lib/lib.es2019.string.d.ts": {
194
+ "import": "./node_modules/typescript/lib/lib.es2019.string.d.js",
195
+ "types": "./node_modules/typescript/lib/lib.es2019.string.d.d.ts"
196
+ },
197
+ "./node_modules/typescript/lib/lib.es2019.symbol.d.ts": {
198
+ "import": "./node_modules/typescript/lib/lib.es2019.symbol.d.js",
199
+ "types": "./node_modules/typescript/lib/lib.es2019.symbol.d.d.ts"
200
+ },
201
+ "./node_modules/typescript/lib/lib.es2020.bigint.d.ts": {
202
+ "import": "./node_modules/typescript/lib/lib.es2020.bigint.d.js",
203
+ "types": "./node_modules/typescript/lib/lib.es2020.bigint.d.d.ts"
204
+ },
205
+ "./node_modules/typescript/lib/lib.es2020.d.ts": {
206
+ "import": "./node_modules/typescript/lib/lib.es2020.d.js",
207
+ "types": "./node_modules/typescript/lib/lib.es2020.d.d.ts"
208
+ },
209
+ "./node_modules/typescript/lib/lib.es2020.date.d.ts": {
210
+ "import": "./node_modules/typescript/lib/lib.es2020.date.d.js",
211
+ "types": "./node_modules/typescript/lib/lib.es2020.date.d.d.ts"
212
+ },
213
+ "./node_modules/typescript/lib/lib.es2020.full.d.ts": {
214
+ "import": "./node_modules/typescript/lib/lib.es2020.full.d.js",
215
+ "types": "./node_modules/typescript/lib/lib.es2020.full.d.d.ts"
216
+ },
217
+ "./node_modules/typescript/lib/lib.es2020.intl.d.ts": {
218
+ "import": "./node_modules/typescript/lib/lib.es2020.intl.d.js",
219
+ "types": "./node_modules/typescript/lib/lib.es2020.intl.d.d.ts"
220
+ },
221
+ "./node_modules/typescript/lib/lib.es2020.number.d.ts": {
222
+ "import": "./node_modules/typescript/lib/lib.es2020.number.d.js",
223
+ "types": "./node_modules/typescript/lib/lib.es2020.number.d.d.ts"
224
+ },
225
+ "./node_modules/typescript/lib/lib.es2020.promise.d.ts": {
226
+ "import": "./node_modules/typescript/lib/lib.es2020.promise.d.js",
227
+ "types": "./node_modules/typescript/lib/lib.es2020.promise.d.d.ts"
228
+ },
229
+ "./node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts": {
230
+ "import": "./node_modules/typescript/lib/lib.es2020.sharedmemory.d.js",
231
+ "types": "./node_modules/typescript/lib/lib.es2020.sharedmemory.d.d.ts"
232
+ },
233
+ "./node_modules/typescript/lib/lib.es2020.string.d.ts": {
234
+ "import": "./node_modules/typescript/lib/lib.es2020.string.d.js",
235
+ "types": "./node_modules/typescript/lib/lib.es2020.string.d.d.ts"
236
+ },
237
+ "./node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts": {
238
+ "import": "./node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.js",
239
+ "types": "./node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.d.ts"
240
+ },
241
+ "./node_modules/typescript/lib/lib.es2021.d.ts": {
242
+ "import": "./node_modules/typescript/lib/lib.es2021.d.js",
243
+ "types": "./node_modules/typescript/lib/lib.es2021.d.d.ts"
244
+ },
245
+ "./node_modules/typescript/lib/lib.es2021.full.d.ts": {
246
+ "import": "./node_modules/typescript/lib/lib.es2021.full.d.js",
247
+ "types": "./node_modules/typescript/lib/lib.es2021.full.d.d.ts"
248
+ },
249
+ "./node_modules/typescript/lib/lib.es2021.intl.d.ts": {
250
+ "import": "./node_modules/typescript/lib/lib.es2021.intl.d.js",
251
+ "types": "./node_modules/typescript/lib/lib.es2021.intl.d.d.ts"
252
+ },
253
+ "./node_modules/typescript/lib/lib.es2021.promise.d.ts": {
254
+ "import": "./node_modules/typescript/lib/lib.es2021.promise.d.js",
255
+ "types": "./node_modules/typescript/lib/lib.es2021.promise.d.d.ts"
256
+ },
257
+ "./node_modules/typescript/lib/lib.es2021.string.d.ts": {
258
+ "import": "./node_modules/typescript/lib/lib.es2021.string.d.js",
259
+ "types": "./node_modules/typescript/lib/lib.es2021.string.d.d.ts"
260
+ },
261
+ "./node_modules/typescript/lib/lib.es2021.weakref.d.ts": {
262
+ "import": "./node_modules/typescript/lib/lib.es2021.weakref.d.js",
263
+ "types": "./node_modules/typescript/lib/lib.es2021.weakref.d.d.ts"
264
+ },
265
+ "./node_modules/typescript/lib/lib.es2022.array.d.ts": {
266
+ "import": "./node_modules/typescript/lib/lib.es2022.array.d.js",
267
+ "types": "./node_modules/typescript/lib/lib.es2022.array.d.d.ts"
268
+ },
269
+ "./node_modules/typescript/lib/lib.es2022.d.ts": {
270
+ "import": "./node_modules/typescript/lib/lib.es2022.d.js",
271
+ "types": "./node_modules/typescript/lib/lib.es2022.d.d.ts"
272
+ },
273
+ "./node_modules/typescript/lib/lib.es2022.error.d.ts": {
274
+ "import": "./node_modules/typescript/lib/lib.es2022.error.d.js",
275
+ "types": "./node_modules/typescript/lib/lib.es2022.error.d.d.ts"
276
+ },
277
+ "./node_modules/typescript/lib/lib.es2022.full.d.ts": {
278
+ "import": "./node_modules/typescript/lib/lib.es2022.full.d.js",
279
+ "types": "./node_modules/typescript/lib/lib.es2022.full.d.d.ts"
280
+ },
281
+ "./node_modules/typescript/lib/lib.es2022.intl.d.ts": {
282
+ "import": "./node_modules/typescript/lib/lib.es2022.intl.d.js",
283
+ "types": "./node_modules/typescript/lib/lib.es2022.intl.d.d.ts"
284
+ },
285
+ "./node_modules/typescript/lib/lib.es2022.object.d.ts": {
286
+ "import": "./node_modules/typescript/lib/lib.es2022.object.d.js",
287
+ "types": "./node_modules/typescript/lib/lib.es2022.object.d.d.ts"
288
+ },
289
+ "./node_modules/typescript/lib/lib.es2022.regexp.d.ts": {
290
+ "import": "./node_modules/typescript/lib/lib.es2022.regexp.d.js",
291
+ "types": "./node_modules/typescript/lib/lib.es2022.regexp.d.d.ts"
292
+ },
293
+ "./node_modules/typescript/lib/lib.es2022.string.d.ts": {
294
+ "import": "./node_modules/typescript/lib/lib.es2022.string.d.js",
295
+ "types": "./node_modules/typescript/lib/lib.es2022.string.d.d.ts"
296
+ },
297
+ "./node_modules/typescript/lib/lib.es2023.array.d.ts": {
298
+ "import": "./node_modules/typescript/lib/lib.es2023.array.d.js",
299
+ "types": "./node_modules/typescript/lib/lib.es2023.array.d.d.ts"
300
+ },
301
+ "./node_modules/typescript/lib/lib.es2023.collection.d.ts": {
302
+ "import": "./node_modules/typescript/lib/lib.es2023.collection.d.js",
303
+ "types": "./node_modules/typescript/lib/lib.es2023.collection.d.d.ts"
304
+ },
305
+ "./node_modules/typescript/lib/lib.es2023.d.ts": {
306
+ "import": "./node_modules/typescript/lib/lib.es2023.d.js",
307
+ "types": "./node_modules/typescript/lib/lib.es2023.d.d.ts"
308
+ },
309
+ "./node_modules/typescript/lib/lib.es2023.full.d.ts": {
310
+ "import": "./node_modules/typescript/lib/lib.es2023.full.d.js",
311
+ "types": "./node_modules/typescript/lib/lib.es2023.full.d.d.ts"
312
+ },
313
+ "./node_modules/typescript/lib/lib.es2023.intl.d.ts": {
314
+ "import": "./node_modules/typescript/lib/lib.es2023.intl.d.js",
315
+ "types": "./node_modules/typescript/lib/lib.es2023.intl.d.d.ts"
316
+ },
317
+ "./node_modules/typescript/lib/lib.es2024.arraybuffer.d.ts": {
318
+ "import": "./node_modules/typescript/lib/lib.es2024.arraybuffer.d.js",
319
+ "types": "./node_modules/typescript/lib/lib.es2024.arraybuffer.d.d.ts"
320
+ },
321
+ "./node_modules/typescript/lib/lib.es2024.collection.d.ts": {
322
+ "import": "./node_modules/typescript/lib/lib.es2024.collection.d.js",
323
+ "types": "./node_modules/typescript/lib/lib.es2024.collection.d.d.ts"
324
+ },
325
+ "./node_modules/typescript/lib/lib.es2024.d.ts": {
326
+ "import": "./node_modules/typescript/lib/lib.es2024.d.js",
327
+ "types": "./node_modules/typescript/lib/lib.es2024.d.d.ts"
328
+ },
329
+ "./node_modules/typescript/lib/lib.es2024.full.d.ts": {
330
+ "import": "./node_modules/typescript/lib/lib.es2024.full.d.js",
331
+ "types": "./node_modules/typescript/lib/lib.es2024.full.d.d.ts"
332
+ },
333
+ "./node_modules/typescript/lib/lib.es2024.object.d.ts": {
334
+ "import": "./node_modules/typescript/lib/lib.es2024.object.d.js",
335
+ "types": "./node_modules/typescript/lib/lib.es2024.object.d.d.ts"
336
+ },
337
+ "./node_modules/typescript/lib/lib.es2024.promise.d.ts": {
338
+ "import": "./node_modules/typescript/lib/lib.es2024.promise.d.js",
339
+ "types": "./node_modules/typescript/lib/lib.es2024.promise.d.d.ts"
340
+ },
341
+ "./node_modules/typescript/lib/lib.es2024.regexp.d.ts": {
342
+ "import": "./node_modules/typescript/lib/lib.es2024.regexp.d.js",
343
+ "types": "./node_modules/typescript/lib/lib.es2024.regexp.d.d.ts"
344
+ },
345
+ "./node_modules/typescript/lib/lib.es2024.sharedmemory.d.ts": {
346
+ "import": "./node_modules/typescript/lib/lib.es2024.sharedmemory.d.js",
347
+ "types": "./node_modules/typescript/lib/lib.es2024.sharedmemory.d.d.ts"
348
+ },
349
+ "./node_modules/typescript/lib/lib.es2024.string.d.ts": {
350
+ "import": "./node_modules/typescript/lib/lib.es2024.string.d.js",
351
+ "types": "./node_modules/typescript/lib/lib.es2024.string.d.d.ts"
352
+ },
353
+ "./node_modules/typescript/lib/lib.es5.d.ts": {
354
+ "import": "./node_modules/typescript/lib/lib.es5.d.js",
355
+ "types": "./node_modules/typescript/lib/lib.es5.d.d.ts"
356
+ },
357
+ "./node_modules/typescript/lib/lib.es6.d.ts": {
358
+ "import": "./node_modules/typescript/lib/lib.es6.d.js",
359
+ "types": "./node_modules/typescript/lib/lib.es6.d.d.ts"
360
+ },
361
+ "./node_modules/typescript/lib/lib.esnext.array.d.ts": {
362
+ "import": "./node_modules/typescript/lib/lib.esnext.array.d.js",
363
+ "types": "./node_modules/typescript/lib/lib.esnext.array.d.d.ts"
364
+ },
365
+ "./node_modules/typescript/lib/lib.esnext.collection.d.ts": {
366
+ "import": "./node_modules/typescript/lib/lib.esnext.collection.d.js",
367
+ "types": "./node_modules/typescript/lib/lib.esnext.collection.d.d.ts"
368
+ },
369
+ "./node_modules/typescript/lib/lib.esnext.d.ts": {
370
+ "import": "./node_modules/typescript/lib/lib.esnext.d.js",
371
+ "types": "./node_modules/typescript/lib/lib.esnext.d.d.ts"
372
+ },
373
+ "./node_modules/typescript/lib/lib.esnext.decorators.d.ts": {
374
+ "import": "./node_modules/typescript/lib/lib.esnext.decorators.d.js",
375
+ "types": "./node_modules/typescript/lib/lib.esnext.decorators.d.d.ts"
376
+ },
377
+ "./node_modules/typescript/lib/lib.esnext.disposable.d.ts": {
378
+ "import": "./node_modules/typescript/lib/lib.esnext.disposable.d.js",
379
+ "types": "./node_modules/typescript/lib/lib.esnext.disposable.d.d.ts"
380
+ },
381
+ "./node_modules/typescript/lib/lib.esnext.error.d.ts": {
382
+ "import": "./node_modules/typescript/lib/lib.esnext.error.d.js",
383
+ "types": "./node_modules/typescript/lib/lib.esnext.error.d.d.ts"
384
+ },
385
+ "./node_modules/typescript/lib/lib.esnext.float16.d.ts": {
386
+ "import": "./node_modules/typescript/lib/lib.esnext.float16.d.js",
387
+ "types": "./node_modules/typescript/lib/lib.esnext.float16.d.d.ts"
388
+ },
389
+ "./node_modules/typescript/lib/lib.esnext.full.d.ts": {
390
+ "import": "./node_modules/typescript/lib/lib.esnext.full.d.js",
391
+ "types": "./node_modules/typescript/lib/lib.esnext.full.d.d.ts"
392
+ },
393
+ "./node_modules/typescript/lib/lib.esnext.intl.d.ts": {
394
+ "import": "./node_modules/typescript/lib/lib.esnext.intl.d.js",
395
+ "types": "./node_modules/typescript/lib/lib.esnext.intl.d.d.ts"
396
+ },
397
+ "./node_modules/typescript/lib/lib.esnext.iterator.d.ts": {
398
+ "import": "./node_modules/typescript/lib/lib.esnext.iterator.d.js",
399
+ "types": "./node_modules/typescript/lib/lib.esnext.iterator.d.d.ts"
400
+ },
401
+ "./node_modules/typescript/lib/lib.esnext.promise.d.ts": {
402
+ "import": "./node_modules/typescript/lib/lib.esnext.promise.d.js",
403
+ "types": "./node_modules/typescript/lib/lib.esnext.promise.d.d.ts"
404
+ },
405
+ "./node_modules/typescript/lib/lib.esnext.sharedmemory.d.ts": {
406
+ "import": "./node_modules/typescript/lib/lib.esnext.sharedmemory.d.js",
407
+ "types": "./node_modules/typescript/lib/lib.esnext.sharedmemory.d.d.ts"
408
+ },
409
+ "./node_modules/typescript/lib/lib.scripthost.d.ts": {
410
+ "import": "./node_modules/typescript/lib/lib.scripthost.d.js",
411
+ "types": "./node_modules/typescript/lib/lib.scripthost.d.d.ts"
412
+ },
413
+ "./node_modules/typescript/lib/lib.webworker.asynciterable.d.ts": {
414
+ "import": "./node_modules/typescript/lib/lib.webworker.asynciterable.d.js",
415
+ "types": "./node_modules/typescript/lib/lib.webworker.asynciterable.d.d.ts"
416
+ },
417
+ "./node_modules/typescript/lib/lib.webworker.d.ts": {
418
+ "import": "./node_modules/typescript/lib/lib.webworker.d.js",
419
+ "types": "./node_modules/typescript/lib/lib.webworker.d.d.ts"
420
+ },
421
+ "./node_modules/typescript/lib/lib.webworker.importscripts.d.ts": {
422
+ "import": "./node_modules/typescript/lib/lib.webworker.importscripts.d.js",
423
+ "types": "./node_modules/typescript/lib/lib.webworker.importscripts.d.d.ts"
424
+ },
425
+ "./node_modules/typescript/lib/lib.webworker.iterable.d.ts": {
426
+ "import": "./node_modules/typescript/lib/lib.webworker.iterable.d.js",
427
+ "types": "./node_modules/typescript/lib/lib.webworker.iterable.d.d.ts"
428
+ },
429
+ "./node_modules/typescript/lib/tsserverlibrary.d.ts": {
430
+ "import": "./node_modules/typescript/lib/tsserverlibrary.d.js",
431
+ "types": "./node_modules/typescript/lib/tsserverlibrary.d.d.ts"
432
+ },
433
+ "./node_modules/typescript/lib/typescript.d.ts": {
434
+ "import": "./node_modules/typescript/lib/typescript.d.js",
435
+ "types": "./node_modules/typescript/lib/typescript.d.d.ts"
436
+ },
437
+ "./service.test.ts": {
438
+ "import": "./service.test.js",
439
+ "types": "./service.test.d.ts"
440
+ },
441
+ "./service.ts": {
442
+ "import": "./service.js",
443
+ "types": "./service.d.ts"
444
+ },
445
+ "./type.ts": {
446
+ "import": "./type.js",
447
+ "types": "./type.d.ts"
448
+ }
449
+ }
450
+ }
package/service.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ import { type RandomBackend, type RandomGenerator } from './type.ts';
2
+ export declare const createRandomService: (randomBackend: RandomBackend) => RandomGenerator;
package/service.js ADDED
@@ -0,0 +1,23 @@
1
+ import { MAX_RANDOM_INTEGER, MAX_RANDOM_STRING_LENGTH, } from './type.js';
2
+ import { createCausedError } from '@dungarees/core/error.ts';
3
+ export const createRandomService = (randomBackend) => ({
4
+ generateString: (length = 16) => {
5
+ if (length > MAX_RANDOM_STRING_LENGTH) {
6
+ throw new Error(`Random string cannot be longer than ${MAX_RANDOM_STRING_LENGTH} characters`);
7
+ }
8
+ try {
9
+ return randomBackend.generateString(length);
10
+ }
11
+ catch (cause) {
12
+ throw createCausedError({ message: 'Random string generation failed', cause });
13
+ }
14
+ },
15
+ generateInteger: ({ min = 0, max = MAX_RANDOM_INTEGER } = {}) => {
16
+ try {
17
+ return randomBackend.generateInteger(min, max);
18
+ }
19
+ catch (cause) {
20
+ throw createCausedError({ message: 'Random integer generation failed', cause });
21
+ }
22
+ },
23
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,88 @@
1
+ import { createFakeRandomBackend } from './fake.js';
2
+ import { createNodeCryptoBackend } from './node-crypto.js';
3
+ import { createRandomService } from './service.js';
4
+ import { expect, test } from 'vitest';
5
+ test('generateString returns a string of the requested length', () => {
6
+ const random = createRandomService(createNodeCryptoBackend());
7
+ expect(random.generateString(8)).toHaveLength(8);
8
+ });
9
+ test('generateString returns 16 characters when no length is given', () => {
10
+ const random = createRandomService(createNodeCryptoBackend());
11
+ expect(random.generateString()).toHaveLength(16);
12
+ });
13
+ test('generateString handles an odd length, which is half a hex byte', () => {
14
+ const random = createRandomService(createNodeCryptoBackend());
15
+ expect(random.generateString(7)).toHaveLength(7);
16
+ });
17
+ test('generateString returns a different string every time', () => {
18
+ const random = createRandomService(createNodeCryptoBackend());
19
+ const values = new Set(Array.from({ length: 100 }, () => random.generateString(16)));
20
+ expect(values.size).toBe(100);
21
+ });
22
+ test('generateString refuses a length beyond the 1024 character limit', () => {
23
+ const random = createRandomService(createNodeCryptoBackend());
24
+ expect(() => random.generateString(1025)).toThrow('Random string cannot be longer than 1024 characters');
25
+ });
26
+ test('generateString accepts a length exactly at the limit', () => {
27
+ const random = createRandomService(createNodeCryptoBackend());
28
+ expect(random.generateString(1024)).toHaveLength(1024);
29
+ });
30
+ test('generateString reports a failing backend as a random string failure', () => {
31
+ const random = createRandomService({
32
+ generateString: () => {
33
+ throw new Error('no entropy');
34
+ },
35
+ generateInteger: () => 0,
36
+ });
37
+ expect(() => random.generateString(8)).toThrow('Random string generation failed: no entropy');
38
+ });
39
+ test('generateInteger returns a number within the requested range', () => {
40
+ const random = createRandomService(createNodeCryptoBackend());
41
+ const values = Array.from({ length: 100 }, () => random.generateInteger({ min: 5, max: 10 }));
42
+ expect(values.every((value) => value >= 5 && value <= 10)).toBe(true);
43
+ });
44
+ test('generateInteger can return both ends of the range', () => {
45
+ const random = createRandomService(createNodeCryptoBackend());
46
+ const values = new Set(Array.from({ length: 200 }, () => random.generateInteger({ min: 0, max: 1 })));
47
+ expect([...values].sort()).toEqual([0, 1]);
48
+ });
49
+ test('generateInteger returns the only value a single-value range allows', () => {
50
+ const random = createRandomService(createNodeCryptoBackend());
51
+ expect(random.generateInteger({ min: 7, max: 7 })).toBe(7);
52
+ });
53
+ test('generateInteger returns a safe integer when no range is given', () => {
54
+ const random = createRandomService(createNodeCryptoBackend());
55
+ const value = random.generateInteger();
56
+ expect(Number.isSafeInteger(value) && value >= 0).toBe(true);
57
+ });
58
+ test('generateInteger reports a failing backend as a random integer failure', () => {
59
+ const random = createRandomService({
60
+ generateString: () => '',
61
+ generateInteger: () => {
62
+ throw new Error('no entropy');
63
+ },
64
+ });
65
+ expect(() => random.generateInteger({ min: 0, max: 1 })).toThrow('Random integer generation failed: no entropy');
66
+ });
67
+ test('the fake backend records the ranges it was asked for', () => {
68
+ const { backend, integerRequests } = createFakeRandomBackend();
69
+ const random = createRandomService(backend);
70
+ random.generateInteger({ min: 10, max: 20 });
71
+ expect(integerRequests).toEqual([[10, 20]]);
72
+ });
73
+ test('the fake backend records the lengths it was asked for', () => {
74
+ const { backend, stringRequests } = createFakeRandomBackend();
75
+ const random = createRandomService(backend);
76
+ random.generateString(8);
77
+ expect(stringRequests).toEqual([8]);
78
+ });
79
+ test('the fake backend returns a string of the requested length', () => {
80
+ const { backend } = createFakeRandomBackend();
81
+ const random = createRandomService(backend);
82
+ expect(random.generateString(4)).toBe('aaaa');
83
+ });
84
+ test('the fake backend returns a different character on each call', () => {
85
+ const { backend } = createFakeRandomBackend();
86
+ const random = createRandomService(backend);
87
+ expect([random.generateString(2), random.generateString(2)]).toEqual(['aa', 'bb']);
88
+ });
package/type.d.ts ADDED
@@ -0,0 +1,14 @@
1
+ export declare const MAX_RANDOM_INTEGER: number;
2
+ export declare const MAX_RANDOM_STRING_LENGTH = 1024;
3
+ export type IntegerRange = {
4
+ min?: number;
5
+ max?: number;
6
+ };
7
+ export type RandomGenerator = {
8
+ generateString: (length?: number) => string;
9
+ generateInteger: (range?: IntegerRange) => number;
10
+ };
11
+ export type RandomBackend = {
12
+ generateString: (length: number) => string;
13
+ generateInteger: (min: number, max: number) => number;
14
+ };
package/type.js ADDED
@@ -0,0 +1,4 @@
1
+ // crypto.randomInt cannot span more than 2**48 values, and it takes an exclusive upper bound, so
2
+ // this is the widest inclusive maximum a backend built on it can serve.
3
+ export const MAX_RANDOM_INTEGER = 2 ** 48 - 2;
4
+ export const MAX_RANDOM_STRING_LENGTH = 1024;