io-ts-reporters
Advanced tools
Comparing version 1.1.0 to 1.2.0
{ | ||
"name": "io-ts-reporters", | ||
"version": "1.2.0", | ||
"description": "Formatting of io-ts validation errors", | ||
"main": "./target/src/index.js", | ||
"typings": "./target/src/index.d.ts", | ||
"version": "1.1.0", | ||
"sideEffects": false, | ||
"scripts": { | ||
"docs": "yarn docs-ts", | ||
"lint": "npm run typecheck && npm run lint:only", | ||
@@ -11,3 +14,3 @@ "lint:only": "xo", | ||
"compile": "rm -rf ./target/* && tsc", | ||
"test": "npm run lint && npm run test:unit", | ||
"test": "npm run lint && npm run test:unit && yarn docs", | ||
"test:unit": "ava", | ||
@@ -20,3 +23,13 @@ "prepublishOnly": "npm run compile && npm run lint" | ||
], | ||
"dependencies": { | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/gillchristian/io-ts-reporters.git" | ||
}, | ||
"license": "MIT", | ||
"bugs": { | ||
"url": "https://github.com/gillchristian/io-ts-reporters/issues" | ||
}, | ||
"homepage": "https://github.com/gillchristian/io-ts-reporters", | ||
"dependencies": {}, | ||
"peerDependencies": { | ||
"fp-ts": "^2.0.2", | ||
@@ -28,2 +41,5 @@ "io-ts": "^2.0.0" | ||
"ava": "^3.8.2", | ||
"docs-ts": "^0.5.1", | ||
"fp-ts": "^2.0.2", | ||
"io-ts": "^2.0.0", | ||
"io-ts-types": "^0.5.6", | ||
@@ -33,3 +49,17 @@ "ts-node": "^8.6.2", | ||
"xo": "^0.30.0" | ||
} | ||
}, | ||
"tags": [ | ||
"typescript", | ||
"runtime", | ||
"decoder", | ||
"encoder", | ||
"schema" | ||
], | ||
"keywords": [ | ||
"typescript", | ||
"runtime", | ||
"decoder", | ||
"encoder", | ||
"schema" | ||
] | ||
} |
# io-ts-reporters | ||
[Error reporters](https://github.com/gcanti/io-ts#error-reporters) for io-ts. | ||
[Error reporters](https://github.com/gcanti/io-ts#error-reporters) for | ||
[io-ts](https://github.com/gcanti/io-ts). | ||
Currently this package only includes one reporter. The output is an array of strings in the format of: | ||
Currently this package only includes one reporter. The output is an array of | ||
strings in the format of: | ||
`Expected type of ${path} to be ${expectedType}, but got ${actualType}: ${actualValue}.` | ||
``` | ||
Expecting ${expectedType} at ${path} but instead got: ${expectedType} | ||
``` | ||
## TypeScript compatibility | ||
And for union types: | ||
| io-ts-reporters version | required typescript version | | ||
| ----------------------- | --------------------------- | | ||
| 1.0.0 | 3.5+ | | ||
| <= 0.0.21 | 2.7+ | | ||
``` | ||
Expecting one of: | ||
${unionType1} | ||
${unionType2} | ||
${...} | ||
${unionTypeN} | ||
at ${path} but instead got: ${actualValue} | ||
``` | ||
@@ -24,4 +32,42 @@ ## Installation | ||
See [the tests](./tests/index.ts). | ||
```ts | ||
import * as t from 'io-ts'; | ||
import reporter from 'io-ts-reporters'; | ||
const User = t.interface({ name: t.string }); | ||
// When decoding fails, the errors are reported | ||
reporter.report(User.decode({ nam: 'Jane' })); | ||
//=> ['Expecting string at name but instead got: undefined'] | ||
// Nothing gets reported on success | ||
reporter.report(User.decode({ name: 'Jane' })); | ||
//=> [] | ||
``` | ||
To only format the validation errors in case the validation failed (ie. | ||
`mapLeft`) use `formatValidationErrors` instead. | ||
```ts | ||
import * as t from 'io-ts'; | ||
import { formatValidationErrors } from 'io-ts-reporters'; | ||
import * as E from 'fp-ts/lib/Either'; | ||
import { pipe } from 'fp-ts/lib/pipeable'; | ||
const User = t.interface({ name: t.string }); | ||
const result = User.decode({ nam: 'Jane' }); // Either<t.Errors, User> | ||
E.mapLeft(formatValidationErrors)(result); // Either<string[], User> | ||
``` | ||
For more examples see [the tests](./tests/index.test.ts). | ||
## TypeScript compatibility | ||
| io-ts-reporters version | required typescript version | | ||
| ----------------------- | --------------------------- | | ||
| 1.0.0 | 3.5+ | | ||
| <= 0.0.21 | 2.7+ | | ||
## Testing | ||
@@ -35,1 +81,5 @@ | ||
[io-ts]: https://github.com/gcanti/io-ts#error-reporters | ||
## Credits | ||
This library was created by [OliverJAsh](https://github.com/OliverJAsh). |
@@ -0,1 +1,19 @@ | ||
/** | ||
* An [io-ts Reporter](https://gcanti.github.io/io-ts/modules/Reporter.ts.html#reporter-interface). | ||
* | ||
* @example | ||
* | ||
* import * as t from 'io-ts'; | ||
* import Reporter from 'io-ts-reporters'; | ||
* | ||
* const User = t.interface({ name: t.string }); | ||
* | ||
* assert.deepEqual( | ||
* Reporter.report(User.decode({ nam: 'Jane' })), | ||
* ['Expecting string at name but instead got: undefined'], | ||
* ) | ||
* assert.deepEqual( Reporter.report(User.decode({ name: 'Jane' })), []) | ||
* | ||
* @since 1.2.0 | ||
*/ | ||
import * as A from 'fp-ts/lib/Array'; | ||
@@ -8,2 +26,3 @@ import * as E from 'fp-ts/lib/Either'; | ||
import * as t from 'io-ts'; | ||
import { Reporter } from 'io-ts/lib/Reporter'; | ||
@@ -98,3 +117,3 @@ import { takeUntil } from './utils'; | ||
const formatValidationError = (path: string, error: t.ValidationError) => | ||
const formatValidationCommonError = (path: string, error: t.ValidationError) => | ||
pipe( | ||
@@ -108,19 +127,59 @@ error, | ||
const groupByKey = NEA.groupBy((error: t.ValidationError) => | ||
pipe(error.context, takeUntil(isUnionType), keyPath) | ||
); | ||
const format = (path: string, errors: NEA.NonEmptyArray<t.ValidationError>) => | ||
NEA.tail(errors).length > 0 | ||
? formatValidationErrorOfUnion(path, errors) | ||
: formatValidationError(path, NEA.head(errors)); | ||
: formatValidationCommonError(path, NEA.head(errors)); | ||
const groupByKey = NEA.groupBy((error: t.ValidationError) => | ||
pipe(error.context, takeUntil(isUnionType), keyPath) | ||
); | ||
/** | ||
* Format a single validation error. | ||
* | ||
* @category formatters | ||
* @since 1.0.0 | ||
*/ | ||
export const formatValidationError = (error: t.ValidationError) => | ||
formatValidationCommonError(keyPath(error.context), error); | ||
/** | ||
* Format validation errors (`t.Errors`). | ||
* | ||
* @example | ||
* import * as E from 'fp-ts/lib/Either' | ||
* import * as t from 'io-ts' | ||
* import { formatValidationErrors } from 'io-ts-reporters' | ||
* | ||
* const result = t.string.decode(123) | ||
* | ||
* assert.deepEqual( | ||
* E.mapLeft(formatValidationErrors)(result), | ||
* E.left(['Expecting string but instead got: 123']) | ||
* ) | ||
* | ||
* @category formatters | ||
* @since 1.2.0 | ||
*/ | ||
export const formatValidationErrors = (errors: t.Errors) => | ||
pipe( | ||
errors, | ||
groupByKey, | ||
R.mapWithIndex(format), | ||
R.compact, | ||
R.toArray, | ||
A.map(([_key, error]) => error) | ||
); | ||
/** | ||
* Deprecated, use the default export instead. | ||
* | ||
* @category deprecated | ||
* @deprecated | ||
* @since 1.0.0 | ||
*/ | ||
export const reporter = <T>(validation: t.Validation<T>) => | ||
pipe( | ||
validation, | ||
E.mapLeft(groupByKey), | ||
E.mapLeft(R.mapWithIndex(format)), | ||
E.mapLeft(R.compact), | ||
E.mapLeft(R.toArray), | ||
E.mapLeft(A.map(([_key, error]) => error)), | ||
E.mapLeft(formatValidationErrors), | ||
E.fold( | ||
@@ -131,1 +190,4 @@ errors => errors, | ||
); | ||
const prettyReporter: Reporter<string[]> = { report: reporter }; | ||
export default prettyReporter; |
@@ -0,3 +1,9 @@ | ||
/** | ||
* @since 1.1.0 | ||
*/ | ||
import { Predicate } from 'fp-ts/lib/function'; | ||
/** | ||
* @since 1.1.0 | ||
*/ | ||
/* eslint-disable @typescript-eslint/array-type */ | ||
@@ -4,0 +10,0 @@ export const takeUntil = <A = unknown>(predicate: Predicate<A>) => ( |
import * as E from 'fp-ts/lib/Either'; | ||
import * as O from 'fp-ts/lib/Option'; | ||
import * as t from 'io-ts'; | ||
import { Reporter } from 'io-ts/lib/Reporter'; | ||
/** | ||
* Format a single validation error. | ||
* | ||
* @category formatters | ||
* @since 1.0.0 | ||
*/ | ||
export declare const formatValidationError: (error: t.ValidationError) => O.Option<string>; | ||
/** | ||
* Format validation errors (`t.Errors`). | ||
* | ||
* @example | ||
* import * as E from 'fp-ts/lib/Either' | ||
* import * as t from 'io-ts' | ||
* import { formatValidationErrors } from 'io-ts-reporters' | ||
* | ||
* const result = t.string.decode(123) | ||
* | ||
* assert.deepEqual( | ||
* E.mapLeft(formatValidationErrors)(result), | ||
* E.left(['Expecting string but instead got: 123']) | ||
* ) | ||
* | ||
* @category formatters | ||
* @since 1.2.0 | ||
*/ | ||
export declare const formatValidationErrors: (errors: t.Errors) => string[]; | ||
/** | ||
* Deprecated, use the default export instead. | ||
* | ||
* @category deprecated | ||
* @deprecated | ||
* @since 1.0.0 | ||
*/ | ||
export declare const reporter: <T>(validation: E.Either<t.Errors, T>) => string[]; | ||
declare const prettyReporter: Reporter<string[]>; | ||
export default prettyReporter; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.reporter = void 0; | ||
exports.reporter = exports.formatValidationErrors = exports.formatValidationError = void 0; | ||
/** | ||
* An [io-ts Reporter](https://gcanti.github.io/io-ts/modules/Reporter.ts.html#reporter-interface). | ||
* | ||
* @example | ||
* | ||
* import * as t from 'io-ts'; | ||
* import Reporter from 'io-ts-reporters'; | ||
* | ||
* const User = t.interface({ name: t.string }); | ||
* | ||
* assert.deepEqual( | ||
* Reporter.report(User.decode({ nam: 'Jane' })), | ||
* ['Expecting string at name but instead got: undefined'], | ||
* ) | ||
* assert.deepEqual( Reporter.report(User.decode({ name: 'Jane' })), []) | ||
* | ||
* @since 1.2.0 | ||
*/ | ||
var A = require("fp-ts/lib/Array"); | ||
@@ -74,3 +92,3 @@ var E = require("fp-ts/lib/Either"); | ||
}; | ||
var formatValidationError = function (path, error) { | ||
var formatValidationCommonError = function (path, error) { | ||
return pipeable_1.pipe(error, getErrorFromCtx, O.map(function (errorContext) { | ||
@@ -80,16 +98,55 @@ return errorMessageSimple(errorContext.type.name, path, error); | ||
}; | ||
var groupByKey = NEA.groupBy(function (error) { | ||
return pipeable_1.pipe(error.context, utils_1.takeUntil(isUnionType), keyPath); | ||
}); | ||
var format = function (path, errors) { | ||
return NEA.tail(errors).length > 0 | ||
? formatValidationErrorOfUnion(path, errors) | ||
: formatValidationError(path, NEA.head(errors)); | ||
: formatValidationCommonError(path, NEA.head(errors)); | ||
}; | ||
var groupByKey = NEA.groupBy(function (error) { | ||
return pipeable_1.pipe(error.context, utils_1.takeUntil(isUnionType), keyPath); | ||
}); | ||
exports.reporter = function (validation) { | ||
return pipeable_1.pipe(validation, E.mapLeft(groupByKey), E.mapLeft(R.mapWithIndex(format)), E.mapLeft(R.compact), E.mapLeft(R.toArray), E.mapLeft(A.map(function (_a) { | ||
/** | ||
* Format a single validation error. | ||
* | ||
* @category formatters | ||
* @since 1.0.0 | ||
*/ | ||
exports.formatValidationError = function (error) { | ||
return formatValidationCommonError(keyPath(error.context), error); | ||
}; | ||
/** | ||
* Format validation errors (`t.Errors`). | ||
* | ||
* @example | ||
* import * as E from 'fp-ts/lib/Either' | ||
* import * as t from 'io-ts' | ||
* import { formatValidationErrors } from 'io-ts-reporters' | ||
* | ||
* const result = t.string.decode(123) | ||
* | ||
* assert.deepEqual( | ||
* E.mapLeft(formatValidationErrors)(result), | ||
* E.left(['Expecting string but instead got: 123']) | ||
* ) | ||
* | ||
* @category formatters | ||
* @since 1.2.0 | ||
*/ | ||
exports.formatValidationErrors = function (errors) { | ||
return pipeable_1.pipe(errors, groupByKey, R.mapWithIndex(format), R.compact, R.toArray, A.map(function (_a) { | ||
var _key = _a[0], error = _a[1]; | ||
return error; | ||
})), E.fold(function (errors) { return errors; }, function () { return []; })); | ||
})); | ||
}; | ||
/** | ||
* Deprecated, use the default export instead. | ||
* | ||
* @category deprecated | ||
* @deprecated | ||
* @since 1.0.0 | ||
*/ | ||
exports.reporter = function (validation) { | ||
return pipeable_1.pipe(validation, E.mapLeft(exports.formatValidationErrors), E.fold(function (errors) { return errors; }, function () { return []; })); | ||
}; | ||
var prettyReporter = { report: exports.reporter }; | ||
exports.default = prettyReporter; | ||
//# sourceMappingURL=index.js.map |
@@ -0,2 +1,8 @@ | ||
/** | ||
* @since 1.1.0 | ||
*/ | ||
import { Predicate } from 'fp-ts/lib/function'; | ||
/** | ||
* @since 1.1.0 | ||
*/ | ||
export declare const takeUntil: <A = unknown>(predicate: Predicate<A>) => (as: readonly A[]) => readonly A[]; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.takeUntil = void 0; | ||
/** | ||
* @since 1.1.0 | ||
*/ | ||
/* eslint-disable @typescript-eslint/array-type */ | ||
@@ -5,0 +8,0 @@ exports.takeUntil = function (predicate) { return function (as) { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
No website
QualityPackage does not have a website.
Found 1 instance in 1 package
21487
407
1
0
84
0
0
9
- Removedfp-ts@^2.0.2
- Removedio-ts@^2.0.0