@fgv/ts-json-base 5.1.0-21 → 5.1.0-23
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/dist/packlets/converters/converters.js +11 -0
- package/dist/packlets/converters/converters.js.map +1 -1
- package/dist/ts-json-base.d.ts +29 -0
- package/lib/packlets/converters/converters.d.ts +27 -1
- package/lib/packlets/converters/converters.d.ts.map +1 -1
- package/lib/packlets/converters/converters.js +12 -0
- package/lib/packlets/converters/converters.js.map +1 -1
- package/package.json +6 -6
|
@@ -184,6 +184,17 @@ export function enumeratedValue(values, message) {
|
|
|
184
184
|
return fail(message !== null && message !== void 0 ? message : `Invalid enumerated value ${JSON.stringify(from)}`);
|
|
185
185
|
});
|
|
186
186
|
}
|
|
187
|
+
export function stringifiedJson(inner) {
|
|
188
|
+
const step = inner !== null && inner !== void 0 ? inner : jsonValue;
|
|
189
|
+
return new Conversion.BaseConverter((from) => {
|
|
190
|
+
if (typeof from !== 'string') {
|
|
191
|
+
return fail('stringifiedJson: input must be a string.');
|
|
192
|
+
}
|
|
193
|
+
return captureResult(() => JSON.parse(from))
|
|
194
|
+
.withErrorFormat((msg) => `stringifiedJson: failed to parse JSON: ${msg}`)
|
|
195
|
+
.onSuccess((parsed) => step.convert(parsed));
|
|
196
|
+
});
|
|
197
|
+
}
|
|
187
198
|
/**
|
|
188
199
|
* Creates a converter that parses JSON string content and then applies the supplied converter.
|
|
189
200
|
* @param converter - Converter to apply to the parsed JSON
|
|
@@ -1 +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 {\n Conversion,\n Converter,\n Converters as BaseConverters,\n Result,\n StringConverter,\n captureResult,\n fail,\n succeed\n} from '@fgv/ts-utils';\nimport { JsonArray, JsonObject, JsonPrimitive, JsonValue, isJsonArray, isJsonObject } from '../json';\n\n/* eslint-disable @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)}\": invalid 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 * `IJsonConverterContext` 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('invalid 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(`invalid 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 * `IJsonConverterContext` 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 * `IJsonConverterContext` 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\n/**\n * A `StringConverter` which converts `unknown` to a `string`.\n * Accepts `IJsonConverterContext` but ignores it.\n * @public\n */\nexport const string: StringConverter<string, IJsonConverterContext> = new StringConverter<\n string,\n IJsonConverterContext\n>();\n\n/**\n * A `Converter` which converts `unknown` to a `number`.\n * Accepts `IJsonConverterContext` but ignores it.\n * Mirrors the behavior of `@fgv/ts-utils`.\n * @public\n */\nexport const number: Converter<number, IJsonConverterContext> = new Conversion.BaseConverter<\n number,\n IJsonConverterContext\n>((from: unknown): Result<number> => BaseConverters.number.convert(from));\n\n/**\n * A `Converter` which converts `unknown` to a `boolean`.\n * Accepts `IJsonConverterContext` but ignores it.\n * Mirrors the behavior of `@fgv/ts-utils`.\n * @public\n */\nexport const boolean: Converter<boolean, IJsonConverterContext> = new Conversion.BaseConverter<\n boolean,\n IJsonConverterContext\n>((from: unknown): Result<boolean> => BaseConverters.boolean.convert(from));\n\n/**\n * Helper to create a converter for a literal value.\n * Accepts `IJsonConverterContext` but ignores it.\n * Mirrors the behavior of `@fgv/ts-utils`.\n * @public\n */\nexport function literal<T>(value: T): Converter<T, IJsonConverterContext> {\n return BaseConverters.literal<T, IJsonConverterContext>(value);\n}\n\n/**\n * Helper function to create a `Converter` which converts `unknown` to one of a set of\n * supplied enumerated values. Anything else fails.\n *\n * @remarks\n * This JSON variant accepts an `IJsonConverterContext` OR\n * a `ReadonlyArray<T>` as its conversion context. If the context is an array, it is used to override the\n * allowed values for that conversion; otherwise, the original `values` supplied at creation time are used.\n *\n * @param values - Array of allowed values.\n * @param message - Optional custom failure message.\n * @returns A new `Converter` returning `<T>`.\n * @public\n */\nexport function enumeratedValue<T>(\n values: ReadonlyArray<T>,\n message?: string\n): Converter<T, IJsonConverterContext | ReadonlyArray<T>> {\n return new Conversion.BaseConverter<T, IJsonConverterContext | ReadonlyArray<T>>(\n (\n from: unknown,\n __self: Converter<T, IJsonConverterContext | ReadonlyArray<T>>,\n context?: IJsonConverterContext | ReadonlyArray<T>\n ): Result<T> => {\n const effectiveValues = Array.isArray(context) ? (context as ReadonlyArray<T>) : values;\n const index = effectiveValues.indexOf(from as T);\n if (index >= 0) {\n return succeed(effectiveValues[index]);\n }\n return fail(message ?? `Invalid enumerated value ${JSON.stringify(from)}`);\n }\n );\n}\n\n/**\n * Creates a converter that parses JSON string content and then applies the supplied converter.\n * @param converter - Converter to apply to the parsed JSON\n * @returns Converter that parses JSON then validates\n * @public\n */\nexport function jsonConverter<T>(converter: Converter<T>): Converter<T> {\n return new Conversion.BaseConverter<T>((from: unknown): Result<T> => {\n if (typeof from !== 'string') {\n return fail('Input must be a string');\n }\n\n const parseResult = captureResult(() => JSON.parse(from));\n if (parseResult.isFailure()) {\n return fail(`Failed to parse JSON: ${parseResult.message}`);\n }\n\n const parsed = parseResult.value;\n if (typeof parsed !== 'object' || parsed === null) {\n return fail('Failed to parse JSON: JSON content must be an object');\n }\n\n return converter.convert(parsed);\n });\n}\n"]}
|
|
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 {\n Conversion,\n Converter,\n Converters as BaseConverters,\n Result,\n StringConverter,\n Validator,\n captureResult,\n fail,\n succeed\n} from '@fgv/ts-utils';\nimport { JsonArray, JsonObject, JsonPrimitive, JsonValue, isJsonArray, isJsonObject } from '../json';\n\n/* eslint-disable @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)}\": invalid 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 * `IJsonConverterContext` 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('invalid 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(`invalid 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 * `IJsonConverterContext` 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 * `IJsonConverterContext` 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\n/**\n * A `StringConverter` which converts `unknown` to a `string`.\n * Accepts `IJsonConverterContext` but ignores it.\n * @public\n */\nexport const string: StringConverter<string, IJsonConverterContext> = new StringConverter<\n string,\n IJsonConverterContext\n>();\n\n/**\n * A `Converter` which converts `unknown` to a `number`.\n * Accepts `IJsonConverterContext` but ignores it.\n * Mirrors the behavior of `@fgv/ts-utils`.\n * @public\n */\nexport const number: Converter<number, IJsonConverterContext> = new Conversion.BaseConverter<\n number,\n IJsonConverterContext\n>((from: unknown): Result<number> => BaseConverters.number.convert(from));\n\n/**\n * A `Converter` which converts `unknown` to a `boolean`.\n * Accepts `IJsonConverterContext` but ignores it.\n * Mirrors the behavior of `@fgv/ts-utils`.\n * @public\n */\nexport const boolean: Converter<boolean, IJsonConverterContext> = new Conversion.BaseConverter<\n boolean,\n IJsonConverterContext\n>((from: unknown): Result<boolean> => BaseConverters.boolean.convert(from));\n\n/**\n * Helper to create a converter for a literal value.\n * Accepts `IJsonConverterContext` but ignores it.\n * Mirrors the behavior of `@fgv/ts-utils`.\n * @public\n */\nexport function literal<T>(value: T): Converter<T, IJsonConverterContext> {\n return BaseConverters.literal<T, IJsonConverterContext>(value);\n}\n\n/**\n * Helper function to create a `Converter` which converts `unknown` to one of a set of\n * supplied enumerated values. Anything else fails.\n *\n * @remarks\n * This JSON variant accepts an `IJsonConverterContext` OR\n * a `ReadonlyArray<T>` as its conversion context. If the context is an array, it is used to override the\n * allowed values for that conversion; otherwise, the original `values` supplied at creation time are used.\n *\n * @param values - Array of allowed values.\n * @param message - Optional custom failure message.\n * @returns A new `Converter` returning `<T>`.\n * @public\n */\nexport function enumeratedValue<T>(\n values: ReadonlyArray<T>,\n message?: string\n): Converter<T, IJsonConverterContext | ReadonlyArray<T>> {\n return new Conversion.BaseConverter<T, IJsonConverterContext | ReadonlyArray<T>>(\n (\n from: unknown,\n __self: Converter<T, IJsonConverterContext | ReadonlyArray<T>>,\n context?: IJsonConverterContext | ReadonlyArray<T>\n ): Result<T> => {\n const effectiveValues = Array.isArray(context) ? (context as ReadonlyArray<T>) : values;\n const index = effectiveValues.indexOf(from as T);\n if (index >= 0) {\n return succeed(effectiveValues[index]);\n }\n return fail(message ?? `Invalid enumerated value ${JSON.stringify(from)}`);\n }\n );\n}\n\n/**\n * Creates a converter that accepts a string, parses it as JSON, and optionally\n * applies the supplied inner converter or validator to the parsed value.\n *\n * @remarks\n * Unlike {@link Converters.jsonConverter}, the inner step is optional. When omitted, the\n * converter resolves to the parsed `JsonValue` (object, array, or primitive).\n * Both `Converter<T>` and `Validator<T>` are accepted because both expose\n * `convert(unknown): Result<T>`.\n *\n * @param inner - Optional `Converter<T>` or `Validator<T>` applied to the\n * parsed JSON value.\n * @returns Converter that parses a JSON string into `T` (or `JsonValue` when\n * no inner step is supplied).\n * @public\n */\nexport function stringifiedJson(): Converter<JsonValue>;\n/**\n * Creates a converter that accepts a string, parses it as JSON, and applies\n * the supplied inner converter or validator to the parsed value.\n *\n * @param inner - `Converter<T>` or `Validator<T>` applied to the parsed JSON.\n * @returns Converter that parses a JSON string into `T`.\n * @public\n */\nexport function stringifiedJson<T>(inner: Converter<T> | Validator<T>): Converter<T>;\nexport function stringifiedJson<T>(inner?: Converter<T> | Validator<T>): Converter<T | JsonValue> {\n const step: { convert(from: unknown): Result<T | JsonValue> } = inner ?? jsonValue;\n return new Conversion.BaseConverter<T | JsonValue>((from: unknown): Result<T | JsonValue> => {\n if (typeof from !== 'string') {\n return fail('stringifiedJson: input must be a string.');\n }\n return captureResult<unknown>(() => JSON.parse(from))\n .withErrorFormat((msg) => `stringifiedJson: failed to parse JSON: ${msg}`)\n .onSuccess((parsed) => step.convert(parsed));\n });\n}\n\n/**\n * Creates a converter that parses JSON string content and then applies the supplied converter.\n * @param converter - Converter to apply to the parsed JSON\n * @returns Converter that parses JSON then validates\n * @public\n */\nexport function jsonConverter<T>(converter: Converter<T>): Converter<T> {\n return new Conversion.BaseConverter<T>((from: unknown): Result<T> => {\n if (typeof from !== 'string') {\n return fail('Input must be a string');\n }\n\n const parseResult = captureResult(() => JSON.parse(from));\n if (parseResult.isFailure()) {\n return fail(`Failed to parse JSON: ${parseResult.message}`);\n }\n\n const parsed = parseResult.value;\n if (typeof parsed !== 'object' || parsed === null) {\n return fail('Failed to parse JSON: JSON content must be an object');\n }\n\n return converter.convert(parsed);\n });\n}\n"]}
|
package/dist/ts-json-base.d.ts
CHANGED
|
@@ -105,6 +105,7 @@ declare namespace Converters {
|
|
|
105
105
|
export {
|
|
106
106
|
literal,
|
|
107
107
|
enumeratedValue,
|
|
108
|
+
stringifiedJson,
|
|
108
109
|
jsonConverter,
|
|
109
110
|
IJsonConverterContext,
|
|
110
111
|
jsonPrimitive,
|
|
@@ -1819,6 +1820,34 @@ declare const string: StringConverter<string, IJsonConverterContext>;
|
|
|
1819
1820
|
*/
|
|
1820
1821
|
declare const string_2: Validation.Classes.StringValidator<string, IJsonValidatorContext>;
|
|
1821
1822
|
|
|
1823
|
+
/**
|
|
1824
|
+
* Creates a converter that accepts a string, parses it as JSON, and optionally
|
|
1825
|
+
* applies the supplied inner converter or validator to the parsed value.
|
|
1826
|
+
*
|
|
1827
|
+
* @remarks
|
|
1828
|
+
* Unlike {@link Converters.jsonConverter}, the inner step is optional. When omitted, the
|
|
1829
|
+
* converter resolves to the parsed `JsonValue` (object, array, or primitive).
|
|
1830
|
+
* Both `Converter<T>` and `Validator<T>` are accepted because both expose
|
|
1831
|
+
* `convert(unknown): Result<T>`.
|
|
1832
|
+
*
|
|
1833
|
+
* @param inner - Optional `Converter<T>` or `Validator<T>` applied to the
|
|
1834
|
+
* parsed JSON value.
|
|
1835
|
+
* @returns Converter that parses a JSON string into `T` (or `JsonValue` when
|
|
1836
|
+
* no inner step is supplied).
|
|
1837
|
+
* @public
|
|
1838
|
+
*/
|
|
1839
|
+
declare function stringifiedJson(): Converter<JsonValue>;
|
|
1840
|
+
|
|
1841
|
+
/**
|
|
1842
|
+
* Creates a converter that accepts a string, parses it as JSON, and applies
|
|
1843
|
+
* the supplied inner converter or validator to the parsed value.
|
|
1844
|
+
*
|
|
1845
|
+
* @param inner - `Converter<T>` or `Validator<T>` applied to the parsed JSON.
|
|
1846
|
+
* @returns Converter that parses a JSON string into `T`.
|
|
1847
|
+
* @public
|
|
1848
|
+
*/
|
|
1849
|
+
declare function stringifiedJson<T>(inner: Converter<T> | Validator<T>): Converter<T>;
|
|
1850
|
+
|
|
1822
1851
|
/**
|
|
1823
1852
|
* A validator which validates a supplied `unknown` value to a valid {@link JsonCompatibleType | JsonCompatible} value.
|
|
1824
1853
|
* @public
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Converter, StringConverter } from '@fgv/ts-utils';
|
|
1
|
+
import { Converter, StringConverter, Validator } from '@fgv/ts-utils';
|
|
2
2
|
import { JsonArray, JsonObject, JsonPrimitive, JsonValue } from '../json';
|
|
3
3
|
/**
|
|
4
4
|
* Conversion context for JSON converters.
|
|
@@ -82,6 +82,32 @@ export declare function literal<T>(value: T): Converter<T, IJsonConverterContext
|
|
|
82
82
|
* @public
|
|
83
83
|
*/
|
|
84
84
|
export declare function enumeratedValue<T>(values: ReadonlyArray<T>, message?: string): Converter<T, IJsonConverterContext | ReadonlyArray<T>>;
|
|
85
|
+
/**
|
|
86
|
+
* Creates a converter that accepts a string, parses it as JSON, and optionally
|
|
87
|
+
* applies the supplied inner converter or validator to the parsed value.
|
|
88
|
+
*
|
|
89
|
+
* @remarks
|
|
90
|
+
* Unlike {@link Converters.jsonConverter}, the inner step is optional. When omitted, the
|
|
91
|
+
* converter resolves to the parsed `JsonValue` (object, array, or primitive).
|
|
92
|
+
* Both `Converter<T>` and `Validator<T>` are accepted because both expose
|
|
93
|
+
* `convert(unknown): Result<T>`.
|
|
94
|
+
*
|
|
95
|
+
* @param inner - Optional `Converter<T>` or `Validator<T>` applied to the
|
|
96
|
+
* parsed JSON value.
|
|
97
|
+
* @returns Converter that parses a JSON string into `T` (or `JsonValue` when
|
|
98
|
+
* no inner step is supplied).
|
|
99
|
+
* @public
|
|
100
|
+
*/
|
|
101
|
+
export declare function stringifiedJson(): Converter<JsonValue>;
|
|
102
|
+
/**
|
|
103
|
+
* Creates a converter that accepts a string, parses it as JSON, and applies
|
|
104
|
+
* the supplied inner converter or validator to the parsed value.
|
|
105
|
+
*
|
|
106
|
+
* @param inner - `Converter<T>` or `Validator<T>` applied to the parsed JSON.
|
|
107
|
+
* @returns Converter that parses a JSON string into `T`.
|
|
108
|
+
* @public
|
|
109
|
+
*/
|
|
110
|
+
export declare function stringifiedJson<T>(inner: Converter<T> | Validator<T>): Converter<T>;
|
|
85
111
|
/**
|
|
86
112
|
* Creates a converter that parses JSON string content and then applies the supplied converter.
|
|
87
113
|
* @param converter - Converter to apply to the parsed JSON
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"converters.d.ts","sourceRoot":"","sources":["../../../src/packlets/converters/converters.ts"],"names":[],"mappings":"AAsBA,OAAO,EAEL,SAAS,EAGT,eAAe,
|
|
1
|
+
{"version":3,"file":"converters.d.ts","sourceRoot":"","sources":["../../../src/packlets/converters/converters.ts"],"names":[],"mappings":"AAsBA,OAAO,EAEL,SAAS,EAGT,eAAe,EACf,SAAS,EAIV,MAAM,eAAe,CAAC;AACvB,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;AAEF;;;;GAIG;AACH,eAAO,MAAM,MAAM,EAAE,eAAe,CAAC,MAAM,EAAE,qBAAqB,CAG/D,CAAC;AAEJ;;;;;GAKG;AACH,eAAO,MAAM,MAAM,EAAE,SAAS,CAAC,MAAM,EAAE,qBAAqB,CAGa,CAAC;AAE1E;;;;;GAKG;AACH,eAAO,MAAM,OAAO,EAAE,SAAS,CAAC,OAAO,EAAE,qBAAqB,CAGa,CAAC;AAE5E;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,SAAS,CAAC,CAAC,EAAE,qBAAqB,CAAC,CAExE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAC/B,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC,EACxB,OAAO,CAAC,EAAE,MAAM,GACf,SAAS,CAAC,CAAC,EAAE,qBAAqB,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC,CAexD;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,eAAe,IAAI,SAAS,CAAC,SAAS,CAAC,CAAC;AACxD;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;AAarF;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAkBtE"}
|
|
@@ -24,6 +24,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
24
24
|
exports.boolean = exports.number = exports.string = exports.jsonValue = exports.jsonArray = exports.jsonObject = exports.jsonPrimitive = void 0;
|
|
25
25
|
exports.literal = literal;
|
|
26
26
|
exports.enumeratedValue = enumeratedValue;
|
|
27
|
+
exports.stringifiedJson = stringifiedJson;
|
|
27
28
|
exports.jsonConverter = jsonConverter;
|
|
28
29
|
const ts_utils_1 = require("@fgv/ts-utils");
|
|
29
30
|
const json_1 = require("../json");
|
|
@@ -190,6 +191,17 @@ function enumeratedValue(values, message) {
|
|
|
190
191
|
return (0, ts_utils_1.fail)(message !== null && message !== void 0 ? message : `Invalid enumerated value ${JSON.stringify(from)}`);
|
|
191
192
|
});
|
|
192
193
|
}
|
|
194
|
+
function stringifiedJson(inner) {
|
|
195
|
+
const step = inner !== null && inner !== void 0 ? inner : exports.jsonValue;
|
|
196
|
+
return new ts_utils_1.Conversion.BaseConverter((from) => {
|
|
197
|
+
if (typeof from !== 'string') {
|
|
198
|
+
return (0, ts_utils_1.fail)('stringifiedJson: input must be a string.');
|
|
199
|
+
}
|
|
200
|
+
return (0, ts_utils_1.captureResult)(() => JSON.parse(from))
|
|
201
|
+
.withErrorFormat((msg) => `stringifiedJson: failed to parse JSON: ${msg}`)
|
|
202
|
+
.onSuccess((parsed) => step.convert(parsed));
|
|
203
|
+
});
|
|
204
|
+
}
|
|
193
205
|
/**
|
|
194
206
|
* Creates a converter that parses JSON string content and then applies the supplied converter.
|
|
195
207
|
* @param converter - Converter to apply to the parsed JSON
|
|
@@ -1 +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 {\n Conversion,\n Converter,\n Converters as BaseConverters,\n Result,\n StringConverter,\n captureResult,\n fail,\n succeed\n} from '@fgv/ts-utils';\nimport { JsonArray, JsonObject, JsonPrimitive, JsonValue, isJsonArray, isJsonObject } from '../json';\n\n/* eslint-disable @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)}\": invalid 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 * `IJsonConverterContext` 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('invalid 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(`invalid 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 * `IJsonConverterContext` 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 * `IJsonConverterContext` 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\n/**\n * A `StringConverter` which converts `unknown` to a `string`.\n * Accepts `IJsonConverterContext` but ignores it.\n * @public\n */\nexport const string: StringConverter<string, IJsonConverterContext> = new StringConverter<\n string,\n IJsonConverterContext\n>();\n\n/**\n * A `Converter` which converts `unknown` to a `number`.\n * Accepts `IJsonConverterContext` but ignores it.\n * Mirrors the behavior of `@fgv/ts-utils`.\n * @public\n */\nexport const number: Converter<number, IJsonConverterContext> = new Conversion.BaseConverter<\n number,\n IJsonConverterContext\n>((from: unknown): Result<number> => BaseConverters.number.convert(from));\n\n/**\n * A `Converter` which converts `unknown` to a `boolean`.\n * Accepts `IJsonConverterContext` but ignores it.\n * Mirrors the behavior of `@fgv/ts-utils`.\n * @public\n */\nexport const boolean: Converter<boolean, IJsonConverterContext> = new Conversion.BaseConverter<\n boolean,\n IJsonConverterContext\n>((from: unknown): Result<boolean> => BaseConverters.boolean.convert(from));\n\n/**\n * Helper to create a converter for a literal value.\n * Accepts `IJsonConverterContext` but ignores it.\n * Mirrors the behavior of `@fgv/ts-utils`.\n * @public\n */\nexport function literal<T>(value: T): Converter<T, IJsonConverterContext> {\n return BaseConverters.literal<T, IJsonConverterContext>(value);\n}\n\n/**\n * Helper function to create a `Converter` which converts `unknown` to one of a set of\n * supplied enumerated values. Anything else fails.\n *\n * @remarks\n * This JSON variant accepts an `IJsonConverterContext` OR\n * a `ReadonlyArray<T>` as its conversion context. If the context is an array, it is used to override the\n * allowed values for that conversion; otherwise, the original `values` supplied at creation time are used.\n *\n * @param values - Array of allowed values.\n * @param message - Optional custom failure message.\n * @returns A new `Converter` returning `<T>`.\n * @public\n */\nexport function enumeratedValue<T>(\n values: ReadonlyArray<T>,\n message?: string\n): Converter<T, IJsonConverterContext | ReadonlyArray<T>> {\n return new Conversion.BaseConverter<T, IJsonConverterContext | ReadonlyArray<T>>(\n (\n from: unknown,\n __self: Converter<T, IJsonConverterContext | ReadonlyArray<T>>,\n context?: IJsonConverterContext | ReadonlyArray<T>\n ): Result<T> => {\n const effectiveValues = Array.isArray(context) ? (context as ReadonlyArray<T>) : values;\n const index = effectiveValues.indexOf(from as T);\n if (index >= 0) {\n return succeed(effectiveValues[index]);\n }\n return fail(message ?? `Invalid enumerated value ${JSON.stringify(from)}`);\n }\n );\n}\n\n/**\n * Creates a converter that parses JSON string content and then applies the supplied converter.\n * @param converter - Converter to apply to the parsed JSON\n * @returns Converter that parses JSON then validates\n * @public\n */\nexport function jsonConverter<T>(converter: Converter<T>): Converter<T> {\n return new Conversion.BaseConverter<T>((from: unknown): Result<T> => {\n if (typeof from !== 'string') {\n return fail('Input must be a string');\n }\n\n const parseResult = captureResult(() => JSON.parse(from));\n if (parseResult.isFailure()) {\n return fail(`Failed to parse JSON: ${parseResult.message}`);\n }\n\n const parsed = parseResult.value;\n if (typeof parsed !== 'object' || parsed === null) {\n return fail('Failed to parse JSON: JSON content must be an object');\n }\n\n return converter.convert(parsed);\n });\n}\n"]}
|
|
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 {\n Conversion,\n Converter,\n Converters as BaseConverters,\n Result,\n StringConverter,\n Validator,\n captureResult,\n fail,\n succeed\n} from '@fgv/ts-utils';\nimport { JsonArray, JsonObject, JsonPrimitive, JsonValue, isJsonArray, isJsonObject } from '../json';\n\n/* eslint-disable @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)}\": invalid 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 * `IJsonConverterContext` 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('invalid 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(`invalid 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 * `IJsonConverterContext` 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 * `IJsonConverterContext` 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\n/**\n * A `StringConverter` which converts `unknown` to a `string`.\n * Accepts `IJsonConverterContext` but ignores it.\n * @public\n */\nexport const string: StringConverter<string, IJsonConverterContext> = new StringConverter<\n string,\n IJsonConverterContext\n>();\n\n/**\n * A `Converter` which converts `unknown` to a `number`.\n * Accepts `IJsonConverterContext` but ignores it.\n * Mirrors the behavior of `@fgv/ts-utils`.\n * @public\n */\nexport const number: Converter<number, IJsonConverterContext> = new Conversion.BaseConverter<\n number,\n IJsonConverterContext\n>((from: unknown): Result<number> => BaseConverters.number.convert(from));\n\n/**\n * A `Converter` which converts `unknown` to a `boolean`.\n * Accepts `IJsonConverterContext` but ignores it.\n * Mirrors the behavior of `@fgv/ts-utils`.\n * @public\n */\nexport const boolean: Converter<boolean, IJsonConverterContext> = new Conversion.BaseConverter<\n boolean,\n IJsonConverterContext\n>((from: unknown): Result<boolean> => BaseConverters.boolean.convert(from));\n\n/**\n * Helper to create a converter for a literal value.\n * Accepts `IJsonConverterContext` but ignores it.\n * Mirrors the behavior of `@fgv/ts-utils`.\n * @public\n */\nexport function literal<T>(value: T): Converter<T, IJsonConverterContext> {\n return BaseConverters.literal<T, IJsonConverterContext>(value);\n}\n\n/**\n * Helper function to create a `Converter` which converts `unknown` to one of a set of\n * supplied enumerated values. Anything else fails.\n *\n * @remarks\n * This JSON variant accepts an `IJsonConverterContext` OR\n * a `ReadonlyArray<T>` as its conversion context. If the context is an array, it is used to override the\n * allowed values for that conversion; otherwise, the original `values` supplied at creation time are used.\n *\n * @param values - Array of allowed values.\n * @param message - Optional custom failure message.\n * @returns A new `Converter` returning `<T>`.\n * @public\n */\nexport function enumeratedValue<T>(\n values: ReadonlyArray<T>,\n message?: string\n): Converter<T, IJsonConverterContext | ReadonlyArray<T>> {\n return new Conversion.BaseConverter<T, IJsonConverterContext | ReadonlyArray<T>>(\n (\n from: unknown,\n __self: Converter<T, IJsonConverterContext | ReadonlyArray<T>>,\n context?: IJsonConverterContext | ReadonlyArray<T>\n ): Result<T> => {\n const effectiveValues = Array.isArray(context) ? (context as ReadonlyArray<T>) : values;\n const index = effectiveValues.indexOf(from as T);\n if (index >= 0) {\n return succeed(effectiveValues[index]);\n }\n return fail(message ?? `Invalid enumerated value ${JSON.stringify(from)}`);\n }\n );\n}\n\n/**\n * Creates a converter that accepts a string, parses it as JSON, and optionally\n * applies the supplied inner converter or validator to the parsed value.\n *\n * @remarks\n * Unlike {@link Converters.jsonConverter}, the inner step is optional. When omitted, the\n * converter resolves to the parsed `JsonValue` (object, array, or primitive).\n * Both `Converter<T>` and `Validator<T>` are accepted because both expose\n * `convert(unknown): Result<T>`.\n *\n * @param inner - Optional `Converter<T>` or `Validator<T>` applied to the\n * parsed JSON value.\n * @returns Converter that parses a JSON string into `T` (or `JsonValue` when\n * no inner step is supplied).\n * @public\n */\nexport function stringifiedJson(): Converter<JsonValue>;\n/**\n * Creates a converter that accepts a string, parses it as JSON, and applies\n * the supplied inner converter or validator to the parsed value.\n *\n * @param inner - `Converter<T>` or `Validator<T>` applied to the parsed JSON.\n * @returns Converter that parses a JSON string into `T`.\n * @public\n */\nexport function stringifiedJson<T>(inner: Converter<T> | Validator<T>): Converter<T>;\nexport function stringifiedJson<T>(inner?: Converter<T> | Validator<T>): Converter<T | JsonValue> {\n const step: { convert(from: unknown): Result<T | JsonValue> } = inner ?? jsonValue;\n return new Conversion.BaseConverter<T | JsonValue>((from: unknown): Result<T | JsonValue> => {\n if (typeof from !== 'string') {\n return fail('stringifiedJson: input must be a string.');\n }\n return captureResult<unknown>(() => JSON.parse(from))\n .withErrorFormat((msg) => `stringifiedJson: failed to parse JSON: ${msg}`)\n .onSuccess((parsed) => step.convert(parsed));\n });\n}\n\n/**\n * Creates a converter that parses JSON string content and then applies the supplied converter.\n * @param converter - Converter to apply to the parsed JSON\n * @returns Converter that parses JSON then validates\n * @public\n */\nexport function jsonConverter<T>(converter: Converter<T>): Converter<T> {\n return new Conversion.BaseConverter<T>((from: unknown): Result<T> => {\n if (typeof from !== 'string') {\n return fail('Input must be a string');\n }\n\n const parseResult = captureResult(() => JSON.parse(from));\n if (parseResult.isFailure()) {\n return fail(`Failed to parse JSON: ${parseResult.message}`);\n }\n\n const parsed = parseResult.value;\n if (typeof parsed !== 'object' || parsed === null) {\n return fail('Failed to parse JSON: JSON content must be an object');\n }\n\n return converter.convert(parsed);\n });\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fgv/ts-json-base",
|
|
3
|
-
"version": "5.1.0-
|
|
3
|
+
"version": "5.1.0-23",
|
|
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",
|
|
@@ -55,13 +55,13 @@
|
|
|
55
55
|
"@rushstack/heft-node-rig": "2.11.27",
|
|
56
56
|
"@microsoft/api-extractor": "^7.55.2",
|
|
57
57
|
"typedoc": "~0.28.16",
|
|
58
|
-
"@fgv/ts-utils
|
|
59
|
-
"@fgv/
|
|
60
|
-
"@fgv/
|
|
61
|
-
"@fgv/
|
|
58
|
+
"@fgv/ts-utils": "5.1.0-23",
|
|
59
|
+
"@fgv/ts-utils-jest": "5.1.0-23",
|
|
60
|
+
"@fgv/heft-dual-rig": "5.1.0-23",
|
|
61
|
+
"@fgv/typedoc-compact-theme": "5.1.0-23"
|
|
62
62
|
},
|
|
63
63
|
"peerDependencies": {
|
|
64
|
-
"@fgv/ts-utils": "5.1.0-
|
|
64
|
+
"@fgv/ts-utils": "5.1.0-23"
|
|
65
65
|
},
|
|
66
66
|
"dependencies": {
|
|
67
67
|
"luxon": "^3.7.2"
|