Skip to content

Commit

Permalink
feat: abstract
Browse files Browse the repository at this point in the history
  • Loading branch information
raveclassic committed Jan 27, 2022
1 parent 0df7bef commit 560de6b
Show file tree
Hide file tree
Showing 7 changed files with 136 additions and 300 deletions.
46 changes: 0 additions & 46 deletions packages/form/src/abstract/build-state.spec.ts

This file was deleted.

57 changes: 0 additions & 57 deletions packages/form/src/abstract/build-state.ts

This file was deleted.

39 changes: 33 additions & 6 deletions packages/form/src/form.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@ import { NumberFromString } from 'io-ts-types/lib/NumberFromString'
import * as Z from 'zod'
import * as J from 'joi'
import * as R from 'runtypes'
import { Schema11, Schema21, Validation1C } from './abstract/schema-f'
import { Schema11, Schema21, Validation1C } from './types'
import { either } from 'fp-ts'
import { makeNewForm } from './form'
import { ValidationError } from 'joi'
import { Failure } from 'runtypes/lib/result'

declare module './hkt' {
interface URItoKind3<R, E, A> {}
interface URItoKind2<E, A> {
readonly IOTSSchema: I.Type<A, E>
}
Expand All @@ -20,14 +19,14 @@ declare module './hkt' {
readonly JOISchema: J.Schema<A>
readonly RuntypesSchema: R.Runtype<A>
readonly IOTSValidation: I.Validation<A>
readonly Exception: A
readonly Identity: A
readonly ZODSafeParseReturnType: Z.SafeParseReturnType<A, A>
readonly JOIValidationResult: J.ValidationResult<A>
readonly RuntypesResult: R.Result<A>
}
}

const ZODSchema: Schema11<'ZODSchema', 'Exception'> = {
const ZODSchema: Schema11<'ZODSchema', 'Identity'> = {
URI: 'ZODSchema',
encode: (schema, decoded) => decoded,
decode: (schema, encoded) => schema.parse(encoded),
Expand Down Expand Up @@ -57,8 +56,14 @@ const RuntypesSchema: Schema11<'RuntypesSchema', 'RuntypesResult'> = {
decode: (schema, value) => schema.validate(value),
}

const Exception: Validation1C<'Exception', never> = {
URI: 'Exception',
const IdentitySchema: Schema11<'Identity', 'Identity'> = {
URI: 'Identity',
encode: (schema, value) => value,
decode: (schema, value) => value,
}

const IdentityValidation: Validation1C<'Identity', never> = {
URI: 'Identity',
success: identity,
failure: identity,
isSuccess: () => true,
Expand All @@ -70,8 +75,10 @@ const ZODSafeParseReturnType: Validation1C<'ZODSafeParseReturnType', Z.ZodError>
URI: 'ZODSafeParseReturnType',
success: (data) => ({ success: true, data }),
failure: (error) => ({ success: false, error }),
// eslint-disable-next-line no-restricted-syntax
map: (value, f) => (value.success ? { success: true, data: f(value.data) } : (value as never)),
isSuccess: (value) => value.success,
// eslint-disable-next-line no-restricted-syntax
chain: (value, f) => (value.success ? f(value.data) : (value as never)),
}

Expand Down Expand Up @@ -503,3 +510,23 @@ describe('form', () => {
})
})
})

describe('zod + exception', () => {
const newForm = makeNewForm(ZODSchema, IdentityValidation)
it('encodes', () => {
const form = newForm({ foo: Z.string() }, { foo: 'foo' })
expect(form.get()).toEqual({ foo: 'foo' })
form.views.foo.set('123')
expect(form.get()).toEqual({ foo: '123' })
})
})

describe('identity + identity', () => {
const newForm = makeNewForm(IdentitySchema, IdentityValidation)
it('encodes', () => {
const form = newForm({ foo: '' }, { foo: 'foo' })
expect(form.get()).toEqual({ foo: 'foo' })
form.views.foo.set('123')
expect(form.get()).toEqual({ foo: '123' })
})
})
123 changes: 31 additions & 92 deletions packages/form/src/form.ts
Original file line number Diff line number Diff line change
@@ -1,110 +1,29 @@
import { Atom, combine, newAtom, Property } from '@frp-ts/core'
import { HKT, Kind, URIS, URIS2 } from './hkt'
import { combine, newAtom, Property } from '@frp-ts/core'
import { HKT, URIS, URIS2 } from './hkt'
import {
DecodedObjectValue1,
DecodedObjectValue2,
DecodedObjectValueHKT,
DecodedValue1,
DecodedValue2,
DecodedValueHKT,
EncodedValue2,
Form11,
Form21,
FormHKT,
FormStateHKT,
FormViewHKT,
FormViewsHKT,
Schema11,
Schema21,
SchemaHKT,
StateItemHKT,
UnknownObjectSchema1,
UnknownObjectSchema2,
UnknownObjectSchemaHKT,
Validation1,
Validation1C,
ValidationHKT,
} from './abstract/schema-f'
import { buildState } from './abstract/build-state'
} from './types'
import { mapRecord, objectEntries, objectValues } from '@frp-ts/utils'

export interface FormViewHKT<ValidationURI, Value> extends Atom<Value> {
readonly decoded: Property<HKT<ValidationURI, Value>>
readonly isDirty: Property<boolean>
readonly isDecoded: Property<boolean>
}

export interface FormView11<ValidationURI extends URIS, Value> extends Atom<Value> {
readonly decoded: Property<Kind<ValidationURI, Value>>
readonly isDirty: Property<boolean>
readonly isDecoded: Property<boolean>
}

export interface FormView21<ValidationURI extends URIS, Decoded, Encoded> extends Atom<Encoded> {
readonly decoded: Property<Kind<ValidationURI, Decoded>>
readonly isDirty: Property<boolean>
readonly isDecoded: Property<boolean>
}

export type FormViewsHKT<SchemaURI, ValidationURI, Schema extends UnknownObjectSchemaHKT<SchemaURI>> = {
readonly [Field in keyof Schema]: FormViewHKT<ValidationURI, DecodedValueHKT<SchemaURI, Schema[Field]>>
}

export type FormViews11<
SchemaURI extends URIS,
ValidationURI extends URIS,
Schema extends UnknownObjectSchema1<SchemaURI>,
> = {
readonly [Field in keyof Schema]: FormView11<ValidationURI, DecodedValue1<SchemaURI, Schema[Field]>>
}

export type FormViews21<
SchemaURI extends URIS2,
ValidationURI extends URIS,
Schema extends UnknownObjectSchema2<SchemaURI>,
> = {
readonly [Field in keyof Schema]: FormView21<
ValidationURI,
DecodedValue2<SchemaURI, Schema[Field]>,
EncodedValue2<SchemaURI, Schema[Field]>
>
}

export interface FormHKT<SchemaURI, ValidationURI, Schema extends UnknownObjectSchemaHKT<SchemaURI>>
extends Property<HKT<ValidationURI, DecodedObjectValueHKT<SchemaURI, Schema>>> {
readonly reset: (value?: DecodedObjectValueHKT<SchemaURI, Schema>) => void
readonly commit: () => void
readonly views: FormViewsHKT<SchemaURI, ValidationURI, Schema>
readonly isDirty: Property<boolean>
readonly isDecoded: Property<boolean>
}

export interface Form11<
SchemaURI extends URIS,
ValidationURI extends URIS,
Schema extends UnknownObjectSchema1<SchemaURI>,
> extends Property<Kind<ValidationURI, DecodedObjectValue1<SchemaURI, Schema>>> {
readonly reset: (value?: DecodedObjectValue1<SchemaURI, Schema>) => void
readonly commit: () => void
readonly views: FormViews11<SchemaURI, ValidationURI, Schema>
readonly isDirty: Property<boolean>
readonly isDecoded: Property<boolean>
}

export interface Form21<
SchemaURI extends URIS2,
ValidationURI extends URIS,
Schema extends UnknownObjectSchema2<SchemaURI>,
> extends Property<Kind<ValidationURI, DecodedObjectValue2<SchemaURI, Schema>>> {
readonly reset: (value?: DecodedObjectValue2<SchemaURI, Schema>) => void
readonly commit: () => void
readonly views: FormViews21<SchemaURI, ValidationURI, Schema>
readonly isDirty: Property<boolean>
readonly isDecoded: Property<boolean>
}

interface StateItemHKT<ValidationURI, Value> {
readonly encoded: Value
readonly decoded: HKT<ValidationURI, Value>
readonly isDirty: boolean
}

type FormStateHKT<SchemaURI, ValidationURI, Schema extends UnknownObjectSchemaHKT<SchemaURI>> = {
readonly [Field in keyof Schema]: StateItemHKT<ValidationURI, DecodedValueHKT<SchemaURI, Schema[Field]>>
}
export { FormHKT, Form11, Form21, SchemaHKT, Schema11, Schema21, ValidationHKT, Validation1, Validation1C }

export function makeNewForm<SchemaURI extends URIS2, ValidationURI extends URIS, Failure>(
schemaF: Schema21<SchemaURI, ValidationURI>,
Expand Down Expand Up @@ -244,3 +163,23 @@ export function makeNewForm<SchemaURI, ValidationURI>(
}
}
}

function buildState<SchemaURI, ValidationURI>(
schemaF: SchemaHKT<SchemaURI, ValidationURI>,
validationF: ValidationHKT<ValidationURI>,
): (
schema: Record<string, HKT<SchemaURI, unknown>>,
initial: Record<string, unknown>,
) => FormStateHKT<SchemaURI, ValidationURI, Record<string, HKT<SchemaURI, unknown>>> {
return (schema, initial) =>
mapRecord(schema, (field, name) => {
const value = initial[name]
const encoded = schemaF.encode(field, value)
const decoded = validationF.success(value)
return {
encoded,
decoded,
isDirty: false,
}
})
}
3 changes: 3 additions & 0 deletions packages/form/src/hkt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,15 @@ export interface HKT3<URI, R, E, A> extends HKT2<URI, E, A> {
const URI_TO_KIND = Symbol('URI_TO_KIND')
const URI_TO_KIND2 = Symbol('URI_TO_KIND2')
const URI_TO_KIND3 = Symbol('URI_TO_KIND3')
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export interface URItoKind<A> {
readonly [URI_TO_KIND]: never
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export interface URItoKind2<E, A> {
readonly [URI_TO_KIND2]: never
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export interface URItoKind3<R, E, A> {
readonly [URI_TO_KIND3]: never
}
Expand Down
31 changes: 13 additions & 18 deletions packages/form/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,14 @@
export { FormView, FormViews, Form, newForm } from './form'
export * as form from './form'
export {
numberFromStringSchema,
UnknownObjectSchema,
DecodedValue,
EncodedValue,
DecodedObjectValue,
EncodedObjectValue,
numberSchema,
objectSchema,
stringSchema,
ValueSchema,
arraySchema,
optionalSchema,
recordSchema,
booleanSchema,
} from './schema'
export * as schema from './schema'
makeNewForm,
Form11,
Form21,
FormHKT,
Schema21,
Schema11,
SchemaHKT,
ValidationHKT,
Validation1,
Validation1C,
} from './form'
export * as form from './form'
export * as hkt from './hkt'
Loading

0 comments on commit 560de6b

Please sign in to comment.