@learncard/create-http-bridge 1.1.34

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.
@@ -0,0 +1,565 @@
1
+ import { SetStateAction } from 'react';
2
+ import produce, { Draft, castDraft } from 'immer';
3
+ import { DraftFunction, Updater } from 'use-immer';
4
+
5
+ import { SetState } from './types';
6
+
7
+ // Inlined version of the hopefully one day npm package curriedStateSlice
8
+
9
+ type ImmerOrReact = 'immer' | 'react';
10
+
11
+ type UpdaterArgs<T> = T | DraftFunction<T>;
12
+
13
+ type CurriedReturn<ValueArg, Value> = undefined extends ValueArg
14
+ ? (innerValue: Value) => void
15
+ : void;
16
+
17
+ type InnerImmerOuterImmer<State> = <
18
+ Field extends keyof Draft<State>,
19
+ Value extends UpdaterArgs<Draft<State>[Field]>,
20
+ ValueArg extends Value | undefined
21
+ >(
22
+ field: Field,
23
+ value?: ValueArg
24
+ ) => CurriedReturn<ValueArg, Value>;
25
+
26
+ type InnerReactOuterImmer<State> = <
27
+ Field extends keyof Draft<State>,
28
+ Value extends SetStateAction<Draft<State>[Field]>,
29
+ ValueArg extends Value | undefined
30
+ >(
31
+ field: Field,
32
+ value?: ValueArg
33
+ ) => CurriedReturn<ValueArg, Value>;
34
+
35
+ type InnerImmerOuterReact<State> = <
36
+ Field extends keyof State,
37
+ Value extends UpdaterArgs<State[Field]>,
38
+ ValueArg extends Value | undefined
39
+ >(
40
+ field: Field,
41
+ value?: ValueArg
42
+ ) => CurriedReturn<ValueArg, Value>;
43
+
44
+ type InnerReactOuterReact<State> = <
45
+ Field extends keyof State,
46
+ Value extends SetStateAction<State[Field]>,
47
+ ValueArg extends Value | undefined
48
+ >(
49
+ field: Field,
50
+ value?: ValueArg
51
+ ) => CurriedReturn<ValueArg, Value>;
52
+
53
+ export function innerImmerOuterImmer<
54
+ State,
55
+ Field extends keyof Draft<State>,
56
+ Value extends UpdaterArgs<Draft<State>[Field]>
57
+ >(setState: Updater<State>, field: Field): (innerValue: NonNullable<Value>) => void;
58
+ export function innerImmerOuterImmer<
59
+ State,
60
+ Field extends keyof Draft<State>,
61
+ Value extends UpdaterArgs<Draft<State>[Field]>,
62
+ ValueArg extends Value | undefined
63
+ >(setState: Updater<State>, field: Field, value: ValueArg): void;
64
+
65
+ /**
66
+ * Creates a useImmer Updater style function for a given field. This is useful for creating mini
67
+ * pieces of state from larger pieces of state, or for creating manual setState functions for
68
+ * components that expect setState as a prop.
69
+ *
70
+ * This function assumes you are using useImmer instead of useState
71
+ *
72
+ * Use like so:
73
+ *
74
+ * [state, setState] = useImmer<{ num: number; string: string; }>({ num: 1, string: 'str' });
75
+ *
76
+ * innerImmerOuterImmer(setState, 'num', 3); // Updates state to { num: 3, string: 'str' }
77
+ *
78
+ * innerImmerOuterImmer(
79
+ * setState,
80
+ * 'num',
81
+ * oldNum => {
82
+ * oldNum += 1;
83
+ * },
84
+ * ); // Updates state to { num: 4, string: 'str' }
85
+ *
86
+ * innerImmerOuterImmer(setState, 'num', 'three'); // TS Error due to invalid type
87
+ *
88
+ */
89
+ export function innerImmerOuterImmer<
90
+ State,
91
+ Field extends keyof Draft<State>,
92
+ Value extends UpdaterArgs<Draft<State>[Field]>,
93
+ ValueArg extends Value | undefined
94
+ >(setState: Updater<State>, field: Field, value?: ValueArg): any {
95
+ if (value === undefined) {
96
+ return (innerValue: NonNullable<Value>) => {
97
+ setState(oldState => {
98
+ if (innerValue instanceof Function) innerValue(oldState[field]);
99
+ else oldState[field] = innerValue as Draft<State>[Field];
100
+ });
101
+ };
102
+ }
103
+
104
+ setState(oldState => {
105
+ if (value instanceof Function) value(oldState[field]);
106
+ else oldState[field] = value as Draft<State>[Field];
107
+ });
108
+ }
109
+
110
+ /**
111
+ * Curry function to allow innerImmerOuterImmer to be used without constantly passing in setState
112
+ *
113
+ * Use like so:
114
+ *
115
+ * [state, setState] = useImmer<{ num: number; string: string; }>({ num: 1, string: 'str' });
116
+ *
117
+ * const updateField = curriedInnerImmerOuterImmer(setState);
118
+ *
119
+ * updateField('num', 3); // Updates state to { num: 3, string: 'str' }
120
+ *
121
+ * updateField(
122
+ * 'num',
123
+ * oldNum => {
124
+ * oldNum += 1;
125
+ * },
126
+ * ); // Updates state to { num: 4, string: 'str' }
127
+ *
128
+ * updateField(setState, 'num', 'three'); // TS Error due to invalid type
129
+ */
130
+ export const curriedInnerImmerOuterImmer =
131
+ <State>(setState: Updater<State>): InnerImmerOuterImmer<State> =>
132
+ <
133
+ Field extends keyof Draft<State>,
134
+ Value extends UpdaterArgs<Draft<State>[Field]>,
135
+ ValueArg extends Value | undefined
136
+ >(
137
+ field: Field,
138
+ value?: ValueArg
139
+ ) =>
140
+ innerImmerOuterImmer<State, Field, Value, ValueArg>(setState, field, value);
141
+
142
+ export function innerReactOuterImmer<
143
+ State,
144
+ Field extends keyof Draft<State>,
145
+ Value extends SetStateAction<Draft<State>[Field]>
146
+ >(setState: Updater<State>, field: Field): (innerValue: NonNullable<Value>) => void;
147
+
148
+ export function innerReactOuterImmer<
149
+ State,
150
+ Field extends keyof Draft<State>,
151
+ Value extends SetStateAction<Draft<State>[Field]>,
152
+ ValueArg extends Value | undefined
153
+ >(setState: Updater<State>, field: Field, value: ValueArg): void;
154
+ /**
155
+ * Creates a React setState style function for a given field. This is useful for creating mini
156
+ * pieces of state from larger pieces of state, or for creating manual setState functions for
157
+ * components that expect setState as a prop.
158
+ *
159
+ * This function assumes you are using useImmer instead of useState
160
+ *
161
+ * Use like so:
162
+ *
163
+ * [state, setState] = useImmer<{ num: number; string: string; }>({ num: 1, string: 'str' });
164
+ *
165
+ * innerReactOuterImmer(setState, 'num', 3); // Updates state to { num: 3, string: 'str' }
166
+ *
167
+ * innerReactOuterImmer(
168
+ * setState,
169
+ * 'num',
170
+ * oldNum => oldNum + 1,
171
+ * ); // Updates state to { num: 4, string: 'str' }
172
+ *
173
+ * innerReactOuterImmer(setState, 'num', 'three'); // TS Error due to invalid type
174
+ *
175
+ */
176
+ export function innerReactOuterImmer<
177
+ State,
178
+ Field extends keyof Draft<State>,
179
+ Value extends SetStateAction<Draft<State>[Field]>,
180
+ ValueArg extends Value | undefined
181
+ >(setState: Updater<State>, field: Field, value?: ValueArg) {
182
+ if (value === undefined) {
183
+ return (innerValue: NonNullable<Value>) => {
184
+ setState(oldState => {
185
+ if (innerValue instanceof Function) innerValue(oldState[field]);
186
+ else oldState[field] = innerValue as Draft<State>[Field];
187
+ });
188
+ };
189
+ }
190
+
191
+ setState(oldState => {
192
+ oldState[field] =
193
+ typeof value === 'function'
194
+ ? (value(oldState[field]) as Draft<State>[Field])
195
+ : (value as Draft<State>[Field]);
196
+ });
197
+ }
198
+
199
+ /**
200
+ * Curry function to allow innerReactOuterImmer to be used without constantly passing in setState
201
+ *
202
+ * Use like so:
203
+ *
204
+ * [state, setState] = useImmer<{ num: number; string: string; }>({ num: 1, string: 'str' });
205
+ *
206
+ * const updateField = curriedUpdateImmerSetStateField(setState);
207
+ *
208
+ * updateField('num', 3); // Updates state to { num: 3, string: 'str' }
209
+ *
210
+ * updateField('num', oldNum => oldNum + 1); // Updates state to { num: 4, string: 'str' }
211
+ *
212
+ * updateField(setState, 'num', 'three'); // TS Error due to invalid type
213
+ */
214
+ export const curriedInnerReactOuterImmer =
215
+ <State>(setState: Updater<State>): InnerReactOuterImmer<State> =>
216
+ <
217
+ Field extends keyof Draft<State>,
218
+ Value extends SetStateAction<Draft<State>[Field]>,
219
+ ValueArg extends Value | undefined
220
+ >(
221
+ field: Field,
222
+ value?: ValueArg
223
+ ) =>
224
+ innerReactOuterImmer<State, Field, Value, ValueArg>(setState, field, value);
225
+
226
+ export function innerImmerOuterReact<
227
+ State,
228
+ Field extends keyof State,
229
+ Value extends UpdaterArgs<State[Field]>
230
+ >(setState: SetState<State>, field: Field): (innerValue: NonNullable<Value>) => void;
231
+ export function innerImmerOuterReact<
232
+ State,
233
+ Field extends keyof State,
234
+ Value extends UpdaterArgs<State[Field]>,
235
+ ValueArg extends Value | undefined
236
+ >(setState: SetState<State>, field: Field, value: ValueArg): void;
237
+ /**
238
+ * Creates a useImmer Updater style function for a given field. This is useful for creating mini
239
+ * pieces of state from larger pieces of state, or for creating manual setState functions for
240
+ * components that expect setState as a prop.
241
+ *
242
+ * If possible, please consider updating your useState calls to useImmer and using the immer
243
+ * versions of these functions
244
+ *
245
+ * Use like so:
246
+ *
247
+ * [state, setState] = useImmer<{ num: number; string: string; }>({ num: 1, string: 'str' });
248
+ *
249
+ * innerImmerOuterReact(setState, 'num', 3); // Updates state to { num: 3, string: 'str' }
250
+ *
251
+ * innerImmerOuterReact(
252
+ * setState,
253
+ * 'num',
254
+ * oldNum => {
255
+ * oldNum += 1;
256
+ * },
257
+ * ); // Updates state to { num: 4, string: 'str' }
258
+ *
259
+ * innerImmerOuterReact(setState, 'num', 'three'); // TS Error due to invalid type
260
+ *
261
+ */
262
+ export function innerImmerOuterReact<
263
+ State,
264
+ Field extends keyof State,
265
+ Value extends UpdaterArgs<State[Field]>,
266
+ ValueArg extends Value | undefined
267
+ >(setState: SetState<State>, field: Field, value?: ValueArg) {
268
+ if (value === undefined) {
269
+ return (innerValue: NonNullable<Value>) => {
270
+ if (innerValue instanceof Function) {
271
+ setState(produce(oldState => innerValue(oldState[field])));
272
+ } else setState(oldState => ({ ...oldState, [field]: innerValue }));
273
+ };
274
+ }
275
+
276
+ if (value instanceof Function) {
277
+ setState(produce(oldState => value(oldState[field])));
278
+ } else setState(oldState => ({ ...oldState, [field]: value }));
279
+ }
280
+
281
+ /**
282
+ * Curry function to allow innerImmerOuterReact to be used without constantly passing in setState
283
+ *
284
+ * Use like so:
285
+ *
286
+ * [state, setState] = useImmer<{ num: number; string: string; }>({ num: 1, string: 'str' });
287
+ *
288
+ * const updateField = curriedInnerImmerOuterImmer(setState);
289
+ *
290
+ * updateField('num', 3); // Updates state to { num: 3, string: 'str' }
291
+ *
292
+ * updateField(
293
+ * 'num',
294
+ * oldNum => {
295
+ * oldNum += 1;
296
+ * },
297
+ * ); // Updates state to { num: 4, string: 'str' }
298
+ *
299
+ * updateField(setState, 'num', 'three'); // TS Error due to invalid type
300
+ */
301
+ export const curriedInnerImmerOuterReact =
302
+ <State>(setState: SetState<State>): InnerImmerOuterReact<State> =>
303
+ <
304
+ Field extends keyof State,
305
+ Value extends UpdaterArgs<State[Field]>,
306
+ ValueArg extends Value | undefined
307
+ >(
308
+ field: Field,
309
+ value?: ValueArg
310
+ ) =>
311
+ innerImmerOuterReact<State, Field, Value, ValueArg>(setState, field, value);
312
+
313
+ export function innerReactOuterReact<
314
+ State,
315
+ Field extends keyof State,
316
+ Value extends SetStateAction<State[Field]>
317
+ >(setState: SetState<State>, field: Field): (innerValue: NonNullable<Value>) => void;
318
+ export function innerReactOuterReact<
319
+ State,
320
+ Field extends keyof State,
321
+ Value extends SetStateAction<State[Field]>,
322
+ ValueArg extends Value | undefined
323
+ >(setState: SetState<State>, field: Field, value: ValueArg): void;
324
+ /**
325
+ * Creates a React setState style function for a given field. This is useful for creating mini
326
+ * pieces of state from larger pieces of state, or for creating manual setState functions for
327
+ * components that expect setState as a prop.
328
+ *
329
+ * If possible, please consider updating your useState calls to useImmer and using the immer
330
+ * versions of these functions
331
+ *
332
+ * Use like so:
333
+ *
334
+ * [state, setState] = useState<{ num: number; string: string; }>({ num: 1, string: 'str' });
335
+ *
336
+ * innerReactOuterReact(setState, 'num', 3); // Updates state to { num: 3, string: 'str' }
337
+ *
338
+ * innerReactOuterReact(
339
+ * setState,
340
+ * 'num',
341
+ * oldNum => oldNum + 1,
342
+ * ); // Updates state to { num: 4, string: 'str' }
343
+ *
344
+ * innerReactOuterReact(setState, 'num', 'three'); // TS Error due to invalid type
345
+ *
346
+ */
347
+ export function innerReactOuterReact<
348
+ State,
349
+ Field extends keyof State,
350
+ Value extends SetStateAction<State[Field]>,
351
+ ValueArg extends Value | undefined
352
+ >(setState: SetState<State>, field: Field, value?: ValueArg) {
353
+ if (value === undefined) {
354
+ return (innerValue: NonNullable<Value>) => {
355
+ setState(oldState => ({
356
+ ...oldState,
357
+ [field]: innerValue instanceof Function ? innerValue(oldState[field]) : innerValue,
358
+ }));
359
+ };
360
+ }
361
+
362
+ setState(oldState => ({
363
+ ...oldState,
364
+ [field]: value instanceof Function ? value(oldState[field]) : value,
365
+ }));
366
+ }
367
+
368
+ /**
369
+ * Curry function to allow updateSetStateField to be used without constantly passing in setState
370
+ *
371
+ * If possible, please consider updating your useState calls to useImmer and using the immer
372
+ * versions of these functions
373
+ *
374
+ * Use like so:
375
+ *
376
+ * [state, setState] = useState<{ num: number; string: string; }>({ num: 1, string: 'str' });
377
+ *
378
+ * const updateField = curriedInnerReactOuterReact(setState);
379
+ *
380
+ * updateField('num', 3); // Updates state to { num: 3, string: 'str' }
381
+ *
382
+ * updateField('num', oldNum => oldNum + 1); // Updates state to { num: 4, string: 'str' }
383
+ *
384
+ * updateField(setState, 'num', 'three'); // TS Error due to invalid type
385
+ */
386
+ export const curriedInnerReactOuterReact =
387
+ <State>(setState: SetState<State>): InnerReactOuterReact<State> =>
388
+ <
389
+ Field extends keyof State,
390
+ Value extends SetStateAction<State[Field]>,
391
+ ValueArg extends Value | undefined
392
+ >(
393
+ field: Field,
394
+ value?: ValueArg
395
+ ) =>
396
+ innerReactOuterReact<State, Field, Value, ValueArg>(setState, field, value);
397
+
398
+ export function curriedStateSlice<State>(setState: Updater<State>): InnerImmerOuterImmer<State>;
399
+ export function curriedStateSlice<State>(
400
+ setState: Updater<State>,
401
+ options: { inner: 'immer'; outer: 'immer' }
402
+ ): InnerImmerOuterImmer<State>;
403
+ export function curriedStateSlice<State>(
404
+ setState: Updater<State>,
405
+ options: { inner: 'immer'; outer: 'react' }
406
+ ): InnerImmerOuterReact<State>;
407
+ export function curriedStateSlice<State>(
408
+ setState: SetState<State>,
409
+ options: { inner: 'react'; outer: 'immer' }
410
+ ): InnerReactOuterImmer<State>;
411
+ export function curriedStateSlice<State>(
412
+ setState: SetState<State>,
413
+ options: { inner: 'react'; outer: 'react' }
414
+ ): InnerReactOuterReact<State>;
415
+ /**
416
+ * This is a magical function that allows you to slice up complex state into smaller pieces of state
417
+ * that are completely contained.
418
+ *
419
+ * This function works with both useImmer and useState, and allows you to seamlessly transform
420
+ * between the two when creating state slices.
421
+ *
422
+ * Use like so:
423
+ *
424
+ * // This component will have access to the whole state, while dealing with subcomponents who only
425
+ * // want access to the individual pieces as if they were their own pieces of state
426
+ * type ComplexStateObject = {
427
+ * piece1: { num: number; str: string };
428
+ * piece2: { arr: number[]; obj: { num: number } };
429
+ * piece3: string;
430
+ * }
431
+ * const ComplexState = () => {
432
+ * [state, setState] = useImmer<ComplexStateObject>({
433
+ * piece1: { num: 1, str: '' },
434
+ * piece2: { arr: [], obj: { num: 2 } },
435
+ * piece3: '',
436
+ * });
437
+ *
438
+ * const updateSlice = curriedStateSlice(setState);
439
+ *
440
+ * return (
441
+ * <>
442
+ * <ComponentWantingOnlyPiece1
443
+ * state={state.piece1}
444
+ * setState={updateSlice('piece1')}
445
+ * />
446
+ * <ComponentWantingOnlyPiece2
447
+ * state={state.piece2}
448
+ * setState={updateSlice('piece2')}
449
+ * />
450
+ * <input
451
+ * type="text"
452
+ * onChange={e => updateSlice('piece3', e.target.value)}
453
+ * value={state.piece3}
454
+ * />
455
+ * </>
456
+ * )
457
+ * }
458
+ *
459
+ * The function returned by this function takes in a type-safe string representing a key from the
460
+ * state object, followed by a type-checked value for that key's field.
461
+ *
462
+ * // Assuming updateSlice is called in the above component
463
+ * updateSlice('piece4', 'nice'); // This errors because piece4 is not in our state object
464
+ * updateSlice('piece3', 123); // This errors because piece3 should be a string, not a number
465
+ *
466
+ * If you are not using immer everywhere (you really should be when dealing with complex state),
467
+ * you can pass in an object as the second parameter specifying whether you want to use immer or
468
+ * react's setState functions for both your outer and inner state objects
469
+ *
470
+ * If you have any questions about this guy, please send a scribbled note via carrier pigeon to T2!
471
+ */
472
+ export function curriedStateSlice<
473
+ State,
474
+ Inner extends ImmerOrReact = 'immer',
475
+ Outer extends ImmerOrReact = 'immer'
476
+ >(
477
+ setState: Updater<State> | SetState<State>,
478
+ options?: { inner: Inner; outer: Outer }
479
+ ):
480
+ | InnerImmerOuterImmer<State>
481
+ | InnerReactOuterImmer<State>
482
+ | InnerImmerOuterReact<State>
483
+ | InnerReactOuterReact<State> {
484
+ // The type errors in this function can safely be ignored.
485
+ // For some reason, this type signature works for consumers of this function, but fails to
486
+ // correctly type-check the function body itself
487
+ if ((options?.outer ?? 'immer') === 'immer') {
488
+ return (options?.inner ?? 'immer') === 'immer'
489
+ ? curriedInnerImmerOuterImmer(setState as Updater<State>)
490
+ : curriedInnerReactOuterImmer(setState as Updater<State>);
491
+ }
492
+
493
+ return (options?.inner ?? 'immer') === 'immer'
494
+ ? curriedInnerImmerOuterReact(setState as SetState<State>)
495
+ : curriedInnerReactOuterReact(setState as SetState<State>);
496
+ }
497
+
498
+ type UpdateSlice<State> = {
499
+ (index: number): Updater<State>;
500
+ (index: number, value: UpdaterArgs<State>): void;
501
+ };
502
+
503
+ type CurriedArraySlice = {
504
+ <State>(setState: SetState<State[]>): UpdateSlice<State>;
505
+ <State>(setState: SetState<State[]>, index: number): Updater<State>;
506
+ <State>(setState: SetState<State[]>, index: number, value: State): void;
507
+ };
508
+
509
+ export const curriedArraySlice = (<State>(
510
+ setState: SetState<State[]>,
511
+ index?: number,
512
+ value?: State
513
+ ) => {
514
+ const updateSlice = ((innerIndex: number, innerValue?: State) => {
515
+ const update: Updater<State> = reallyInnerValue =>
516
+ setState(
517
+ produce(draft => {
518
+ draft[innerIndex] =
519
+ reallyInnerValue instanceof Function
520
+ ? produce(draft[innerIndex]!, reallyInnerValue)
521
+ : castDraft(reallyInnerValue);
522
+ })
523
+ );
524
+
525
+ if (!innerValue) return update;
526
+
527
+ return update(innerValue);
528
+ }) as UpdateSlice<State>;
529
+
530
+ if (!index) return updateSlice;
531
+
532
+ if (!value) return updateSlice(index);
533
+
534
+ return updateSlice(index, value);
535
+ }) as CurriedArraySlice;
536
+
537
+ type ImmerArraySlice = {
538
+ <State>(setState: Updater<State[]>): UpdateSlice<State>;
539
+ <State>(setState: Updater<State[]>, index: number): Updater<State>;
540
+ <State>(setState: Updater<State[]>, index: number, value: State): void;
541
+ };
542
+
543
+ export const immerArraySlice = (<State>(
544
+ setState: Updater<State[]>,
545
+ index?: number,
546
+ value?: State
547
+ ) => {
548
+ const updateSlice = ((innerIndex: number, innerValue?: State) => {
549
+ const update: Updater<State> = reallyInnerValue =>
550
+ setState(oldState => {
551
+ if (reallyInnerValue instanceof Function) reallyInnerValue(oldState[innerIndex]!);
552
+ else oldState[innerIndex] = castDraft(reallyInnerValue);
553
+ });
554
+
555
+ if (!innerValue) return update;
556
+
557
+ return update(innerValue);
558
+ }) as UpdateSlice<State>;
559
+
560
+ if (!index) return updateSlice;
561
+
562
+ if (!value) return updateSlice(index);
563
+
564
+ return updateSlice(index, value);
565
+ }) as ImmerArraySlice;
package/cli/index.tsx ADDED
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ import { render } from 'ink';
3
+ import { program } from 'commander';
4
+
5
+ import App from './App';
6
+
7
+ import packageJson from '../package.json';
8
+
9
+ program
10
+ .version(packageJson.version)
11
+ .argument('[name]')
12
+ .action(async name => {
13
+ console.clear();
14
+
15
+ render(<App name={name} />);
16
+ })
17
+ .parse(process.argv);
package/cli/random.ts ADDED
@@ -0,0 +1,3 @@
1
+ import crypto from 'crypto';
2
+
3
+ export const generateRandomSeed = () => crypto.randomBytes(32).toString('hex');
package/cli/types.ts ADDED
@@ -0,0 +1,8 @@
1
+ import { Dispatch, SetStateAction } from 'react';
2
+
3
+ export type FormState = {
4
+ name: string;
5
+ seed: string;
6
+ };
7
+
8
+ export type SetState<T> = Dispatch<SetStateAction<T>>;