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

0.3.0 #17

Merged
merged 2 commits into from
Feb 12, 2018
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@
**Note**: Gaps between patch versions are faulty/broken releases. **Note**: A feature tagged as Experimental is in a
high state of flux, you're at risk of it changing without notice.

# 0.3.0

* **Breaking Change**
* upgrade to `fp-ts@1.0.0`, `io-ts@1.0.0`, `monocle-ts@1.0.0`, `newtype-ts@0.2.0` (@gcanti)

# 0.2.4

* **Bug Fix**
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ Solution
import * as t from 'io-ts'
import { fromNewtype } from 'io-ts-types/lib/newtype-ts/fromNewtype'

const Person = t.interface({
const Person = t.type({
name: t.string,
age: fromNewtype<Age>(t.Integer)
})
Expand All @@ -47,6 +47,6 @@ const ageLens = Lens.fromProp<Person, 'age'>('age').composeIso(iso<Age>())

const sum = (a: number) => (b: number) => a + b

console.log(t.validate({ name: 'Giulio', age: 43 }, Person).map(ageLens.modify(sum(1))))
console.log(Person.decode({ name: 'Giulio', age: 44 }).map(ageLens.modify(sum(1))))
// => right({ name: 'Giulio', age: 44 })
```
1,103 changes: 1,103 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

14 changes: 7 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
{
"name": "io-ts-types",
"version": "0.2.4",
"version": "0.3.0",
"description": "A collection of runtime types for use with io-ts",
"files": ["lib"],
"main": "lib/index.js",
"typings": "lib/index.d.ts",
"scripts": {
"lint": "tslint src/**/*.ts test/**/*.ts",
"mocha": "mocha -r ts-node/register test/*.ts",
"mocha": "TS_NODE_CACHE=false mocha -r ts-node/register test/*.ts",
"prettier":
"prettier --no-semi --single-quote --print-width 120 --parser typescript --list-different \"{src,test}/**/*.ts\"",
"fix-prettier":
Expand All @@ -27,10 +27,10 @@
},
"homepage": "https://github.com/gcanti/io-ts-types",
"dependencies": {
"fp-ts": "^0.6.4",
"io-ts": "^0.9.5",
"monocle-ts": "^0.5.2",
"newtype-ts": "^0.1.0"
"fp-ts": "^1.0.0",
"io-ts": "^1.0.0",
"monocle-ts": "^1.0.0",
"newtype-ts": "^0.2.0"
},
"devDependencies": {
"@types/mocha": "2.2.38",
Expand All @@ -40,7 +40,7 @@
"ts-node": "3.2.1",
"tslint": "4.4.2",
"tslint-config-standard": "4.0.0",
"typescript": "2.6.2"
"typescript": "2.7.1"
},
"tags": ["io-ts", "fp-ts", "monocle-ts", "newtype-ts"],
"keywords": ["io-ts", "fp-ts", "monocle-ts", "newtype-ts"]
Expand Down
14 changes: 8 additions & 6 deletions src/Date/DateFromISOString.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import * as t from 'io-ts'
import { reverseGet } from '../monocle-ts/TypePrismIso'
import { AnyStringPrism } from '../monocle-ts/AnyStringPrism'
import { ISOStringDatePrism } from '../monocle-ts/ISOStringDatePrism'

export const DateFromISOString: t.Type<t.mixed, Date> = reverseGet(
export const DateFromISOString = new t.Type<Date, string>(
'DateFromISOString',
AnyStringPrism.compose(ISOStringDatePrism),
(v): v is Date => v instanceof Date
(m): m is Date => m instanceof Date,
(m, c) =>
t.string.validate(m, c).chain(s => {
const d = new Date(s)
return isNaN(d.getTime()) ? t.failure(s, c) : t.success(d)
}),
a => a.toISOString()
)
14 changes: 8 additions & 6 deletions src/Date/DateFromNumber.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import * as t from 'io-ts'
import { reverseGet } from '../monocle-ts/TypePrismIso'
import { AnyNumberPrism } from '../monocle-ts/AnyNumberPrism'
import { NumberDatePrism } from '../monocle-ts/NumberDatePrism'

export const DateFromNumber: t.Type<t.mixed, Date> = reverseGet(
export const DateFromNumber = new t.Type<Date, number>(
'DateFromNumber',
AnyNumberPrism.compose(NumberDatePrism),
(v): v is Date => v instanceof Date
(m): m is Date => m instanceof Date,
(m, c) =>
t.number.validate(m, c).chain(n => {
const d = new Date(n)
return isNaN(d.getTime()) ? t.failure(n, c) : t.success(d)
}),
a => a.getTime()
)
15 changes: 8 additions & 7 deletions src/Date/DateFromUnixTime.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import * as t from 'io-ts'
import { reverseGet } from '../monocle-ts/TypePrismIso'
import { AnyNumberPrism } from '../monocle-ts/AnyNumberPrism'
import { NumberDatePrism } from '../monocle-ts/NumberDatePrism'
import { MillisecondSecondIso } from '../monocle-ts/MillisecondSecondIso'

export const DateFromUnixTime: t.Type<t.mixed, Date> = reverseGet(
export const DateFromUnixTime = new t.Type<Date, number>(
'DateFromUnixTime',
AnyNumberPrism.composeIso(MillisecondSecondIso.reverse()).compose(NumberDatePrism),
(v): v is Date => v instanceof Date
(m): m is Date => m instanceof Date,
(m, c) =>
t.Integer.validate(m, c).chain(n => {
const d = new Date(n * 1000)
return isNaN(d.getTime()) ? t.failure(n, c) : t.success(d)
}),
a => a.getTime() / 1000
)
13 changes: 6 additions & 7 deletions src/JSON/JSONFromString.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import * as t from 'io-ts'
import { reverseGet } from '../monocle-ts/TypePrismIso'
import { AnyStringPrism } from '../monocle-ts/AnyStringPrism'
import { JSONType, StringJSONPrism } from '../monocle-ts/StringJSONPrism'
import { JSONTypeRT } from './JSONTypeRT'
import { JSONType, JSONTypeRT } from './JSONTypeRT'
import { tryCatch } from 'fp-ts/lib/Either'

export type JSONType = JSONType

export const JSONFromString: t.Type<t.mixed, JSONType> = reverseGet(
export const JSONFromString = new t.Type<JSONType>(
'JSONFromString',
AnyStringPrism.compose(StringJSONPrism),
JSONTypeRT.is
JSONTypeRT.is,
(m, c) => t.string.validate(m, c).chain(s => tryCatch(() => JSON.parse(s)).fold(() => t.failure(s, c), t.success)),
JSON.stringify
)
5 changes: 3 additions & 2 deletions src/JSON/JSONTypeRT.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import * as t from 'io-ts'
import { JSONType } from '../monocle-ts/StringJSONPrism'

export type JSONType = JSONType
export type JSONObject = { [key: string]: JSONType }
export interface JSONArray extends Array<JSONType> {}
export type JSONType = null | string | number | boolean | JSONArray | JSONObject

export const JSONTypeRT = t.recursion<JSONType>('JSONType', Self =>
t.union([t.null, t.string, t.number, t.boolean, t.array(Self), t.dictionary(t.string, Self)])
Expand Down
33 changes: 17 additions & 16 deletions src/fp-ts/createEitherFromJSON.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,38 @@
import * as t from 'io-ts'

import { Either, left, right } from 'fp-ts/lib/Either'
import { Either, Right, Left, left, right } from 'fp-ts/lib/Either'

export type JSONLeft<L> = {
export interface JSONLeft<L> {
type: 'Left'
value: L
}

export type JSONRight<A> = {
export interface JSONRight<A> {
type: 'Right'
value: A
}

export type JSONEither<L, A> = JSONLeft<L> | JSONRight<A>

export function createEitherFromJSON<L, A>(
leftType: t.Type<t.mixed, L>,
rightType: t.Type<t.mixed, A>
): t.Type<t.mixed, Either<L, A>> {
const JSONLeft = t.interface({
export function createEitherFromJSON<L, IL, A, IA>(
leftType: t.Type<L, IL>,
rightType: t.Type<A, IA>
): t.Type<Either<L, A>, JSONEither<IL, IA>> {
const JSONLeft = t.type({
type: t.literal('Left'),
value: leftType
})
const JSONRight = t.interface({
const JSONRight = t.type({
type: t.literal('Right'),
value: rightType
})
const JSONEither = t.union([JSONLeft, JSONRight])
const JSONEither = t.taggedUnion('type', [JSONLeft, JSONRight])
return new t.Type(
`Either<${leftType.name}, ${rightType.name}>`,
(v): v is Either<L, A> => leftType.is(v) || rightType.is(v),
(s, c) =>
JSONEither.validate(s, c).chain(e => {
(m): m is Either<L, A> =>
(m instanceof Right && rightType.is(m.value)) || (m instanceof Left && leftType.is(m.value)),
(m, c) =>
JSONEither.validate(m, c).chain(e => {
switch (e.type) {
case 'Left':
return t.success(left(e.value))
Expand All @@ -40,9 +41,9 @@ export function createEitherFromJSON<L, A>(
}
}),
a =>
a.fold<JSONEither<t.mixed, t.mixed>>(
l => ({ type: 'Left', value: leftType.serialize(l) }),
a => ({ type: 'Right', value: rightType.serialize(a) })
a.fold<JSONEither<IL, IA>>(
l => ({ type: 'Left', value: leftType.encode(l) }),
a => ({ type: 'Right', value: rightType.encode(a) })
)
)
}
21 changes: 11 additions & 10 deletions src/fp-ts/createOptionFromJSON.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
import * as t from 'io-ts'

import { None, Option, Some, fromNullable } from 'fp-ts/lib/Option'
import { Option, None, Some, fromNullable } from 'fp-ts/lib/Option'

export type JSONOption<A> = {
export interface JSONOption<A> {
type: 'Option'
value: A | null | undefined
}

export function createOptionFromJSON<A>(type: t.Type<t.mixed, A>): t.Type<t.mixed, Option<A>> {
const JSONOption = t.interface({
export function createOptionFromJSON<A, I>(type: t.Type<A, I>): t.Type<Option<A>, JSONOption<I>> {
const JSONOption = t.type({
type: t.literal('Option'),
value: t.union([type, t.null, t.undefined])
})
return new t.Type(
`Option<${type.name}>`,
(v): v is Option<A> => v instanceof Some || v instanceof None,
(s, c) => JSONOption.validate(s, c).chain(o => t.success(fromNullable(o.value))),
a => {
const res = a.toNullable()
return { type: 'Option', value: res !== null ? type.serialize(res) : null }
}
(m): m is Option<A> => m instanceof None || (m instanceof Some && type.is(m.value)),
(m, c) => JSONOption.validate(m, c).chain(o => t.success(fromNullable(o.value))),
a =>
a.foldL<JSONOption<I>>(
() => ({ type: 'Option', value: null }),
value => ({ type: 'Option', value: type.encode(value) })
)
)
}
4 changes: 2 additions & 2 deletions src/fp-ts/createOptionFromNullable.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import * as t from 'io-ts'
import { Option, Some, None, fromNullable } from 'fp-ts/lib/Option'

export const createOptionFromNullable = <A>(type: t.Type<t.mixed, A>): t.Type<t.mixed, Option<A>> => {
export const createOptionFromNullable = <A>(type: t.Type<A>): t.Type<Option<A>, A | null> => {
const Nullable = t.union([type, t.null, t.undefined])
return new t.Type(
`Option<${type.name}>`,
(v): v is Option<A> => v instanceof Some || v instanceof None,
(m): m is Option<A> => m instanceof None || (m instanceof Some && type.is(m.value)),
(s, c) => Nullable.validate(s, c).chain(u => t.success(fromNullable(u))),
a => a.toNullable()
)
Expand Down
14 changes: 0 additions & 14 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,11 @@ export { createOptionFromNullable } from './fp-ts/createOptionFromNullable'
export { JSONFromString, JSONType } from './JSON/JSONFromString'
export { JSONTypeRT } from './JSON/JSONTypeRT'

export { AnyNumberPrism } from './monocle-ts/AnyNumberPrism'
export { AnyStringPrism } from './monocle-ts/AnyStringPrism'
export { createRangePrism } from './monocle-ts/createRangePrism'
export { ISOStringDatePrism } from './monocle-ts/ISOStringDatePrism'
export { lensesFromInterface } from './monocle-ts/lensesFromInterface'
export { lensesFromProps } from './monocle-ts/lensesFromProps'
export { MillisecondSecondIso } from './monocle-ts/MillisecondSecondIso'
export { MixedStringPrism } from './monocle-ts/MixedStringPrism'
export { NumberDatePrism } from './monocle-ts/NumberDatePrism'
export { NumberIntegerPrism } from './monocle-ts/NumberIntegerPrism'
export { StringJSONPrism } from './monocle-ts/StringJSONPrism'
export { StringNumberPrism } from './monocle-ts/StringNumberPrism'
import * as TypePrismIso from './monocle-ts/TypePrismIso'
export { TypePrismIso }
export { fromNewtype } from './newtype-ts/fromNewtype'

export { createInfRange } from './number/createInfRange'
export { createInfSupRange } from './number/createInfSupRange'
export { createRange } from './number/createRange'
export { createSupRange } from './number/createSupRange'
export { IntegerFromString } from './number/IntegerFromString'
export { NumberFromString } from './number/NumberFromString'
4 changes: 0 additions & 4 deletions src/monocle-ts/AnyNumberPrism.ts

This file was deleted.

4 changes: 0 additions & 4 deletions src/monocle-ts/AnyStringPrism.ts

This file was deleted.

10 changes: 0 additions & 10 deletions src/monocle-ts/ISOStringDatePrism.ts

This file was deleted.

3 changes: 0 additions & 3 deletions src/monocle-ts/MillisecondSecondIso.ts

This file was deleted.

5 changes: 0 additions & 5 deletions src/monocle-ts/MixedStringPrism.ts

This file was deleted.

10 changes: 0 additions & 10 deletions src/monocle-ts/NumberDatePrism.ts

This file was deleted.

4 changes: 0 additions & 4 deletions src/monocle-ts/NumberIntegerPrism.ts

This file was deleted.

11 changes: 0 additions & 11 deletions src/monocle-ts/StringJSONPrism.ts

This file was deleted.

10 changes: 0 additions & 10 deletions src/monocle-ts/StringNumberPrism.ts

This file was deleted.

9 changes: 5 additions & 4 deletions src/monocle-ts/TypePrismIso.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { Prism } from 'monocle-ts'
import * as t from 'io-ts'
import { fromEither } from 'fp-ts/lib/Option'

export function get<S, A>(type: t.Type<S, A>): Prism<S, A> {
return new Prism<S, A>(s => t.validate(s, type).toOption(), type.serialize)
export function get<A, O extends I, I>(type: t.Type<A, O, I>): Prism<O, A> {
return new Prism<O, A>(s => fromEither(type.decode(s)), type.encode)
}

export function reverseGet<S, A>(name: string, prism: Prism<S, A>, is: t.Is<A>): t.Type<S, A> {
return new t.Type(name, is, (s, c) => prism.getOption(s).fold(() => t.failure(s, c), t.success), prism.reverseGet)
export function reverseGet<S, A>(name: string, prism: Prism<S, A>, is: t.Is<A>): t.Type<A, S, S> {
return new t.Type(name, is, (s, c) => prism.getOption(s).foldL(() => t.failure(s, c), t.success), prism.reverseGet)
}
5 changes: 0 additions & 5 deletions src/monocle-ts/createRangePrism.ts

This file was deleted.

2 changes: 1 addition & 1 deletion src/monocle-ts/lensesFromInterface.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as t from 'io-ts'
import { lensesFromProps, LensesFromProps } from './lensesFromProps'

export const lensesFromInterface = <P extends t.Props>(i: t.InterfaceType<P, t.InterfaceOf<P>>): LensesFromProps<P> => {
export const lensesFromInterface = <P extends t.Props>(i: t.InterfaceType<P> | t.StrictType<P>): LensesFromProps<P> => {
return lensesFromProps(i.props)
}
Loading