Last active
September 29, 2023 10:26
-
-
Save schickling/7f8ef3a53088f801c55f70b5bc6080ab to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { describe, expect, it } from 'vitest' | |
import { Equal } from '../index.js' | |
import * as Schema from './index.js' | |
import { JsonWrapper, jsonWrapper } from './SchemaJsonWrapper.js' | |
describe('wrapper', () => { | |
it('wrapper', () => { | |
const wrapped = jsonWrapper(Schema.number) | |
const decoded = Schema.parseSync(wrapped)(10) | |
expect(decoded).toEqual(new JsonWrapper(10)) | |
}) | |
it('wrapper array', () => { | |
const wrapped = Schema.array(jsonWrapper(Schema.number)) | |
const decoded = Schema.parseSync(wrapped)([10, 20]) | |
expect(decoded).toEqual([new JsonWrapper(10), new JsonWrapper(20)]) | |
}) | |
it('wrapper schema-class', () => { | |
type ProfilePicture = { url: string; description: string } | |
const makeProfilePicture = () => ({ url: 'https://example.com', description: 'example' }) | |
class User extends Schema.Class<User>()({ | |
id: Schema.string, | |
profilePicture: Schema.jsonUnsafe<ProfilePicture>(), | |
}) {} | |
const parse = Schema.parseSync(User) | |
const userA = parse({ id: 'u1', profilePicture: makeProfilePicture() }) | |
const userB = parse({ id: 'u1', profilePicture: makeProfilePicture() }) | |
expect(Equal.equals(userA, userB)).toBe(true) | |
}) | |
it('wrapper schema-class array', () => { | |
type ProfilePicture = { url: string; description: string } | |
const makeProfilePicture = () => ({ url: 'https://example.com', description: 'example' }) | |
class User extends Schema.Class<User>()({ | |
id: Schema.string, | |
profilePictures: Schema.data(Schema.array(Schema.jsonUnsafe<ProfilePicture>())), | |
}) {} | |
const parse = Schema.parseSync(User) | |
const userA = parse({ id: 'u1', profilePictures: [makeProfilePicture()] }) | |
// console.dir(userA, { depth: null, colors: true }) | |
const userB = parse({ id: 'u1', profilePictures: [makeProfilePicture()] }) | |
expect(Equal.equals(userA, userB)).toBe(true) | |
}) | |
}) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* eslint-disable prefer-arrow/prefer-arrow-functions */ | |
import * as Equal from '@effect/data/Equal' | |
import * as Hash from '@effect/data/Hash' | |
import type { Arbitrary } from '@effect/schema/Arbitrary' | |
import { ArbitraryHookId } from '@effect/schema/Arbitrary' | |
import * as AST from '@effect/schema/AST' | |
import * as P from '@effect/schema/Parser' | |
import * as PR from '@effect/schema/ParseResult' | |
import type { Pretty } from '@effect/schema/Pretty' | |
import { PrettyHookId } from '@effect/schema/Pretty' | |
import * as Schema from '@effect/schema/Schema' | |
// TODO get rid of this in favor of a better upstream solution | |
export class JsonWrapper<A> { | |
constructor(readonly value: A) {} | |
[Hash.symbol]() { | |
return Hash.string(JSON.stringify(this.value)) | |
} | |
[Equal.symbol](that: Equal.Equal): boolean { | |
return that instanceof JsonWrapper && JSON.stringify(this.value) === JSON.stringify(that.value) | |
} | |
} | |
const arb = | |
<A>(item: Arbitrary<A>): Arbitrary<JsonWrapper<A>> => | |
(fc) => | |
item(fc).map((a) => new JsonWrapper(a)) | |
const pretty = | |
<A>(item: Pretty<A>): Pretty<JsonWrapper<A>> => | |
(c) => | |
`Wrapper(${item(c.value)})` | |
const wrapperFromSelf = <I, A>(item: Schema.Schema<I, A>): Schema.Schema<JsonWrapper<I>, JsonWrapper<A>> => { | |
const schema = Schema.declare( | |
[item], | |
Schema.struct({ value: item }), | |
<A>(_isDecoding: boolean, item: Schema.Schema<A>) => { | |
const parse = P.parse(item) | |
return (u, options) => | |
typeof u === 'object' && u !== null && u instanceof JsonWrapper | |
? PR.map(parse(u.value, options), (a) => new JsonWrapper(a)) | |
: PR.failure(PR.type(schema.ast, u)) | |
}, | |
{ | |
[AST.IdentifierAnnotationId]: 'Wrapper', | |
[PrettyHookId]: pretty, | |
[ArbitraryHookId]: arb, | |
}, | |
) | |
return schema | |
} | |
export const jsonWrapper = <I, A>(item: Schema.Schema<I, A>): Schema.Schema<I, JsonWrapper<A>> => | |
Schema.transform( | |
item, | |
Schema.to(wrapperFromSelf(item)), | |
(a) => new JsonWrapper(a), | |
(w) => w.value, | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment