@promptbook/documents 0.112.0-73 → 0.112.0-80

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
@@ -24,7 +24,7 @@
24
24
  * @generated
25
25
  * @see https://github.com/webgptorg/promptbook
26
26
  */
27
- const PROMPTBOOK_ENGINE_VERSION = '0.112.0-73';
27
+ const PROMPTBOOK_ENGINE_VERSION = '0.112.0-80';
28
28
  /**
29
29
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
30
30
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -292,6 +292,111 @@
292
292
  }
293
293
  }
294
294
 
295
+ /**
296
+ * Shared immutable channel storage and serialization helpers for `Color`.
297
+ *
298
+ * @private base class of Color
299
+ */
300
+ class ColorValue {
301
+ constructor(red, green, blue, alpha = 255) {
302
+ this.red = red;
303
+ this.green = green;
304
+ this.blue = blue;
305
+ this.alpha = alpha;
306
+ checkChannelValue('Red', red);
307
+ checkChannelValue('Green', green);
308
+ checkChannelValue('Blue', blue);
309
+ checkChannelValue('Alpha', alpha);
310
+ }
311
+ /**
312
+ * Shortcut for `red` property
313
+ * Number from 0 to 255
314
+ * @alias red
315
+ */
316
+ get r() {
317
+ return this.red;
318
+ }
319
+ /**
320
+ * Shortcut for `green` property
321
+ * Number from 0 to 255
322
+ * @alias green
323
+ */
324
+ get g() {
325
+ return this.green;
326
+ }
327
+ /**
328
+ * Shortcut for `blue` property
329
+ * Number from 0 to 255
330
+ * @alias blue
331
+ */
332
+ get b() {
333
+ return this.blue;
334
+ }
335
+ /**
336
+ * Shortcut for `alpha` property
337
+ * Number from 0 (transparent) to 255 (opaque)
338
+ * @alias alpha
339
+ */
340
+ get a() {
341
+ return this.alpha;
342
+ }
343
+ /**
344
+ * Shortcut for `alpha` property
345
+ * Number from 0 (transparent) to 255 (opaque)
346
+ * @alias alpha
347
+ */
348
+ get opacity() {
349
+ return this.alpha;
350
+ }
351
+ /**
352
+ * Shortcut for 1-`alpha` property
353
+ */
354
+ get transparency() {
355
+ return 255 - this.alpha;
356
+ }
357
+ clone() {
358
+ return take(this.createColor(this.red, this.green, this.blue, this.alpha));
359
+ }
360
+ toString() {
361
+ return this.toHex();
362
+ }
363
+ toHex() {
364
+ if (this.alpha === 255) {
365
+ return `#${this.red.toString(16).padStart(2, '0')}${this.green.toString(16).padStart(2, '0')}${this.blue
366
+ .toString(16)
367
+ .padStart(2, '0')}`;
368
+ }
369
+ else {
370
+ return `#${this.red.toString(16).padStart(2, '0')}${this.green.toString(16).padStart(2, '0')}${this.blue
371
+ .toString(16)
372
+ .padStart(2, '0')}${this.alpha.toString(16).padStart(2, '0')}`;
373
+ }
374
+ }
375
+ toRgb() {
376
+ if (this.alpha === 255) {
377
+ return `rgb(${this.red}, ${this.green}, ${this.blue})`;
378
+ }
379
+ else {
380
+ return `rgba(${this.red}, ${this.green}, ${this.blue}, ${Math.round((this.alpha / 255) * 100)}%)`;
381
+ }
382
+ }
383
+ toHsl() {
384
+ throw new Error(`Getting HSL is not implemented`);
385
+ }
386
+ }
387
+
388
+ /**
389
+ * Checks if the given value is a valid hex color string
390
+ *
391
+ * @param value - value to check
392
+ * @returns true if the value is a valid hex color string (e.g., `#009edd`, `#fff`, etc.)
393
+ *
394
+ * @private function of Color
395
+ */
396
+ function isHexColorString(value) {
397
+ 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));
398
+ }
399
+
295
400
  /**
296
401
  * Constant for short hex lengths.
297
402
  */
@@ -503,16 +608,53 @@
503
608
 
504
609
  /**
505
610
  * Pattern matching hsl regex.
611
+ *
612
+ * @private function of Color
506
613
  */
507
614
  const HSL_REGEX_PATTERN = /^hsl\(\s*([0-9.]+)\s*,\s*([0-9.]+)%\s*,\s*([0-9.]+)%\s*\)$/;
508
615
  /**
509
616
  * Pattern matching RGB regex.
617
+ *
618
+ * @private function of Color
510
619
  */
511
620
  const RGB_REGEX_PATTERN = /^rgb\(\s*([0-9.%-]+)\s*,\s*([0-9.%-]+)\s*,\s*([0-9.%-]+)\s*\)$/;
512
621
  /**
513
622
  * Pattern matching rgba regex.
623
+ *
624
+ * @private function of Color
514
625
  */
515
626
  const RGBA_REGEX_PATTERN = /^rgba\(\s*([0-9.%-]+)\s*,\s*([0-9.%-]+)\s*,\s*([0-9.%-]+)\s*,\s*([0-9.%-]+)\s*\)$/;
627
+ /**
628
+ * Parses a supported color string into RGBA channels.
629
+ *
630
+ * @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`,...
631
+ * @returns RGBA channel values.
632
+ *
633
+ * @private function of Color
634
+ */
635
+ function parseColorString(color) {
636
+ const trimmed = color.trim();
637
+ const cssColor = CSS_COLORS[trimmed];
638
+ if (cssColor) {
639
+ return parseColorString(cssColor);
640
+ }
641
+ else if (isHexColorString(trimmed)) {
642
+ return parseHexColor(trimmed);
643
+ }
644
+ if (HSL_REGEX_PATTERN.test(trimmed)) {
645
+ return parseHslColor(trimmed);
646
+ }
647
+ else if (RGB_REGEX_PATTERN.test(trimmed)) {
648
+ return parseRgbColor(trimmed);
649
+ }
650
+ else if (RGBA_REGEX_PATTERN.test(trimmed)) {
651
+ return parseRgbaColor(trimmed);
652
+ }
653
+ else {
654
+ throw new Error(`Can not create a new Color instance from string "${trimmed}".`);
655
+ }
656
+ }
657
+
516
658
  /**
517
659
  * Color object represents an RGB color with alpha channel
518
660
  *
@@ -520,7 +662,7 @@
520
662
  *
521
663
  * @public exported from `@promptbook/color`
522
664
  */
523
- class Color {
665
+ class Color extends ColorValue {
524
666
  /**
525
667
  * Creates a new Color instance from miscellaneous formats
526
668
  * - It can receive Color instance and just return the same instance
@@ -593,25 +735,7 @@
593
735
  * @returns Color object
594
736
  */
595
737
  static fromString(color) {
596
- const trimmed = color.trim();
597
- if (CSS_COLORS[trimmed]) {
598
- return Color.fromString(CSS_COLORS[trimmed]);
599
- }
600
- else if (Color.isHexColorString(trimmed)) {
601
- return Color.fromHex(trimmed);
602
- }
603
- if (HSL_REGEX_PATTERN.test(trimmed)) {
604
- return Color.fromHsl(trimmed);
605
- }
606
- else if (RGB_REGEX_PATTERN.test(trimmed)) {
607
- return Color.fromRgbString(trimmed);
608
- }
609
- else if (RGBA_REGEX_PATTERN.test(trimmed)) {
610
- return Color.fromRgbaString(trimmed);
611
- }
612
- else {
613
- throw new Error(`Can not create a new Color instance from string "${trimmed}".`);
614
- }
738
+ return Color.fromColorChannels(parseColorString(color));
615
739
  }
616
740
  /**
617
741
  * Gets common color
@@ -641,8 +765,7 @@
641
765
  * @returns Color object
642
766
  */
643
767
  static fromHex(hex) {
644
- const { red, green, blue, alpha } = parseHexColor(hex);
645
- return take(new Color(red, green, blue, alpha));
768
+ return Color.fromColorChannels(parseHexColor(hex));
646
769
  }
647
770
  /**
648
771
  * Creates a new Color instance from color in hsl format
@@ -651,8 +774,7 @@
651
774
  * @returns Color object
652
775
  */
653
776
  static fromHsl(hsl) {
654
- const { red, green, blue, alpha } = parseHslColor(hsl);
655
- return take(new Color(red, green, blue, alpha));
777
+ return Color.fromColorChannels(parseHslColor(hsl));
656
778
  }
657
779
  /**
658
780
  * Creates a new Color instance from color in rgb format
@@ -661,8 +783,7 @@
661
783
  * @returns Color object
662
784
  */
663
785
  static fromRgbString(rgb) {
664
- const { red, green, blue, alpha } = parseRgbColor(rgb);
665
- return take(new Color(red, green, blue, alpha));
786
+ return Color.fromColorChannels(parseRgbColor(rgb));
666
787
  }
667
788
  /**
668
789
  * Creates a new Color instance from color in rbga format
@@ -671,8 +792,7 @@
671
792
  * @returns Color object
672
793
  */
673
794
  static fromRgbaString(rgba) {
674
- const { red, green, blue, alpha } = parseRgbaColor(rgba);
675
- return take(new Color(red, green, blue, alpha));
795
+ return Color.fromColorChannels(parseRgbaColor(rgba));
676
796
  }
677
797
  /**
678
798
  * Creates a new Color for color channels values
@@ -684,7 +804,7 @@
684
804
  * @returns Color object
685
805
  */
686
806
  static fromValues(red, green, blue, alpha = 255) {
687
- return take(new Color(red, green, blue, alpha));
807
+ return Color.fromColorChannels({ red, green, blue, alpha });
688
808
  }
689
809
  /**
690
810
  * Checks if the given value is a valid Color object.
@@ -717,8 +837,7 @@
717
837
  * @returns true if the value is a valid hex color string (e.g., `#009edd`, `#fff`, etc.)
718
838
  */
719
839
  static isHexColorString(value) {
720
- return (typeof value === 'string' &&
721
- /^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/.test(value));
840
+ return isHexColorString(value);
722
841
  }
723
842
  /**
724
843
  * Creates new Color object
@@ -731,89 +850,13 @@
731
850
  * @param alpha number from 0 (transparent) to 255 (opaque)
732
851
  */
733
852
  constructor(red, green, blue, alpha = 255) {
734
- this.red = red;
735
- this.green = green;
736
- this.blue = blue;
737
- this.alpha = alpha;
738
- checkChannelValue('Red', red);
739
- checkChannelValue('Green', green);
740
- checkChannelValue('Blue', blue);
741
- checkChannelValue('Alpha', alpha);
853
+ super(red, green, blue, alpha);
742
854
  }
743
- /**
744
- * Shortcut for `red` property
745
- * Number from 0 to 255
746
- * @alias red
747
- */
748
- get r() {
749
- return this.red;
855
+ createColor(red, green, blue, alpha) {
856
+ return new Color(red, green, blue, alpha);
750
857
  }
751
- /**
752
- * Shortcut for `green` property
753
- * Number from 0 to 255
754
- * @alias green
755
- */
756
- get g() {
757
- return this.green;
758
- }
759
- /**
760
- * Shortcut for `blue` property
761
- * Number from 0 to 255
762
- * @alias blue
763
- */
764
- get b() {
765
- return this.blue;
766
- }
767
- /**
768
- * Shortcut for `alpha` property
769
- * Number from 0 (transparent) to 255 (opaque)
770
- * @alias alpha
771
- */
772
- get a() {
773
- return this.alpha;
774
- }
775
- /**
776
- * Shortcut for `alpha` property
777
- * Number from 0 (transparent) to 255 (opaque)
778
- * @alias alpha
779
- */
780
- get opacity() {
781
- return this.alpha;
782
- }
783
- /**
784
- * Shortcut for 1-`alpha` property
785
- */
786
- get transparency() {
787
- return 255 - this.alpha;
788
- }
789
- clone() {
790
- return take(new Color(this.red, this.green, this.blue, this.alpha));
791
- }
792
- toString() {
793
- return this.toHex();
794
- }
795
- toHex() {
796
- if (this.alpha === 255) {
797
- return `#${this.red.toString(16).padStart(2, '0')}${this.green.toString(16).padStart(2, '0')}${this.blue
798
- .toString(16)
799
- .padStart(2, '0')}`;
800
- }
801
- else {
802
- return `#${this.red.toString(16).padStart(2, '0')}${this.green.toString(16).padStart(2, '0')}${this.blue
803
- .toString(16)
804
- .padStart(2, '0')}${this.alpha.toString(16).padStart(2, '0')}`;
805
- }
806
- }
807
- toRgb() {
808
- if (this.alpha === 255) {
809
- return `rgb(${this.red}, ${this.green}, ${this.blue})`;
810
- }
811
- else {
812
- return `rgba(${this.red}, ${this.green}, ${this.blue}, ${Math.round((this.alpha / 255) * 100)}%)`;
813
- }
814
- }
815
- toHsl() {
816
- throw new Error(`Getting HSL is not implemented`);
858
+ static fromColorChannels({ red, green, blue, alpha }) {
859
+ return take(new Color(red, green, blue, alpha));
817
860
  }
818
861
  }
819
862
 
@@ -1975,7 +2018,7 @@
1975
2018
  */
1976
2019
  function createPostprocessingCommands(task) {
1977
2020
  var _a;
1978
- return ((_a = task.postprocessingFunctionNames) === null || _a === void 0 ? void 0 : _a.map((postprocessingFunctionName) => `POSTPROCESSING \`${postprocessingFunctionName}\``)) || [];
2021
+ return (((_a = task.postprocessingFunctionNames) === null || _a === void 0 ? void 0 : _a.map((postprocessingFunctionName) => `POSTPROCESSING \`${postprocessingFunctionName}\``)) || []);
1979
2022
  }
1980
2023
  /**
1981
2024
  * Collects expectation commands.
@@ -2140,120 +2183,183 @@
2140
2183
  * @public exported from `@promptbook/utils`
2141
2184
  */
2142
2185
  function checkSerializableAsJson(options) {
2143
- const { value, name, message } = options;
2186
+ checkSerializableValue(options);
2187
+ }
2188
+ // TODO: Can be return type more type-safe? like `asserts options.value is JsonValue`
2189
+ // TODO: [🧠][main] !!3 In-memory cache of same values to prevent multiple checks
2190
+ // Note: [🐠] This is how `checkSerializableAsJson` + `isSerializableAsJson` together can just retun true/false or rich error message
2191
+ /**
2192
+ * Checks one value and dispatches to the appropriate specialized validator.
2193
+ *
2194
+ * @private function of `checkSerializableAsJson`
2195
+ */
2196
+ function checkSerializableValue(options) {
2197
+ const { value } = options;
2198
+ if (isSerializablePrimitive(value)) {
2199
+ return;
2200
+ }
2144
2201
  if (value === undefined) {
2145
- throw new UnexpectedError(`${name} is undefined`);
2202
+ throw new UnexpectedError(`${options.name} is undefined`);
2146
2203
  }
2147
- else if (value === null) {
2148
- return;
2204
+ if (typeof value === 'symbol') {
2205
+ throw new UnexpectedError(`${options.name} is symbol`);
2149
2206
  }
2150
- else if (typeof value === 'boolean') {
2151
- return;
2207
+ if (typeof value === 'function') {
2208
+ throw new UnexpectedError(`${options.name} is function`);
2152
2209
  }
2153
- else if (typeof value === 'number' && !isNaN(value)) {
2210
+ if (Array.isArray(value)) {
2211
+ checkSerializableArray(options, value);
2154
2212
  return;
2155
2213
  }
2156
- else if (typeof value === 'string') {
2214
+ if (value !== null && typeof value === 'object') {
2215
+ checkSerializableObject(options, value);
2157
2216
  return;
2158
2217
  }
2159
- else if (typeof value === 'symbol') {
2160
- throw new UnexpectedError(`${name} is symbol`);
2161
- }
2162
- else if (typeof value === 'function') {
2163
- throw new UnexpectedError(`${name} is function`);
2164
- }
2165
- else if (typeof value === 'object' && Array.isArray(value)) {
2166
- for (let i = 0; i < value.length; i++) {
2167
- checkSerializableAsJson({ name: `${name}[${i}]`, value: value[i], message });
2168
- }
2218
+ throwUnknownTypeError(options);
2219
+ }
2220
+ /**
2221
+ * Checks the primitive values that are directly JSON serializable.
2222
+ *
2223
+ * @private function of `checkSerializableAsJson`
2224
+ */
2225
+ function isSerializablePrimitive(value) {
2226
+ return (value === null ||
2227
+ typeof value === 'boolean' ||
2228
+ (typeof value === 'number' && !isNaN(value)) ||
2229
+ typeof value === 'string');
2230
+ }
2231
+ /**
2232
+ * Recursively checks JSON array items.
2233
+ *
2234
+ * @private function of `checkSerializableAsJson`
2235
+ */
2236
+ function checkSerializableArray(context, arrayValue) {
2237
+ for (let index = 0; index < arrayValue.length; index++) {
2238
+ checkSerializableAsJson({
2239
+ ...context,
2240
+ name: `${context.name}[${index}]`,
2241
+ value: arrayValue[index],
2242
+ });
2169
2243
  }
2170
- else if (typeof value === 'object') {
2171
- if (value instanceof Date) {
2172
- throw new UnexpectedError(spacetrim.spaceTrim((block) => `
2173
- \`${name}\` is Date
2244
+ }
2245
+ /**
2246
+ * Checks object-like values and dispatches special unsupported built-ins.
2247
+ *
2248
+ * @private function of `checkSerializableAsJson`
2249
+ */
2250
+ function checkSerializableObject(context, objectValue) {
2251
+ checkUnsupportedObjectType(context, objectValue);
2252
+ checkSerializableObjectEntries(context, objectValue);
2253
+ assertJsonStringificationSucceeds(context, objectValue);
2254
+ }
2255
+ /**
2256
+ * Rejects built-in objects that must be converted before JSON serialization.
2257
+ *
2258
+ * @private function of `checkSerializableAsJson`
2259
+ */
2260
+ function checkUnsupportedObjectType(context, objectValue) {
2261
+ if (objectValue instanceof Date) {
2262
+ throw new UnexpectedError(spacetrim.spaceTrim((block) => `
2263
+ \`${context.name}\` is Date
2174
2264
 
2175
- Use \`string_date_iso8601\` instead
2265
+ Use \`string_date_iso8601\` instead
2176
2266
 
2177
- Additional message for \`${name}\`:
2178
- ${block(message || '(nothing)')}
2179
- `));
2180
- }
2181
- else if (value instanceof Map) {
2182
- throw new UnexpectedError(`${name} is Map`);
2183
- }
2184
- else if (value instanceof Set) {
2185
- throw new UnexpectedError(`${name} is Set`);
2186
- }
2187
- else if (value instanceof RegExp) {
2188
- throw new UnexpectedError(`${name} is RegExp`);
2189
- }
2190
- else if (value instanceof Error) {
2191
- throw new UnexpectedError(spacetrim.spaceTrim((block) => `
2192
- \`${name}\` is unserialized Error
2267
+ Additional message for \`${context.name}\`:
2268
+ ${block(context.message || '(nothing)')}
2269
+ `));
2270
+ }
2271
+ if (objectValue instanceof Map) {
2272
+ throw new UnexpectedError(`${context.name} is Map`);
2273
+ }
2274
+ if (objectValue instanceof Set) {
2275
+ throw new UnexpectedError(`${context.name} is Set`);
2276
+ }
2277
+ if (objectValue instanceof RegExp) {
2278
+ throw new UnexpectedError(`${context.name} is RegExp`);
2279
+ }
2280
+ if (objectValue instanceof Error) {
2281
+ throw new UnexpectedError(spacetrim.spaceTrim((block) => `
2282
+ \`${context.name}\` is unserialized Error
2193
2283
 
2194
- Use function \`serializeError\`
2284
+ Use function \`serializeError\`
2195
2285
 
2196
- Additional message for \`${name}\`:
2197
- ${block(message || '(nothing)')}
2286
+ Additional message for \`${context.name}\`:
2287
+ ${block(context.message || '(nothing)')}
2198
2288
 
2199
- `));
2289
+ `));
2290
+ }
2291
+ }
2292
+ /**
2293
+ * Recursively checks object properties while preserving omitted `undefined` keys.
2294
+ *
2295
+ * @private function of `checkSerializableAsJson`
2296
+ */
2297
+ function checkSerializableObjectEntries(context, objectValue) {
2298
+ for (const [subName, subValue] of Object.entries(objectValue)) {
2299
+ if (subValue === undefined) {
2300
+ // Note: undefined in object is serializable - it is just omitted
2301
+ continue;
2200
2302
  }
2201
- else {
2202
- for (const [subName, subValue] of Object.entries(value)) {
2203
- if (subValue === undefined) {
2204
- // Note: undefined in object is serializable - it is just omitted
2205
- continue;
2206
- }
2207
- checkSerializableAsJson({ name: `${name}.${subName}`, value: subValue, message });
2208
- }
2209
- try {
2210
- JSON.stringify(value); // <- TODO: [0]
2211
- }
2212
- catch (error) {
2213
- assertsError(error);
2214
- throw new UnexpectedError(spacetrim.spaceTrim((block) => `
2215
- \`${name}\` is not serializable
2303
+ checkSerializableAsJson({
2304
+ ...context,
2305
+ name: `${context.name}.${subName}`,
2306
+ value: subValue,
2307
+ });
2308
+ }
2309
+ }
2310
+ /**
2311
+ * Uses `JSON.stringify` as the final guard for cases like circular references.
2312
+ *
2313
+ * @private function of `checkSerializableAsJson`
2314
+ */
2315
+ function assertJsonStringificationSucceeds(context, objectValue) {
2316
+ try {
2317
+ JSON.stringify(objectValue); // <- TODO: [0]
2318
+ }
2319
+ catch (error) {
2320
+ assertsError(error);
2321
+ throw new UnexpectedError(spacetrim.spaceTrim((block) => `
2322
+ \`${context.name}\` is not serializable
2216
2323
 
2217
- ${block(error.stack || error.message)}
2324
+ ${block(error.stack || error.message)}
2218
2325
 
2219
- Additional message for \`${name}\`:
2220
- ${block(message || '(nothing)')}
2221
- `));
2326
+ Additional message for \`${context.name}\`:
2327
+ ${block(context.message || '(nothing)')}
2328
+ `));
2329
+ }
2330
+ /*
2331
+ TODO: [0] Is there some more elegant way to check circular references?
2332
+ const seen = new Set();
2333
+ const stack = [{ value }];
2334
+ while (stack.length > 0) {
2335
+ const { value } = stack.pop()!;
2336
+ if (typeof value === 'object' && value !== null) {
2337
+ if (seen.has(value)) {
2338
+ throw new UnexpectedError(`${name} has circular reference`);
2222
2339
  }
2223
- /*
2224
- TODO: [0] Is there some more elegant way to check circular references?
2225
- const seen = new Set();
2226
- const stack = [{ value }];
2227
- while (stack.length > 0) {
2228
- const { value } = stack.pop()!;
2229
- if (typeof value === 'object' && value !== null) {
2230
- if (seen.has(value)) {
2231
- throw new UnexpectedError(`${name} has circular reference`);
2232
- }
2233
- seen.add(value);
2234
- if (Array.isArray(value)) {
2235
- stack.push(...value.map((value) => ({ value })));
2236
- } else {
2237
- stack.push(...Object.values(value).map((value) => ({ value })));
2238
- }
2239
- }
2340
+ seen.add(value);
2341
+ if (Array.isArray(value)) {
2342
+ stack.push(...value.map((value) => ({ value })));
2343
+ } else {
2344
+ stack.push(...Object.values(value).map((value) => ({ value })));
2240
2345
  }
2241
- */
2242
- return;
2243
2346
  }
2244
2347
  }
2245
- else {
2246
- throw new UnexpectedError(spacetrim.spaceTrim((block) => `
2247
- \`${name}\` is unknown type
2348
+ */
2349
+ }
2350
+ /**
2351
+ * Throws the fallback error for unsupported value types like `bigint` and `NaN`.
2352
+ *
2353
+ * @private function of `checkSerializableAsJson`
2354
+ */
2355
+ function throwUnknownTypeError(context) {
2356
+ throw new UnexpectedError(spacetrim.spaceTrim((block) => `
2357
+ \`${context.name}\` is unknown type
2248
2358
 
2249
- Additional message for \`${name}\`:
2250
- ${block(message || '(nothing)')}
2251
- `));
2252
- }
2359
+ Additional message for \`${context.name}\`:
2360
+ ${block(context.message || '(nothing)')}
2361
+ `));
2253
2362
  }
2254
- // TODO: Can be return type more type-safe? like `asserts options.value is JsonValue`
2255
- // TODO: [🧠][main] !!3 In-memory cache of same values to prevent multiple checks
2256
- // Note: [🐠] This is how `checkSerializableAsJson` + `isSerializableAsJson` together can just retun true/false or rich error message
2257
2363
 
2258
2364
  /**
2259
2365
  * Creates a deep clone of the given object
@@ -2817,8 +2923,7 @@
2817
2923
  * @private internal utility of `validatePipeline`
2818
2924
  */
2819
2925
  function validateTaskSupportsJokers(task, pipelineIdentification) {
2820
- if (task.format ||
2821
- task.expectations /* <- TODO: Require at least 1 -> min <- expectation to use jokers */) {
2926
+ if (task.format || task.expectations /* <- TODO: Require at least 1 -> min <- expectation to use jokers */) {
2822
2927
  return;
2823
2928
  }
2824
2929
  throw new PipelineLogicError(spacetrim.spaceTrim((block) => `
@@ -7231,9 +7336,7 @@
7231
7336
  ${block(quoteMultilineText(((_b = failure.error) === null || _b === void 0 ? void 0 : _b.message) || ''))}
7232
7337
 
7233
7338
  Result:
7234
- ${block(failure.result === null
7235
- ? 'null'
7236
- : quoteMultilineText(spacetrim.spaceTrim(failure.result)))}
7339
+ ${block(failure.result === null ? 'null' : quoteMultilineText(spacetrim.spaceTrim(failure.result)))}
7237
7340
  `;
7238
7341
  }))
7239
7342
  .join('\n\n---\n\n');