Skip to content

Commit

Permalink
feat(struct): add SchemaImplementation, StructSchema, and pick/omit m…
Browse files Browse the repository at this point in the history
…ethods
  • Loading branch information
jacob-alford committed Oct 7, 2023
1 parent bcc4af1 commit 3adf236
Show file tree
Hide file tree
Showing 11 changed files with 319 additions and 81 deletions.
60 changes: 60 additions & 0 deletions docs/Schema.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ Added in v1.0.0
- [InputOf (type alias)](#inputof-type-alias)
- [OutputOf (type alias)](#outputof-type-alias)
- [TypeOf (type alias)](#typeof-type-alias)
- [utils](#utils)
- [SchemaImplementation (class)](#schemaimplementation-class)
- [[SchemaSymbol] (property)](#schemasymbol-property)
- [input (property)](#input-property)
- [output (property)](#output-property)
- [runSchema (property)](#runschema-property)

---

Expand Down Expand Up @@ -93,3 +99,57 @@ export type TypeOf<S> = S extends Schema<any, infer A> ? A : never
```
Added in v1.0.0
# utils
## SchemaImplementation (class)
**Signature**
```ts
export declare class SchemaImplementation<I, O> {
protected constructor(runSchema: <S extends hkt.SchemableLambda>(S: Schemable<S>) => hkt.SchemableKind<S, I, O>)
}
```

Added in v2.1.0

### [SchemaSymbol] (property)

**Signature**

```ts
readonly [SchemaSymbol]: typeof SchemaSymbol
```

Added in v2.0.0

### input (property)

**Signature**

```ts
readonly input: (_: I) => I
```

Added in v2.0.0

### output (property)

**Signature**

```ts
readonly output: (_: O) => O
```

Added in v2.0.0

### runSchema (property)

**Signature**

```ts
readonly runSchema: <S extends hkt.SchemableLambda>(S: Schemable<S>) => hkt.SchemableKind<S, I, O>
```

Added in v2.0.0
5 changes: 4 additions & 1 deletion docs/schemata/Either.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ The fp-ts Either type as a schemata-ts schema.
export declare const Either: <EI, EO, AI, AO>(
left: Schema<EI, EO>,
right: Schema<AI, AO>
) => Schema<{ readonly _tag: 'Left'; left: EI } | { readonly _tag: 'Right'; right: AI }, Either_<EO, AO>>
) => Schema<
{ readonly _tag: 'Left'; readonly left: EI } | { readonly _tag: 'Right'; readonly right: AI },
Either_<EO, AO>
>
```

Added in v2.1.0
19 changes: 3 additions & 16 deletions docs/schemata/Struct.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,23 +30,10 @@ construction of such a type
**Signature**

```ts
export declare const Struct: <
T extends Record<string, Schema<any, any>>,
IndexSignature extends Schema<any, any> | undefined
>(
export declare const Struct: <T extends Record<string, Schema<any, any>>, Ix extends IxSigBase>(
props: T,
extraProps?: IndexSignature | 'strip' | 'error'
) => Schema<
{
[KeyType in keyof (RestInput<IndexSignature> &
RequiredInputProps<T> &
OptionalInputProps<T>)]: (RestInput<IndexSignature> & RequiredInputProps<T> & OptionalInputProps<T>)[KeyType]
},
{
[KeyType in keyof (RestOutput<IndexSignature> & OutputProps<T>)]: (RestOutput<IndexSignature> &
OutputProps<T>)[KeyType]
}
>
extraProps?: ExtraProps<Ix>
) => StructSchema<T, Ix>
```

Added in v1.0.0
30 changes: 15 additions & 15 deletions docs/schemata/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,23 +82,23 @@ has_children: true

### String (17)

* Ascii ([docs](https://jacob-alford.github.io/schemata-ts/schemata/Ascii.html)) ([source](https://github.com/jacob-alford/schemata-ts/tree/main/src/schemata/Ascii.ts)) (e.g: `DMBp]3`, `
* Base64 ([docs](https://jacob-alford.github.io/schemata-ts/schemata/Base64.html)) ([source](https://github.com/jacob-alford/schemata-ts/tree/main/src/schemata/Base64.ts)) (e.g: `+/A+K/87a/lV+y7/+28=`, `d/1Xc5eE+/E/+E==`, `4/S0++w/A+b/+4d/+0++Zk188/81++b=`)
* Base64Url ([docs](https://jacob-alford.github.io/schemata-ts/schemata/Base64Url.html)) ([source](https://github.com/jacob-alford/schemata-ts/tree/main/src/schemata/Base64Url.ts)) (e.g: `ABaw_9N4-9`, `d_uCP7__`, `X_-m-8`)
* BitcoinAddress ([docs](https://jacob-alford.github.io/schemata-ts/schemata/BitcoinAddress.html)) ([source](https://github.com/jacob-alford/schemata-ts/tree/main/src/schemata/BitcoinAddress.ts)) (e.g: `2e7AKymhN3LWikM8VDrjEK5DFmKP8mbj`, `bc19vebs1b1s23v10199az22ucc7`, `bc11x70o9g7c9831508kx4penko7vh`)
* Ascii ([docs](https://jacob-alford.github.io/schemata-ts/schemata/Ascii.html)) ([source](https://github.com/jacob-alford/schemata-ts/tree/main/src/schemata/Ascii.ts)) (e.g: `kOw!>;<#`, `G!+:ppi`, `W:@jd_Ms`)
* Base64 ([docs](https://jacob-alford.github.io/schemata-ts/schemata/Base64.html)) ([source](https://github.com/jacob-alford/schemata-ts/tree/main/src/schemata/Base64.ts)) (e.g: `/Z++5faVd+2+btu60db/9H00+/NCb0E/++KJEu/i`, `/W+H/p++7/l+jam/C/a/`, `xSDX/K9+6L/2zIk+`)
* Base64Url ([docs](https://jacob-alford.github.io/schemata-ts/schemata/Base64Url.html)) ([source](https://github.com/jacob-alford/schemata-ts/tree/main/src/schemata/Base64Url.ts)) (e.g: `-j00Q__`, `4C-4-s9_`, `--SNp31`)
* BitcoinAddress ([docs](https://jacob-alford.github.io/schemata-ts/schemata/BitcoinAddress.html)) ([source](https://github.com/jacob-alford/schemata-ts/tree/main/src/schemata/BitcoinAddress.ts)) (e.g: `bc149u1082oa114x5z9ek43o707c2b910`, `bc1u9wjd8b0awh7248a42g3edc0w3oh`, `1MMXC1nKKhB2JHhkRFXyvPDRkEgKCMqMdBb2pcH`)
* CamelCaseString ([docs](https://jacob-alford.github.io/schemata-ts/schemata/CamelCaseString.html)) ([source](https://github.com/jacob-alford/schemata-ts/tree/main/src/schemata/CamelCaseString.ts)) (e.g: `Camel_case-string``camelCaseString`)
* CreditCard ([docs](https://jacob-alford.github.io/schemata-ts/schemata/CreditCard.html)) ([source](https://github.com/jacob-alford/schemata-ts/tree/main/src/schemata/CreditCard.ts)) (e.g: `6221272306310132`, `62844733161743063`, `3529393243393399`)
* EmailAddress ([docs](https://jacob-alford.github.io/schemata-ts/schemata/EmailAddress.html)) ([source](https://github.com/jacob-alford/schemata-ts/tree/main/src/schemata/EmailAddress.ts)) (e.g: `"㑂鑬"@.42l346MlA.7.s4j.5.9-.qwxbrcLjdceQc`, `%^|.a~-?~9!~.$~##+.r'*R}~^_k.+.*.|{*@[5.1.919.8]`, `_}&$!'*$W#.#&.'^*_#+~d%@[279.977.590.6]`)
* EthereumAddress ([docs](https://jacob-alford.github.io/schemata-ts/schemata/EthereumAddress.html)) ([source](https://github.com/jacob-alford/schemata-ts/tree/main/src/schemata/EthereumAddress.ts)) (e.g: `0x2A80CeC004780fbfacD0DbFcbCBbc4Dee1A8Fa7E`, `0x3BAdfaC5bA8cfcf7bC3AdFbf11CaFBC70A19D6E1`, `0x7aA8dAAab980a7BcBEcaEcFcfaa3afE7ea372bB2`)
* HexColor ([docs](https://jacob-alford.github.io/schemata-ts/schemata/HexColor.html)) ([source](https://github.com/jacob-alford/schemata-ts/tree/main/src/schemata/HexColor.ts)) (e.g: `DacDac`, `bbcaD7`, `00cEa60c`)
* Hexadecimal ([docs](https://jacob-alford.github.io/schemata-ts/schemata/Hexadecimal.html)) ([source](https://github.com/jacob-alford/schemata-ts/tree/main/src/schemata/Hexadecimal.ts)) (e.g: `c9A41aAec`, `0XD6C3C`, `64Ce0b4e1847`)
* HslColor ([docs](https://jacob-alford.github.io/schemata-ts/schemata/HslColor.html)) ([source](https://github.com/jacob-alford/schemata-ts/tree/main/src/schemata/HslColor.ts)) (e.g: `hsl(.7829e59446263,000.3985798%,00031.1226%)`, `hsl(+88,000000.37242374%,+00000.900%)`, `hsla(04e-416988rad,000.38e+638451659%,+0.0062e384754552%,2.3255934e26914606)`)
* Jwt ([docs](https://jacob-alford.github.io/schemata-ts/schemata/Jwt.html)) ([source](https://github.com/jacob-alford/schemata-ts/tree/main/src/schemata/Jwt.ts)) (e.g: `1.__8rl--6_.__0`, `Wug.-0z-9A._`, `_a.e_c`)
* LatLong ([docs](https://jacob-alford.github.io/schemata-ts/schemata/LatLong.html)) ([source](https://github.com/jacob-alford/schemata-ts/tree/main/src/schemata/LatLong.ts)) (e.g: `-90.0000,+180`, `(81,+5)`, `-90.000,180`)
* NonEmptyString ([docs](https://jacob-alford.github.io/schemata-ts/schemata/NonEmptyString.html)) ([source](https://github.com/jacob-alford/schemata-ts/tree/main/src/schemata/NonEmptyString.ts)) (e.g: `}N2fg`, `]L)w:9=<b`, `WM9WXXSW4Cz=`)
* RGB ([docs](https://jacob-alford.github.io/schemata-ts/schemata/RGB.html)) ([source](https://github.com/jacob-alford/schemata-ts/tree/main/src/schemata/RGB.ts)) (e.g: `rgb(117,254,123)`, `rgba(100%,95%,90%,1)`, `rgb(239,202,204)`)
* CreditCard ([docs](https://jacob-alford.github.io/schemata-ts/schemata/CreditCard.html)) ([source](https://github.com/jacob-alford/schemata-ts/tree/main/src/schemata/CreditCard.ts)) (e.g: `8251209734106095`, `6221298095132671717`, `50876316200140438`)
* EmailAddress ([docs](https://jacob-alford.github.io/schemata-ts/schemata/EmailAddress.html)) ([source](https://github.com/jacob-alford/schemata-ts/tree/main/src/schemata/EmailAddress.ts)) (e.g: `"璤뭿㭡럟"@[6.28.1.0]`, `"੉⚼៌꓎歊￱￲掤蚻蕲捇"@[554.173.3.204]`, `-*.#e*+~.8~N+.|'r*$h$*.Ed.!/@yw52.pBicCEA`)
* EthereumAddress ([docs](https://jacob-alford.github.io/schemata-ts/schemata/EthereumAddress.html)) ([source](https://github.com/jacob-alford/schemata-ts/tree/main/src/schemata/EthereumAddress.ts)) (e.g: `0xAD3baCce2E0cABcC7AF2bDFB1fd1DFFEa7ec8A9e`, `0xbFAcebd8ef0F82BFcAB49ADdD8bCBAc93eBC1Dd7`, `0xbaCC19E37eDA0aCbBbeB9Ba91Df9Dc71FC310EbD`)
* HexColor ([docs](https://jacob-alford.github.io/schemata-ts/schemata/HexColor.html)) ([source](https://github.com/jacob-alford/schemata-ts/tree/main/src/schemata/HexColor.ts)) (e.g: `4AbAAC65`, `#fceCDfDC`, `85aBF86c`)
* Hexadecimal ([docs](https://jacob-alford.github.io/schemata-ts/schemata/Hexadecimal.html)) ([source](https://github.com/jacob-alford/schemata-ts/tree/main/src/schemata/Hexadecimal.ts)) (e.g: `Ddfab7fDb857`, `037B1abE`, `0H0dDEEB`)
* HslColor ([docs](https://jacob-alford.github.io/schemata-ts/schemata/HslColor.html)) ([source](https://github.com/jacob-alford/schemata-ts/tree/main/src/schemata/HslColor.ts)) (e.g: `hsla(01,+00000.3%,0.17e+43%,2459e+40119641)`, `hsl(.82741072919e-35570502904turn+000000000100.00000000e1244136193%+00000000097.842623%/6996301397e0389)`, `hsla(.04e-893268396turn0000100.00000e241682238%+026%)`)
* Jwt ([docs](https://jacob-alford.github.io/schemata-ts/schemata/Jwt.html)) ([source](https://github.com/jacob-alford/schemata-ts/tree/main/src/schemata/Jwt.ts)) (e.g: `Y2..___--_nH`, `q_.q78q_.-lR-d4`, `eWsc_a_-._-_`)
* LatLong ([docs](https://jacob-alford.github.io/schemata-ts/schemata/LatLong.html)) ([source](https://github.com/jacob-alford/schemata-ts/tree/main/src/schemata/LatLong.ts)) (e.g: `(80.43393119,9)`, `(90.0000,180.0000000000)`, `(-90.0000,171)`)
* NonEmptyString ([docs](https://jacob-alford.github.io/schemata-ts/schemata/NonEmptyString.html)) ([source](https://github.com/jacob-alford/schemata-ts/tree/main/src/schemata/NonEmptyString.ts)) (e.g: `f1930b5000`, `!#ypelltr`, `40201258`)
* RGB ([docs](https://jacob-alford.github.io/schemata-ts/schemata/RGB.html)) ([source](https://github.com/jacob-alford/schemata-ts/tree/main/src/schemata/RGB.ts)) (e.g: `rgba(100%,8%,7%,0.32678374049)`, `rgba(100%,100%,100%,0)`, `rgba(95%,100%,2%,.22)`)
* String ([docs](https://jacob-alford.github.io/schemata-ts/schemata/String.html)) ([source](https://github.com/jacob-alford/schemata-ts/tree/main/src/schemata/String.ts))
* UUID ([docs](https://jacob-alford.github.io/schemata-ts/schemata/UUID.html)) ([source](https://github.com/jacob-alford/schemata-ts/tree/main/src/schemata/UUID.ts)) (e.g: `c0dACC1a-360c-7a69-CC51-E8cc7EFBAcdc`, `afA1B1CA-5371-EDCc-1Cb8-A7a7ce3aaFDC`, `ddCd08e3-dc37-5cAa-EDf0-9ADbffBbb3B6`)
* UUID ([docs](https://jacob-alford.github.io/schemata-ts/schemata/UUID.html)) ([source](https://github.com/jacob-alford/schemata-ts/tree/main/src/schemata/UUID.ts)) (e.g: `BAb0d1Cc-31f8-73eB-31e0-cBf1BFbbfAAf`, `1bfB511d-326d-cEDf-5374-CCa20BDbBccC`, `6B81AE6a-b3B9-b14B-b676-acCBEcaa0bFf`)

### Unit (1)

Expand Down
49 changes: 49 additions & 0 deletions src/Schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*
* @since 1.0.0
*/
import { identity, unsafeCoerce } from 'fp-ts/function'
import type * as hkt from 'schemata-ts/internal/schemable'
import { type Schemable } from 'schemata-ts/Schemable'

Expand All @@ -22,6 +23,41 @@ export interface Schema<I, O = I> {
) => hkt.SchemableKind<S, I, O>
}

/** @since 2.1.0 */
export class SchemaImplementation<I, O = I> implements Schema<I, O> {
/** @since 2.0.0 */
readonly [SchemaSymbol]: SchemaSymbol = SchemaSymbol

/** @since 2.0.0 */
readonly input: (_: I) => I = identity

/** @since 2.0.0 */
readonly output: (_: O) => O = identity

/** @since 2.0.0 */
readonly runSchema: <S extends hkt.SchemableLambda>(
S: Schemable<S>,
) => hkt.SchemableKind<S, I, O>

protected constructor(
runSchema: <S extends hkt.SchemableLambda>(
S: Schemable<S>,
) => hkt.SchemableKind<S, I, O>,
) {
this.runSchema = memoize(runSchema)
}

/** @internal */
public static make = <S extends Schema<any, any>['runSchema']>(
f: S,
): S extends (...args: ReadonlyArray<any>) => {
Input: (...args: ReadonlyArray<any>) => infer I
Output: (...args: ReadonlyArray<any>) => infer O
}
? Schema<I, O>
: never => unsafeCoerce(new SchemaImplementation(f))
}

/**
* @since 2.0.0
* @category Guards
Expand Down Expand Up @@ -54,3 +90,16 @@ export type OutputOf<S> = TypeOf<S>
* @category Type Helpers
*/
export type InputOf<S> = S extends Schema<infer I, any> ? I : never

/** @internal */
export const memoize = <A, B>(f: (a: A) => B): ((a: A) => B) => {
const cache = new Map()
return a => {
if (!cache.has(a)) {
const b = f(a)
cache.set(a, b)
return b
}
return cache.get(a)
}
}
34 changes: 9 additions & 25 deletions src/internal/schema.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
/* eslint-disable @typescript-eslint/ban-types */
import { identity, unsafeCoerce } from 'fp-ts/function'
import { type SchemableKind, type SchemableLambda } from 'schemata-ts/internal/schemable'
import type * as s from 'schemata-ts/internal/struct'
import { type InputOf, type OutputOf, type Schema } from 'schemata-ts/Schema'
import {
type InputOf,
type OutputOf,
type Schema,
SchemaImplementation,
} from 'schemata-ts/Schema'
import { type Schemable } from 'schemata-ts/Schemable'

/** @since 2.0.0 */
Expand Down Expand Up @@ -39,21 +42,6 @@ export type RestOutput<RestKind> = RestKind extends undefined
? unknown
: { [key: string]: RestKind extends Schema<any, infer O> ? O : never }

/** @internal */
export const memoize = <A, B>(f: (a: A) => B): ((a: A) => B) => {
const cache = new Map()
return a => {
if (!cache.has(a)) {
const b = f(a)
cache.set(a, b)
return b
}
return cache.get(a)
}
}

const SchemaSymbol = Symbol.for('schemata-ts/Schema')

/** @internal */
export const make = <S extends Schema<any, any>['runSchema']>(
f: S,
Expand All @@ -62,13 +50,7 @@ export const make = <S extends Schema<any, any>['runSchema']>(
Output: (...args: ReadonlyArray<any>) => infer A
}
? Schema<E, A>
: never =>
unsafeCoerce({
[SchemaSymbol]: SchemaSymbol,
runSchema: memoize(f),
input: identity,
output: identity,
})
: never => SchemaImplementation.make(f)

/** @since 2.0.0 */
export type Interpreter<S extends SchemableLambda> = <I, O>(
Expand All @@ -79,3 +61,5 @@ export type Interpreter<S extends SchemableLambda> = <I, O>(
export const interpret: <S extends SchemableLambda>(S: Schemable<S>) => Interpreter<S> =
S => schema =>
schema.runSchema(S)

export { memoize } from 'schemata-ts/Schema'

0 comments on commit 3adf236

Please sign in to comment.