@fgv/ts-utils 5.0.1-0 → 5.0.1-10

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 (94) hide show
  1. package/dist/index.js +32 -0
  2. package/dist/packlets/base/brand.js +23 -0
  3. package/dist/packlets/base/index.js +28 -0
  4. package/dist/packlets/base/mapResults.js +217 -0
  5. package/dist/packlets/base/messageAggregator.js +110 -0
  6. package/dist/packlets/base/normalize.js +132 -0
  7. package/dist/packlets/base/result.js +611 -0
  8. package/dist/packlets/base/utils.js +185 -0
  9. package/dist/packlets/collections/collectible.js +82 -0
  10. package/dist/packlets/collections/collector.js +189 -0
  11. package/dist/packlets/collections/collectorValidator.js +94 -0
  12. package/dist/packlets/collections/common.js +23 -0
  13. package/dist/packlets/collections/convertingCollector.js +118 -0
  14. package/dist/packlets/collections/convertingCollectorValidator.js +95 -0
  15. package/dist/packlets/collections/index.js +37 -0
  16. package/dist/packlets/collections/keyValueConverters.js +100 -0
  17. package/dist/packlets/collections/readonlyResultMap.js +23 -0
  18. package/dist/packlets/collections/resultMap.js +214 -0
  19. package/dist/packlets/collections/resultMapValidator.js +122 -0
  20. package/dist/packlets/collections/utils.js +31 -0
  21. package/dist/packlets/collections/validatingCollector.js +63 -0
  22. package/dist/packlets/collections/validatingConvertingCollector.js +64 -0
  23. package/dist/packlets/collections/validatingResultMap.js +57 -0
  24. package/dist/packlets/conversion/baseConverter.js +242 -0
  25. package/dist/packlets/conversion/converter.js +2 -0
  26. package/dist/packlets/conversion/converters.js +637 -0
  27. package/dist/packlets/conversion/defaultingConverter.js +149 -0
  28. package/dist/packlets/conversion/index.js +29 -0
  29. package/dist/packlets/conversion/objectConverter.js +141 -0
  30. package/dist/packlets/conversion/stringConverter.js +93 -0
  31. package/dist/packlets/hash/crcNormalizer.js +114 -0
  32. package/dist/packlets/hash/hashingNormalizer.js +92 -0
  33. package/dist/packlets/hash/index.js +24 -0
  34. package/dist/packlets/logging/index.js +24 -0
  35. package/dist/packlets/logging/logReporter.js +114 -0
  36. package/dist/packlets/logging/logger.js +258 -0
  37. package/dist/packlets/validation/array.js +64 -0
  38. package/dist/packlets/validation/boolean.js +52 -0
  39. package/dist/packlets/validation/classes.js +31 -0
  40. package/dist/packlets/validation/common.js +23 -0
  41. package/dist/packlets/validation/field.js +67 -0
  42. package/dist/packlets/validation/genericValidator.js +160 -0
  43. package/dist/packlets/validation/index.js +29 -0
  44. package/dist/packlets/validation/number.js +52 -0
  45. package/dist/packlets/validation/object.js +134 -0
  46. package/dist/packlets/validation/oneOf.js +58 -0
  47. package/dist/packlets/validation/string.js +52 -0
  48. package/dist/packlets/validation/traits.js +56 -0
  49. package/dist/packlets/validation/typeGuard.js +59 -0
  50. package/dist/packlets/validation/validator.js +23 -0
  51. package/dist/packlets/validation/validatorBase.js +37 -0
  52. package/dist/packlets/validation/validators.js +191 -0
  53. package/dist/test/helpers/jest/helpers/fsHelpers.js +139 -0
  54. package/dist/test/helpers/jest/helpers/index.js +2 -0
  55. package/dist/test/helpers/jest/index.js +17 -0
  56. package/dist/test/helpers/jest/matchers/index.js +14 -0
  57. package/dist/test/helpers/jest/matchers/toFail/index.js +23 -0
  58. package/dist/test/helpers/jest/matchers/toFail/predicate.js +5 -0
  59. package/dist/test/helpers/jest/matchers/toFailTest/index.js +28 -0
  60. package/dist/test/helpers/jest/matchers/toFailTest/predicate.js +8 -0
  61. package/dist/test/helpers/jest/matchers/toFailTestAndMatchSnapshot/index.js +24 -0
  62. package/dist/test/helpers/jest/matchers/toFailTestAndMatchSnapshot/predicate.js +11 -0
  63. package/dist/test/helpers/jest/matchers/toFailTestWith/index.js +29 -0
  64. package/dist/test/helpers/jest/matchers/toFailTestWith/predicate.js +26 -0
  65. package/dist/test/helpers/jest/matchers/toFailWith/index.js +27 -0
  66. package/dist/test/helpers/jest/matchers/toFailWith/predicate.js +16 -0
  67. package/dist/test/helpers/jest/matchers/toFailWithDetail/index.js +27 -0
  68. package/dist/test/helpers/jest/matchers/toFailWithDetail/predicate.js +22 -0
  69. package/dist/test/helpers/jest/matchers/toSucceed/index.js +23 -0
  70. package/dist/test/helpers/jest/matchers/toSucceed/predicate.js +5 -0
  71. package/dist/test/helpers/jest/matchers/toSucceedAndMatchInlineSnapshot/index.js +24 -0
  72. package/dist/test/helpers/jest/matchers/toSucceedAndMatchSnapshot/index.js +24 -0
  73. package/dist/test/helpers/jest/matchers/toSucceedAndSatisfy/index.js +53 -0
  74. package/dist/test/helpers/jest/matchers/toSucceedAndSatisfy/predicate.js +17 -0
  75. package/dist/test/helpers/jest/matchers/toSucceedWith/index.js +27 -0
  76. package/dist/test/helpers/jest/matchers/toSucceedWith/predicate.js +12 -0
  77. package/dist/test/helpers/jest/matchers/toSucceedWithDetail/index.js +27 -0
  78. package/dist/test/helpers/jest/matchers/toSucceedWithDetail/predicate.js +17 -0
  79. package/dist/test/helpers/jest/resolvers/cli.js +10 -0
  80. package/dist/test/helpers/jest/resolvers/ide.js +10 -0
  81. package/dist/test/helpers/jest/ts-utils.js +2 -0
  82. package/dist/test/helpers/jest/types/index.js +3 -0
  83. package/dist/test/helpers/jest/utils/matcherHelpers.js +47 -0
  84. package/dist/test/helpers/jest/utils/snapshotResolver.js +11 -0
  85. package/dist/test/unit/collections/helpers.js +106 -0
  86. package/dist/test/unit/hashTextEncodeCompat.js +23 -0
  87. package/dist/ts-utils.d.ts +28 -16
  88. package/dist/tsdoc-metadata.json +1 -1
  89. package/lib/packlets/base/result.d.ts +17 -12
  90. package/lib/packlets/base/result.js +20 -10
  91. package/lib/packlets/hash/crcNormalizer.js +42 -2
  92. package/lib/packlets/logging/logReporter.d.ts +11 -5
  93. package/lib/packlets/logging/logReporter.js +22 -9
  94. package/package.json +25 -15
@@ -145,8 +145,9 @@ class Success {
145
145
  */
146
146
  report(reporter, options) {
147
147
  var _a;
148
- const level = (_a = options === null || options === void 0 ? void 0 : options.success) !== null && _a !== void 0 ? _a : 'quiet';
149
- reporter === null || reporter === void 0 ? void 0 : reporter.reportSuccess(level, this._value);
148
+ const successOptions = typeof (options === null || options === void 0 ? void 0 : options.success) === 'object' ? options.success : { level: options === null || options === void 0 ? void 0 : options.success };
149
+ const level = (_a = successOptions.level) !== null && _a !== void 0 ? _a : 'quiet';
150
+ reporter === null || reporter === void 0 ? void 0 : reporter.reportSuccess(level, this._value, undefined, successOptions.message);
150
151
  return this;
151
152
  }
152
153
  /**
@@ -272,8 +273,9 @@ class Failure {
272
273
  */
273
274
  report(reporter, options) {
274
275
  var _a, _b, _c;
275
- const level = (_a = options === null || options === void 0 ? void 0 : options.failure) !== null && _a !== void 0 ? _a : 'error';
276
- const message = (_c = (_b = options === null || options === void 0 ? void 0 : options.message) === null || _b === void 0 ? void 0 : _b.call(options, this._message)) !== null && _c !== void 0 ? _c : this._message;
276
+ const failureOptions = typeof (options === null || options === void 0 ? void 0 : options.failure) === 'object' ? options.failure : { level: options === null || options === void 0 ? void 0 : options.failure };
277
+ const level = (_a = failureOptions.level) !== null && _a !== void 0 ? _a : 'error';
278
+ const message = (_c = (_b = failureOptions.message) === null || _b === void 0 ? void 0 : _b.call(failureOptions, this._message)) !== null && _c !== void 0 ? _c : this._message;
277
279
  reporter === null || reporter === void 0 ? void 0 : reporter.reportFailure(level, message);
278
280
  return this;
279
281
  }
@@ -411,8 +413,11 @@ class DetailedSuccess extends Success {
411
413
  */
412
414
  report(reporter, options) {
413
415
  var _a;
414
- const level = (_a = options === null || options === void 0 ? void 0 : options.success) !== null && _a !== void 0 ? _a : 'quiet';
415
- reporter === null || reporter === void 0 ? void 0 : reporter.reportSuccess(level, this._value, this._detail);
416
+ const successOptions = typeof (options === null || options === void 0 ? void 0 : options.success) === 'object' ? options.success : { level: options === null || options === void 0 ? void 0 : options.success };
417
+ const level = (_a = successOptions.level) !== null && _a !== void 0 ? _a : 'quiet';
418
+ // Cast reporter to preserve detail type when calling reportSuccess
419
+ const detailedReporter = reporter;
420
+ detailedReporter === null || detailedReporter === void 0 ? void 0 : detailedReporter.reportSuccess(level, this._value, this._detail, successOptions.message);
416
421
  return this;
417
422
  }
418
423
  /**
@@ -503,10 +508,15 @@ class DetailedFailure extends Failure {
503
508
  * {@inheritdoc IResult.report}
504
509
  */
505
510
  report(reporter, options) {
506
- var _a, _b, _c;
507
- const level = (_a = options === null || options === void 0 ? void 0 : options.failure) !== null && _a !== void 0 ? _a : 'error';
508
- const message = (_c = (_b = options === null || options === void 0 ? void 0 : options.message) === null || _b === void 0 ? void 0 : _b.call(options, this._message, this._detail)) !== null && _c !== void 0 ? _c : this._message;
509
- reporter === null || reporter === void 0 ? void 0 : reporter.reportFailure(level, message, this._detail);
511
+ var _a, _b;
512
+ const failureOptions = typeof (options === null || options === void 0 ? void 0 : options.failure) === 'object' ? options.failure : { level: options === null || options === void 0 ? void 0 : options.failure };
513
+ const level = (_a = failureOptions.level) !== null && _a !== void 0 ? _a : 'error';
514
+ // Cast formatter to handle detail type properly
515
+ const formatter = failureOptions.message;
516
+ const message = (_b = formatter === null || formatter === void 0 ? void 0 : formatter(this._message, this._detail)) !== null && _b !== void 0 ? _b : this._message;
517
+ // Cast reporter to preserve detail type when calling reportFailure
518
+ const detailedReporter = reporter;
519
+ detailedReporter === null || detailedReporter === void 0 ? void 0 : detailedReporter.reportFailure(level, message, this._detail);
510
520
  return this;
511
521
  }
512
522
  orThrow(logOrFormat) {
@@ -23,7 +23,47 @@
23
23
  Object.defineProperty(exports, "__esModule", { value: true });
24
24
  exports.Crc32Normalizer = void 0;
25
25
  const hashingNormalizer_1 = require("./hashingNormalizer");
26
- const textEncoder = new TextEncoder();
26
+ function encodeUtf8(input) {
27
+ // Prefer built-in TextEncoder when available (browsers and modern Node)
28
+ // @ts-ignore - global TextEncoder may be unavailable in some environments
29
+ const GlobalTextEncoder = typeof TextEncoder !== 'undefined' ? TextEncoder : undefined;
30
+ if (GlobalTextEncoder) {
31
+ return new GlobalTextEncoder().encode(input);
32
+ }
33
+ // Very small manual UTF-8 encoder as a last resort
34
+ /* eslint-disable no-bitwise */
35
+ const bytes = [];
36
+ for (let i = 0; i < input.length; i++) {
37
+ let codePoint = input.charCodeAt(i);
38
+ if (codePoint >= 0xd800 && codePoint <= 0xdbff && i + 1 < input.length) {
39
+ const next = input.charCodeAt(i + 1);
40
+ if (next >= 0xdc00 && next <= 0xdfff) {
41
+ codePoint = ((codePoint - 0xd800) << 10) + (next - 0xdc00) + 0x10000;
42
+ i++;
43
+ }
44
+ }
45
+ if (codePoint < 0x80) {
46
+ bytes.push(codePoint);
47
+ }
48
+ else if (codePoint < 0x800) {
49
+ bytes.push(0xc0 | (codePoint >> 6));
50
+ bytes.push(0x80 | (codePoint & 0x3f));
51
+ }
52
+ else if (codePoint < 0x10000) {
53
+ bytes.push(0xe0 | (codePoint >> 12));
54
+ bytes.push(0x80 | ((codePoint >> 6) & 0x3f));
55
+ bytes.push(0x80 | (codePoint & 0x3f));
56
+ }
57
+ else {
58
+ bytes.push(0xf0 | (codePoint >> 18));
59
+ bytes.push(0x80 | ((codePoint >> 12) & 0x3f));
60
+ bytes.push(0x80 | ((codePoint >> 6) & 0x3f));
61
+ bytes.push(0x80 | (codePoint & 0x3f));
62
+ }
63
+ }
64
+ /* eslint-enable no-bitwise */
65
+ return new Uint8Array(bytes);
66
+ }
27
67
  const POLYNOMIAL = 0xedb88320;
28
68
  const crc32Table = [];
29
69
  function crc32(bytes, crc = 0xffffffff) {
@@ -69,7 +109,7 @@ class Crc32Normalizer extends hashingNormalizer_1.HashingNormalizer {
69
109
  super(Crc32Normalizer.crc32Hash);
70
110
  }
71
111
  static crc32Hash(parts) {
72
- return crc32(textEncoder.encode(parts.join('|')))
112
+ return crc32(encodeUtf8(parts.join('|')))
73
113
  .toString(16)
74
114
  .padStart(8, '0');
75
115
  }
@@ -1,5 +1,5 @@
1
1
  import { ILogger, ReporterLogLevel } from './logger';
2
- import { IResultReporter, MessageLogLevel, Success } from '../base';
2
+ import { ErrorFormatter, IResultReporter, MessageLogLevel, Success } from '../base';
3
3
  /**
4
4
  * A function that formats a value for logging.
5
5
  * @public
@@ -26,10 +26,10 @@ export interface ILogReporterCreateParams<T, TD = unknown> {
26
26
  */
27
27
  export declare class LogReporter<T, TD = unknown> implements ILogger, IResultReporter<T, TD> {
28
28
  /**
29
- * The logger to wrap.
30
- * @internal
29
+ * Base logger used to by this reporter.
30
+ * @public
31
31
  */
32
- protected readonly _logger: ILogger;
32
+ readonly logger: ILogger;
33
33
  /**
34
34
  * The formatter to use for values.
35
35
  * @internal
@@ -72,11 +72,17 @@ export declare class LogReporter<T, TD = unknown> implements ILogger, IResultRep
72
72
  /**
73
73
  * {@inheritDoc IResultReporter.reportSuccess}
74
74
  */
75
- reportSuccess(level: MessageLogLevel, value: T, detail?: TD): void;
75
+ reportSuccess(level: MessageLogLevel, value: T, detail?: TD, message?: ErrorFormatter<TD>): void;
76
76
  /**
77
77
  * {@inheritDoc IResultReporter.reportFailure}
78
78
  */
79
79
  reportFailure(level: MessageLogLevel, message: string, detail?: TD): void;
80
+ /**
81
+ * Creates a new {@link Logging.LogReporter | LogReporter} with the same logger but a different value formatter.
82
+ * @param valueFormatter - The value formatter to use.
83
+ * @returns A new {@link Logging.LogReporter | LogReporter} with the same logger but a different value formatter.
84
+ */
85
+ withValueFormatter<TN>(valueFormatter: LogValueFormatter<TN, TD>): LogReporter<TN, TD>;
80
86
  /**
81
87
  * Generic method to try to format an object for logging.
82
88
  * @param value - The value to format.
@@ -37,7 +37,7 @@ class LogReporter {
37
37
  var _a, _b, _c;
38
38
  /* c8 ignore next 1 */
39
39
  params = params !== null && params !== void 0 ? params : {};
40
- this._logger = (_a = params.logger) !== null && _a !== void 0 ? _a : new logger_1.NoOpLogger();
40
+ this.logger = (_a = params.logger) !== null && _a !== void 0 ? _a : new logger_1.NoOpLogger();
41
41
  this._valueFormatter = (_b = params.valueFormatter) !== null && _b !== void 0 ? _b : LogReporter.tryFormatObject;
42
42
  this._messageFormatter = (_c = params.messageFormatter) !== null && _c !== void 0 ? _c : ((message, __detail) => message);
43
43
  }
@@ -45,43 +45,44 @@ class LogReporter {
45
45
  * {@inheritDoc Logging.ILogger.logLevel}
46
46
  */
47
47
  get logLevel() {
48
- return this._logger.logLevel;
48
+ return this.logger.logLevel;
49
49
  }
50
50
  /**
51
51
  * {@inheritDoc Logging.ILogger.detail}
52
52
  */
53
53
  detail(message, ...parameters) {
54
- return this._logger.detail(message, ...parameters);
54
+ return this.logger.detail(message, ...parameters);
55
55
  }
56
56
  /**
57
57
  * {@inheritDoc Logging.ILogger.info}
58
58
  */
59
59
  info(message, ...parameters) {
60
- return this._logger.info(message, ...parameters);
60
+ return this.logger.info(message, ...parameters);
61
61
  }
62
62
  /**
63
63
  * {@inheritDoc Logging.ILogger.warn}
64
64
  */
65
65
  warn(message, ...parameters) {
66
- return this._logger.warn(message, ...parameters);
66
+ return this.logger.warn(message, ...parameters);
67
67
  }
68
68
  /**
69
69
  * {@inheritDoc Logging.ILogger.error}
70
70
  */
71
71
  error(message, ...parameters) {
72
- return this._logger.error(message, ...parameters);
72
+ return this.logger.error(message, ...parameters);
73
73
  }
74
74
  /**
75
75
  * {@inheritDoc Logging.ILogger.log}
76
76
  */
77
77
  log(level, message, ...parameters) {
78
- return this._logger.log(level, message, ...parameters);
78
+ return this.logger.log(level, message, ...parameters);
79
79
  }
80
80
  /**
81
81
  * {@inheritDoc IResultReporter.reportSuccess}
82
82
  */
83
- reportSuccess(level, value, detail) {
84
- const formatted = this._valueFormatter(value, detail);
83
+ reportSuccess(level, value, detail, message) {
84
+ const formattedValue = this._valueFormatter(value, detail);
85
+ const formatted = message ? message(formattedValue, detail) : formattedValue;
85
86
  this.log(level, formatted);
86
87
  }
87
88
  /**
@@ -91,6 +92,18 @@ class LogReporter {
91
92
  const formatted = this._messageFormatter(message, detail);
92
93
  this.log(level, formatted);
93
94
  }
95
+ /**
96
+ * Creates a new {@link Logging.LogReporter | LogReporter} with the same logger but a different value formatter.
97
+ * @param valueFormatter - The value formatter to use.
98
+ * @returns A new {@link Logging.LogReporter | LogReporter} with the same logger but a different value formatter.
99
+ */
100
+ withValueFormatter(valueFormatter) {
101
+ return new LogReporter({
102
+ logger: this.logger,
103
+ valueFormatter,
104
+ messageFormatter: this._messageFormatter
105
+ });
106
+ }
94
107
  /**
95
108
  * Generic method to try to format an object for logging.
96
109
  * @param value - The value to format.
package/package.json CHANGED
@@ -1,9 +1,18 @@
1
1
  {
2
2
  "name": "@fgv/ts-utils",
3
- "version": "5.0.1-0",
3
+ "version": "5.0.1-10",
4
4
  "description": "Assorted Typescript Utilities",
5
5
  "main": "lib/index.js",
6
+ "module": "dist/index.js",
6
7
  "types": "dist/ts-utils.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/ts-utils.d.ts",
11
+ "import": "./dist/index.js",
12
+ "require": "./lib/index.js",
13
+ "default": "./lib/index.js"
14
+ }
15
+ },
7
16
  "sideEffects": false,
8
17
  "keywords": [
9
18
  "typescript",
@@ -17,33 +26,34 @@
17
26
  "homepage": "https://github.com/ErikFortune/fgv/tree/main/libraries/ts-utils#readme",
18
27
  "devDependencies": {
19
28
  "@jest/expect-utils": "^29.7.0",
20
- "@microsoft/api-documenter": "^7.26.31",
21
- "@microsoft/api-extractor": "^7.52.10",
29
+ "@microsoft/api-documenter": "^7.27.3",
30
+ "@microsoft/api-extractor": "^7.53.3",
22
31
  "@types/jest": "^29.5.14",
23
32
  "@types/luxon": "^3.7.1",
24
33
  "@types/mustache": "^4.2.5",
25
34
  "@types/node": "^20.14.9",
26
- "@typescript-eslint/eslint-plugin": "^8.42.0",
27
- "@typescript-eslint/parser": "^8.42.0",
28
- "eslint": "^9.35.0",
35
+ "@typescript-eslint/eslint-plugin": "^8.46.2",
36
+ "@typescript-eslint/parser": "^8.46.2",
37
+ "eslint": "^9.39.0",
29
38
  "eslint-plugin-import": "^2.32.0",
30
39
  "eslint-plugin-node": "^11.1.0",
31
40
  "eslint-plugin-promise": "^7.2.1",
32
41
  "jest": "^29.7.0",
33
42
  "jest-extended": "^4.0.2",
34
43
  "jest-matcher-utils": "^29.7.0",
35
- "rimraf": "^6.0.1",
36
- "ts-jest": "^29.4.1",
44
+ "rimraf": "^6.1.0",
45
+ "ts-jest": "^29.4.5",
37
46
  "ts-node": "^10.9.2",
38
- "typescript": "5.8.3",
39
- "eslint-plugin-n": "^17.21.3",
47
+ "typescript": "5.9.3",
48
+ "eslint-plugin-n": "^17.23.1",
40
49
  "jest-snapshot": "~29.7.0",
41
- "@rushstack/heft": "0.74.4",
42
- "@rushstack/heft-node-rig": "2.9.5",
43
- "@rushstack/eslint-config": "4.4.0",
50
+ "@rushstack/heft": "1.1.3",
51
+ "@rushstack/heft-node-rig": "2.11.4",
52
+ "@rushstack/eslint-config": "4.5.3",
44
53
  "@types/heft-jest": "1.0.6",
45
- "@rushstack/heft-jest-plugin": "0.16.13",
46
- "eslint-plugin-tsdoc": "~0.4.0"
54
+ "@rushstack/heft-jest-plugin": "1.1.3",
55
+ "eslint-plugin-tsdoc": "~0.4.0",
56
+ "@fgv/heft-dual-rig": "0.1.0"
47
57
  },
48
58
  "scripts": {
49
59
  "build": "heft build --clean",