@promptbook/website-crawler 0.112.0-73 → 0.112.0-79

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.
Files changed (74) hide show
  1. package/README.md +9 -9
  2. package/esm/index.es.js +313 -210
  3. package/esm/index.es.js.map +1 -1
  4. package/esm/src/avatars/types/AvatarVisualDefinition.d.ts +1 -1
  5. package/esm/src/avatars/visuals/octopus3d2AvatarVisual.d.ts +7 -0
  6. package/esm/src/avatars/visuals/octopus3dAvatarVisualShared.d.ts +37 -0
  7. package/esm/src/book-components/Chat/save/_common/chatExportRendering.d.ts +47 -0
  8. package/esm/src/book-components/Chat/save/html/htmlSaveFormatDefinition.d.ts +12 -0
  9. package/esm/src/book-components/Chat/save/index.d.ts +2 -2
  10. package/esm/src/book-components/Chat/save/markdown/mdSaveFormatDefinition.d.ts +5 -3
  11. package/esm/src/book-components/Chat/save/pdf/buildChatPdf.d.ts +3 -3
  12. package/esm/src/book-components/Chat/save/pdf/pdfSaveFormatDefinition.d.ts +1 -1
  13. package/esm/src/cli/cli-commands/agent/agentProjectPaths.d.ts +8 -8
  14. package/esm/src/cli/cli-commands/agent/initializeAgentRunnerCommand.d.ts +1 -1
  15. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer.d.ts +56 -0
  16. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer.test.d.ts +1 -0
  17. package/esm/src/cli/cli-commands/agents-server/ensureAgentsServerEnvFile.d.ts +7 -0
  18. package/esm/src/cli/cli-commands/agents-server/ensureAgentsServerGitignoreFile.d.ts +7 -0
  19. package/esm/src/cli/cli-commands/agents-server/init.d.ts +9 -0
  20. package/esm/src/cli/cli-commands/agents-server/init.test.d.ts +1 -0
  21. package/esm/src/cli/cli-commands/agents-server/initializeAgentsServerProjectConfiguration.d.ts +17 -0
  22. package/esm/src/cli/cli-commands/agents-server/printAgentsServerInitializationSummary.d.ts +7 -0
  23. package/esm/src/cli/cli-commands/agents-server/run.d.ts +14 -0
  24. package/esm/src/cli/cli-commands/agents-server/run.test.d.ts +1 -0
  25. package/esm/src/cli/cli-commands/agents-server/startAgentsServer.d.ts +23 -0
  26. package/esm/src/cli/cli-commands/agents-server.d.ts +8 -0
  27. package/esm/src/cli/cli-commands/common/projectInitialization.d.ts +65 -0
  28. package/esm/src/cli/cli-commands/common/promptRunnerCliOptions.d.ts +44 -0
  29. package/esm/src/cli/common/$deprecateCliCommand.d.ts +8 -0
  30. package/esm/src/cli/common/$deprecateCliCommand.test.d.ts +1 -0
  31. package/esm/src/utils/color/Color.d.ts +4 -44
  32. package/esm/src/utils/color/ColorValue.d.ts +55 -0
  33. package/esm/src/utils/color/isHexColorString.d.ts +10 -0
  34. package/esm/src/utils/color/parseColorString.d.ts +11 -0
  35. package/esm/src/version.d.ts +1 -1
  36. package/package.json +2 -2
  37. package/umd/index.umd.js +313 -210
  38. package/umd/index.umd.js.map +1 -1
  39. package/umd/src/avatars/types/AvatarVisualDefinition.d.ts +1 -1
  40. package/umd/src/avatars/visuals/octopus3d2AvatarVisual.d.ts +7 -0
  41. package/umd/src/avatars/visuals/octopus3dAvatarVisualShared.d.ts +37 -0
  42. package/umd/src/book-components/Chat/save/_common/chatExportRendering.d.ts +47 -0
  43. package/umd/src/book-components/Chat/save/html/htmlSaveFormatDefinition.d.ts +12 -0
  44. package/umd/src/book-components/Chat/save/index.d.ts +2 -2
  45. package/umd/src/book-components/Chat/save/markdown/mdSaveFormatDefinition.d.ts +5 -3
  46. package/umd/src/book-components/Chat/save/pdf/buildChatPdf.d.ts +3 -3
  47. package/umd/src/book-components/Chat/save/pdf/pdfSaveFormatDefinition.d.ts +1 -1
  48. package/umd/src/cli/cli-commands/agent/agentProjectPaths.d.ts +8 -8
  49. package/umd/src/cli/cli-commands/agent/initializeAgentRunnerCommand.d.ts +1 -1
  50. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer.d.ts +56 -0
  51. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer.test.d.ts +1 -0
  52. package/umd/src/cli/cli-commands/agents-server/ensureAgentsServerEnvFile.d.ts +7 -0
  53. package/umd/src/cli/cli-commands/agents-server/ensureAgentsServerGitignoreFile.d.ts +7 -0
  54. package/umd/src/cli/cli-commands/agents-server/init.d.ts +9 -0
  55. package/umd/src/cli/cli-commands/agents-server/init.test.d.ts +1 -0
  56. package/umd/src/cli/cli-commands/agents-server/initializeAgentsServerProjectConfiguration.d.ts +17 -0
  57. package/umd/src/cli/cli-commands/agents-server/printAgentsServerInitializationSummary.d.ts +7 -0
  58. package/umd/src/cli/cli-commands/agents-server/run.d.ts +14 -0
  59. package/umd/src/cli/cli-commands/agents-server/run.test.d.ts +1 -0
  60. package/umd/src/cli/cli-commands/agents-server/startAgentsServer.d.ts +23 -0
  61. package/umd/src/cli/cli-commands/agents-server.d.ts +8 -0
  62. package/umd/src/cli/cli-commands/common/projectInitialization.d.ts +65 -0
  63. package/umd/src/cli/cli-commands/common/promptRunnerCliOptions.d.ts +44 -0
  64. package/umd/src/cli/common/$deprecateCliCommand.d.ts +8 -0
  65. package/umd/src/cli/common/$deprecateCliCommand.test.d.ts +1 -0
  66. package/umd/src/utils/color/Color.d.ts +4 -44
  67. package/umd/src/utils/color/ColorValue.d.ts +55 -0
  68. package/umd/src/utils/color/isHexColorString.d.ts +10 -0
  69. package/umd/src/utils/color/parseColorString.d.ts +11 -0
  70. package/umd/src/version.d.ts +1 -1
  71. package/esm/src/cli/cli-commands/coder/appendBlock.d.ts +0 -6
  72. package/esm/src/cli/cli-commands/coder/readTextFileIfExists.d.ts +0 -6
  73. package/umd/src/cli/cli-commands/coder/appendBlock.d.ts +0 -6
  74. package/umd/src/cli/cli-commands/coder/readTextFileIfExists.d.ts +0 -6
package/umd/index.umd.js CHANGED
@@ -23,7 +23,7 @@
23
23
  * @generated
24
24
  * @see https://github.com/webgptorg/promptbook
25
25
  */
26
- const PROMPTBOOK_ENGINE_VERSION = '0.112.0-73';
26
+ const PROMPTBOOK_ENGINE_VERSION = '0.112.0-79';
27
27
  /**
28
28
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
29
29
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -317,6 +317,111 @@
317
317
  }
318
318
  }
319
319
 
320
+ /**
321
+ * Shared immutable channel storage and serialization helpers for `Color`.
322
+ *
323
+ * @private base class of Color
324
+ */
325
+ class ColorValue {
326
+ constructor(red, green, blue, alpha = 255) {
327
+ this.red = red;
328
+ this.green = green;
329
+ this.blue = blue;
330
+ this.alpha = alpha;
331
+ checkChannelValue('Red', red);
332
+ checkChannelValue('Green', green);
333
+ checkChannelValue('Blue', blue);
334
+ checkChannelValue('Alpha', alpha);
335
+ }
336
+ /**
337
+ * Shortcut for `red` property
338
+ * Number from 0 to 255
339
+ * @alias red
340
+ */
341
+ get r() {
342
+ return this.red;
343
+ }
344
+ /**
345
+ * Shortcut for `green` property
346
+ * Number from 0 to 255
347
+ * @alias green
348
+ */
349
+ get g() {
350
+ return this.green;
351
+ }
352
+ /**
353
+ * Shortcut for `blue` property
354
+ * Number from 0 to 255
355
+ * @alias blue
356
+ */
357
+ get b() {
358
+ return this.blue;
359
+ }
360
+ /**
361
+ * Shortcut for `alpha` property
362
+ * Number from 0 (transparent) to 255 (opaque)
363
+ * @alias alpha
364
+ */
365
+ get a() {
366
+ return this.alpha;
367
+ }
368
+ /**
369
+ * Shortcut for `alpha` property
370
+ * Number from 0 (transparent) to 255 (opaque)
371
+ * @alias alpha
372
+ */
373
+ get opacity() {
374
+ return this.alpha;
375
+ }
376
+ /**
377
+ * Shortcut for 1-`alpha` property
378
+ */
379
+ get transparency() {
380
+ return 255 - this.alpha;
381
+ }
382
+ clone() {
383
+ return take(this.createColor(this.red, this.green, this.blue, this.alpha));
384
+ }
385
+ toString() {
386
+ return this.toHex();
387
+ }
388
+ toHex() {
389
+ if (this.alpha === 255) {
390
+ return `#${this.red.toString(16).padStart(2, '0')}${this.green.toString(16).padStart(2, '0')}${this.blue
391
+ .toString(16)
392
+ .padStart(2, '0')}`;
393
+ }
394
+ else {
395
+ return `#${this.red.toString(16).padStart(2, '0')}${this.green.toString(16).padStart(2, '0')}${this.blue
396
+ .toString(16)
397
+ .padStart(2, '0')}${this.alpha.toString(16).padStart(2, '0')}`;
398
+ }
399
+ }
400
+ toRgb() {
401
+ if (this.alpha === 255) {
402
+ return `rgb(${this.red}, ${this.green}, ${this.blue})`;
403
+ }
404
+ else {
405
+ return `rgba(${this.red}, ${this.green}, ${this.blue}, ${Math.round((this.alpha / 255) * 100)}%)`;
406
+ }
407
+ }
408
+ toHsl() {
409
+ throw new Error(`Getting HSL is not implemented`);
410
+ }
411
+ }
412
+
413
+ /**
414
+ * Checks if the given value is a valid hex color string
415
+ *
416
+ * @param value - value to check
417
+ * @returns true if the value is a valid hex color string (e.g., `#009edd`, `#fff`, etc.)
418
+ *
419
+ * @private function of Color
420
+ */
421
+ function isHexColorString(value) {
422
+ return (typeof value === 'string' && /^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/.test(value));
423
+ }
424
+
320
425
  /**
321
426
  * Constant for short hex lengths.
322
427
  */
@@ -528,16 +633,53 @@
528
633
 
529
634
  /**
530
635
  * Pattern matching hsl regex.
636
+ *
637
+ * @private function of Color
531
638
  */
532
639
  const HSL_REGEX_PATTERN = /^hsl\(\s*([0-9.]+)\s*,\s*([0-9.]+)%\s*,\s*([0-9.]+)%\s*\)$/;
533
640
  /**
534
641
  * Pattern matching RGB regex.
642
+ *
643
+ * @private function of Color
535
644
  */
536
645
  const RGB_REGEX_PATTERN = /^rgb\(\s*([0-9.%-]+)\s*,\s*([0-9.%-]+)\s*,\s*([0-9.%-]+)\s*\)$/;
537
646
  /**
538
647
  * Pattern matching rgba regex.
648
+ *
649
+ * @private function of Color
539
650
  */
540
651
  const RGBA_REGEX_PATTERN = /^rgba\(\s*([0-9.%-]+)\s*,\s*([0-9.%-]+)\s*,\s*([0-9.%-]+)\s*,\s*([0-9.%-]+)\s*\)$/;
652
+ /**
653
+ * Parses a supported color string into RGBA channels.
654
+ *
655
+ * @param color as a string for example `#009edd`, `rgb(0,158,221)`, `rgb(0%,62%,86.7%)`, `hsl(197.1,100%,43.3%)`, `red`, `darkgrey`,...
656
+ * @returns RGBA channel values.
657
+ *
658
+ * @private function of Color
659
+ */
660
+ function parseColorString(color) {
661
+ const trimmed = color.trim();
662
+ const cssColor = CSS_COLORS[trimmed];
663
+ if (cssColor) {
664
+ return parseColorString(cssColor);
665
+ }
666
+ else if (isHexColorString(trimmed)) {
667
+ return parseHexColor(trimmed);
668
+ }
669
+ if (HSL_REGEX_PATTERN.test(trimmed)) {
670
+ return parseHslColor(trimmed);
671
+ }
672
+ else if (RGB_REGEX_PATTERN.test(trimmed)) {
673
+ return parseRgbColor(trimmed);
674
+ }
675
+ else if (RGBA_REGEX_PATTERN.test(trimmed)) {
676
+ return parseRgbaColor(trimmed);
677
+ }
678
+ else {
679
+ throw new Error(`Can not create a new Color instance from string "${trimmed}".`);
680
+ }
681
+ }
682
+
541
683
  /**
542
684
  * Color object represents an RGB color with alpha channel
543
685
  *
@@ -545,7 +687,7 @@
545
687
  *
546
688
  * @public exported from `@promptbook/color`
547
689
  */
548
- class Color {
690
+ class Color extends ColorValue {
549
691
  /**
550
692
  * Creates a new Color instance from miscellaneous formats
551
693
  * - It can receive Color instance and just return the same instance
@@ -618,25 +760,7 @@
618
760
  * @returns Color object
619
761
  */
620
762
  static fromString(color) {
621
- const trimmed = color.trim();
622
- if (CSS_COLORS[trimmed]) {
623
- return Color.fromString(CSS_COLORS[trimmed]);
624
- }
625
- else if (Color.isHexColorString(trimmed)) {
626
- return Color.fromHex(trimmed);
627
- }
628
- if (HSL_REGEX_PATTERN.test(trimmed)) {
629
- return Color.fromHsl(trimmed);
630
- }
631
- else if (RGB_REGEX_PATTERN.test(trimmed)) {
632
- return Color.fromRgbString(trimmed);
633
- }
634
- else if (RGBA_REGEX_PATTERN.test(trimmed)) {
635
- return Color.fromRgbaString(trimmed);
636
- }
637
- else {
638
- throw new Error(`Can not create a new Color instance from string "${trimmed}".`);
639
- }
763
+ return Color.fromColorChannels(parseColorString(color));
640
764
  }
641
765
  /**
642
766
  * Gets common color
@@ -666,8 +790,7 @@
666
790
  * @returns Color object
667
791
  */
668
792
  static fromHex(hex) {
669
- const { red, green, blue, alpha } = parseHexColor(hex);
670
- return take(new Color(red, green, blue, alpha));
793
+ return Color.fromColorChannels(parseHexColor(hex));
671
794
  }
672
795
  /**
673
796
  * Creates a new Color instance from color in hsl format
@@ -676,8 +799,7 @@
676
799
  * @returns Color object
677
800
  */
678
801
  static fromHsl(hsl) {
679
- const { red, green, blue, alpha } = parseHslColor(hsl);
680
- return take(new Color(red, green, blue, alpha));
802
+ return Color.fromColorChannels(parseHslColor(hsl));
681
803
  }
682
804
  /**
683
805
  * Creates a new Color instance from color in rgb format
@@ -686,8 +808,7 @@
686
808
  * @returns Color object
687
809
  */
688
810
  static fromRgbString(rgb) {
689
- const { red, green, blue, alpha } = parseRgbColor(rgb);
690
- return take(new Color(red, green, blue, alpha));
811
+ return Color.fromColorChannels(parseRgbColor(rgb));
691
812
  }
692
813
  /**
693
814
  * Creates a new Color instance from color in rbga format
@@ -696,8 +817,7 @@
696
817
  * @returns Color object
697
818
  */
698
819
  static fromRgbaString(rgba) {
699
- const { red, green, blue, alpha } = parseRgbaColor(rgba);
700
- return take(new Color(red, green, blue, alpha));
820
+ return Color.fromColorChannels(parseRgbaColor(rgba));
701
821
  }
702
822
  /**
703
823
  * Creates a new Color for color channels values
@@ -709,7 +829,7 @@
709
829
  * @returns Color object
710
830
  */
711
831
  static fromValues(red, green, blue, alpha = 255) {
712
- return take(new Color(red, green, blue, alpha));
832
+ return Color.fromColorChannels({ red, green, blue, alpha });
713
833
  }
714
834
  /**
715
835
  * Checks if the given value is a valid Color object.
@@ -742,8 +862,7 @@
742
862
  * @returns true if the value is a valid hex color string (e.g., `#009edd`, `#fff`, etc.)
743
863
  */
744
864
  static isHexColorString(value) {
745
- return (typeof value === 'string' &&
746
- /^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/.test(value));
865
+ return isHexColorString(value);
747
866
  }
748
867
  /**
749
868
  * Creates new Color object
@@ -756,89 +875,13 @@
756
875
  * @param alpha number from 0 (transparent) to 255 (opaque)
757
876
  */
758
877
  constructor(red, green, blue, alpha = 255) {
759
- this.red = red;
760
- this.green = green;
761
- this.blue = blue;
762
- this.alpha = alpha;
763
- checkChannelValue('Red', red);
764
- checkChannelValue('Green', green);
765
- checkChannelValue('Blue', blue);
766
- checkChannelValue('Alpha', alpha);
878
+ super(red, green, blue, alpha);
767
879
  }
768
- /**
769
- * Shortcut for `red` property
770
- * Number from 0 to 255
771
- * @alias red
772
- */
773
- get r() {
774
- return this.red;
880
+ createColor(red, green, blue, alpha) {
881
+ return new Color(red, green, blue, alpha);
775
882
  }
776
- /**
777
- * Shortcut for `green` property
778
- * Number from 0 to 255
779
- * @alias green
780
- */
781
- get g() {
782
- return this.green;
783
- }
784
- /**
785
- * Shortcut for `blue` property
786
- * Number from 0 to 255
787
- * @alias blue
788
- */
789
- get b() {
790
- return this.blue;
791
- }
792
- /**
793
- * Shortcut for `alpha` property
794
- * Number from 0 (transparent) to 255 (opaque)
795
- * @alias alpha
796
- */
797
- get a() {
798
- return this.alpha;
799
- }
800
- /**
801
- * Shortcut for `alpha` property
802
- * Number from 0 (transparent) to 255 (opaque)
803
- * @alias alpha
804
- */
805
- get opacity() {
806
- return this.alpha;
807
- }
808
- /**
809
- * Shortcut for 1-`alpha` property
810
- */
811
- get transparency() {
812
- return 255 - this.alpha;
813
- }
814
- clone() {
815
- return take(new Color(this.red, this.green, this.blue, this.alpha));
816
- }
817
- toString() {
818
- return this.toHex();
819
- }
820
- toHex() {
821
- if (this.alpha === 255) {
822
- return `#${this.red.toString(16).padStart(2, '0')}${this.green.toString(16).padStart(2, '0')}${this.blue
823
- .toString(16)
824
- .padStart(2, '0')}`;
825
- }
826
- else {
827
- return `#${this.red.toString(16).padStart(2, '0')}${this.green.toString(16).padStart(2, '0')}${this.blue
828
- .toString(16)
829
- .padStart(2, '0')}${this.alpha.toString(16).padStart(2, '0')}`;
830
- }
831
- }
832
- toRgb() {
833
- if (this.alpha === 255) {
834
- return `rgb(${this.red}, ${this.green}, ${this.blue})`;
835
- }
836
- else {
837
- return `rgba(${this.red}, ${this.green}, ${this.blue}, ${Math.round((this.alpha / 255) * 100)}%)`;
838
- }
839
- }
840
- toHsl() {
841
- throw new Error(`Getting HSL is not implemented`);
883
+ static fromColorChannels({ red, green, blue, alpha }) {
884
+ return take(new Color(red, green, blue, alpha));
842
885
  }
843
886
  }
844
887
 
@@ -1962,7 +2005,7 @@
1962
2005
  */
1963
2006
  function createPostprocessingCommands(task) {
1964
2007
  var _a;
1965
- return ((_a = task.postprocessingFunctionNames) === null || _a === void 0 ? void 0 : _a.map((postprocessingFunctionName) => `POSTPROCESSING \`${postprocessingFunctionName}\``)) || [];
2008
+ return (((_a = task.postprocessingFunctionNames) === null || _a === void 0 ? void 0 : _a.map((postprocessingFunctionName) => `POSTPROCESSING \`${postprocessingFunctionName}\``)) || []);
1966
2009
  }
1967
2010
  /**
1968
2011
  * Collects expectation commands.
@@ -2101,120 +2144,183 @@
2101
2144
  * @public exported from `@promptbook/utils`
2102
2145
  */
2103
2146
  function checkSerializableAsJson(options) {
2104
- const { value, name, message } = options;
2147
+ checkSerializableValue(options);
2148
+ }
2149
+ // TODO: Can be return type more type-safe? like `asserts options.value is JsonValue`
2150
+ // TODO: [🧠][main] !!3 In-memory cache of same values to prevent multiple checks
2151
+ // Note: [🐠] This is how `checkSerializableAsJson` + `isSerializableAsJson` together can just retun true/false or rich error message
2152
+ /**
2153
+ * Checks one value and dispatches to the appropriate specialized validator.
2154
+ *
2155
+ * @private function of `checkSerializableAsJson`
2156
+ */
2157
+ function checkSerializableValue(options) {
2158
+ const { value } = options;
2159
+ if (isSerializablePrimitive(value)) {
2160
+ return;
2161
+ }
2105
2162
  if (value === undefined) {
2106
- throw new UnexpectedError(`${name} is undefined`);
2163
+ throw new UnexpectedError(`${options.name} is undefined`);
2107
2164
  }
2108
- else if (value === null) {
2109
- return;
2165
+ if (typeof value === 'symbol') {
2166
+ throw new UnexpectedError(`${options.name} is symbol`);
2110
2167
  }
2111
- else if (typeof value === 'boolean') {
2112
- return;
2168
+ if (typeof value === 'function') {
2169
+ throw new UnexpectedError(`${options.name} is function`);
2113
2170
  }
2114
- else if (typeof value === 'number' && !isNaN(value)) {
2171
+ if (Array.isArray(value)) {
2172
+ checkSerializableArray(options, value);
2115
2173
  return;
2116
2174
  }
2117
- else if (typeof value === 'string') {
2175
+ if (value !== null && typeof value === 'object') {
2176
+ checkSerializableObject(options, value);
2118
2177
  return;
2119
2178
  }
2120
- else if (typeof value === 'symbol') {
2121
- throw new UnexpectedError(`${name} is symbol`);
2122
- }
2123
- else if (typeof value === 'function') {
2124
- throw new UnexpectedError(`${name} is function`);
2125
- }
2126
- else if (typeof value === 'object' && Array.isArray(value)) {
2127
- for (let i = 0; i < value.length; i++) {
2128
- checkSerializableAsJson({ name: `${name}[${i}]`, value: value[i], message });
2129
- }
2179
+ throwUnknownTypeError(options);
2180
+ }
2181
+ /**
2182
+ * Checks the primitive values that are directly JSON serializable.
2183
+ *
2184
+ * @private function of `checkSerializableAsJson`
2185
+ */
2186
+ function isSerializablePrimitive(value) {
2187
+ return (value === null ||
2188
+ typeof value === 'boolean' ||
2189
+ (typeof value === 'number' && !isNaN(value)) ||
2190
+ typeof value === 'string');
2191
+ }
2192
+ /**
2193
+ * Recursively checks JSON array items.
2194
+ *
2195
+ * @private function of `checkSerializableAsJson`
2196
+ */
2197
+ function checkSerializableArray(context, arrayValue) {
2198
+ for (let index = 0; index < arrayValue.length; index++) {
2199
+ checkSerializableAsJson({
2200
+ ...context,
2201
+ name: `${context.name}[${index}]`,
2202
+ value: arrayValue[index],
2203
+ });
2130
2204
  }
2131
- else if (typeof value === 'object') {
2132
- if (value instanceof Date) {
2133
- throw new UnexpectedError(spacetrim.spaceTrim((block) => `
2134
- \`${name}\` is Date
2205
+ }
2206
+ /**
2207
+ * Checks object-like values and dispatches special unsupported built-ins.
2208
+ *
2209
+ * @private function of `checkSerializableAsJson`
2210
+ */
2211
+ function checkSerializableObject(context, objectValue) {
2212
+ checkUnsupportedObjectType(context, objectValue);
2213
+ checkSerializableObjectEntries(context, objectValue);
2214
+ assertJsonStringificationSucceeds(context, objectValue);
2215
+ }
2216
+ /**
2217
+ * Rejects built-in objects that must be converted before JSON serialization.
2218
+ *
2219
+ * @private function of `checkSerializableAsJson`
2220
+ */
2221
+ function checkUnsupportedObjectType(context, objectValue) {
2222
+ if (objectValue instanceof Date) {
2223
+ throw new UnexpectedError(spacetrim.spaceTrim((block) => `
2224
+ \`${context.name}\` is Date
2135
2225
 
2136
- Use \`string_date_iso8601\` instead
2226
+ Use \`string_date_iso8601\` instead
2137
2227
 
2138
- Additional message for \`${name}\`:
2139
- ${block(message || '(nothing)')}
2140
- `));
2141
- }
2142
- else if (value instanceof Map) {
2143
- throw new UnexpectedError(`${name} is Map`);
2144
- }
2145
- else if (value instanceof Set) {
2146
- throw new UnexpectedError(`${name} is Set`);
2147
- }
2148
- else if (value instanceof RegExp) {
2149
- throw new UnexpectedError(`${name} is RegExp`);
2150
- }
2151
- else if (value instanceof Error) {
2152
- throw new UnexpectedError(spacetrim.spaceTrim((block) => `
2153
- \`${name}\` is unserialized Error
2228
+ Additional message for \`${context.name}\`:
2229
+ ${block(context.message || '(nothing)')}
2230
+ `));
2231
+ }
2232
+ if (objectValue instanceof Map) {
2233
+ throw new UnexpectedError(`${context.name} is Map`);
2234
+ }
2235
+ if (objectValue instanceof Set) {
2236
+ throw new UnexpectedError(`${context.name} is Set`);
2237
+ }
2238
+ if (objectValue instanceof RegExp) {
2239
+ throw new UnexpectedError(`${context.name} is RegExp`);
2240
+ }
2241
+ if (objectValue instanceof Error) {
2242
+ throw new UnexpectedError(spacetrim.spaceTrim((block) => `
2243
+ \`${context.name}\` is unserialized Error
2154
2244
 
2155
- Use function \`serializeError\`
2245
+ Use function \`serializeError\`
2156
2246
 
2157
- Additional message for \`${name}\`:
2158
- ${block(message || '(nothing)')}
2247
+ Additional message for \`${context.name}\`:
2248
+ ${block(context.message || '(nothing)')}
2159
2249
 
2160
- `));
2250
+ `));
2251
+ }
2252
+ }
2253
+ /**
2254
+ * Recursively checks object properties while preserving omitted `undefined` keys.
2255
+ *
2256
+ * @private function of `checkSerializableAsJson`
2257
+ */
2258
+ function checkSerializableObjectEntries(context, objectValue) {
2259
+ for (const [subName, subValue] of Object.entries(objectValue)) {
2260
+ if (subValue === undefined) {
2261
+ // Note: undefined in object is serializable - it is just omitted
2262
+ continue;
2161
2263
  }
2162
- else {
2163
- for (const [subName, subValue] of Object.entries(value)) {
2164
- if (subValue === undefined) {
2165
- // Note: undefined in object is serializable - it is just omitted
2166
- continue;
2167
- }
2168
- checkSerializableAsJson({ name: `${name}.${subName}`, value: subValue, message });
2169
- }
2170
- try {
2171
- JSON.stringify(value); // <- TODO: [0]
2172
- }
2173
- catch (error) {
2174
- assertsError(error);
2175
- throw new UnexpectedError(spacetrim.spaceTrim((block) => `
2176
- \`${name}\` is not serializable
2264
+ checkSerializableAsJson({
2265
+ ...context,
2266
+ name: `${context.name}.${subName}`,
2267
+ value: subValue,
2268
+ });
2269
+ }
2270
+ }
2271
+ /**
2272
+ * Uses `JSON.stringify` as the final guard for cases like circular references.
2273
+ *
2274
+ * @private function of `checkSerializableAsJson`
2275
+ */
2276
+ function assertJsonStringificationSucceeds(context, objectValue) {
2277
+ try {
2278
+ JSON.stringify(objectValue); // <- TODO: [0]
2279
+ }
2280
+ catch (error) {
2281
+ assertsError(error);
2282
+ throw new UnexpectedError(spacetrim.spaceTrim((block) => `
2283
+ \`${context.name}\` is not serializable
2177
2284
 
2178
- ${block(error.stack || error.message)}
2285
+ ${block(error.stack || error.message)}
2179
2286
 
2180
- Additional message for \`${name}\`:
2181
- ${block(message || '(nothing)')}
2182
- `));
2287
+ Additional message for \`${context.name}\`:
2288
+ ${block(context.message || '(nothing)')}
2289
+ `));
2290
+ }
2291
+ /*
2292
+ TODO: [0] Is there some more elegant way to check circular references?
2293
+ const seen = new Set();
2294
+ const stack = [{ value }];
2295
+ while (stack.length > 0) {
2296
+ const { value } = stack.pop()!;
2297
+ if (typeof value === 'object' && value !== null) {
2298
+ if (seen.has(value)) {
2299
+ throw new UnexpectedError(`${name} has circular reference`);
2183
2300
  }
2184
- /*
2185
- TODO: [0] Is there some more elegant way to check circular references?
2186
- const seen = new Set();
2187
- const stack = [{ value }];
2188
- while (stack.length > 0) {
2189
- const { value } = stack.pop()!;
2190
- if (typeof value === 'object' && value !== null) {
2191
- if (seen.has(value)) {
2192
- throw new UnexpectedError(`${name} has circular reference`);
2193
- }
2194
- seen.add(value);
2195
- if (Array.isArray(value)) {
2196
- stack.push(...value.map((value) => ({ value })));
2197
- } else {
2198
- stack.push(...Object.values(value).map((value) => ({ value })));
2199
- }
2200
- }
2301
+ seen.add(value);
2302
+ if (Array.isArray(value)) {
2303
+ stack.push(...value.map((value) => ({ value })));
2304
+ } else {
2305
+ stack.push(...Object.values(value).map((value) => ({ value })));
2201
2306
  }
2202
- */
2203
- return;
2204
2307
  }
2205
2308
  }
2206
- else {
2207
- throw new UnexpectedError(spacetrim.spaceTrim((block) => `
2208
- \`${name}\` is unknown type
2309
+ */
2310
+ }
2311
+ /**
2312
+ * Throws the fallback error for unsupported value types like `bigint` and `NaN`.
2313
+ *
2314
+ * @private function of `checkSerializableAsJson`
2315
+ */
2316
+ function throwUnknownTypeError(context) {
2317
+ throw new UnexpectedError(spacetrim.spaceTrim((block) => `
2318
+ \`${context.name}\` is unknown type
2209
2319
 
2210
- Additional message for \`${name}\`:
2211
- ${block(message || '(nothing)')}
2212
- `));
2213
- }
2320
+ Additional message for \`${context.name}\`:
2321
+ ${block(context.message || '(nothing)')}
2322
+ `));
2214
2323
  }
2215
- // TODO: Can be return type more type-safe? like `asserts options.value is JsonValue`
2216
- // TODO: [🧠][main] !!3 In-memory cache of same values to prevent multiple checks
2217
- // Note: [🐠] This is how `checkSerializableAsJson` + `isSerializableAsJson` together can just retun true/false or rich error message
2218
2324
 
2219
2325
  /**
2220
2326
  * Creates a deep clone of the given object
@@ -2778,8 +2884,7 @@
2778
2884
  * @private internal utility of `validatePipeline`
2779
2885
  */
2780
2886
  function validateTaskSupportsJokers(task, pipelineIdentification) {
2781
- if (task.format ||
2782
- task.expectations /* <- TODO: Require at least 1 -> min <- expectation to use jokers */) {
2887
+ if (task.format || task.expectations /* <- TODO: Require at least 1 -> min <- expectation to use jokers */) {
2783
2888
  return;
2784
2889
  }
2785
2890
  throw new PipelineLogicError(spacetrim.spaceTrim((block) => `
@@ -7074,9 +7179,7 @@
7074
7179
  ${block(quoteMultilineText(((_b = failure.error) === null || _b === void 0 ? void 0 : _b.message) || ''))}
7075
7180
 
7076
7181
  Result:
7077
- ${block(failure.result === null
7078
- ? 'null'
7079
- : quoteMultilineText(spacetrim.spaceTrim(failure.result)))}
7182
+ ${block(failure.result === null ? 'null' : quoteMultilineText(spacetrim.spaceTrim(failure.result)))}
7080
7183
  `;
7081
7184
  }))
7082
7185
  .join('\n\n---\n\n');