Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Require Node.js 14 and TypeScript 4.7 #238

Merged
merged 3 commits into from Jun 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 4 additions & 3 deletions .github/workflows/main.yml
Expand Up @@ -10,16 +10,17 @@ jobs:
fail-fast: false
matrix:
node-version:
- 18
- 16
- 14
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- run: npm install --force
- run: npm test
- uses: codecov/codecov-action@v2
- uses: codecov/codecov-action@v3
if: matrix.node-version == 16
with:
fail_ci_if_error: true
11 changes: 6 additions & 5 deletions dev-only.js
@@ -1,12 +1,13 @@
'use strict';

let ow;
if (process.env.NODE_ENV === 'production') {
const shim = new Proxy((() => {}), {
get: () => shim,
apply: () => shim
apply: () => shim,
});

module.exports = shim;
ow = shim;
} else {
module.exports = require('./dist');
ow = await import('./dist/index.js');
}

export default ow;
65 changes: 32 additions & 33 deletions package.json
Expand Up @@ -4,18 +4,25 @@
"description": "Function argument validation for humans",
"license": "MIT",
"repository": "sindresorhus/ow",
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
},
"funding": "https://github.com/sponsors/sindresorhus",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "https://sindresorhus.com"
},
"type": "module",
"main": "dist/index.js",
"exports": {
".": {
"types": "./dist/index.d.ts",
"node": "./dist/index.js"
},
"./dev-only": {
"types": "./dist/index.d.ts",
"node": "./dev-only.js"
}
},
"engines": {
"node": ">=12"
"node": ">=14.16"
},
"scripts": {
"test": "xo && c8 ava",
Expand Down Expand Up @@ -50,37 +57,33 @@
"object"
],
"dependencies": {
"@sindresorhus/is": "^4.2.0",
"callsites": "^3.1.0",
"dot-prop": "^6.0.1",
"@sindresorhus/is": "^5.1.0",
"callsites": "^4.0.0",
"dot-prop": "^7.2.0",
"lodash.isequal": "^4.5.0",
"type-fest": "^2.3.4",
"type-fest": "^2.13.0",
"vali-date": "^1.0.0"
},
"devDependencies": {
"@sindresorhus/tsconfig": "^0.8.0",
"@types/lodash.isequal": "^4.5.5",
"@types/node": "^16.10.2",
"@sindresorhus/tsconfig": "^3.0.1",
"@types/lodash.isequal": "^4.5.6",
"@types/node": "^17.0.42",
"@types/vali-date": "^1.0.0",
"ava": "^3.15.0",
"c8": "^7.10.0",
"del-cli": "^4.0.0",
"expect-type": "^0.12.0",
"gh-pages": "^3.2.3",
"ts-node": "^10.4.0",
"typedoc": "^0.22.5",
"typescript": "^4.5.0-beta",
"xo": "^0.46.4"
"ava": "^4.3.0",
"c8": "^7.11.3",
"del-cli": "^4.0.1",
"expect-type": "^0.13.0",
"gh-pages": "^4.0.0",
"ts-node": "^10.8.1",
"typedoc": "^0.22.17",
"typescript": "^4.7.3",
"xo": "^0.50.0"
},
"browser": {
"./dist/utils/infer-label.js": "./dist/utils/infer-label.browser.js"
},
"types": "dist",
"sideEffects": false,
"xo": {
"parserOptions": {
"project": "./tsconfig.xo.json"
},
"ignores": [
"example.js",
"dev-only.js",
Expand All @@ -98,20 +101,16 @@
}
},
"ava": {
"nonSemVerExperiments": {
"configurableModuleFormat": true
},
"nodeArguments": [
"--loader=ts-node/esm",
"--experimental-specifier-resolution=node"
],
"files": [
"test/**",
"!test/fixtures/**"
],
"extensions": {
"ts": "module"
}
},
"nodeArguments": [
"--loader=ts-node/esm"
]
},
"c8": {
"reporter": [
Expand Down
13 changes: 8 additions & 5 deletions readme.md
Expand Up @@ -20,14 +20,12 @@

## Install

```
$ npm install ow
```sh
npm install ow
```

## Usage

*If you use CommonJS, you need to import is as `const {default: ow} = require('ow')`.*

```ts
import ow from 'ow';

Expand Down Expand Up @@ -65,7 +63,7 @@ ow(unicorn, ow.object.exactShape({
//=> ArgumentError: Expected property `stars.value` to be of type `number` but received type `string` in object `unicorn`
```

***Note:*** If you intend on using `ow` for development purposes only, use `require('ow/dev-only')` instead of the usual `import 'ow'`, and run the bundler with `NODE_ENV` set to `production` (e.g. `$ NODE_ENV="production" parcel build index.js`). This will make `ow` automatically export a shim when running in production, which should result in a significantly lower bundle size.
***Note:*** If you intend on using `ow` for development purposes only, use `import ow from 'ow/dev-only'` instead of the usual `import ow from 'ow'`, and run the bundler with `NODE_ENV` set to `production` (e.g. `$ NODE_ENV="production" parcel build index.js`). This will make `ow` automatically export a shim when running in production, which should result in a significantly lower bundle size.

## API

Expand Down Expand Up @@ -291,6 +289,8 @@ This can be useful for creating your own reusable validators which can be extrac

### TypeScript

**Requires TypeScript 4.7 or later.**

Ow includes a type utility that lets you to extract a TypeScript type from the given predicate.

```ts
Expand All @@ -306,6 +306,9 @@ type User = Infer<typeof userPredicate>;
## Maintainers

- [Sindre Sorhus](https://github.com/sindresorhus)

**Former:**

- [Sam Verschueren](https://github.com/SamVerschueren)

## Related
Expand Down
9 changes: 5 additions & 4 deletions source/index.ts
@@ -1,6 +1,5 @@
import callsites from 'callsites';
import {inferLabel} from './utils/infer-label.js';
import {Predicate} from './predicates/predicate.js';
import {BasePredicate, isPredicate} from './predicates/base-predicate.js';
import modifiers, {Modifiers} from './modifiers.js';
import predicates, {Predicates} from './predicates.js';
Expand Down Expand Up @@ -72,7 +71,7 @@ export interface ReusableValidator<T> {
@param value - Value to test.
@param label - Override the label which should be used in error messages.
*/
// eslint-disable-next-line @typescript-eslint/prefer-function-type
// eslint-disable-next-line @typescript-eslint/prefer-function-type, @typescript-eslint/no-redundant-type-constituents
(value: unknown | T, label?: string): void;
}

Expand Down Expand Up @@ -117,7 +116,7 @@ const ow = <T>(value: unknown, labelOrPredicate: unknown, predicate?: BasePredic

Object.defineProperties(ow, {
isValid: {
value: <T>(value: unknown, predicate: BasePredicate<T>): boolean => {
value<T>(value: unknown, predicate: BasePredicate<T>): boolean {
try {
test(value, '', predicate);
return true;
Expand Down Expand Up @@ -148,6 +147,8 @@ const _ow: Ow = predicates(modifiers(ow)) as Ow;

export default _ow;

export {BasePredicate, Predicate};
export * from './predicates.js';
export {ArgumentError} from './argument-error.js';

export {Predicate} from './predicates/predicate.js';
export type {BasePredicate} from './predicates/base-predicate.js';
38 changes: 18 additions & 20 deletions source/predicates.ts
Expand Up @@ -6,7 +6,7 @@ import {BigIntPredicate} from './predicates/bigint.js';
import {BooleanPredicate} from './predicates/boolean.js';
import {Predicate, PredicateOptions} from './predicates/predicate.js';
import {ArrayPredicate} from './predicates/array.js';
import {ObjectPredicate, Shape} from './predicates/object.js';
import {ObjectPredicate} from './predicates/object.js';
import {DatePredicate} from './predicates/date.js';
import {ErrorPredicate} from './predicates/error.js';
import {MapPredicate} from './predicates/map.js';
Expand Down Expand Up @@ -328,22 +328,20 @@ const predicates = <T>(object: T, options?: PredicateOptions): T & Predicates =>

export default predicates;

export {
StringPredicate,
NumberPredicate,
BigIntPredicate,
BooleanPredicate,
ArrayPredicate,
ObjectPredicate,
DatePredicate,
ErrorPredicate,
MapPredicate,
WeakMapPredicate,
SetPredicate,
WeakSetPredicate,
TypedArrayPredicate,
ArrayBufferPredicate,
DataViewPredicate,
AnyPredicate,
Shape,
};
export {ObjectPredicate} from './predicates/object.js';
export type {Shape} from './predicates/object.js';
export {StringPredicate} from './predicates/string.js';
export {NumberPredicate} from './predicates/number.js';
export {BigIntPredicate} from './predicates/bigint.js';
export {BooleanPredicate} from './predicates/boolean.js';
export {ArrayPredicate} from './predicates/array.js';
export {DatePredicate} from './predicates/date.js';
export {ErrorPredicate} from './predicates/error.js';
export {MapPredicate} from './predicates/map.js';
export {WeakMapPredicate} from './predicates/weak-map.js';
export {SetPredicate} from './predicates/set.js';
export {WeakSetPredicate} from './predicates/weak-set.js';
export {TypedArrayPredicate} from './predicates/typed-array.js';
export {ArrayBufferPredicate} from './predicates/array-buffer.js';
export {DataViewPredicate} from './predicates/data-view.js';
export {AnyPredicate} from './predicates/any.js';
2 changes: 1 addition & 1 deletion source/predicates/error.ts
Expand Up @@ -25,7 +25,7 @@ export class ErrorPredicate extends Predicate<Error> {

@param expected - Expected message of the Error.
*/
message(expected: string): this {
override message(expected: string): this {
return this.addValidator({
message: (error, label) => `Expected ${label} message to be \`${expected}\`, got \`${error.message}\``,
validator: error => error.message === expected,
Expand Down
2 changes: 1 addition & 1 deletion source/predicates/map.ts
Expand Up @@ -93,7 +93,7 @@ export class MapPredicate<T1 = unknown, T2 = unknown> extends Predicate<Map<T1,
hasAnyValues(...values: readonly T2[]): this {
return this.addValidator({
message: (_, label) => `Expected ${label} to have any value of \`${JSON.stringify(values)}\``,
validator: map => {
validator(map) {
const valueSet = new Set(map.values());
return values.some(key => valueSet.has(key));
},
Expand Down
2 changes: 1 addition & 1 deletion source/predicates/number.ts
Expand Up @@ -89,7 +89,7 @@ export class NumberPredicate extends Predicate<number> {
*/
oneOf(list: readonly number[]): this {
return this.addValidator({
message: (value, label) => {
message(value, label) {
let printedList = JSON.stringify(list);

if (list.length > 10) {
Expand Down
13 changes: 6 additions & 7 deletions source/predicates/object.ts
@@ -1,6 +1,5 @@
import is from '@sindresorhus/is';

import dotProp from 'dot-prop';
import {hasProperty} from 'dot-prop';
import isEqual from 'lodash.isequal';
import hasItems from '../utils/has-items.js';
import ofType from '../utils/of-type.js';
Expand All @@ -9,8 +8,6 @@ import {partial, exact, Shape, TypeOfShape} from '../utils/match-shape.js';
import {Predicate, PredicateOptions} from './predicate.js';
import {BasePredicate} from './base-predicate.js';

export {Shape};

export class ObjectPredicate<T extends object = object> extends Predicate<T> {
/**
@hidden
Expand Down Expand Up @@ -92,7 +89,7 @@ export class ObjectPredicate<T extends object = object> extends Predicate<T> {
*/
instanceOf(instance: Function): this {
return this.addValidator({
message: (object: object, label: string) => {
message(object: object, label: string) {
let {name} = object?.constructor ?? {};

if (!name || name === 'Object') {
Expand All @@ -115,7 +112,7 @@ export class ObjectPredicate<T extends object = object> extends Predicate<T> {
message: (_, label, missingKeys) => `Expected ${label} to have keys \`${JSON.stringify(missingKeys)}\``,
validator: object => hasItems(
{
has: item => dotProp.has(object, item),
has: item => hasProperty(object, item),
},
keys,
),
Expand All @@ -130,7 +127,7 @@ export class ObjectPredicate<T extends object = object> extends Predicate<T> {
hasAnyKeys(...keys: readonly string[]): this {
return this.addValidator({
message: (_, label) => `Expected ${label} to have any key of \`${JSON.stringify(keys)}\``,
validator: object => keys.some(key => dotProp.has(object, key)),
validator: object => keys.some(key => hasProperty(object, key)),
});
}

Expand Down Expand Up @@ -191,3 +188,5 @@ export class ObjectPredicate<T extends object = object> extends Predicate<T> {
}) as ObjectPredicate<any>;
}
}

export type {Shape} from '../utils/match-shape.js';
2 changes: 1 addition & 1 deletion source/predicates/predicate.ts
Expand Up @@ -179,7 +179,7 @@ export class Predicate<T = unknown> implements BasePredicate<T> {
? `(${label}) ${error}`
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
: error(label),
validator: value => {
validator(value) {
const {message, validator} = customValidator(value);

if (validator) {
Expand Down
4 changes: 2 additions & 2 deletions source/predicates/string.ts
Expand Up @@ -103,7 +103,7 @@ export class StringPredicate extends Predicate<string> {
*/
oneOf(list: readonly string[]): this {
return this.addValidator({
message: (value, label) => {
message(value, label) {
let printedList = JSON.stringify(list);

if (list.length > 10) {
Expand Down Expand Up @@ -132,7 +132,7 @@ export class StringPredicate extends Predicate<string> {
*/
get nonBlank(): this {
return this.addValidator({
message: (value, label) => {
message(value, label) {
// Unicode's formal substitute characters can be barely legible and may not be easily recognized.
// Hence this alternative substitution scheme.
const madeVisible = value
Expand Down
5 changes: 2 additions & 3 deletions source/utils/infer-label.ts
Expand Up @@ -51,14 +51,13 @@ export const inferLabel = (callsites: readonly CallSite[]): void | string => {
line = line.slice(columnNumber - 1);

const match = labelRegex.exec(line);
const token = match?.groups?.['label'];

if (!match?.groups?.label) {
if (!token) {
// Exit if we didn't find a label
return;
}

const token = match.groups.label;

if (isValidIdentifier(token) || isValidIdentifier(token.split('.').pop())) {
return token;
}
Expand Down