@reykjavik/webtools 0.1.31 → 0.1.33

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 CHANGED
@@ -4,6 +4,26 @@
4
4
 
5
5
  - ... <!-- Add new lines here. -->
6
6
 
7
+ ## 0.1.33
8
+
9
+ _2024-10-16_
10
+
11
+ - `@reykjavik/webtools/next/vanillaExtract`:
12
+ - feat: Deprecate `vanillaNest` and `vanillaClassNested` — in favor of
13
+ `vanillaClass` with `className` function parameter, or other home-brew
14
+ solutions.
15
+ - docs: Improve inline JSDocs and README for the `vanilla*` helpers
16
+ - `@reykjavik/webtools/errorhandling`:
17
+ - docs: Improve code examples in README
18
+
19
+ ## 0.1.32
20
+
21
+ _2024-10-02_
22
+
23
+ - feat: Add module `@reykjavik/webtools/errorhandling` with `asError` and
24
+ `Result.*` helpers for safe, structured error handling with discriminated
25
+ `[error, result]` tuples.
26
+
7
27
  ## 0.1.31
8
28
 
9
29
  _2024-09-23_
package/README.md CHANGED
@@ -24,11 +24,21 @@ bun add @reykjavik/webtools
24
24
  - [Type `TTLConfig`](#type-ttlconfig)
25
25
  - [`toSec` TTL helper](#tosec-ttl-helper)
26
26
  - [`toMs` duration helper](#toms-duration-helper)
27
+ - [`@reykjavik/webtools/fixIcelandicLocale`](#reykjavikwebtoolsfixicelandiclocale)
28
+ - [Limitations](#limitations)
27
29
  - [`@reykjavik/webtools/async`](#reykjavikwebtoolsasync)
28
30
  - [`promiseAllObject`](#promiseallobject)
29
31
  - [`maxWait`](#maxwait)
30
- - [`@reykjavik/webtools/fixIcelandicLocale`](#reykjavikwebtoolsfixicelandiclocale)
31
- - [Limitations](#limitations)
32
+ - [`@reykjavik/webtools/errorhandling`](#reykjavikwebtoolserrorhandling)
33
+ - [`asError`](#aserror)
34
+ - [`Result` Singleton](#result-singleton)
35
+ - [Type `ResultTuple`](#type-resulttuple)
36
+ - [Type `ResultTupleObj`](#type-resulttupleobj)
37
+ - [`Result.catch`](#resultcatch)
38
+ - [`Result.map`](#resultmap)
39
+ - [`Result.Success`](#resultsuccess)
40
+ - [`Result.Fail`](#resultfail)
41
+ - [`Result.throw`](#resultthrow)
32
42
  - [`@reykjavik/webtools/SiteImprove`](#reykjavikwebtoolssiteimprove)
33
43
  - [`SiteImprove` component](#siteimprove-component)
34
44
  - [`pingSiteImprove` helper](#pingsiteimprove-helper)
@@ -37,11 +47,9 @@ bun add @reykjavik/webtools
37
47
  - [`CookieHubProvider` component](#cookiehubprovider-component)
38
48
  - [`useCookieHubConsent`](#usecookiehubconsent)
39
49
  - [`@reykjavik/webtools/vanillaExtract`](#reykjavikwebtoolsvanillaextract)
50
+ - [`vanillaClass`](#vanillaclass)
40
51
  - [`vanillaGlobal`](#vanillaglobal)
41
52
  - [`vanillaProps`](#vanillaprops)
42
- - [`vanillaClass`](#vanillaclass)
43
- - [`vanillaClassNested`](#vanillaclassnested)
44
- - [`vanillaNest`](#vanillanest)
45
53
  - [Framework Specific Tools](#framework-specific-tools)
46
54
  - [Remix.run Tools](#remixrun-tools)
47
55
  - [Next.js Tools](#nextjs-tools)
@@ -236,6 +244,70 @@ const ttlSec = toMs(ttl);
236
244
 
237
245
  ---
238
246
 
247
+ ## `@reykjavik/webtools/fixIcelandicLocale`
248
+
249
+ As of early 2024, Google Chrome still does not support the Icelandic locale
250
+ `is`/`is-IS` in any way. Meanwhile other browsers have supported it for over a
251
+ decade.
252
+
253
+ This module patches the following methods/classes by substituting the `is`
254
+ locale with `da` (Danish) and apply a few post-hoc fixes to their return
255
+ values.
256
+
257
+ - `Intl.Collator` and `String.prototype.localeCompare` (\*)
258
+ - `Intl.NumberFormat` and `Number.prototype.toLocaleString` (\*)
259
+ - `Intl.DateTimeFormat` and `Date.prototype.toLocaleString`,
260
+ `.toLocaleDateString`, and `.toLocaleTimeString` (\*)
261
+ - `Intl.RelativeDateFormat`
262
+ - `Intl.PluralRules`
263
+ - `Intl.ListFormat`
264
+
265
+ (\*) The results are quite usable, but not entirely perfect. The
266
+ limitations/caveats are listed below.
267
+
268
+ To apply the patch, simply "side-effect import" this module at the top of your
269
+ app's entry point:
270
+
271
+ ```ts
272
+ import '@reykjavik/webtools/fixIcelandicLocale';
273
+
274
+ // Then continue with your day and use `localeCompare` and other Intl.* methods
275
+ // as you normally would. (See "limitations" below.)
276
+ ```
277
+
278
+ (**NOTE** The patch is only applied in engines that fail a simple feature
279
+ detection test.)
280
+
281
+ ### Limitations
282
+
283
+ **`Intl.Collator` and `localeCompare`:**
284
+
285
+ - It sorts initial letters correctly but in the rest of the string, it
286
+ incorrectly treats `ð` and `d` as the same letter (most of the time), and
287
+ lumps the acute-accented characters `á`, `é`, `í`, `ó`, `ú` and `ý` in with
288
+ their non-accented counterparts.
289
+
290
+ **`Intl.NumberFormat` and `toLocaleString`:**
291
+
292
+ - The `style: "unit"` option is not supported and prints units in Danish. (Soo
293
+ many units and unit-variants…)
294
+ - The `currencyDisplay: "name"` option is not supported and prints the
295
+ currency's full name in Danish.
296
+
297
+ **`Intl.DateTimeFormat` and `toLocaleDateString`:**
298
+
299
+ - The `month: 'narrow'` and `weekday: 'narrow'` options are not supported, and
300
+ print the corresponding Danish initials.
301
+ - For `timeZoneName` the values `"long"`, `"shortGeneric"` and `"longGeneric"`
302
+ will appear in Danish.
303
+ - The `timeStyle: 'full'` option prints the timezone names in Danish
304
+ - The `dayPeriod` option has a couple of slight mismatches, at 5 am and 12
305
+ noon.
306
+
307
+ We eagerly accept bugfixes, additions, etc. to this module!
308
+
309
+ ---
310
+
239
311
  ## `@reykjavik/webtools/async`
240
312
 
241
313
  Contains a few small helpers for working with async functions and promises.
@@ -295,67 +367,232 @@ console.log(posts?.reason); // undefined | unknown
295
367
 
296
368
  ---
297
369
 
298
- ## `@reykjavik/webtools/fixIcelandicLocale`
370
+ ## `@reykjavik/webtools/errorhandling`
299
371
 
300
- As of early 2024, Google Chrome still does not support the Icelandic locale
301
- `is`/`is-IS` in any way. Meanwhile other browsers have supported it for over a
302
- decade.
372
+ A small set of lightweight tools for handling errors and promises in a safer,
373
+ more structured, FP-ish way.
303
374
 
304
- This module patches the following methods/classes by substituting the `is`
305
- locale with `da` (Danish) and apply a few post-hoc fixes to their return
306
- values.
375
+ Errors are always the first return value to promote early, explicit error
376
+ handling.
307
377
 
308
- - `Intl.Collator` and `String.prototype.localeCompare` (\*)
309
- - `Intl.NumberFormat` and `Number.prototype.toLocaleString` (\*)
310
- - `Intl.DateTimeFormat` and `Date.prototype.toLocaleString`,
311
- `.toLocaleDateString`, and `.toLocaleTimeString` (\*)
312
- - `Intl.RelativeDateFormat`
313
- - `Intl.PluralRules`
314
- - `Intl.ListFormat`
378
+ ### `asError`
315
379
 
316
- (\*) The results are quite usable, but not entirely perfect. The
317
- limitations/caveats are listed below.
380
+ **Syntax:** `asError(maybeError: unknown): ErrorFromPayload`
318
381
 
319
- To apply the patch, simply "side-effect import" this module at the top of your
320
- app's entry point:
382
+ Guarantees that a caught (`catch (e)`) value of `unknown` type, is indeed an
383
+ `Error` instance.
384
+
385
+ If the input is an `Error` instance, it is returned as-is. If the input is
386
+ something else it is wrapped in a new `ErrorFromPayload` instance, and the
387
+ original value is stored in as a `payload` property.
321
388
 
322
389
  ```ts
323
- import '@reykjavik/webtools/fixIcelandicLocale';
390
+ import { asError, type ErrorFromPayload } from '@reykjavik/webtools/errorhandling';
391
+
392
+ const theError = new Error('Something went wrong');
393
+ try {
394
+ throw theError;
395
+ } catch (err) {
396
+ const error = asError(theError);
397
+ console.error(error === theError); // true
398
+ console.error('patload' in error); // false
399
+ }
324
400
 
325
- // Then continue with your day and use `localeCompare` and other Intl.* methods
326
- // as you normally would. (See "limitations" below.)
401
+ const someObject = ['Something went wrong'];
402
+ try {
403
+ throw someObject;
404
+ } catch (err) {
405
+ const error = asError(someObject);
406
+ console.error(error === someObject); // false
407
+ console.error(error.message === someObject.join(',')); // false
408
+ console.error(error instanceOf ErrorFromPayload); // true
409
+
410
+ console.error(error.payload === someObject); // true
411
+ }
327
412
  ```
328
413
 
329
- (**NOTE** The patch is only applied in engines that fail a simple feature
330
- detection test.)
414
+ ### `Result` Singleton
331
415
 
332
- ### Limitations
416
+ Singleton object with the following small methods for creating, mapping or
417
+ handling `ResultTupleObj` instances:
333
418
 
334
- **`Intl.Collator` and `localeCompare`:**
419
+ - `Result.Success`
420
+ - `Result.Fail`
421
+ - `Result.catch`
422
+ - `Result.map`
423
+ - `Result.throw`
335
424
 
336
- - It sorts initial letters correctly but in the rest of the string, it
337
- incorrectly treats `ð` and `d` as the same letter (most of the time), and
338
- lumps the acute-accented characters `á`, `é`, `í`, `ó`, `ú` and `ý` in with
339
- their non-accented counterparts.
425
+ ### Type `ResultTuple`
340
426
 
341
- **`Intl.NumberFormat` and `toLocaleString`:**
427
+ **Syntax:** `ResultTuple<ResultType, OptionalErrorType>`
342
428
 
343
- - The `style: "unit"` option is not supported and prints units in Danish. (Soo
344
- many units and unit-variants…)
345
- - The `currencyDisplay: "name"` option is not supported and prints the
346
- currency's full name in Danish.
429
+ (Also aliased as `Result.Tuple`)
347
430
 
348
- **`Intl.DateTimeFormat` and `toLocaleDateString`:**
431
+ Simple bare-bones discriminated tuple type for a `[error, result]` pair.
349
432
 
350
- - The `month: 'narrow'` and `weekday: 'narrow'` options are not supported, and
351
- print the corresponding Danish initials.
352
- - For `timeZoneName` the values `"long"`, `"shortGeneric"` and `"longGeneric"`
353
- will appear in Danish.
354
- - The `timeStyle: 'full'` option prints the timezone names in Danish
355
- - The `dayPeriod` option has a couple of slight mismatches, at 5 am and 12
356
- noon.
433
+ ```ts
434
+ import { type ResultTuple } from '@reykjavik/webtools/errorhandling';
357
435
 
358
- We eagerly accept bugfixes, additions, etc. to this module!
436
+ declare const myResult: ResultTuple<string, Error>;
437
+
438
+ const [error, result] = myResult;
439
+ // (One of these two is always `undefined`)
440
+
441
+ if (error) {
442
+ // Here `error` is an Error instance
443
+ console.error(error.message);
444
+ } else {
445
+ // Here `result` is guaranteed to be a string
446
+ console.log(result);
447
+ }
448
+ ```
449
+
450
+ ### Type `ResultTupleObj`
451
+
452
+ **Syntax:** `ResultTupleObj<ResultType, OptionalErrorType>`
453
+
454
+ (Also aliased as `Result.TupleObj`)
455
+
456
+ Discriminated tuple type for a `[error, result]` pair (same as `ResultTuple`)
457
+ but with named properties `error` and `result` attached for dev convenience.
458
+
459
+ ```ts
460
+ import { type ResultTuple } from '@reykjavik/webtools/errorhandling';
461
+
462
+ declare const myResult: ResultTuple<string, Error>;
463
+
464
+ const [error, result] = myResult;
465
+ // (One of these two is always `undefined`)
466
+
467
+ if (error) {
468
+ // Here `error` is an Error instance
469
+ console.error(error.message);
470
+ } else {
471
+ // Here `result` is guaranteed to be a string
472
+ console.log(result);
473
+ }
474
+
475
+ // But `myResults` also has named properties, for convenience
476
+ if (myResult.error) {
477
+ // Here `myResult.error` is an Error instance
478
+ console.error(myResult.error.message);
479
+ } else {
480
+ // Here `myResult.result` is a string
481
+ console.log(myResult.result);
482
+ }
483
+ ```
484
+
485
+ ### `Result.catch`
486
+
487
+ **Syntax:** `Result.catch<T, Err>(callback: () => T): ResultTupleObj<T, Err>`
488
+ **Syntax:**
489
+ `Result.catch<T, Err>(promise: Promise<T>): Promise<ResultTupleObj<T, Err>>`
490
+
491
+ Error handling utility that wraps a promise or a callback function.
492
+
493
+ Catches errors and returns a `ResultTupleObj` — a nice discriminated
494
+ `[error, results]` tuple with the `result` and `error` also attached as named
495
+ properties.
496
+
497
+ Works on both promises and sync callback functions.
498
+
499
+ ```ts
500
+ import { Result } from '@reykjavik/webtools/errorhandling';
501
+
502
+ // Callback:
503
+ const [error, fooObject] = Result.catch(() => getFooSyncMayThrow());
504
+ // Promise:
505
+ const [error, fooObject] = await Result.catch(getFooPromiseMayThrow());
506
+
507
+ // Example of object property access:
508
+ const fooQuery = await Result.catch(getFooPromiseMayThrow());
509
+ if (fooQuery.error) {
510
+ console.log(fooQuery.error === fooQuery[0]); // true
511
+ throw fooQuery.error;
512
+ }
513
+ console.log(fooQuery.result === fooQuery[1]); // true
514
+ fooQuery.result; // Guaranteed to be defined
515
+ ```
516
+
517
+ This function acts as the inverse of [`Result.throw()`](#resultthrow).
518
+
519
+ ### `Result.map`
520
+
521
+ **Syntax:**
522
+ `Result.map<T, T2, E>(result: ResultTuple<T, E>, mapResult: (resultValue: T) => T2): ResultTuple<T2, E>`
523
+
524
+ Helper to map a `ResultTuple`-like object to a new `ResultTupleObj` object,
525
+ applying a transformation function to the result, but retaining the error
526
+ as-is.
527
+
528
+ ```ts
529
+ import { Result } from '@reykjavik/webtools/errorhandling';
530
+
531
+ const getStrLength = (str: string) => str.length;
532
+
533
+ const resultTuple =
534
+ Math.random() < 0.5 ? [new Error('Fail')] : [undefined, 'Hello!'];
535
+
536
+ const [error, mappedResult] = Result.map(resultTuple, getStrLength);
537
+
538
+ if (result) {
539
+ console.log(result); // 6
540
+ }
541
+ ```
542
+
543
+ ### `Result.Success`
544
+
545
+ **Syntax:** `Result.Success<T>(result: T): ResultTuple<T>`
546
+
547
+ Factory for creating a successful `ResultTupleObj`.
548
+
549
+ ```ts
550
+ import { Result } from '@reykjavik/webtools/errorhandling';
551
+
552
+ const happyResult: Result.SuccessObj<string> =
553
+ Result.Success('My result value');
554
+
555
+ console.log(happyResult.error); // undefined
556
+ console.log(happyResult[0]); // undefined
557
+ console.log(happyResult.result); // 'My result value'
558
+ console.log(happyResult[1]); // 'My result value'
559
+ ```
560
+
561
+ ### `Result.Fail`
562
+
563
+ **Syntax:** `Result.Fail<E extends Error>(err: T): ResultTuple<unknown, Err>`
564
+
565
+ Factory for creating a failed `ResultTupleObj`.
566
+
567
+ ```ts
568
+ import { Result } from '@reykjavik/webtools/errorhandling';
569
+
570
+ const happyResult: Result.FailObj<string> = Result.Fail(new Error('Oh no!'));
571
+
572
+ console.log(happyResult.error.message); // 'Oh no!'
573
+ console.log(happyResult[0].message); // 'Oh no!'
574
+ console.log(happyResult.result); // undefined
575
+ console.log(happyResult[1]); // undefined
576
+ ```
577
+
578
+ ### `Result.throw`
579
+
580
+ **Syntax:** `Result.throw<T>(result: ResultTuple<T>): T`
581
+
582
+ Unwraps a discriminated `ResultTuple`-like `[error, result]` tuple and throws
583
+ if there's an error, but returns the result otherwise.
584
+
585
+ ```ts
586
+ import { Result } from '@reykjavik/webtools/errorhandling';
587
+
588
+ try {
589
+ const fooResults = Result.throw(await getFooResultsTuple());
590
+ } catch (fooError) {
591
+ // Do something with the error from `getFooResultsTuple()`
592
+ }
593
+ ```
594
+
595
+ This function acts as the inverse of [`Result.catch()`](#resultcatch).
359
596
 
360
597
  ---
361
598
 
@@ -527,48 +764,6 @@ local type-safety for access to the full features and expressiveness of real
527
764
  CSS.
528
765
  ([Background info](https://github.com/vanilla-extract-css/vanilla-extract/discussions/898#discussioncomment-7125457).)
529
766
 
530
- ### `vanillaGlobal`
531
-
532
- **Syntax:** `vanillaGlobal(css: string): void`
533
-
534
- Inserts free-form CSS as a vanilla-extract `globalStyle`.
535
-
536
- ```ts
537
- // someFile.css.ts
538
- import { vanillaGlobal } from '@reykjavik/webtools/vanillaExtract';
539
-
540
- vanillaGlobal(`
541
- body {
542
- background-color: rebeccapurple;
543
- }
544
- `);
545
- ```
546
-
547
- ### `vanillaProps`
548
-
549
- **Syntax:** `vanillaProps(css: string): GlobalStyleRule`
550
-
551
- Spreads the return value into a style object, to inject free-form CSS
552
- properties (or nested blocks)
553
-
554
- ```ts
555
- // someFile.css.ts
556
- import { style } from '@vanilla-extract/css';
557
- import { vanillaProps } from '@reykjavik/webtools/vanillaExtract';
558
-
559
- const myStyle = style({
560
- color: 'darksalmon',
561
- // ...other style props...
562
-
563
- ...vanillaProps(`
564
- /* Plain CSS that's injected into the "myStyle" style block */
565
- border-bottom: 1px solid red;
566
- color: ${theme.color.primary}; /* I can still use typesafe values */
567
- random-css-prop-normally-rejected-by-vanilla-extract: 'YOLO!';
568
- `),
569
- });
570
- ```
571
-
572
767
  ### `vanillaClass`
573
768
 
574
769
  **Syntax:**
@@ -616,112 +811,57 @@ export const humanReadableClass = vanillaClass(
616
811
  );
617
812
  ```
618
813
 
619
- ### `vanillaClassNested`
620
-
621
- **Syntax:** `vanillaClassNested(css: string): string`
622
- **Syntax:** `vanillaClassNested(debugId: string, css: string): string`
814
+ ### `vanillaGlobal`
623
815
 
624
- Returns a scoped cssClassName styled with free-form CSS.
816
+ **Syntax:** `vanillaGlobal(css: string): void`
625
817
 
626
- It also automatically replaces all `&`-tokens with the selector for the
627
- auto-generated class-name.
818
+ Inserts free-form CSS as a vanilla-extract `globalStyle`.
628
819
 
629
820
  ```ts
630
821
  // someFile.css.ts
631
- import { vanillaClassNested } from '@reykjavik/webtools/vanillaExtract';
632
-
633
- export const myClass = vanillaClassNested(`
634
- background-color: #ccc;
635
- padding: .5em 1em;
822
+ import { vanillaGlobal } from '@reykjavik/webtools/vanillaExtract';
636
823
 
637
- /* Nested blocks begin: */
638
- &:hover {
639
- background-color: #666;
640
- color: white;
641
- }
642
- & > strong {
643
- color: maroon;
644
- }
645
- html[data-color-theme="unicorn"] & {
646
- background-color: pink;
824
+ vanillaGlobal(`
825
+ body {
826
+ background-color: rebeccapurple;
647
827
  }
648
828
  `);
649
829
  ```
650
830
 
651
- **NOTE:** All "bare" (un-nested) style properties **must come first**, before
652
- any nested blocks.
653
-
654
- **NOTE 2:** `vanillaClassNested` does NOT support deeply nested blocks, or
655
- anything so fancy. It will also replace `&` characters inside values,
656
- comments, etc. If you need something more sophisticated, use a custom
657
- `postcss` config.
658
-
659
- ### `vanillaNest`
660
-
661
- **Syntax:** `vanillaNest(ampSelector: string, css: string): string`
831
+ ### `vanillaProps`
662
832
 
663
- Replaces all `&` tokens with the given selector string, in a direct (read.
664
- "dumb") way. It's mainly useful when used with style-mixins, etc.
833
+ **Syntax:** `vanillaProps(css: string): GlobalStyleRule`
665
834
 
666
- `vanillaNest` does NOT support deeply nested blocks, or anything so fancy. It
667
- will also replace `&` characters inside values, comments, etc. If you need
668
- something more sophisticated, use a custom `postcss` config.
835
+ Returns an object that can be safely spread into a vanilla-extract style
836
+ object, to inject free-form CSS properties (or nested blocks).
669
837
 
670
838
  ```ts
671
- // someCssHelper.ts
672
- import { vanillaNest } from '@reykjavik/webtools/vanillaExtract';
673
-
674
- export const hoverGlow = (
675
- ampSelector: string,
676
- glowiness?: 'normal' | 'insane'
677
- ) =>
678
- vanillaNest(
679
- ampSelector,
680
- `
681
- &:hover {
682
- box-shadow: 0 0 20px 5px ${
683
- glowiness === 'insane' ? 'hotpink' : 'salmon'
684
- };
685
- }
686
- `
687
- );
688
-
689
- // ...then, somewhere else in a *.css.ts file:
690
-
691
- import { hoverGlow } from '~/someCssHelper.js';
692
- import { vanillaGlobal } from '@reykjavik/webtools/vanillaExtract';
839
+ // someFile.css.ts
840
+ import { style } from '@vanilla-extract/css';
841
+ import { vanillaProps } from '@reykjavik/webtools/vanillaExtract';
693
842
 
694
- vanillaGlobal(`
695
- .MyComponent {
696
- border: 1px solid #ccc;
697
- padding: 1em;
698
- }
699
- ${hoverGlow('.MyComponent')}
843
+ const myStyle = style({
844
+ color: 'darksalmon',
845
+ // ...other style props...
700
846
 
701
- .MyOtherComponent {
702
- border: 1px solid #ccc;
703
- padding: 1em;
704
- }
705
- ${hoverGlow('.MyOtherComponent', 'insane')}
706
- `);
847
+ ...vanillaProps(`
848
+ /* Plain CSS that's injected into the "myStyle" style block */
849
+ border-bottom: 1px solid red;
850
+ color: ${theme.color.primary}; /* I can still use typesafe values */
851
+ random-css-prop-normally-rejected-by-vanilla-extract: 'YOLO!';
852
+ `),
853
+ });
707
854
  ```
708
855
 
709
- (This low-level utility function is used internally by
710
- [`vanillaClassNested`](#vanillaclassnested).)
711
-
712
856
  ---
713
857
 
714
858
  ## Framework Specific Tools
715
859
 
716
- ---
717
-
718
860
  ### Remix.run Tools
719
861
 
720
862
  See [README-remix.md](./README-remix.md) for helpers and components
721
863
  specifically designed for use in Remix.run projects.
722
864
 
723
- ---
724
-
725
865
  <!-- #fragment anchors to not break older v0.1 @see links -->
726
866
 
727
867
  <a name="reykjavikwebtoolsnexthttp"></a> <a name="makeerrorizeapphoc"></a>
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Error subclass for thrown values that got cought and turned into an actual
3
+ * Error, with the thrown value as the `payload` property.
4
+ *
5
+ * @see https://github.com/reykjavikcity/webtools/blob/v0.1/README.md#aserror
6
+ */
7
+ export declare class ErrorFromPayload extends Error {
8
+ payload?: unknown;
9
+ constructor(payload: unknown);
10
+ name: string;
11
+ }
12
+ /**v
13
+ * Guarantees that a caught (`catch (e)`) value of `unknown` type,
14
+ * is indeed an `Error` instance.
15
+ *
16
+ *If the input is an `Error` instance, it is returned as-is. If the input is
17
+ * something else it is wrapped in a new `ErrorFromPayload` instance, and the
18
+ * original value is stored in a `payload`
19
+ *
20
+ * @see https://github.com/reykjavikcity/webtools/blob/v0.1/README.md#aserror
21
+ */
22
+ export declare const asError: (maybeError: unknown) => ErrorFromPayload;
23
+ type SuccessResult<T> = [error: undefined, result: T] & {
24
+ error?: undefined;
25
+ result: T;
26
+ };
27
+ type FailResult<E extends Error> = [error: E] & {
28
+ error: E;
29
+ result?: undefined;
30
+ };
31
+ /**
32
+ * Simple bare-bones discriminated tuple type for a [error, result] pair.
33
+ *
34
+ * @see https://github.com/reykjavikcity/webtools/blob/v0.1/README.md#type-resulttuple
35
+ */
36
+ export type ResultTuple<T, E extends Error = Error> = [error: undefined, result: T] | [error: E];
37
+ /**
38
+ * Discriminated tuple type for a `[error, result]` pair (same as `ResultTuple`)
39
+ * but with named properties `error` and `result` attached for dev convenience.
40
+ *
41
+ * @see https://github.com/reykjavikcity/webtools/blob/v0.1/README.md#type-resulttupleobj
42
+ */
43
+ export type ResultTupleObj<T, E extends Error = Error> = SuccessResult<T> | FailResult<E>;
44
+ /**
45
+ * Error handling utility that wraps a promise or a callback function.
46
+ *
47
+ * Catches errors and returns a `ResultTupleObj` — a nice discriminated
48
+ * `[error, results]` tuple with the `result` and `error` also attached as
49
+ * named properties.
50
+ *
51
+ * Works on both promises and sync callback functions.
52
+ *
53
+ * @see https://github.com/reykjavikcity/webtools/blob/v0.1/README.md#resultcatch
54
+ */
55
+ declare function catch_<T, E extends Error = ErrorFromPayload>(promise: Promise<T>): Promise<ResultTupleObj<T, E>>;
56
+ declare function catch_<T, E extends Error = ErrorFromPayload>(callback: () => T): ResultTupleObj<T, E>;
57
+ /**
58
+ * Singleton object with small methods for creating, mapping or handling
59
+ * `ResultTupleObj` instances.
60
+ *
61
+ * @see https://github.com/reykjavikcity/webtools/blob/v0.1/README.md#result-singleton
62
+ */
63
+ export declare const Result: {
64
+ /**
65
+ * Factory for creating a successful `Result.TupleObj`.
66
+ *
67
+ * @see https://github.com/reykjavikcity/webtools/blob/v0.1/README.md#resultsuccess
68
+ */
69
+ Success: <T>(result: T) => SuccessResult<T>;
70
+ /**
71
+ * Factory for creating a failed `Result.TupleObj`.
72
+ *
73
+ * @see https://github.com/reykjavikcity/webtools/blob/v0.1/README.md#resultsfail
74
+ */
75
+ Fail: <E extends Error = Error>(e: unknown) => FailResult<E>;
76
+ catch: typeof catch_;
77
+ /**
78
+ * Helper to map a `ResultTuple`-like object to a new `ResultTupleObj`
79
+ * object, applying a transformation function to the result, but retaining
80
+ * the error as-is.
81
+ *
82
+ * @see https://github.com/reykjavikcity/webtools/blob/v0.1/README.md#resulmap
83
+ */
84
+ map: <T_1, T2, E_1 extends Error>(result: ResultTuple<T_1, E_1>, mapFn: (resultValue: T_1) => T2) => ResultTupleObj<T2, E_1>;
85
+ /**
86
+ * Unwraps a discriminated [error, result] `Result.Tuple`-like object
87
+ * and throws if there's an error, but returns the result otherwise.
88
+ *
89
+ * @see https://github.com/reykjavikcity/webtools/blob/v0.1/README.md#resulthrow
90
+ */
91
+ throw: <T_2>(result: ResultTuple<T_2, Error>) => T_2;
92
+ };
93
+ export declare namespace Result {
94
+ type Tuple<T, E extends Error = Error> = ResultTuple<T, E>;
95
+ type TupleObj<T, E extends Error = Error> = ResultTupleObj<T, E>;
96
+ type SuccessObj<T> = SuccessResult<T>;
97
+ type FailObj<E extends Error> = FailResult<E>;
98
+ }
99
+ export {};