@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.
- package/CHANGELOG.md +400 -0
- package/LICENSE +25 -0
- package/README.md +34 -0
- package/cli/App.tsx +74 -0
- package/cli/Banner.tsx +18 -0
- package/cli/Button.tsx +62 -0
- package/cli/Cloning.tsx +51 -0
- package/cli/Form.tsx +80 -0
- package/cli/FullScreenBox.tsx +19 -0
- package/cli/Info.tsx +79 -0
- package/cli/Input.tsx +33 -0
- package/cli/curriedStateSlice.ts +565 -0
- package/cli/index.tsx +17 -0
- package/cli/random.ts +3 -0
- package/cli/types.ts +8 -0
- package/dist/index.js +803 -0
- package/esbuildWasmPlugin.cjs +31 -0
- package/lambda.ts +18 -0
- package/package.json +56 -0
- package/project.json +22 -0
- package/rollup.config.js +12 -0
- package/serverless.yml +56 -0
- package/src/app.ts +297 -0
- package/src/didkit_wasm_bg.wasm +0 -0
- package/src/learn-card.ts +13 -0
- package/src/types.helpers.ts +7 -0
- package/src/validators.ts +59 -0
- package/tsconfig.json +36 -0
|
@@ -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