@fgv/ts-utils 5.0.2 → 5.1.0-1
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/README.md +152 -84
- package/dist/index.js +2 -2
- package/dist/packlets/base/messageAggregator.js +6 -6
- package/dist/packlets/base/result.js +39 -39
- package/dist/packlets/base/utils.js +47 -0
- package/dist/packlets/collections/aggregatedResultMap.js +722 -0
- package/dist/packlets/collections/collector.js +9 -9
- package/dist/packlets/collections/collectorValidator.js +4 -4
- package/dist/packlets/collections/converters.js +39 -0
- package/dist/packlets/collections/convertingCollectorValidator.js +3 -3
- package/dist/packlets/collections/convertingResultMap.js +208 -0
- package/dist/packlets/collections/index.js +4 -0
- package/dist/packlets/collections/keyValueConverters.js +1 -4
- package/dist/packlets/collections/readOnlyConvertingResultMap.js +193 -0
- package/dist/packlets/collections/resultMapValidator.js +50 -6
- package/dist/packlets/collections/validatingConvertingResultMap.js +78 -0
- package/dist/packlets/conversion/advancedConverters.js +249 -0
- package/dist/packlets/conversion/baseConverter.js +23 -16
- package/dist/packlets/conversion/basicConverters.js +571 -0
- package/dist/packlets/conversion/converters.js +3 -617
- package/dist/packlets/conversion/defaultingConverter.js +21 -15
- package/dist/packlets/logging/bootLogger.js +122 -0
- package/dist/packlets/logging/index.js +1 -0
- package/dist/packlets/logging/logReporter.js +32 -1
- package/dist/packlets/logging/logger.js +25 -5
- package/dist/packlets/validation/classes.js +1 -0
- package/dist/packlets/validation/compositeId.js +60 -0
- package/dist/packlets/validation/field.js +1 -1
- package/dist/packlets/validation/genericValidator.js +24 -10
- package/dist/packlets/validation/object.js +3 -6
- package/dist/packlets/validation/validators.js +12 -0
- package/dist/ts-utils.d.ts +1633 -200
- package/dist/tsdoc-metadata.json +1 -1
- package/lib/index.d.ts +2 -2
- package/lib/index.js +2 -1
- package/lib/packlets/base/mapResults.d.ts +3 -3
- package/lib/packlets/base/messageAggregator.d.ts +6 -6
- package/lib/packlets/base/messageAggregator.js +6 -6
- package/lib/packlets/base/result.d.ts +74 -51
- package/lib/packlets/base/result.js +39 -39
- package/lib/packlets/base/utils.d.ts +42 -0
- package/lib/packlets/base/utils.js +52 -0
- package/lib/packlets/collections/aggregatedResultMap.d.ts +433 -0
- package/lib/packlets/collections/aggregatedResultMap.js +728 -0
- package/lib/packlets/collections/collector.d.ts +11 -10
- package/lib/packlets/collections/collector.js +9 -9
- package/lib/packlets/collections/collectorValidator.d.ts +12 -10
- package/lib/packlets/collections/collectorValidator.js +4 -4
- package/lib/packlets/collections/converters.d.ts +18 -0
- package/lib/packlets/collections/converters.js +42 -0
- package/lib/packlets/collections/convertingCollector.d.ts +4 -4
- package/lib/packlets/collections/convertingCollectorValidator.d.ts +10 -7
- package/lib/packlets/collections/convertingCollectorValidator.js +3 -3
- package/lib/packlets/collections/convertingResultMap.d.ts +176 -0
- package/lib/packlets/collections/convertingResultMap.js +213 -0
- package/lib/packlets/collections/index.d.ts +4 -0
- package/lib/packlets/collections/index.js +4 -0
- package/lib/packlets/collections/keyValueConverters.d.ts +1 -4
- package/lib/packlets/collections/keyValueConverters.js +1 -4
- package/lib/packlets/collections/readOnlyConvertingResultMap.d.ts +153 -0
- package/lib/packlets/collections/readOnlyConvertingResultMap.js +197 -0
- package/lib/packlets/collections/readonlyResultMap.d.ts +7 -7
- package/lib/packlets/collections/resultMap.d.ts +108 -2
- package/lib/packlets/collections/resultMapValidator.d.ts +45 -11
- package/lib/packlets/collections/resultMapValidator.js +52 -7
- package/lib/packlets/collections/validatingCollector.d.ts +5 -5
- package/lib/packlets/collections/validatingConvertingCollector.d.ts +3 -3
- package/lib/packlets/collections/validatingConvertingResultMap.d.ts +102 -0
- package/lib/packlets/collections/validatingConvertingResultMap.js +83 -0
- package/lib/packlets/collections/validatingResultMap.d.ts +1 -1
- package/lib/packlets/conversion/advancedConverters.d.ts +170 -0
- package/lib/packlets/conversion/advancedConverters.js +258 -0
- package/lib/packlets/conversion/baseConverter.d.ts +39 -23
- package/lib/packlets/conversion/baseConverter.js +23 -16
- package/lib/packlets/conversion/basicConverters.d.ts +470 -0
- package/lib/packlets/conversion/basicConverters.js +595 -0
- package/lib/packlets/conversion/converter.d.ts +7 -0
- package/lib/packlets/conversion/converters.d.ts +2 -535
- package/lib/packlets/conversion/converters.js +17 -639
- package/lib/packlets/conversion/defaultingConverter.d.ts +20 -16
- package/lib/packlets/conversion/defaultingConverter.js +21 -15
- package/lib/packlets/logging/bootLogger.d.ts +84 -0
- package/lib/packlets/logging/bootLogger.js +126 -0
- package/lib/packlets/logging/index.d.ts +1 -0
- package/lib/packlets/logging/index.js +1 -0
- package/lib/packlets/logging/logReporter.d.ts +18 -3
- package/lib/packlets/logging/logReporter.js +31 -0
- package/lib/packlets/logging/logger.d.ts +39 -6
- package/lib/packlets/logging/logger.js +26 -5
- package/lib/packlets/validation/classes.d.ts +1 -0
- package/lib/packlets/validation/classes.js +3 -1
- package/lib/packlets/validation/compositeId.d.ts +29 -0
- package/lib/packlets/validation/compositeId.js +64 -0
- package/lib/packlets/validation/field.d.ts +1 -1
- package/lib/packlets/validation/field.js +1 -1
- package/lib/packlets/validation/genericValidator.d.ts +15 -11
- package/lib/packlets/validation/genericValidator.js +24 -10
- package/lib/packlets/validation/object.d.ts +3 -6
- package/lib/packlets/validation/object.js +3 -6
- package/lib/packlets/validation/traits.d.ts +3 -3
- package/lib/packlets/validation/validator.d.ts +7 -0
- package/lib/packlets/validation/validators.d.ts +10 -0
- package/lib/packlets/validation/validators.js +13 -0
- package/package.json +27 -27
|
@@ -27,13 +27,13 @@ import { succeed } from '../base';
|
|
|
27
27
|
*/
|
|
28
28
|
export class GenericDefaultingConverter {
|
|
29
29
|
/**
|
|
30
|
-
* {@
|
|
30
|
+
* {@inheritDoc Converter.isOptional}
|
|
31
31
|
*/
|
|
32
32
|
get isOptional() {
|
|
33
33
|
return this._converter.isOptional;
|
|
34
34
|
}
|
|
35
35
|
/**
|
|
36
|
-
* {@
|
|
36
|
+
* {@inheritDoc Converter.isOptional}
|
|
37
37
|
*/
|
|
38
38
|
get brand() {
|
|
39
39
|
return this._converter.brand;
|
|
@@ -48,13 +48,13 @@ export class GenericDefaultingConverter {
|
|
|
48
48
|
this._converter = converter;
|
|
49
49
|
}
|
|
50
50
|
/**
|
|
51
|
-
* {@
|
|
51
|
+
* {@inheritDoc Converter.convert}
|
|
52
52
|
*/
|
|
53
53
|
convert(from, ctx) {
|
|
54
54
|
return this._applyDefault(this._converter.convert(from, ctx));
|
|
55
55
|
}
|
|
56
56
|
/**
|
|
57
|
-
* {@
|
|
57
|
+
* {@inheritDoc Converter.convertOptional}
|
|
58
58
|
*/
|
|
59
59
|
convertOptional(from, context, onError) {
|
|
60
60
|
const converted = this._converter.convertOptional(from, context, onError);
|
|
@@ -64,7 +64,7 @@ export class GenericDefaultingConverter {
|
|
|
64
64
|
return converted;
|
|
65
65
|
}
|
|
66
66
|
/**
|
|
67
|
-
* {@
|
|
67
|
+
* {@inheritDoc Converter.optional}
|
|
68
68
|
*/
|
|
69
69
|
optional(onError) {
|
|
70
70
|
// need to let the inner converter do its optional thing first or our default
|
|
@@ -72,61 +72,61 @@ export class GenericDefaultingConverter {
|
|
|
72
72
|
return this._converter.optional(onError).withAction((result) => this._applyDefault(result));
|
|
73
73
|
}
|
|
74
74
|
/**
|
|
75
|
-
* {@
|
|
75
|
+
* {@inheritDoc Converter.map}
|
|
76
76
|
*/
|
|
77
77
|
map(mapper) {
|
|
78
78
|
return this._converter.withAction((result) => this._applyDefault(result)).map(mapper);
|
|
79
79
|
}
|
|
80
80
|
/**
|
|
81
|
-
* {@
|
|
81
|
+
* {@inheritDoc Converter.mapConvert}
|
|
82
82
|
*/
|
|
83
83
|
mapConvert(mapConverter) {
|
|
84
84
|
return this._converter.withAction((result) => this._applyDefault(result)).mapConvert(mapConverter);
|
|
85
85
|
}
|
|
86
86
|
/**
|
|
87
|
-
* {@
|
|
87
|
+
* {@inheritDoc Converter.mapItems}
|
|
88
88
|
*/
|
|
89
89
|
mapItems(mapper) {
|
|
90
90
|
return this._converter.withAction((result) => this._applyDefault(result)).mapItems(mapper);
|
|
91
91
|
}
|
|
92
92
|
/**
|
|
93
|
-
* {@
|
|
93
|
+
* {@inheritDoc Converter.mapConvertItems}
|
|
94
94
|
*/
|
|
95
95
|
mapConvertItems(mapConverter) {
|
|
96
96
|
return this._converter.withAction((result) => this._applyDefault(result)).mapConvertItems(mapConverter);
|
|
97
97
|
}
|
|
98
98
|
/**
|
|
99
|
-
* {@
|
|
99
|
+
* {@inheritDoc Converter.withAction}
|
|
100
100
|
*/
|
|
101
101
|
withAction(action) {
|
|
102
102
|
return this._converter.withAction((result) => this._applyDefault(result)).withAction(action);
|
|
103
103
|
}
|
|
104
104
|
/**
|
|
105
|
-
* {@
|
|
105
|
+
* {@inheritDoc Converter.withTypeGuard}
|
|
106
106
|
*/
|
|
107
107
|
withTypeGuard(guard, message) {
|
|
108
108
|
return this._converter.withAction((result) => this._applyDefault(result)).withTypeGuard(guard);
|
|
109
109
|
}
|
|
110
110
|
/**
|
|
111
|
-
* {@
|
|
111
|
+
* {@inheritDoc Converter.withItemTypeGuard}
|
|
112
112
|
*/
|
|
113
113
|
withItemTypeGuard(guard, message) {
|
|
114
114
|
return this._converter.withAction((result) => this._applyDefault(result)).withItemTypeGuard(guard);
|
|
115
115
|
}
|
|
116
116
|
/**
|
|
117
|
-
* {@
|
|
117
|
+
* {@inheritDoc Converter.withConstraint}
|
|
118
118
|
*/
|
|
119
119
|
withConstraint(constraint, options) {
|
|
120
120
|
return this._converter.withAction((result) => this._applyDefault(result)).withConstraint(constraint);
|
|
121
121
|
}
|
|
122
122
|
/**
|
|
123
|
-
* {@
|
|
123
|
+
* {@inheritDoc Converter.withBrand}
|
|
124
124
|
*/
|
|
125
125
|
withBrand(brand) {
|
|
126
126
|
return this._converter.withAction((result) => this._applyDefault(result)).withBrand(brand);
|
|
127
127
|
}
|
|
128
128
|
/**
|
|
129
|
-
* {@
|
|
129
|
+
* {@inheritDoc Converter.withFormattedError}
|
|
130
130
|
*/
|
|
131
131
|
withFormattedError(formatter) {
|
|
132
132
|
// formatter should never actually be invoked for a defaulting converter
|
|
@@ -142,6 +142,12 @@ export class GenericDefaultingConverter {
|
|
|
142
142
|
withDefault(dflt) {
|
|
143
143
|
return new GenericDefaultingConverter(this._converter, dflt);
|
|
144
144
|
}
|
|
145
|
+
/**
|
|
146
|
+
* {@inheritDoc Converter.or}
|
|
147
|
+
*/
|
|
148
|
+
or(__converter) {
|
|
149
|
+
return this;
|
|
150
|
+
}
|
|
145
151
|
_applyDefault(converted) {
|
|
146
152
|
return converted.success ? converted : succeed(this.defaultValue);
|
|
147
153
|
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { InMemoryLogger, isDetailLogger } from './logger';
|
|
2
|
+
/**
|
|
3
|
+
* A logger that buffers log entries during startup, then replays them
|
|
4
|
+
* to a real logger once it becomes available.
|
|
5
|
+
*
|
|
6
|
+
* @remarks
|
|
7
|
+
* During application bootstrap, the real logger (e.g. one backed by
|
|
8
|
+
* toast notifications) may not be available yet. `BootLogger` solves
|
|
9
|
+
* this by:
|
|
10
|
+
* 1. Buffering all log calls in memory during the boot phase.
|
|
11
|
+
* 2. When {@link BootLogger.ready | ready()} is called with the real
|
|
12
|
+
* logger, replaying all buffered entries and then forwarding all
|
|
13
|
+
* subsequent calls directly.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* // Create early, before the real logger exists
|
|
18
|
+
* const bootLogger = new BootLogger('detail');
|
|
19
|
+
* bootLogger.info('Starting up...');
|
|
20
|
+
*
|
|
21
|
+
* // Later, when the real logger is available
|
|
22
|
+
* bootLogger.ready(realLogger);
|
|
23
|
+
* // 'Starting up...' is replayed to realLogger
|
|
24
|
+
* // All future calls go directly to realLogger
|
|
25
|
+
* ```
|
|
26
|
+
*
|
|
27
|
+
* @public
|
|
28
|
+
*/
|
|
29
|
+
export class BootLogger {
|
|
30
|
+
/**
|
|
31
|
+
* Creates a new boot logger.
|
|
32
|
+
* @param logLevel - The log level for the initial in-memory buffer phase.
|
|
33
|
+
* Defaults to 'detail' to capture everything during boot.
|
|
34
|
+
*/
|
|
35
|
+
constructor(logLevel) {
|
|
36
|
+
this._buffer = [];
|
|
37
|
+
this._isReady = false;
|
|
38
|
+
this._delegate = new InMemoryLogger(logLevel !== null && logLevel !== void 0 ? logLevel : 'detail');
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* {@inheritDoc Logging.ILogger.logLevel}
|
|
42
|
+
*/
|
|
43
|
+
get logLevel() {
|
|
44
|
+
return this._delegate.logLevel;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Whether the boot logger has been connected to a real logger.
|
|
48
|
+
*/
|
|
49
|
+
get isReady() {
|
|
50
|
+
return this._isReady;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Connects this boot logger to a real logger.
|
|
54
|
+
* All buffered entries are replayed to the new logger in order,
|
|
55
|
+
* and all subsequent calls are forwarded directly.
|
|
56
|
+
* @param logger - The real logger to forward to.
|
|
57
|
+
*/
|
|
58
|
+
ready(logger) {
|
|
59
|
+
// Replay buffered entries
|
|
60
|
+
for (const entry of this._buffer) {
|
|
61
|
+
logger.log(entry.level, entry.message, ...entry.parameters);
|
|
62
|
+
}
|
|
63
|
+
// Switch to the real logger and discard the buffer
|
|
64
|
+
this._delegate = logger;
|
|
65
|
+
this._buffer = [];
|
|
66
|
+
this._isReady = true;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* {@inheritDoc Logging.ILogger.log}
|
|
70
|
+
*/
|
|
71
|
+
log(level, message, ...parameters) {
|
|
72
|
+
if (!this._isReady) {
|
|
73
|
+
this._buffer.push({ level, message, parameters });
|
|
74
|
+
}
|
|
75
|
+
return this._delegate.log(level, message, ...parameters);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* {@inheritDoc Logging.ILogger.detail}
|
|
79
|
+
*/
|
|
80
|
+
detail(message, ...parameters) {
|
|
81
|
+
return this.log('detail', message, ...parameters);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* {@inheritDoc Logging.ILogger.info}
|
|
85
|
+
*/
|
|
86
|
+
info(message, ...parameters) {
|
|
87
|
+
return this.log('info', message, ...parameters);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* {@inheritDoc Logging.ILogger.warn}
|
|
91
|
+
*/
|
|
92
|
+
warn(message, ...parameters) {
|
|
93
|
+
return this.log('warning', message, ...parameters);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* {@inheritDoc Logging.ILogger.error}
|
|
97
|
+
*/
|
|
98
|
+
error(message, ...parameters) {
|
|
99
|
+
return this.log('error', message, ...parameters);
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* {@inheritDoc Logging.IDetailLogger.errorWithDetail}
|
|
103
|
+
*/
|
|
104
|
+
errorWithDetail(message, detail) {
|
|
105
|
+
if (isDetailLogger(this._delegate)) {
|
|
106
|
+
return this._delegate.errorWithDetail(message, detail);
|
|
107
|
+
}
|
|
108
|
+
this.log('detail', detail);
|
|
109
|
+
return this.log('error', message);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* {@inheritDoc Logging.IDetailLogger.warnWithDetail}
|
|
113
|
+
*/
|
|
114
|
+
warnWithDetail(message, detail) {
|
|
115
|
+
if (isDetailLogger(this._delegate)) {
|
|
116
|
+
return this._delegate.warnWithDetail(message, detail);
|
|
117
|
+
}
|
|
118
|
+
this.log('detail', detail);
|
|
119
|
+
return this.log('warning', message);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=bootLogger.js.map
|
|
@@ -19,7 +19,8 @@
|
|
|
19
19
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
20
20
|
* SOFTWARE.
|
|
21
21
|
*/
|
|
22
|
-
import { NoOpLogger, stringifyLogValue } from './logger';
|
|
22
|
+
import { isDetailLogger, NoOpLogger, stringifyLogValue } from './logger';
|
|
23
|
+
import { captureResult } from '../base';
|
|
23
24
|
/**
|
|
24
25
|
* Abstract base class which wraps an existing {@link Logging.ILogger | ILogger} to implement
|
|
25
26
|
* both {@link Logging.ILogger | ILogger} and {@link IResultReporter | IResultReporter}.
|
|
@@ -38,6 +39,16 @@ export class LogReporter {
|
|
|
38
39
|
this._valueFormatter = (_b = params.valueFormatter) !== null && _b !== void 0 ? _b : LogReporter.tryFormatObject;
|
|
39
40
|
this._messageFormatter = (_c = params.messageFormatter) !== null && _c !== void 0 ? _c : ((message, __detail) => message);
|
|
40
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* Creates a default {@link Logging.LogReporter | LogReporter} with a {@link Logging.NoOpLogger | NoOpLogger} with the
|
|
44
|
+
* supplied parameters, returning both the logger and reporter.
|
|
45
|
+
* @param logger - Optional logger to use; defaults to a new {@link Logging.NoOpLogger | NoOpLogger} if not provided.
|
|
46
|
+
* @returns
|
|
47
|
+
*/
|
|
48
|
+
static createDefault(logger) {
|
|
49
|
+
logger = logger !== null && logger !== void 0 ? logger : new NoOpLogger();
|
|
50
|
+
return captureResult(() => new LogReporter({ logger }));
|
|
51
|
+
}
|
|
41
52
|
/**
|
|
42
53
|
* {@inheritDoc Logging.ILogger.logLevel}
|
|
43
54
|
*/
|
|
@@ -68,6 +79,26 @@ export class LogReporter {
|
|
|
68
79
|
error(message, ...parameters) {
|
|
69
80
|
return this.logger.error(message, ...parameters);
|
|
70
81
|
}
|
|
82
|
+
/**
|
|
83
|
+
* {@inheritDoc Logging.IDetailLogger.errorWithDetail}
|
|
84
|
+
*/
|
|
85
|
+
errorWithDetail(message, detail) {
|
|
86
|
+
if (isDetailLogger(this.logger)) {
|
|
87
|
+
return this.logger.errorWithDetail(message, detail);
|
|
88
|
+
}
|
|
89
|
+
this.logger.detail(detail);
|
|
90
|
+
return this.logger.error(message);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* {@inheritDoc Logging.IDetailLogger.warnWithDetail}
|
|
94
|
+
*/
|
|
95
|
+
warnWithDetail(message, detail) {
|
|
96
|
+
if (isDetailLogger(this.logger)) {
|
|
97
|
+
return this.logger.warnWithDetail(message, detail);
|
|
98
|
+
}
|
|
99
|
+
this.logger.detail(detail);
|
|
100
|
+
return this.logger.warn(message);
|
|
101
|
+
}
|
|
71
102
|
/**
|
|
72
103
|
* {@inheritDoc Logging.ILogger.log}
|
|
73
104
|
*/
|
|
@@ -70,7 +70,17 @@ export function stringifyLogValue(value, maxLength) {
|
|
|
70
70
|
return str;
|
|
71
71
|
}
|
|
72
72
|
/**
|
|
73
|
-
*
|
|
73
|
+
* Type guard that checks whether a logger implements {@link IDetailLogger}.
|
|
74
|
+
* @param logger - The logger to check.
|
|
75
|
+
* @returns `true` if the logger implements `IDetailLogger`.
|
|
76
|
+
* @public
|
|
77
|
+
*/
|
|
78
|
+
export function isDetailLogger(logger) {
|
|
79
|
+
return (typeof logger.errorWithDetail === 'function' &&
|
|
80
|
+
typeof logger.warnWithDetail === 'function');
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Abstract base class which implements {@link Logging.IDetailLogger | IDetailLogger}.
|
|
74
84
|
* @public
|
|
75
85
|
*/
|
|
76
86
|
export class LoggerBase {
|
|
@@ -105,6 +115,20 @@ export class LoggerBase {
|
|
|
105
115
|
error(message, ...parameters) {
|
|
106
116
|
return this.log('error', message, ...parameters);
|
|
107
117
|
}
|
|
118
|
+
/**
|
|
119
|
+
* {@inheritDoc Logging.IDetailLogger.errorWithDetail}
|
|
120
|
+
*/
|
|
121
|
+
errorWithDetail(message, detail) {
|
|
122
|
+
this.detail(detail);
|
|
123
|
+
return this.error(message);
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* {@inheritDoc Logging.IDetailLogger.warnWithDetail}
|
|
127
|
+
*/
|
|
128
|
+
warnWithDetail(message, detail) {
|
|
129
|
+
this.detail(detail);
|
|
130
|
+
return this.warn(message);
|
|
131
|
+
}
|
|
108
132
|
/**
|
|
109
133
|
* {@inheritDoc Logging.ILogger.log}
|
|
110
134
|
*/
|
|
@@ -188,10 +212,6 @@ export class InMemoryLogger extends LoggerBase {
|
|
|
188
212
|
}
|
|
189
213
|
/**
|
|
190
214
|
* {@inheritDoc Logging.LoggerBase._suppressLog}
|
|
191
|
-
* @param level - The level of the message.
|
|
192
|
-
* @param message - The message to suppress.
|
|
193
|
-
* @param parameters - The parameters to suppress.
|
|
194
|
-
* @returns `Success` with `undefined` if the message is suppressed.
|
|
195
215
|
* @internal
|
|
196
216
|
*/
|
|
197
217
|
_suppressLog(level, message, ...parameters) {
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
/* c8 ignore start */
|
|
23
23
|
export { ArrayValidator } from './array';
|
|
24
24
|
export { BooleanValidator } from './boolean';
|
|
25
|
+
export { CompositeIdValidator } from './compositeId';
|
|
25
26
|
export { NumberValidator } from './number';
|
|
26
27
|
export { ObjectValidator } from './object';
|
|
27
28
|
export { OneOfValidator } from './oneOf';
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2026 Erik Fortune
|
|
3
|
+
*
|
|
4
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
6
|
+
* in the Software without restriction, including without limitation the rights
|
|
7
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
8
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
9
|
+
* furnished to do so, subject to the following conditions:
|
|
10
|
+
*
|
|
11
|
+
* The above copyright notice and this permission notice shall be included in all
|
|
12
|
+
* copies or substantial portions of the Software.
|
|
13
|
+
*
|
|
14
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
15
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
16
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
17
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
18
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
19
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
20
|
+
* SOFTWARE.
|
|
21
|
+
*/
|
|
22
|
+
import { Failure, fail } from '../base';
|
|
23
|
+
import { ValidatorBase } from './validatorBase';
|
|
24
|
+
/**
|
|
25
|
+
* An in-place {@link Validation.Validator | Validator} for a strongly-typed composite ID.
|
|
26
|
+
* @public
|
|
27
|
+
*/
|
|
28
|
+
export class CompositeIdValidator extends ValidatorBase {
|
|
29
|
+
/**
|
|
30
|
+
* Constructs a new {@link Validation.Classes.StringValidator | StringValidator}.
|
|
31
|
+
* @param params - Optional {@link Validation.Classes.StringValidatorConstructorParams | init params}
|
|
32
|
+
* for the new {@link Validation.Classes.StringValidator | StringValidator}.
|
|
33
|
+
*/
|
|
34
|
+
constructor(params) {
|
|
35
|
+
/* c8 ignore next */
|
|
36
|
+
super(Object.assign({}, params));
|
|
37
|
+
const { collectionId, separator, itemId } = params;
|
|
38
|
+
this._collectionIdValidator = collectionId.withFormattedError((value, err) => `${value}: invalid composite collection ID (${err}).`);
|
|
39
|
+
this._itemIdValidator = itemId.withFormattedError((value, err) => `${value}: invalid composite item ID (${err}).`);
|
|
40
|
+
this._separator = separator;
|
|
41
|
+
}
|
|
42
|
+
_validate(value, context) {
|
|
43
|
+
if (typeof value !== 'string') {
|
|
44
|
+
return fail(`${value}: invalid non-string composite ID.`);
|
|
45
|
+
}
|
|
46
|
+
const parts = value.split(this._separator);
|
|
47
|
+
if (parts.length < 2) {
|
|
48
|
+
return fail(`${value}: invalid composite ID - separator '${this._separator}' not found.`);
|
|
49
|
+
}
|
|
50
|
+
else if (parts.length > 2) {
|
|
51
|
+
return fail(`${value}: invalid composite ID - multiple separators '${this._separator}.' found.`);
|
|
52
|
+
}
|
|
53
|
+
const [collectionId, itemId] = parts;
|
|
54
|
+
const result = this._collectionIdValidator
|
|
55
|
+
.validate(collectionId, context)
|
|
56
|
+
.onSuccess(() => this._itemIdValidator.validate(itemId, context));
|
|
57
|
+
return result.isSuccess() ? true : Failure.with(`${value}: invalid composite ID - ${result.message}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=compositeId.js.map
|
|
@@ -43,7 +43,7 @@ export class FieldValidator extends ValidatorBase {
|
|
|
43
43
|
this._fieldOptions = options !== null && options !== void 0 ? options : {};
|
|
44
44
|
}
|
|
45
45
|
/**
|
|
46
|
-
* {@
|
|
46
|
+
* {@inheritDoc Validation.ValidatorBase._validate}
|
|
47
47
|
*/
|
|
48
48
|
_validate(from, context, self) {
|
|
49
49
|
if (typeof from === 'object' && !Array.isArray(from) && from !== null) {
|
|
@@ -41,19 +41,19 @@ export class GenericValidator {
|
|
|
41
41
|
this.traits = new ValidatorTraits(params.traits);
|
|
42
42
|
}
|
|
43
43
|
/**
|
|
44
|
-
* {@
|
|
44
|
+
* {@inheritDoc Validation.Validator.isOptional}
|
|
45
45
|
*/
|
|
46
46
|
get isOptional() {
|
|
47
47
|
return this.traits.isOptional;
|
|
48
48
|
}
|
|
49
49
|
/**
|
|
50
|
-
* {@
|
|
50
|
+
* {@inheritDoc Validation.Validator.brand}
|
|
51
51
|
*/
|
|
52
52
|
get brand() {
|
|
53
53
|
return this.traits.brand;
|
|
54
54
|
}
|
|
55
55
|
/**
|
|
56
|
-
* {@
|
|
56
|
+
* {@inheritDoc Validation.Validator.validate}
|
|
57
57
|
*/
|
|
58
58
|
validate(from, context) {
|
|
59
59
|
const result = this._validator(from, this._context(context), this);
|
|
@@ -63,7 +63,7 @@ export class GenericValidator {
|
|
|
63
63
|
return result;
|
|
64
64
|
}
|
|
65
65
|
/**
|
|
66
|
-
* {@
|
|
66
|
+
* {@inheritDoc Validation.Validator.convert}
|
|
67
67
|
*/
|
|
68
68
|
convert(from, context) {
|
|
69
69
|
const result = this._validator(from, this._context(context), this);
|
|
@@ -73,19 +73,19 @@ export class GenericValidator {
|
|
|
73
73
|
return result;
|
|
74
74
|
}
|
|
75
75
|
/**
|
|
76
|
-
* {@
|
|
76
|
+
* {@inheritDoc Validation.Validator.validateOptional}
|
|
77
77
|
*/
|
|
78
78
|
validateOptional(from, context) {
|
|
79
79
|
return from === undefined ? succeed(undefined) : this.validate(from, context);
|
|
80
80
|
}
|
|
81
81
|
/**
|
|
82
|
-
* {@
|
|
82
|
+
* {@inheritDoc Validation.Validator.guard}
|
|
83
83
|
*/
|
|
84
84
|
guard(from, context) {
|
|
85
85
|
return this._validator(from, this._context(context), this) === true;
|
|
86
86
|
}
|
|
87
87
|
/**
|
|
88
|
-
* {@
|
|
88
|
+
* {@inheritDoc Validation.Validator.optional}
|
|
89
89
|
*/
|
|
90
90
|
optional() {
|
|
91
91
|
return new GenericValidator({
|
|
@@ -96,7 +96,7 @@ export class GenericValidator {
|
|
|
96
96
|
});
|
|
97
97
|
}
|
|
98
98
|
/**
|
|
99
|
-
* {@
|
|
99
|
+
* {@inheritDoc Validation.Validator.withConstraint}
|
|
100
100
|
*/
|
|
101
101
|
withConstraint(constraint, trait) {
|
|
102
102
|
trait = trait !== null && trait !== void 0 ? trait : { type: 'function' };
|
|
@@ -118,7 +118,7 @@ export class GenericValidator {
|
|
|
118
118
|
});
|
|
119
119
|
}
|
|
120
120
|
/**
|
|
121
|
-
* {@
|
|
121
|
+
* {@inheritDoc Validation.Validator.brand}
|
|
122
122
|
*/
|
|
123
123
|
withBrand(brand) {
|
|
124
124
|
if (this.brand) {
|
|
@@ -132,7 +132,7 @@ export class GenericValidator {
|
|
|
132
132
|
});
|
|
133
133
|
}
|
|
134
134
|
/**
|
|
135
|
-
* {@
|
|
135
|
+
* {@inheritDoc Validation.Validator.withFormattedError}
|
|
136
136
|
*/
|
|
137
137
|
withFormattedError(formatter) {
|
|
138
138
|
return new GenericValidator({
|
|
@@ -147,6 +147,20 @@ export class GenericValidator {
|
|
|
147
147
|
}
|
|
148
148
|
});
|
|
149
149
|
}
|
|
150
|
+
/**
|
|
151
|
+
* {@inheritDoc Validation.Validator.or}
|
|
152
|
+
*/
|
|
153
|
+
or(other) {
|
|
154
|
+
return new GenericValidator({
|
|
155
|
+
validator: (from, context, __self) => {
|
|
156
|
+
if (this._validator(from, this._context(context), this) === true) {
|
|
157
|
+
return true;
|
|
158
|
+
}
|
|
159
|
+
const otherResult = other.validate(from, this._context(context));
|
|
160
|
+
return otherResult.isSuccess() ? true : otherResult;
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
}
|
|
150
164
|
/**
|
|
151
165
|
* Gets a default or explicit context.
|
|
152
166
|
* @param explicitContext - Optional explicit context.
|
|
@@ -33,10 +33,7 @@ import { FieldValidator } from './field';
|
|
|
33
33
|
export class ObjectValidator extends ValidatorBase {
|
|
34
34
|
/**
|
|
35
35
|
* Constructs a new {@link Validation.Classes.ObjectValidator | ObjectValidator<T>}.
|
|
36
|
-
* @param
|
|
37
|
-
* a {@link Validation.Validator | Validator} for each field.
|
|
38
|
-
* @param options - An optional {@link Validation.Classes.ObjectValidatorOptions} to configure
|
|
39
|
-
* validation.
|
|
36
|
+
* @param params - Construction parameters including field validators and options.
|
|
40
37
|
*/
|
|
41
38
|
constructor(params) {
|
|
42
39
|
var _a;
|
|
@@ -92,7 +89,7 @@ export class ObjectValidator extends ValidatorBase {
|
|
|
92
89
|
/**
|
|
93
90
|
* Creates a new {@link Validation.Classes.ObjectValidator | ObjectValidator} derived from this one but with
|
|
94
91
|
* new optional properties as specified by a supplied array of `keyof T`.
|
|
95
|
-
* @param
|
|
92
|
+
* @param addOptionalFields - The keys to be made optional.
|
|
96
93
|
* @returns A new {@link Validation.Classes.ObjectValidator | ObjectValidator} with the additional optional
|
|
97
94
|
* source properties.
|
|
98
95
|
*/
|
|
@@ -103,7 +100,7 @@ export class ObjectValidator extends ValidatorBase {
|
|
|
103
100
|
});
|
|
104
101
|
}
|
|
105
102
|
/**
|
|
106
|
-
* {@
|
|
103
|
+
* {@inheritDoc Validation.ValidatorBase._validate}
|
|
107
104
|
* @internal
|
|
108
105
|
*/
|
|
109
106
|
_validate(from, context, self) {
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
*/
|
|
22
22
|
import { fail, isKeyOf, MessageAggregator } from '../base';
|
|
23
23
|
import { ArrayValidator } from './array';
|
|
24
|
+
import { CompositeIdValidator } from './compositeId';
|
|
24
25
|
import { ObjectValidator } from './object';
|
|
25
26
|
import { TypeGuardValidator } from './typeGuard';
|
|
26
27
|
import { BooleanValidator } from './boolean';
|
|
@@ -152,6 +153,17 @@ export function literal(value) {
|
|
|
152
153
|
}
|
|
153
154
|
});
|
|
154
155
|
}
|
|
156
|
+
/** Helper function to create a {@link Validation.Validator | Validator} which validates a
|
|
157
|
+
* strongly-typed composite ID.
|
|
158
|
+
* @param params - {@link Validation.Classes.CompositeIdValidatorConstructorParams | params}
|
|
159
|
+
* used to construct the validator.
|
|
160
|
+
* @returns A new {@link Validation.Validator | Validator} which validates the desired
|
|
161
|
+
* composite ID in place.
|
|
162
|
+
* @public
|
|
163
|
+
*/
|
|
164
|
+
export function compositeId(params) {
|
|
165
|
+
return new CompositeIdValidator(params);
|
|
166
|
+
}
|
|
155
167
|
/**
|
|
156
168
|
* Helper function to create a {@link Validation.Validator | Validator} which validates one
|
|
157
169
|
* of several possible validated values.
|