@fgv/ts-json-base 2.1.1-alpha.2 → 3.0.0-alpha.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/CHANGELOG.json CHANGED
@@ -1,6 +1,21 @@
1
1
  {
2
2
  "name": "@fgv/ts-json-base",
3
3
  "entries": [
4
+ {
5
+ "version": "3.0.0",
6
+ "tag": "@fgv/ts-json-base_v3.0.0",
7
+ "date": "Mon, 22 Jan 2024 07:00:18 GMT",
8
+ "comments": {
9
+ "none": [
10
+ {
11
+ "comment": "add validators"
12
+ },
13
+ {
14
+ "comment": "initial refactor"
15
+ }
16
+ ]
17
+ }
18
+ },
4
19
  {
5
20
  "version": "2.2.0",
6
21
  "tag": "@fgv/ts-json-base_v2.2.0",
package/CHANGELOG.md CHANGED
@@ -1,6 +1,14 @@
1
1
  # Change Log - @fgv/ts-json-base
2
2
 
3
- This log was last generated on Thu, 18 Jan 2024 05:45:04 GMT and should not be manually modified.
3
+ This log was last generated on Mon, 22 Jan 2024 07:00:18 GMT and should not be manually modified.
4
+
5
+ ## 3.0.0
6
+ Mon, 22 Jan 2024 07:00:18 GMT
7
+
8
+ ### Updates
9
+
10
+ - add validators
11
+ - initial refactor
4
12
 
5
13
  ## 2.2.0
6
14
  Thu, 18 Jan 2024 05:45:04 GMT
@@ -1,5 +1,6 @@
1
1
  import { Converter } from '@fgv/ts-utils';
2
2
  import { Result } from '@fgv/ts-utils';
3
+ import { Validator } from '@fgv/ts-utils';
3
4
 
4
5
  /**
5
6
  * Identifies whether some `unknown` value is a {@link JsonPrimitive | primitive},
@@ -11,10 +12,21 @@ import { Result } from '@fgv/ts-utils';
11
12
  */
12
13
  export declare function classifyJsonValue(from: unknown): Result<JsonValueType>;
13
14
 
15
+ declare namespace Converters {
16
+ export {
17
+ IJsonConverterContext,
18
+ jsonPrimitive,
19
+ jsonObject,
20
+ jsonArray,
21
+ jsonValue
22
+ }
23
+ }
24
+ export { Converters }
25
+
14
26
  /**
15
27
  * Reads all JSON files from a directory and apply a supplied converter.
16
28
  * @param srcPath - The path of the folder to be read.
17
- * @param options - {@link Files.IDirectoryConvertOptions | Options} to control
29
+ * @param options - {@link JsonFile.IDirectoryConvertOptions | Options} to control
18
30
  * conversion and filtering
19
31
  * @public
20
32
  */
@@ -25,7 +37,7 @@ declare function convertJsonDirectorySync<T>(srcPath: string, options: IDirector
25
37
  * `Map<string, T>` indexed by file base name (i.e. minus the extension)
26
38
  * with an optional name transformation applied if present.
27
39
  * @param srcPath - The path of the folder to be read.
28
- * @param options - {@link Files.IDirectoryToMapConvertOptions | Options} to control conversion,
40
+ * @param options - {@link JsonFile.IDirectoryToMapConvertOptions | Options} to control conversion,
29
41
  * filtering and naming.
30
42
  * @public
31
43
  */
@@ -61,6 +73,22 @@ declare interface IDirectoryToMapConvertOptions<T, TC = unknown> extends IDirect
61
73
  transformName?: ItemNameTransformFunction<T>;
62
74
  }
63
75
 
76
+ /**
77
+ * Conversion context for JSON converters.
78
+ * @public
79
+ */
80
+ declare interface IJsonConverterContext {
81
+ ignoreUndefinedProperties?: boolean;
82
+ }
83
+
84
+ /**
85
+ * Validation context for in-place JSON validators.
86
+ * @public
87
+ */
88
+ declare interface IJsonValidatorContext {
89
+ ignoreUndefinedProperties?: boolean;
90
+ }
91
+
64
92
  /**
65
93
  * Return value for one item in a directory conversion.
66
94
  * @public
@@ -117,6 +145,26 @@ declare type ItemNameTransformFunction<T> = (name: string, item: T) => Result<st
117
145
  export declare interface JsonArray extends Array<JsonValue> {
118
146
  }
119
147
 
148
+ /**
149
+ * An copying converter which converts a supplied `unknown` value to
150
+ * a valid {@link JsonArray | JsonArray}. Fails by default if any properties or array elements
151
+ * are `undefined` - this default behavior can be overridden by supplying an appropriate
152
+ * {@link Converters.IJsonConverterContext | context} at runtime.
153
+ *
154
+ * Guaranteed to return a new array.
155
+ * @public
156
+ */
157
+ declare const jsonArray: Converter<JsonArray, IJsonConverterContext>;
158
+
159
+ /**
160
+ * An in-place validator which validates that a supplied `unknown` value is
161
+ * a valid {@link JsonArray | JsonArray}. Fails by default if any properties or array elements
162
+ * are `undefined` - this default behavior can be overridden by supplying an appropriate
163
+ * {@link Validators.IJsonValidatorContext | context} at runtime.
164
+ * @public
165
+ */
166
+ declare const jsonArray_2: Validator<JsonArray, IJsonValidatorContext>;
167
+
120
168
  declare namespace JsonFile {
121
169
  export {
122
170
  readJsonFileSync,
@@ -141,12 +189,45 @@ export declare interface JsonObject {
141
189
  [key: string]: JsonValue;
142
190
  }
143
191
 
192
+ /**
193
+ * An copying converter which converts a supplied `unknown` value into
194
+ * a valid {@link JsonObject | JsonObject}. Fails by default if any properties or array elements
195
+ * are `undefined` - this default behavior can be overridden by supplying an appropriate
196
+ * {@link Converters.IJsonConverterContext | context} at runtime.
197
+ *
198
+ * Guaranteed to return a new object.
199
+ * @public
200
+ */
201
+ declare const jsonObject: Converter<JsonObject, IJsonConverterContext>;
202
+
203
+ /**
204
+ * An in-place validator which validates that a supplied `unknown` value is
205
+ * a valid {@link JsonObject | JsonObject}. Fails by default if any properties or array elements
206
+ * are `undefined` - this default behavior can be overridden by supplying an appropriate
207
+ * {@link Validators.IJsonValidatorContext | context} at runtime.
208
+ * @public
209
+ */
210
+ declare const jsonObject_2: Validator<JsonObject, IJsonValidatorContext>;
211
+
144
212
  /**
145
213
  * Primitive (terminal) values allowed in by JSON.
146
214
  * @public
147
215
  */
148
216
  export declare type JsonPrimitive = boolean | number | string | null;
149
217
 
218
+ /**
219
+ * An converter which converts a supplied `unknown` value to a valid {@link JsonPrimitive | JsonPrimitive}.
220
+ * @public
221
+ */
222
+ declare const jsonPrimitive: Converter<JsonPrimitive, IJsonConverterContext>;
223
+
224
+ /**
225
+ * An in-place validator which validates that a supplied `unknown` value is
226
+ * a valid {@link JsonPrimitive | JsonPrimitive}.
227
+ * @public
228
+ */
229
+ declare const jsonPrimitive_2: Validator<JsonPrimitive, IJsonValidatorContext>;
230
+
150
231
  /**
151
232
  * A {@link JsonValue | JsonValue} is one of: a {@link JsonPrimitive | JsonPrimitive},
152
233
  * a {@link JsonObject | JsonObject} or an {@link JsonArray | JsonArray}.
@@ -154,6 +235,24 @@ export declare type JsonPrimitive = boolean | number | string | null;
154
235
  */
155
236
  export declare type JsonValue = JsonPrimitive | JsonObject | JsonArray;
156
237
 
238
+ /**
239
+ * An copying converter which converts a supplied `unknown` value to a
240
+ * valid {@link JsonValue | JsonValue}. Fails by default if any properties or array elements
241
+ * are `undefined` - this default behavior can be overridden by supplying an appropriate
242
+ * {@link Converters.IJsonConverterContext | context} at runtime.
243
+ * @public
244
+ */
245
+ declare const jsonValue: Converter<JsonValue, IJsonConverterContext>;
246
+
247
+ /**
248
+ * An in-place validator which validates that a supplied `unknown` value is
249
+ * a valid {@link JsonValue | JsonValue}. Fails by default if any properties or array elements
250
+ * are `undefined` - this default behavior can be overridden by supplying an appropriate
251
+ * {@link Validators.IJsonValidatorContext | context} at runtime.
252
+ * @public
253
+ */
254
+ declare const jsonValue_2: Validator<JsonValue, IJsonValidatorContext>;
255
+
157
256
  /**
158
257
  * Classes of {@link JsonValue | JsonValue}.
159
258
  * @public
@@ -191,6 +290,28 @@ export declare function pickJsonValue(src: JsonObject, path: string): Result<Jso
191
290
  */
192
291
  declare function readJsonFileSync(srcPath: string): Result<JsonValue>;
193
292
 
293
+ /**
294
+ * "Sanitizes" an `unknown` by stringifying and then parsing it. Guarantees a
295
+ * valid {@link JsonValue | JsonValue} but is not idempotent and gives no guarantees
296
+ * about fidelity. Fails if the supplied value cannot be stringified as Json.
297
+ * @param from - The `unknown` to be sanitized.
298
+ * @returns `Success` with a {@link JsonValue | JsonValue} if conversion succeeds,
299
+ * `Failure` with details if an error occurs.
300
+ * @public
301
+ */
302
+ export declare function sanitizeJson(from: unknown): Result<JsonValue>;
303
+
304
+ declare namespace Validators {
305
+ export {
306
+ IJsonValidatorContext,
307
+ jsonPrimitive_2 as jsonPrimitive,
308
+ jsonObject_2 as jsonObject,
309
+ jsonArray_2 as jsonArray,
310
+ jsonValue_2 as jsonValue
311
+ }
312
+ }
313
+ export { Validators }
314
+
194
315
  /**
195
316
  * Convenience function to write type-safe JSON to a file.
196
317
  * @param srcPath - Path of the file to write.
package/lib/index.d.ts CHANGED
@@ -1,4 +1,6 @@
1
+ import * as Converters from './packlets/converters';
1
2
  import * as JsonFile from './packlets/json-file';
3
+ import * as Validators from './packlets/validators';
2
4
  export * from './packlets/json';
3
- export { JsonFile };
5
+ export { Converters, JsonFile, Validators };
4
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,QAAQ,MAAM,sBAAsB,CAAC;AAEjD,cAAc,iBAAiB,CAAC;AAChC,OAAO,EAAE,QAAQ,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,UAAU,MAAM,uBAAuB,CAAC;AACpD,OAAO,KAAK,QAAQ,MAAM,sBAAsB,CAAC;AACjD,OAAO,KAAK,UAAU,MAAM,uBAAuB,CAAC;AAEpD,cAAc,iBAAiB,CAAC;AAChC,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC"}
package/lib/index.js CHANGED
@@ -47,8 +47,12 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
47
47
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
48
48
  };
49
49
  Object.defineProperty(exports, "__esModule", { value: true });
50
- exports.JsonFile = void 0;
50
+ exports.Validators = exports.JsonFile = exports.Converters = void 0;
51
+ const Converters = __importStar(require("./packlets/converters"));
52
+ exports.Converters = Converters;
51
53
  const JsonFile = __importStar(require("./packlets/json-file"));
52
54
  exports.JsonFile = JsonFile;
55
+ const Validators = __importStar(require("./packlets/validators"));
56
+ exports.Validators = Validators;
53
57
  __exportStar(require("./packlets/json"), exports);
54
58
  //# sourceMappingURL=index.js.map
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEH,+DAAiD;AAGxC,4BAAQ;AADjB,kDAAgC","sourcesContent":["/*\n * Copyright (c) 2023 Erik Fortune\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport * as JsonFile from './packlets/json-file';\n\nexport * from './packlets/json';\nexport { JsonFile };\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEH,kEAAoD;AAK3C,gCAAU;AAJnB,+DAAiD;AAI5B,4BAAQ;AAH7B,kEAAoD;AAGrB,gCAAU;AADzC,kDAAgC","sourcesContent":["/*\n * Copyright (c) 2023 Erik Fortune\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport * as Converters from './packlets/converters';\nimport * as JsonFile from './packlets/json-file';\nimport * as Validators from './packlets/validators';\n\nexport * from './packlets/json';\nexport { Converters, JsonFile, Validators };\n"]}
@@ -0,0 +1,43 @@
1
+ import { Converter } from '@fgv/ts-utils';
2
+ import { JsonArray, JsonObject, JsonPrimitive, JsonValue } from '../json';
3
+ /**
4
+ * Conversion context for JSON converters.
5
+ * @public
6
+ */
7
+ export interface IJsonConverterContext {
8
+ ignoreUndefinedProperties?: boolean;
9
+ }
10
+ /**
11
+ * An converter which converts a supplied `unknown` value to a valid {@link JsonPrimitive | JsonPrimitive}.
12
+ * @public
13
+ */
14
+ export declare const jsonPrimitive: Converter<JsonPrimitive, IJsonConverterContext>;
15
+ /**
16
+ * An copying converter which converts a supplied `unknown` value into
17
+ * a valid {@link JsonObject | JsonObject}. Fails by default if any properties or array elements
18
+ * are `undefined` - this default behavior can be overridden by supplying an appropriate
19
+ * {@link Converters.IJsonConverterContext | context} at runtime.
20
+ *
21
+ * Guaranteed to return a new object.
22
+ * @public
23
+ */
24
+ export declare const jsonObject: Converter<JsonObject, IJsonConverterContext>;
25
+ /**
26
+ * An copying converter which converts a supplied `unknown` value to
27
+ * a valid {@link JsonArray | JsonArray}. Fails by default if any properties or array elements
28
+ * are `undefined` - this default behavior can be overridden by supplying an appropriate
29
+ * {@link Converters.IJsonConverterContext | context} at runtime.
30
+ *
31
+ * Guaranteed to return a new array.
32
+ * @public
33
+ */
34
+ export declare const jsonArray: Converter<JsonArray, IJsonConverterContext>;
35
+ /**
36
+ * An copying converter which converts a supplied `unknown` value to a
37
+ * valid {@link JsonValue | JsonValue}. Fails by default if any properties or array elements
38
+ * are `undefined` - this default behavior can be overridden by supplying an appropriate
39
+ * {@link Converters.IJsonConverterContext | context} at runtime.
40
+ * @public
41
+ */
42
+ export declare const jsonValue: Converter<JsonValue, IJsonConverterContext>;
43
+ //# sourceMappingURL=converters.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"converters.d.ts","sourceRoot":"","sources":["../../../src/packlets/converters/converters.ts"],"names":[],"mappings":"AAsBA,OAAO,EAAc,SAAS,EAAyB,MAAM,eAAe,CAAC;AAC7E,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,aAAa,EAAE,SAAS,EAA6B,MAAM,SAAS,CAAC;AAIrG;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACpC,yBAAyB,CAAC,EAAE,OAAO,CAAC;CACrC;AAED;;;GAGG;AACH,eAAO,MAAM,aAAa,EAAE,SAAS,CAAC,aAAa,EAAE,qBAAqB,CAqBzE,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,UAAU,EAAE,SAAS,CAAC,UAAU,EAAE,qBAAqB,CAgCnE,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,SAAS,EAAE,SAAS,CAAC,SAAS,EAAE,qBAAqB,CAkCjE,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,SAAS,EAAE,SAAS,CAAC,SAAS,EAAE,qBAAqB,CAgBjE,CAAC"}
@@ -0,0 +1,137 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright (c) 2023 Erik Fortune
4
+ *
5
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ * of this software and associated documentation files (the "Software"), to deal
7
+ * in the Software without restriction, including without limitation the rights
8
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ * copies of the Software, and to permit persons to whom the Software is
10
+ * furnished to do so, subject to the following conditions:
11
+ *
12
+ * The above copyright notice and this permission notice shall be included in all
13
+ * copies or substantial portions of the Software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ * SOFTWARE.
22
+ */
23
+ Object.defineProperty(exports, "__esModule", { value: true });
24
+ exports.jsonValue = exports.jsonArray = exports.jsonObject = exports.jsonPrimitive = void 0;
25
+ const ts_utils_1 = require("@fgv/ts-utils");
26
+ const json_1 = require("../json");
27
+ /**
28
+ * An converter which converts a supplied `unknown` value to a valid {@link JsonPrimitive | JsonPrimitive}.
29
+ * @public
30
+ */
31
+ exports.jsonPrimitive = new ts_utils_1.Conversion.BaseConverter((from, __self, ctx) => {
32
+ if (from === null) {
33
+ return (0, ts_utils_1.succeed)(null);
34
+ }
35
+ switch (typeof from) {
36
+ case 'boolean':
37
+ case 'string':
38
+ return (0, ts_utils_1.succeed)(from);
39
+ case 'number':
40
+ if (!Number.isNaN(from)) {
41
+ return (0, ts_utils_1.succeed)(from);
42
+ }
43
+ break;
44
+ }
45
+ return (0, ts_utils_1.fail)(`"${String(from)}": not a valid JSON primitive.`);
46
+ });
47
+ /**
48
+ * An copying converter which converts a supplied `unknown` value into
49
+ * a valid {@link JsonObject | JsonObject}. Fails by default if any properties or array elements
50
+ * are `undefined` - this default behavior can be overridden by supplying an appropriate
51
+ * {@link Converters.IJsonConverterContext | context} at runtime.
52
+ *
53
+ * Guaranteed to return a new object.
54
+ * @public
55
+ */
56
+ exports.jsonObject = new ts_utils_1.Conversion.BaseConverter((from, __self, ctx) => {
57
+ if (!(0, json_1.isJsonObject)(from)) {
58
+ return (0, ts_utils_1.fail)('not a valid JSON object.');
59
+ }
60
+ const obj = {};
61
+ const errors = [];
62
+ for (const [name, value] of Object.entries(from)) {
63
+ if (value === undefined && (ctx === null || ctx === void 0 ? void 0 : ctx.ignoreUndefinedProperties) === true) {
64
+ // optionally ignore undefined values
65
+ continue;
66
+ }
67
+ exports.jsonValue
68
+ .convert(value, ctx)
69
+ .onSuccess((v) => {
70
+ obj[name] = v;
71
+ return (0, ts_utils_1.succeed)(v);
72
+ })
73
+ .onFailure((m) => {
74
+ errors.push(`${name}: ${m}`);
75
+ return (0, ts_utils_1.fail)(m);
76
+ });
77
+ }
78
+ if (errors.length > 0) {
79
+ return (0, ts_utils_1.fail)(`not a valid JSON object:\n${errors.join('\n')}`);
80
+ }
81
+ return (0, ts_utils_1.succeed)(obj);
82
+ });
83
+ /**
84
+ * An copying converter which converts a supplied `unknown` value to
85
+ * a valid {@link JsonArray | JsonArray}. Fails by default if any properties or array elements
86
+ * are `undefined` - this default behavior can be overridden by supplying an appropriate
87
+ * {@link Converters.IJsonConverterContext | context} at runtime.
88
+ *
89
+ * Guaranteed to return a new array.
90
+ * @public
91
+ */
92
+ exports.jsonArray = new ts_utils_1.Conversion.BaseConverter((from, __self, ctx) => {
93
+ if (!(0, json_1.isJsonArray)(from)) {
94
+ return (0, ts_utils_1.fail)('not an array');
95
+ }
96
+ const arr = [];
97
+ const errors = [];
98
+ for (let i = 0; i < from.length; i++) {
99
+ const value = from[i];
100
+ if (value === undefined && (ctx === null || ctx === void 0 ? void 0 : ctx.ignoreUndefinedProperties) === true) {
101
+ // convert undefined to 'null' for parity with JSON.stringify
102
+ arr.push(null);
103
+ continue;
104
+ }
105
+ exports.jsonValue
106
+ .convert(value, ctx)
107
+ .onSuccess((v) => {
108
+ arr.push(v);
109
+ return (0, ts_utils_1.succeed)(v);
110
+ })
111
+ .onFailure((m) => {
112
+ errors.push(`${i}: ${m}`);
113
+ return (0, ts_utils_1.fail)(m);
114
+ });
115
+ }
116
+ if (errors.length > 0) {
117
+ return (0, ts_utils_1.fail)(`array contains non-json elements:\n${errors.join('\n')}`);
118
+ }
119
+ return (0, ts_utils_1.succeed)(arr);
120
+ });
121
+ /**
122
+ * An copying converter which converts a supplied `unknown` value to a
123
+ * valid {@link JsonValue | JsonValue}. Fails by default if any properties or array elements
124
+ * are `undefined` - this default behavior can be overridden by supplying an appropriate
125
+ * {@link Converters.IJsonConverterContext | context} at runtime.
126
+ * @public
127
+ */
128
+ exports.jsonValue = new ts_utils_1.Conversion.BaseConverter((from, __self, ctx) => {
129
+ if ((0, json_1.isJsonArray)(from)) {
130
+ return exports.jsonArray.convert(from, ctx);
131
+ }
132
+ else if ((0, json_1.isJsonObject)(from)) {
133
+ return exports.jsonObject.convert(from, ctx);
134
+ }
135
+ return exports.jsonPrimitive.convert(from, ctx);
136
+ });
137
+ //# sourceMappingURL=converters.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"converters.js","sourceRoot":"","sources":["../../../src/packlets/converters/converters.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright (c) 2023 Erik Fortune\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport { Conversion, Converter, Result, fail, succeed } from '@fgv/ts-utils';\nimport { JsonArray, JsonObject, JsonPrimitive, JsonValue, isJsonArray, isJsonObject } from '../json';\n\n/* eslint-disable no-use-before-define, @typescript-eslint/no-use-before-define */\n\n/**\n * Conversion context for JSON converters.\n * @public\n */\nexport interface IJsonConverterContext {\n ignoreUndefinedProperties?: boolean;\n}\n\n/**\n * An converter which converts a supplied `unknown` value to a valid {@link JsonPrimitive | JsonPrimitive}.\n * @public\n */\nexport const jsonPrimitive: Converter<JsonPrimitive, IJsonConverterContext> = new Conversion.BaseConverter(\n (\n from: unknown,\n __self: Converter<JsonPrimitive, IJsonConverterContext>,\n ctx?: IJsonConverterContext\n ): Result<JsonPrimitive> => {\n if (from === null) {\n return succeed(null);\n }\n switch (typeof from) {\n case 'boolean':\n case 'string':\n return succeed(from);\n case 'number':\n if (!Number.isNaN(from)) {\n return succeed(from);\n }\n break;\n }\n return fail(`\"${String(from)}\": not a valid JSON primitive.`);\n }\n);\n\n/**\n * An copying converter which converts a supplied `unknown` value into\n * a valid {@link JsonObject | JsonObject}. Fails by default if any properties or array elements\n * are `undefined` - this default behavior can be overridden by supplying an appropriate\n * {@link Converters.IJsonConverterContext | context} at runtime.\n *\n * Guaranteed to return a new object.\n * @public\n */\nexport const jsonObject: Converter<JsonObject, IJsonConverterContext> = new Conversion.BaseConverter(\n (\n from: unknown,\n __self: Converter<JsonObject, IJsonConverterContext>,\n ctx?: IJsonConverterContext\n ): Result<JsonObject> => {\n if (!isJsonObject(from)) {\n return fail('not a valid JSON object.');\n }\n const obj: JsonObject = {};\n const errors: string[] = [];\n for (const [name, value] of Object.entries(from)) {\n if (value === undefined && ctx?.ignoreUndefinedProperties === true) {\n // optionally ignore undefined values\n continue;\n }\n jsonValue\n .convert(value, ctx)\n .onSuccess((v: JsonValue) => {\n obj[name] = v;\n return succeed(v);\n })\n .onFailure((m) => {\n errors.push(`${name}: ${m}`);\n return fail(m);\n });\n }\n if (errors.length > 0) {\n return fail(`not a valid JSON object:\\n${errors.join('\\n')}`);\n }\n return succeed(obj);\n }\n);\n\n/**\n * An copying converter which converts a supplied `unknown` value to\n * a valid {@link JsonArray | JsonArray}. Fails by default if any properties or array elements\n * are `undefined` - this default behavior can be overridden by supplying an appropriate\n * {@link Converters.IJsonConverterContext | context} at runtime.\n *\n * Guaranteed to return a new array.\n * @public\n */\nexport const jsonArray: Converter<JsonArray, IJsonConverterContext> = new Conversion.BaseConverter(\n (\n from: unknown,\n __self: Converter<JsonArray, IJsonConverterContext>,\n ctx?: IJsonConverterContext\n ): Result<JsonArray> => {\n if (!isJsonArray(from)) {\n return fail('not an array');\n }\n const arr: JsonValue[] = [];\n const errors: string[] = [];\n for (let i = 0; i < from.length; i++) {\n const value = from[i];\n if (value === undefined && ctx?.ignoreUndefinedProperties === true) {\n // convert undefined to 'null' for parity with JSON.stringify\n arr.push(null);\n continue;\n }\n jsonValue\n .convert(value, ctx)\n .onSuccess((v) => {\n arr.push(v);\n return succeed(v);\n })\n .onFailure((m) => {\n errors.push(`${i}: ${m}`);\n return fail(m);\n });\n }\n if (errors.length > 0) {\n return fail(`array contains non-json elements:\\n${errors.join('\\n')}`);\n }\n return succeed(arr);\n }\n);\n\n/**\n * An copying converter which converts a supplied `unknown` value to a\n * valid {@link JsonValue | JsonValue}. Fails by default if any properties or array elements\n * are `undefined` - this default behavior can be overridden by supplying an appropriate\n * {@link Converters.IJsonConverterContext | context} at runtime.\n * @public\n */\nexport const jsonValue: Converter<JsonValue, IJsonConverterContext> = new Conversion.BaseConverter<\n JsonValue,\n IJsonConverterContext\n>(\n (\n from: unknown,\n __self: Converter<JsonValue, IJsonConverterContext>,\n ctx?: IJsonConverterContext\n ): Result<JsonValue> => {\n if (isJsonArray(from)) {\n return jsonArray.convert(from, ctx);\n } else if (isJsonObject(from)) {\n return jsonObject.convert(from, ctx);\n }\n return jsonPrimitive.convert(from, ctx);\n }\n);\n"]}
@@ -0,0 +1,2 @@
1
+ export * from './converters';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/packlets/converters/index.ts"],"names":[],"mappings":"AAsBA,cAAc,cAAc,CAAC"}
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright (c) 2020 Erik Fortune
4
+ *
5
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ * of this software and associated documentation files (the "Software"), to deal
7
+ * in the Software without restriction, including without limitation the rights
8
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ * copies of the Software, and to permit persons to whom the Software is
10
+ * furnished to do so, subject to the following conditions:
11
+ *
12
+ * The above copyright notice and this permission notice shall be included in all
13
+ * copies or substantial portions of the Software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ * SOFTWARE.
22
+ */
23
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
24
+ if (k2 === undefined) k2 = k;
25
+ var desc = Object.getOwnPropertyDescriptor(m, k);
26
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
27
+ desc = { enumerable: true, get: function() { return m[k]; } };
28
+ }
29
+ Object.defineProperty(o, k2, desc);
30
+ }) : (function(o, m, k, k2) {
31
+ if (k2 === undefined) k2 = k;
32
+ o[k2] = m[k];
33
+ }));
34
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
35
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
36
+ };
37
+ Object.defineProperty(exports, "__esModule", { value: true });
38
+ __exportStar(require("./converters"), exports);
39
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/packlets/converters/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;;;;;;;;;;;;;;;;AAEH,+CAA6B","sourcesContent":["/*\n * Copyright (c) 2020 Erik Fortune\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nexport * from './converters';\n"]}
@@ -82,4 +82,14 @@ export declare function pickJsonValue(src: JsonObject, path: string): Result<Jso
82
82
  * @public
83
83
  */
84
84
  export declare function pickJsonObject(src: JsonObject, path: string): Result<JsonObject>;
85
+ /**
86
+ * "Sanitizes" an `unknown` by stringifying and then parsing it. Guarantees a
87
+ * valid {@link JsonValue | JsonValue} but is not idempotent and gives no guarantees
88
+ * about fidelity. Fails if the supplied value cannot be stringified as Json.
89
+ * @param from - The `unknown` to be sanitized.
90
+ * @returns `Success` with a {@link JsonValue | JsonValue} if conversion succeeds,
91
+ * `Failure` with details if an error occurs.
92
+ * @public
93
+ */
94
+ export declare function sanitizeJson(from: unknown): Result<JsonValue>;
85
95
  //# sourceMappingURL=common.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../../src/packlets/json/common.ts"],"names":[],"mappings":"AAsBA,OAAO,EAAE,MAAM,EAAiB,MAAM,eAAe,CAAC;AAItD;;;GAGG;AAEH,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;AAE7D;;;;GAIG;AAEH,MAAM,WAAW,UAAU;IACzB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;CAC1B;AAED;;;;GAIG;AACH,MAAM,MAAM,SAAS,GAAG,aAAa,GAAG,UAAU,GAAG,SAAS,CAAC;AAE/D;;;GAGG;AAEH,MAAM,WAAW,SAAU,SAAQ,KAAK,CAAC,SAAS,CAAC;CAAG;AAEtD;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE7D;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,aAAa,CAEpE;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,UAAU,CAI9D;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,SAAS,CAE5D;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC,aAAa,CAAC,CAStE;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,CAa9E;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,UAAU,CAAC,CAOhF"}
1
+ {"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../../src/packlets/json/common.ts"],"names":[],"mappings":"AAsBA,OAAO,EAAE,MAAM,EAAgC,MAAM,eAAe,CAAC;AAIrE;;;GAGG;AAEH,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;AAE7D;;;;GAIG;AAEH,MAAM,WAAW,UAAU;IACzB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;CAC1B;AAED;;;;GAIG;AACH,MAAM,MAAM,SAAS,GAAG,aAAa,GAAG,UAAU,GAAG,SAAS,CAAC;AAE/D;;;GAGG;AAEH,MAAM,WAAW,SAAU,SAAQ,KAAK,CAAC,SAAS,CAAC;CAAG;AAEtD;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE7D;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,aAAa,CAEpE;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,UAAU,CAQ9D;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,SAAS,CAE5D;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC,aAAa,CAAC,CAStE;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,CAa9E;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,UAAU,CAAC,CAOhF;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC,SAAS,CAAC,CAE7D"}
@@ -21,7 +21,7 @@
21
21
  * SOFTWARE.
22
22
  */
23
23
  Object.defineProperty(exports, "__esModule", { value: true });
24
- exports.pickJsonObject = exports.pickJsonValue = exports.classifyJsonValue = exports.isJsonArray = exports.isJsonObject = exports.isJsonPrimitive = void 0;
24
+ exports.sanitizeJson = exports.pickJsonObject = exports.pickJsonValue = exports.classifyJsonValue = exports.isJsonArray = exports.isJsonObject = exports.isJsonPrimitive = void 0;
25
25
  const ts_utils_1 = require("@fgv/ts-utils");
26
26
  /**
27
27
  * Test if an `unknown` is a {@link JsonValue | JsonValue}.
@@ -42,7 +42,11 @@ exports.isJsonPrimitive = isJsonPrimitive;
42
42
  * @public
43
43
  */
44
44
  function isJsonObject(from) {
45
- return (typeof from === 'object' && !Array.isArray(from) && !(from instanceof RegExp) && !(from instanceof Date));
45
+ return (typeof from === 'object' &&
46
+ from !== null &&
47
+ !Array.isArray(from) &&
48
+ !(from instanceof RegExp) &&
49
+ !(from instanceof Date));
46
50
  }
47
51
  exports.isJsonObject = isJsonObject;
48
52
  /**
@@ -120,4 +124,17 @@ function pickJsonObject(src, path) {
120
124
  });
121
125
  }
122
126
  exports.pickJsonObject = pickJsonObject;
127
+ /**
128
+ * "Sanitizes" an `unknown` by stringifying and then parsing it. Guarantees a
129
+ * valid {@link JsonValue | JsonValue} but is not idempotent and gives no guarantees
130
+ * about fidelity. Fails if the supplied value cannot be stringified as Json.
131
+ * @param from - The `unknown` to be sanitized.
132
+ * @returns `Success` with a {@link JsonValue | JsonValue} if conversion succeeds,
133
+ * `Failure` with details if an error occurs.
134
+ * @public
135
+ */
136
+ function sanitizeJson(from) {
137
+ return (0, ts_utils_1.captureResult)(() => JSON.parse(JSON.stringify(from)));
138
+ }
139
+ exports.sanitizeJson = sanitizeJson;
123
140
  //# sourceMappingURL=common.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"common.js","sourceRoot":"","sources":["../../../src/packlets/json/common.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;;;AAEH,4CAAsD;AAyCtD;;;;;;GAMG;AACH,SAAgB,eAAe,CAAC,IAAa;IAC3C,OAAO,OAAO,IAAI,KAAK,SAAS,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,CAAC;AAC5G,CAAC;AAFD,0CAEC;AAED;;;;;;GAMG;AACH,SAAgB,YAAY,CAAC,IAAa;IACxC,OAAO,CACL,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,YAAY,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,YAAY,IAAI,CAAC,CACzG,CAAC;AACJ,CAAC;AAJD,oCAIC;AAED;;;;;;GAMG;AACH,SAAgB,WAAW,CAAC,IAAa;IACvC,OAAO,OAAO,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AACzD,CAAC;AAFD,kCAEC;AAED;;;;;;;GAOG;AACH,SAAgB,iBAAiB,CAAC,IAAa;IAC7C,IAAI,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1B,OAAO,IAAA,kBAAO,EAAC,WAAW,CAAC,CAAC;IAC9B,CAAC;SAAM,IAAI,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC;QAC9B,OAAO,IAAA,kBAAO,EAAC,QAAQ,CAAC,CAAC;IAC3B,CAAC;SAAM,IAAI,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;QAC7B,OAAO,IAAA,kBAAO,EAAC,OAAO,CAAC,CAAC;IAC1B,CAAC;IACD,OAAO,IAAA,eAAI,EAAC,iBAAiB,IAAI,EAAE,CAAC,CAAC;AACvC,CAAC;AATD,8CASC;AAED;;;;;;;GAOG;AACH,SAAgB,aAAa,CAAC,GAAe,EAAE,IAAY;IACzD,IAAI,MAAM,GAAc,GAAG,CAAC;IAC5B,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QACnC,IAAI,MAAM,IAAI,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC;YACnC,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;YACtB,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBACzB,OAAO,IAAA,eAAI,EAAC,GAAG,IAAI,YAAY,IAAI,kBAAkB,CAAC,CAAC;YACzD,CAAC;QACH,CAAC;aAAM,CAAC;YACN,OAAO,IAAA,eAAI,EAAC,GAAG,IAAI,YAAY,IAAI,kBAAkB,CAAC,CAAC;QACzD,CAAC;IACH,CAAC;IACD,OAAO,IAAA,kBAAO,EAAC,MAAM,CAAC,CAAC;AACzB,CAAC;AAbD,sCAaC;AAED;;;;;;;;;GASG;AACH,SAAgB,cAAc,CAAC,GAAe,EAAE,IAAY;IAC1D,OAAO,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE;QAC9C,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;YACrB,OAAO,IAAA,eAAI,EAAC,GAAG,IAAI,iBAAiB,CAAC,CAAC;QACxC,CAAC;QACD,OAAO,IAAA,kBAAO,EAAC,CAAC,CAAC,CAAC;IACpB,CAAC,CAAC,CAAC;AACL,CAAC;AAPD,wCAOC","sourcesContent":["/*\n * Copyright (c) 2020 Erik Fortune\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport { Result, fail, succeed } from '@fgv/ts-utils';\n\n/* eslint-disable no-use-before-define */\n\n/**\n * Primitive (terminal) values allowed in by JSON.\n * @public\n */\n// eslint-disable-next-line @rushstack/no-new-null\nexport type JsonPrimitive = boolean | number | string | null;\n\n/**\n * A {@link JsonObject | JsonObject} is a string-keyed object\n * containing only valid {@link JsonValue | JSON values}.\n * @public\n */\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport interface JsonObject {\n [key: string]: JsonValue;\n}\n\n/**\n * A {@link JsonValue | JsonValue} is one of: a {@link JsonPrimitive | JsonPrimitive},\n * a {@link JsonObject | JsonObject} or an {@link JsonArray | JsonArray}.\n * @public\n */\nexport type JsonValue = JsonPrimitive | JsonObject | JsonArray;\n\n/**\n * A {@link JsonArray | JsonArray} is an array containing only valid {@link JsonValue | JsonValues}.\n * @public\n */\n// eslint-disable-next-line @typescript-eslint/no-empty-interface, @typescript-eslint/naming-convention\nexport interface JsonArray extends Array<JsonValue> {}\n\n/**\n * Classes of {@link JsonValue | JsonValue}.\n * @public\n */\nexport type JsonValueType = 'primitive' | 'object' | 'array';\n\n/**\n * Test if an `unknown` is a {@link JsonValue | JsonValue}.\n * @param from - The `unknown` to be tested\n * @returns `true` if the supplied parameter is a valid {@link JsonPrimitive | JsonPrimitive},\n * `false` otherwise.\n * @public\n */\nexport function isJsonPrimitive(from: unknown): from is JsonPrimitive {\n return typeof from === 'boolean' || typeof from === 'number' || typeof from === 'string' || from === null;\n}\n\n/**\n * Test if an `unknown` is potentially a {@link JsonObject | JsonObject}.\n * @param from - The `unknown` to be tested.\n * @returns `true` if the supplied parameter is a non-array, non-special object,\n * `false` otherwise.\n * @public\n */\nexport function isJsonObject(from: unknown): from is JsonObject {\n return (\n typeof from === 'object' && !Array.isArray(from) && !(from instanceof RegExp) && !(from instanceof Date)\n );\n}\n\n/**\n * Test if an `unknown` is potentially a {@link JsonArray | JsonArray}.\n * @param from - The `unknown` to be tested.\n * @returns `true` if the supplied parameter is an array object,\n * `false` otherwise.\n * @public\n */\nexport function isJsonArray(from: unknown): from is JsonArray {\n return typeof from === 'object' && Array.isArray(from);\n}\n\n/**\n * Identifies whether some `unknown` value is a {@link JsonPrimitive | primitive},\n * {@link JsonObject | object} or {@link JsonArray | array}. Fails for any value\n * that cannot be converted to JSON (e.g. a function) _but_ this is a shallow test -\n * it does not test the properties of an object or elements in an array.\n * @param from - The `unknown` value to be tested\n * @public\n */\nexport function classifyJsonValue(from: unknown): Result<JsonValueType> {\n if (isJsonPrimitive(from)) {\n return succeed('primitive');\n } else if (isJsonObject(from)) {\n return succeed('object');\n } else if (isJsonArray(from)) {\n return succeed('array');\n }\n return fail(`Invalid JSON: ${from}`);\n}\n\n/**\n * Picks a nested field from a supplied {@link JsonObject | JsonObject}.\n * @param src - The {@link JsonObject | object} from which the field is to be picked.\n * @param path - Dot-separated path of the member to be picked.\n * @returns `Success` with the property if the path is valid, `Failure`\n * with an error message otherwise.\n * @public\n */\nexport function pickJsonValue(src: JsonObject, path: string): Result<JsonValue> {\n let result: JsonValue = src;\n for (const part of path.split('.')) {\n if (result && isJsonObject(result)) {\n result = result[part];\n if (result === undefined) {\n return fail(`${path}: child '${part}' does not exist`);\n }\n } else {\n return fail(`${path}: child '${part}' does not exist`);\n }\n }\n return succeed(result);\n}\n\n/**\n * Picks a nested {@link JsonObject | JsonObject} from a supplied\n * {@link JsonObject | JsonObject}.\n * @param src - The {@link JsonObject | object} from which the field is\n * to be picked.\n * @param path - Dot-separated path of the member to be picked.\n * @returns `Success` with the property if the path is valid and the value\n * is an object. Returns `Failure` with details if an error occurs.\n * @public\n */\nexport function pickJsonObject(src: JsonObject, path: string): Result<JsonObject> {\n return pickJsonValue(src, path).onSuccess((v) => {\n if (!isJsonObject(v)) {\n return fail(`${path}: not an object`);\n }\n return succeed(v);\n });\n}\n"]}
1
+ {"version":3,"file":"common.js","sourceRoot":"","sources":["../../../src/packlets/json/common.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright (c) 2020 Erik Fortune\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport { Result, captureResult, fail, succeed } from '@fgv/ts-utils';\n\n/* eslint-disable no-use-before-define */\n\n/**\n * Primitive (terminal) values allowed in by JSON.\n * @public\n */\n// eslint-disable-next-line @rushstack/no-new-null\nexport type JsonPrimitive = boolean | number | string | null;\n\n/**\n * A {@link JsonObject | JsonObject} is a string-keyed object\n * containing only valid {@link JsonValue | JSON values}.\n * @public\n */\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport interface JsonObject {\n [key: string]: JsonValue;\n}\n\n/**\n * A {@link JsonValue | JsonValue} is one of: a {@link JsonPrimitive | JsonPrimitive},\n * a {@link JsonObject | JsonObject} or an {@link JsonArray | JsonArray}.\n * @public\n */\nexport type JsonValue = JsonPrimitive | JsonObject | JsonArray;\n\n/**\n * A {@link JsonArray | JsonArray} is an array containing only valid {@link JsonValue | JsonValues}.\n * @public\n */\n// eslint-disable-next-line @typescript-eslint/no-empty-interface, @typescript-eslint/naming-convention\nexport interface JsonArray extends Array<JsonValue> {}\n\n/**\n * Classes of {@link JsonValue | JsonValue}.\n * @public\n */\nexport type JsonValueType = 'primitive' | 'object' | 'array';\n\n/**\n * Test if an `unknown` is a {@link JsonValue | JsonValue}.\n * @param from - The `unknown` to be tested\n * @returns `true` if the supplied parameter is a valid {@link JsonPrimitive | JsonPrimitive},\n * `false` otherwise.\n * @public\n */\nexport function isJsonPrimitive(from: unknown): from is JsonPrimitive {\n return typeof from === 'boolean' || typeof from === 'number' || typeof from === 'string' || from === null;\n}\n\n/**\n * Test if an `unknown` is potentially a {@link JsonObject | JsonObject}.\n * @param from - The `unknown` to be tested.\n * @returns `true` if the supplied parameter is a non-array, non-special object,\n * `false` otherwise.\n * @public\n */\nexport function isJsonObject(from: unknown): from is JsonObject {\n return (\n typeof from === 'object' &&\n from !== null &&\n !Array.isArray(from) &&\n !(from instanceof RegExp) &&\n !(from instanceof Date)\n );\n}\n\n/**\n * Test if an `unknown` is potentially a {@link JsonArray | JsonArray}.\n * @param from - The `unknown` to be tested.\n * @returns `true` if the supplied parameter is an array object,\n * `false` otherwise.\n * @public\n */\nexport function isJsonArray(from: unknown): from is JsonArray {\n return typeof from === 'object' && Array.isArray(from);\n}\n\n/**\n * Identifies whether some `unknown` value is a {@link JsonPrimitive | primitive},\n * {@link JsonObject | object} or {@link JsonArray | array}. Fails for any value\n * that cannot be converted to JSON (e.g. a function) _but_ this is a shallow test -\n * it does not test the properties of an object or elements in an array.\n * @param from - The `unknown` value to be tested\n * @public\n */\nexport function classifyJsonValue(from: unknown): Result<JsonValueType> {\n if (isJsonPrimitive(from)) {\n return succeed('primitive');\n } else if (isJsonObject(from)) {\n return succeed('object');\n } else if (isJsonArray(from)) {\n return succeed('array');\n }\n return fail(`Invalid JSON: ${from}`);\n}\n\n/**\n * Picks a nested field from a supplied {@link JsonObject | JsonObject}.\n * @param src - The {@link JsonObject | object} from which the field is to be picked.\n * @param path - Dot-separated path of the member to be picked.\n * @returns `Success` with the property if the path is valid, `Failure`\n * with an error message otherwise.\n * @public\n */\nexport function pickJsonValue(src: JsonObject, path: string): Result<JsonValue> {\n let result: JsonValue = src;\n for (const part of path.split('.')) {\n if (result && isJsonObject(result)) {\n result = result[part];\n if (result === undefined) {\n return fail(`${path}: child '${part}' does not exist`);\n }\n } else {\n return fail(`${path}: child '${part}' does not exist`);\n }\n }\n return succeed(result);\n}\n\n/**\n * Picks a nested {@link JsonObject | JsonObject} from a supplied\n * {@link JsonObject | JsonObject}.\n * @param src - The {@link JsonObject | object} from which the field is\n * to be picked.\n * @param path - Dot-separated path of the member to be picked.\n * @returns `Success` with the property if the path is valid and the value\n * is an object. Returns `Failure` with details if an error occurs.\n * @public\n */\nexport function pickJsonObject(src: JsonObject, path: string): Result<JsonObject> {\n return pickJsonValue(src, path).onSuccess((v) => {\n if (!isJsonObject(v)) {\n return fail(`${path}: not an object`);\n }\n return succeed(v);\n });\n}\n\n/**\n * \"Sanitizes\" an `unknown` by stringifying and then parsing it. Guarantees a\n * valid {@link JsonValue | JsonValue} but is not idempotent and gives no guarantees\n * about fidelity. Fails if the supplied value cannot be stringified as Json.\n * @param from - The `unknown` to be sanitized.\n * @returns `Success` with a {@link JsonValue | JsonValue} if conversion succeeds,\n * `Failure` with details if an error occurs.\n * @public\n */\nexport function sanitizeJson(from: unknown): Result<JsonValue> {\n return captureResult(() => JSON.parse(JSON.stringify(from)));\n}\n"]}
@@ -45,7 +45,7 @@ export interface IReadDirectoryItem<T> {
45
45
  /**
46
46
  * Reads all JSON files from a directory and apply a supplied converter.
47
47
  * @param srcPath - The path of the folder to be read.
48
- * @param options - {@link Files.IDirectoryConvertOptions | Options} to control
48
+ * @param options - {@link JsonFile.IDirectoryConvertOptions | Options} to control
49
49
  * conversion and filtering
50
50
  * @public
51
51
  */
@@ -68,7 +68,7 @@ export interface IDirectoryToMapConvertOptions<T, TC = unknown> extends IDirecto
68
68
  * `Map<string, T>` indexed by file base name (i.e. minus the extension)
69
69
  * with an optional name transformation applied if present.
70
70
  * @param srcPath - The path of the folder to be read.
71
- * @param options - {@link Files.IDirectoryToMapConvertOptions | Options} to control conversion,
71
+ * @param options - {@link JsonFile.IDirectoryToMapConvertOptions | Options} to control conversion,
72
72
  * filtering and naming.
73
73
  * @public
74
74
  */
@@ -80,7 +80,7 @@ exports.convertJsonFileSync = convertJsonFileSync;
80
80
  /**
81
81
  * Reads all JSON files from a directory and apply a supplied converter.
82
82
  * @param srcPath - The path of the folder to be read.
83
- * @param options - {@link Files.IDirectoryConvertOptions | Options} to control
83
+ * @param options - {@link JsonFile.IDirectoryConvertOptions | Options} to control
84
84
  * conversion and filtering
85
85
  * @public
86
86
  */
@@ -126,7 +126,7 @@ const defaultNameTransformer = (n) => (0, ts_utils_1.succeed)(n);
126
126
  * `Map<string, T>` indexed by file base name (i.e. minus the extension)
127
127
  * with an optional name transformation applied if present.
128
128
  * @param srcPath - The path of the folder to be read.
129
- * @param options - {@link Files.IDirectoryToMapConvertOptions | Options} to control conversion,
129
+ * @param options - {@link JsonFile.IDirectoryToMapConvertOptions | Options} to control conversion,
130
130
  * filtering and naming.
131
131
  * @public
132
132
  */
@@ -1 +1 @@
1
- {"version":3,"file":"file.js","sourceRoot":"","sources":["../../../src/packlets/json-file/file.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright (c) 2020 Erik Fortune\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport { Converter, Result, captureResult, fail, mapResults, succeed } from '@fgv/ts-utils';\nimport * as fs from 'fs';\nimport * as path from 'path';\n\nimport { JsonValue } from '../json';\n\n/**\n * Convenience function to read type-safe JSON from a file\n * @param srcPath - Path of the file to read\n * @returns `Success` with a {@link JsonValue | JsonValue} or `Failure`\n * with a message if an error occurs.\n * @public\n */\nexport function readJsonFileSync(srcPath: string): Result<JsonValue> {\n return captureResult(() => {\n const fullPath = path.resolve(srcPath);\n const body = fs.readFileSync(fullPath, 'utf8').toString();\n return JSON.parse(body) as JsonValue;\n });\n}\n\n/**\n * Convenience function to read a JSON file and apply a supplied converter.\n * @param srcPath - Path of the file to read.\n * @param converter - `Converter` used to convert the file contents\n * @returns `Success` with a result of type `<T>`, or `Failure`\n * with a message if an error occurs.\n * @public\n */\nexport function convertJsonFileSync<T>(srcPath: string, converter: Converter<T>): Result<T> {\n return readJsonFileSync(srcPath).onSuccess((json) => {\n return converter.convert(json);\n });\n}\n\n/**\n * Options for directory conversion.\n * TODO: add filtering, allowed and excluded.\n * @public\n */\nexport interface IDirectoryConvertOptions<T, TC = unknown> {\n /**\n * The converter used to convert incoming JSON objects.\n */\n converter: Converter<T, TC>;\n}\n\n/**\n * Return value for one item in a directory conversion.\n * @public\n */\nexport interface IReadDirectoryItem<T> {\n /**\n * Relative name of the file that was processed\n */\n filename: string;\n\n /**\n * The payload of the file.\n */\n item: T;\n}\n\n/**\n * Reads all JSON files from a directory and apply a supplied converter.\n * @param srcPath - The path of the folder to be read.\n * @param options - {@link Files.IDirectoryConvertOptions | Options} to control\n * conversion and filtering\n * @public\n */\nexport function convertJsonDirectorySync<T>(\n srcPath: string,\n options: IDirectoryConvertOptions<T>\n): Result<IReadDirectoryItem<T>[]> {\n return captureResult<IReadDirectoryItem<T>[]>(() => {\n const fullPath = path.resolve(srcPath);\n if (!fs.statSync(fullPath).isDirectory()) {\n throw new Error(`${fullPath}: Not a directory`);\n }\n const files = fs.readdirSync(fullPath, { withFileTypes: true });\n const results = files\n .map((fi) => {\n if (fi.isFile() && path.extname(fi.name) === '.json') {\n const filePath = path.resolve(fullPath, fi.name);\n return convertJsonFileSync(filePath, options.converter)\n .onSuccess((payload) => {\n return succeed({\n filename: fi.name,\n item: payload\n });\n })\n .onFailure((message) => {\n return fail(`${fi.name}: ${message}`);\n });\n }\n return undefined;\n })\n .filter((r): r is Result<IReadDirectoryItem<T>> => r !== undefined);\n return mapResults(results).orThrow();\n });\n}\n\n/**\n * Function to transform the name of a some entity, given an original name\n * and the contents of the entity.\n * @public\n */\nexport type ItemNameTransformFunction<T> = (name: string, item: T) => Result<string>;\n\n/**\n * Options controlling conversion of a directory.\n * @public\n */\nexport interface IDirectoryToMapConvertOptions<T, TC = unknown> extends IDirectoryConvertOptions<T, TC> {\n transformName?: ItemNameTransformFunction<T>;\n}\n\n/**\n * Function to transform the name of some entity, given only a previous name. This\n * default implementation always returns `Success` with the value that was passed in.\n * @param n - The name to be transformed.\n * @returns - `Success` with the string that was passed in.\n * @public\n */\nconst defaultNameTransformer = (n: string): Result<string> => succeed(n);\n\n/**\n * Reads and converts all JSON files from a directory, returning a\n * `Map<string, T>` indexed by file base name (i.e. minus the extension)\n * with an optional name transformation applied if present.\n * @param srcPath - The path of the folder to be read.\n * @param options - {@link Files.IDirectoryToMapConvertOptions | Options} to control conversion,\n * filtering and naming.\n * @public\n */\nexport function convertJsonDirectoryToMapSync<T, TC = unknown>(\n srcPath: string,\n options: IDirectoryToMapConvertOptions<T, TC>\n): Result<Map<string, T>> {\n return convertJsonDirectorySync(srcPath, options).onSuccess((items) => {\n const transformName = options.transformName ?? defaultNameTransformer;\n return mapResults(\n items.map((item) => {\n const basename = path.basename(item.filename, '.json');\n return transformName(basename, item.item).onSuccess((name) => {\n return succeed<[string, T]>([name, item.item]);\n });\n })\n ).onSuccess((items) => {\n return succeed(new Map<string, T>(items));\n });\n });\n}\n\n/**\n * Convenience function to write type-safe JSON to a file.\n * @param srcPath - Path of the file to write.\n * @param value - The {@link JsonValue | JsonValue} to be written.\n * @public\n */\nexport function writeJsonFileSync(srcPath: string, value: JsonValue): Result<boolean> {\n return captureResult(() => {\n const fullPath = path.resolve(srcPath);\n fs.writeFileSync(fullPath, JSON.stringify(value, undefined, 2));\n return true;\n });\n}\n"]}
1
+ {"version":3,"file":"file.js","sourceRoot":"","sources":["../../../src/packlets/json-file/file.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright (c) 2020 Erik Fortune\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport { Converter, Result, captureResult, fail, mapResults, succeed } from '@fgv/ts-utils';\nimport * as fs from 'fs';\nimport * as path from 'path';\n\nimport { JsonValue } from '../json';\n\n/**\n * Convenience function to read type-safe JSON from a file\n * @param srcPath - Path of the file to read\n * @returns `Success` with a {@link JsonValue | JsonValue} or `Failure`\n * with a message if an error occurs.\n * @public\n */\nexport function readJsonFileSync(srcPath: string): Result<JsonValue> {\n return captureResult(() => {\n const fullPath = path.resolve(srcPath);\n const body = fs.readFileSync(fullPath, 'utf8').toString();\n return JSON.parse(body) as JsonValue;\n });\n}\n\n/**\n * Convenience function to read a JSON file and apply a supplied converter.\n * @param srcPath - Path of the file to read.\n * @param converter - `Converter` used to convert the file contents\n * @returns `Success` with a result of type `<T>`, or `Failure`\n * with a message if an error occurs.\n * @public\n */\nexport function convertJsonFileSync<T>(srcPath: string, converter: Converter<T>): Result<T> {\n return readJsonFileSync(srcPath).onSuccess((json) => {\n return converter.convert(json);\n });\n}\n\n/**\n * Options for directory conversion.\n * TODO: add filtering, allowed and excluded.\n * @public\n */\nexport interface IDirectoryConvertOptions<T, TC = unknown> {\n /**\n * The converter used to convert incoming JSON objects.\n */\n converter: Converter<T, TC>;\n}\n\n/**\n * Return value for one item in a directory conversion.\n * @public\n */\nexport interface IReadDirectoryItem<T> {\n /**\n * Relative name of the file that was processed\n */\n filename: string;\n\n /**\n * The payload of the file.\n */\n item: T;\n}\n\n/**\n * Reads all JSON files from a directory and apply a supplied converter.\n * @param srcPath - The path of the folder to be read.\n * @param options - {@link JsonFile.IDirectoryConvertOptions | Options} to control\n * conversion and filtering\n * @public\n */\nexport function convertJsonDirectorySync<T>(\n srcPath: string,\n options: IDirectoryConvertOptions<T>\n): Result<IReadDirectoryItem<T>[]> {\n return captureResult<IReadDirectoryItem<T>[]>(() => {\n const fullPath = path.resolve(srcPath);\n if (!fs.statSync(fullPath).isDirectory()) {\n throw new Error(`${fullPath}: Not a directory`);\n }\n const files = fs.readdirSync(fullPath, { withFileTypes: true });\n const results = files\n .map((fi) => {\n if (fi.isFile() && path.extname(fi.name) === '.json') {\n const filePath = path.resolve(fullPath, fi.name);\n return convertJsonFileSync(filePath, options.converter)\n .onSuccess((payload) => {\n return succeed({\n filename: fi.name,\n item: payload\n });\n })\n .onFailure((message) => {\n return fail(`${fi.name}: ${message}`);\n });\n }\n return undefined;\n })\n .filter((r): r is Result<IReadDirectoryItem<T>> => r !== undefined);\n return mapResults(results).orThrow();\n });\n}\n\n/**\n * Function to transform the name of a some entity, given an original name\n * and the contents of the entity.\n * @public\n */\nexport type ItemNameTransformFunction<T> = (name: string, item: T) => Result<string>;\n\n/**\n * Options controlling conversion of a directory.\n * @public\n */\nexport interface IDirectoryToMapConvertOptions<T, TC = unknown> extends IDirectoryConvertOptions<T, TC> {\n transformName?: ItemNameTransformFunction<T>;\n}\n\n/**\n * Function to transform the name of some entity, given only a previous name. This\n * default implementation always returns `Success` with the value that was passed in.\n * @param n - The name to be transformed.\n * @returns - `Success` with the string that was passed in.\n * @public\n */\nconst defaultNameTransformer = (n: string): Result<string> => succeed(n);\n\n/**\n * Reads and converts all JSON files from a directory, returning a\n * `Map<string, T>` indexed by file base name (i.e. minus the extension)\n * with an optional name transformation applied if present.\n * @param srcPath - The path of the folder to be read.\n * @param options - {@link JsonFile.IDirectoryToMapConvertOptions | Options} to control conversion,\n * filtering and naming.\n * @public\n */\nexport function convertJsonDirectoryToMapSync<T, TC = unknown>(\n srcPath: string,\n options: IDirectoryToMapConvertOptions<T, TC>\n): Result<Map<string, T>> {\n return convertJsonDirectorySync(srcPath, options).onSuccess((items) => {\n const transformName = options.transformName ?? defaultNameTransformer;\n return mapResults(\n items.map((item) => {\n const basename = path.basename(item.filename, '.json');\n return transformName(basename, item.item).onSuccess((name) => {\n return succeed<[string, T]>([name, item.item]);\n });\n })\n ).onSuccess((items) => {\n return succeed(new Map<string, T>(items));\n });\n });\n}\n\n/**\n * Convenience function to write type-safe JSON to a file.\n * @param srcPath - Path of the file to write.\n * @param value - The {@link JsonValue | JsonValue} to be written.\n * @public\n */\nexport function writeJsonFileSync(srcPath: string, value: JsonValue): Result<boolean> {\n return captureResult(() => {\n const fullPath = path.resolve(srcPath);\n fs.writeFileSync(fullPath, JSON.stringify(value, undefined, 2));\n return true;\n });\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export * from './validators';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/packlets/validators/index.ts"],"names":[],"mappings":"AAsBA,cAAc,cAAc,CAAC"}
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright (c) 2020 Erik Fortune
4
+ *
5
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ * of this software and associated documentation files (the "Software"), to deal
7
+ * in the Software without restriction, including without limitation the rights
8
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ * copies of the Software, and to permit persons to whom the Software is
10
+ * furnished to do so, subject to the following conditions:
11
+ *
12
+ * The above copyright notice and this permission notice shall be included in all
13
+ * copies or substantial portions of the Software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ * SOFTWARE.
22
+ */
23
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
24
+ if (k2 === undefined) k2 = k;
25
+ var desc = Object.getOwnPropertyDescriptor(m, k);
26
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
27
+ desc = { enumerable: true, get: function() { return m[k]; } };
28
+ }
29
+ Object.defineProperty(o, k2, desc);
30
+ }) : (function(o, m, k, k2) {
31
+ if (k2 === undefined) k2 = k;
32
+ o[k2] = m[k];
33
+ }));
34
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
35
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
36
+ };
37
+ Object.defineProperty(exports, "__esModule", { value: true });
38
+ __exportStar(require("./validators"), exports);
39
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/packlets/validators/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;;;;;;;;;;;;;;;;AAEH,+CAA6B","sourcesContent":["/*\n * Copyright (c) 2020 Erik Fortune\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nexport * from './validators';\n"]}
@@ -0,0 +1,40 @@
1
+ import { Validator } from '@fgv/ts-utils';
2
+ import { JsonArray, JsonObject, JsonPrimitive, JsonValue } from '../json';
3
+ /**
4
+ * Validation context for in-place JSON validators.
5
+ * @public
6
+ */
7
+ export interface IJsonValidatorContext {
8
+ ignoreUndefinedProperties?: boolean;
9
+ }
10
+ /**
11
+ * An in-place validator which validates that a supplied `unknown` value is
12
+ * a valid {@link JsonPrimitive | JsonPrimitive}.
13
+ * @public
14
+ */
15
+ export declare const jsonPrimitive: Validator<JsonPrimitive, IJsonValidatorContext>;
16
+ /**
17
+ * An in-place validator which validates that a supplied `unknown` value is
18
+ * a valid {@link JsonObject | JsonObject}. Fails by default if any properties or array elements
19
+ * are `undefined` - this default behavior can be overridden by supplying an appropriate
20
+ * {@link Validators.IJsonValidatorContext | context} at runtime.
21
+ * @public
22
+ */
23
+ export declare const jsonObject: Validator<JsonObject, IJsonValidatorContext>;
24
+ /**
25
+ * An in-place validator which validates that a supplied `unknown` value is
26
+ * a valid {@link JsonArray | JsonArray}. Fails by default if any properties or array elements
27
+ * are `undefined` - this default behavior can be overridden by supplying an appropriate
28
+ * {@link Validators.IJsonValidatorContext | context} at runtime.
29
+ * @public
30
+ */
31
+ export declare const jsonArray: Validator<JsonArray, IJsonValidatorContext>;
32
+ /**
33
+ * An in-place validator which validates that a supplied `unknown` value is
34
+ * a valid {@link JsonValue | JsonValue}. Fails by default if any properties or array elements
35
+ * are `undefined` - this default behavior can be overridden by supplying an appropriate
36
+ * {@link Validators.IJsonValidatorContext | context} at runtime.
37
+ * @public
38
+ */
39
+ export declare const jsonValue: Validator<JsonValue, IJsonValidatorContext>;
40
+ //# sourceMappingURL=validators.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validators.d.ts","sourceRoot":"","sources":["../../../src/packlets/validators/validators.ts"],"names":[],"mappings":"AAsBA,OAAO,EAAuB,SAAS,EAAQ,MAAM,eAAe,CAAC;AACrE,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,aAAa,EAAE,SAAS,EAA6B,MAAM,SAAS,CAAC;AAIrG;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACpC,yBAAyB,CAAC,EAAE,OAAO,CAAC;CACrC;AAED;;;;GAIG;AACH,eAAO,MAAM,aAAa,EAAE,SAAS,CAAC,aAAa,EAAE,qBAAqB,CAqBtE,CAAC;AAEL;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,EAAE,SAAS,CAAC,UAAU,EAAE,qBAAqB,CAiBlE,CAAC;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,SAAS,EAAE,SAAS,CAAC,SAAS,EAAE,qBAAqB,CAkBhE,CAAC;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,SAAS,EAAE,SAAS,CAAC,SAAS,EAAE,qBAAqB,CAehE,CAAC"}
@@ -0,0 +1,125 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright (c) 2023 Erik Fortune
4
+ *
5
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ * of this software and associated documentation files (the "Software"), to deal
7
+ * in the Software without restriction, including without limitation the rights
8
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ * copies of the Software, and to permit persons to whom the Software is
10
+ * furnished to do so, subject to the following conditions:
11
+ *
12
+ * The above copyright notice and this permission notice shall be included in all
13
+ * copies or substantial portions of the Software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ * SOFTWARE.
22
+ */
23
+ Object.defineProperty(exports, "__esModule", { value: true });
24
+ exports.jsonValue = exports.jsonArray = exports.jsonObject = exports.jsonPrimitive = void 0;
25
+ const ts_utils_1 = require("@fgv/ts-utils");
26
+ const json_1 = require("../json");
27
+ /**
28
+ * An in-place validator which validates that a supplied `unknown` value is
29
+ * a valid {@link JsonPrimitive | JsonPrimitive}.
30
+ * @public
31
+ */
32
+ exports.jsonPrimitive = new ts_utils_1.Validation.Base.GenericValidator({
33
+ validator: (from, ctx) => {
34
+ if (from === null) {
35
+ return true;
36
+ }
37
+ switch (typeof from) {
38
+ case 'boolean':
39
+ case 'string':
40
+ return true;
41
+ case 'number':
42
+ if (!Number.isNaN(from)) {
43
+ return true;
44
+ }
45
+ break;
46
+ }
47
+ if (from === undefined && (ctx === null || ctx === void 0 ? void 0 : ctx.ignoreUndefinedProperties) === true) {
48
+ return true;
49
+ }
50
+ return (0, ts_utils_1.fail)(`"${String(from)}": not a valid JSON primitive.`);
51
+ }
52
+ });
53
+ /**
54
+ * An in-place validator which validates that a supplied `unknown` value is
55
+ * a valid {@link JsonObject | JsonObject}. Fails by default if any properties or array elements
56
+ * are `undefined` - this default behavior can be overridden by supplying an appropriate
57
+ * {@link Validators.IJsonValidatorContext | context} at runtime.
58
+ * @public
59
+ */
60
+ exports.jsonObject = new ts_utils_1.Validation.Base.GenericValidator({
61
+ validator: (from, ctx) => {
62
+ if (!(0, json_1.isJsonObject)(from)) {
63
+ return (0, ts_utils_1.fail)('not a valid JSON object.');
64
+ }
65
+ const errors = [];
66
+ for (const [name, value] of Object.entries(from)) {
67
+ exports.jsonValue.validate(value, ctx).onFailure((m) => {
68
+ errors.push(`${name}: ${m}`);
69
+ return (0, ts_utils_1.fail)(m);
70
+ });
71
+ }
72
+ if (errors.length > 0) {
73
+ return (0, ts_utils_1.fail)(`not a valid JSON object:\n${errors.join('\n')}`);
74
+ }
75
+ return true;
76
+ }
77
+ });
78
+ /**
79
+ * An in-place validator which validates that a supplied `unknown` value is
80
+ * a valid {@link JsonArray | JsonArray}. Fails by default if any properties or array elements
81
+ * are `undefined` - this default behavior can be overridden by supplying an appropriate
82
+ * {@link Validators.IJsonValidatorContext | context} at runtime.
83
+ * @public
84
+ */
85
+ exports.jsonArray = new ts_utils_1.Validation.Base.GenericValidator({
86
+ validator: (from, ctx) => {
87
+ if (!(0, json_1.isJsonArray)(from)) {
88
+ return (0, ts_utils_1.fail)('not an array');
89
+ }
90
+ const errors = [];
91
+ for (let i = 0; i < from.length; i++) {
92
+ const value = from[i];
93
+ exports.jsonValue.validate(value, ctx).onFailure((m) => {
94
+ errors.push(`${i}: ${m}`);
95
+ return (0, ts_utils_1.fail)(m);
96
+ });
97
+ }
98
+ if (errors.length > 0) {
99
+ return (0, ts_utils_1.fail)(`array contains non-json elements:\n${errors.join('\n')}`);
100
+ }
101
+ return true;
102
+ }
103
+ });
104
+ /**
105
+ * An in-place validator which validates that a supplied `unknown` value is
106
+ * a valid {@link JsonValue | JsonValue}. Fails by default if any properties or array elements
107
+ * are `undefined` - this default behavior can be overridden by supplying an appropriate
108
+ * {@link Validators.IJsonValidatorContext | context} at runtime.
109
+ * @public
110
+ */
111
+ exports.jsonValue = new ts_utils_1.Validation.Base.GenericValidator({
112
+ validator: (from, ctx) => {
113
+ if ((0, json_1.isJsonArray)(from)) {
114
+ const result = exports.jsonArray.validate(from, ctx);
115
+ return result.success === true ? true : result;
116
+ }
117
+ else if ((0, json_1.isJsonObject)(from)) {
118
+ const result = exports.jsonObject.validate(from, ctx);
119
+ return result.success === true ? true : result;
120
+ }
121
+ const result = exports.jsonPrimitive.validate(from, ctx);
122
+ return result.success === true ? true : result;
123
+ }
124
+ });
125
+ //# sourceMappingURL=validators.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validators.js","sourceRoot":"","sources":["../../../src/packlets/validators/validators.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright (c) 2023 Erik Fortune\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport { Failure, Validation, Validator, fail } from '@fgv/ts-utils';\nimport { JsonArray, JsonObject, JsonPrimitive, JsonValue, isJsonArray, isJsonObject } from '../json';\n\n/* eslint-disable no-use-before-define, @typescript-eslint/no-use-before-define */\n\n/**\n * Validation context for in-place JSON validators.\n * @public\n */\nexport interface IJsonValidatorContext {\n ignoreUndefinedProperties?: boolean;\n}\n\n/**\n * An in-place validator which validates that a supplied `unknown` value is\n * a valid {@link JsonPrimitive | JsonPrimitive}.\n * @public\n */\nexport const jsonPrimitive: Validator<JsonPrimitive, IJsonValidatorContext> =\n new Validation.Base.GenericValidator({\n validator: (from: unknown, ctx?: IJsonValidatorContext): boolean | Failure<JsonPrimitive> => {\n if (from === null) {\n return true;\n }\n switch (typeof from) {\n case 'boolean':\n case 'string':\n return true;\n case 'number':\n if (!Number.isNaN(from)) {\n return true;\n }\n break;\n }\n if (from === undefined && ctx?.ignoreUndefinedProperties === true) {\n return true;\n }\n return fail(`\"${String(from)}\": not a valid JSON primitive.`);\n }\n });\n\n/**\n * An in-place validator which validates that a supplied `unknown` value is\n * a valid {@link JsonObject | JsonObject}. Fails by default if any properties or array elements\n * are `undefined` - this default behavior can be overridden by supplying an appropriate\n * {@link Validators.IJsonValidatorContext | context} at runtime.\n * @public\n */\nexport const jsonObject: Validator<JsonObject, IJsonValidatorContext> = new Validation.Base.GenericValidator({\n validator: (from: unknown, ctx?: IJsonValidatorContext) => {\n if (!isJsonObject(from)) {\n return fail('not a valid JSON object.');\n }\n const errors: string[] = [];\n for (const [name, value] of Object.entries(from)) {\n jsonValue.validate(value, ctx).onFailure((m) => {\n errors.push(`${name}: ${m}`);\n return fail(m);\n });\n }\n if (errors.length > 0) {\n return fail(`not a valid JSON object:\\n${errors.join('\\n')}`);\n }\n return true;\n }\n});\n\n/**\n * An in-place validator which validates that a supplied `unknown` value is\n * a valid {@link JsonArray | JsonArray}. Fails by default if any properties or array elements\n * are `undefined` - this default behavior can be overridden by supplying an appropriate\n * {@link Validators.IJsonValidatorContext | context} at runtime.\n * @public\n */\nexport const jsonArray: Validator<JsonArray, IJsonValidatorContext> = new Validation.Base.GenericValidator({\n validator: (from: unknown, ctx?: IJsonValidatorContext) => {\n if (!isJsonArray(from)) {\n return fail('not an array');\n }\n const errors: string[] = [];\n for (let i = 0; i < from.length; i++) {\n const value = from[i];\n jsonValue.validate(value, ctx).onFailure((m) => {\n errors.push(`${i}: ${m}`);\n return fail(m);\n });\n }\n if (errors.length > 0) {\n return fail(`array contains non-json elements:\\n${errors.join('\\n')}`);\n }\n return true;\n }\n});\n\n/**\n * An in-place validator which validates that a supplied `unknown` value is\n * a valid {@link JsonValue | JsonValue}. Fails by default if any properties or array elements\n * are `undefined` - this default behavior can be overridden by supplying an appropriate\n * {@link Validators.IJsonValidatorContext | context} at runtime.\n * @public\n */\nexport const jsonValue: Validator<JsonValue, IJsonValidatorContext> = new Validation.Base.GenericValidator<\n JsonValue,\n IJsonValidatorContext\n>({\n validator: (from: unknown, ctx?: IJsonValidatorContext) => {\n if (isJsonArray(from)) {\n const result = jsonArray.validate(from, ctx);\n return result.success === true ? true : result;\n } else if (isJsonObject(from)) {\n const result = jsonObject.validate(from, ctx);\n return result.success === true ? true : result;\n }\n const result = jsonPrimitive.validate(from, ctx);\n return result.success === true ? true : result;\n }\n});\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fgv/ts-json-base",
3
- "version": "2.1.1-alpha.2",
3
+ "version": "3.0.0-alpha.1",
4
4
  "description": "Typescript types and basic functions for working with json",
5
5
  "main": "lib/index.js",
6
6
  "types": "dist/ts-json-base.d.ts",
@@ -16,8 +16,8 @@
16
16
  "homepage": "https://github.com/ErikFortune/fgv/tree/main/libraries/ts-json-base#readme",
17
17
  "sideEffects": false,
18
18
  "devDependencies": {
19
- "@fgv/ts-utils": "2.1.1-alpha.2",
20
- "@fgv/ts-utils-jest": "2.1.1-alpha.2",
19
+ "@fgv/ts-utils": "3.0.0-alpha.1",
20
+ "@fgv/ts-utils-jest": "3.0.0-alpha.1",
21
21
  "@types/jest": "^29.5.11",
22
22
  "@types/mustache": "^4.2.5",
23
23
  "@types/node": "^20.11.5",
@@ -43,7 +43,7 @@
43
43
  "@microsoft/api-documenter": "^7.23.17"
44
44
  },
45
45
  "peerDependencies": {
46
- "@fgv/ts-utils": "^2.1.1-alpha.2",
46
+ "@fgv/ts-utils": "^3.0.0-alpha.1",
47
47
  "mustache": "^4.2.0"
48
48
  },
49
49
  "scripts": {