Skip to content

Commit

Permalink
remove from/to APIs (#1878)
Browse files Browse the repository at this point in the history
  • Loading branch information
gcanti authored Jan 9, 2024
1 parent d626c28 commit c4b84f7
Show file tree
Hide file tree
Showing 40 changed files with 1,284 additions and 656 deletions.
5 changes: 5 additions & 0 deletions .changeset/happy-apricots-bathe.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@effect/schema": patch
---

Schema: Pretty add `pretty` annotation API
5 changes: 5 additions & 0 deletions .changeset/nine-buttons-watch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@effect/schema": patch
---

Schema: Arbitrary add `arbitrary` annotation
5 changes: 5 additions & 0 deletions .changeset/pretty-moles-drop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@effect/schema": patch
---

Schema: Equivalence add `equivalence` annotation
9 changes: 9 additions & 0 deletions .changeset/yellow-geckos-exercise.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
"@effect/schema": minor
---

Schema: remove `from`/`to` API in favour of `make` in:

- Equivalence
- JSONSchema
- Pretty
12 changes: 6 additions & 6 deletions packages/schema/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -755,7 +755,7 @@ const Person = S.struct({
age: S.number,
});

const PersonPretty = Pretty.to(Person);
const PersonPretty = Pretty.make(Person);

// returns a string representation of the object
console.log(PersonPretty({ name: "Alice", age: 30 }));
Expand All @@ -778,7 +778,7 @@ const Person = S.struct({
age: S.number,
});

const jsonSchema = JSONSchema.to(Person);
const jsonSchema = JSONSchema.make(Person);

console.log(JSON.stringify(jsonSchema, null, 2));
/*
Expand Down Expand Up @@ -824,7 +824,7 @@ const Person = S.struct({
age: Age,
});

const jsonSchema = JSONSchema.to(Person);
const jsonSchema = JSONSchema.make(Person);

console.log(JSON.stringify(jsonSchema, null, 2));
/*
Expand Down Expand Up @@ -881,7 +881,7 @@ const schema: S.Schema<Category> = S.struct({
categories: S.array(S.suspend(() => schema)),
}).pipe(S.identifier("Category"));

const jsonSchema = JSONSchema.to(schema);
const jsonSchema = JSONSchema.make(schema);

console.log(JSON.stringify(jsonSchema, null, 2));
/*
Expand Down Expand Up @@ -941,7 +941,7 @@ const schema = Positive.pipe(
})
);

console.log(JSONSchema.to(schema));
console.log(JSONSchema.make(schema));
/*
Output:
{
Expand Down Expand Up @@ -971,7 +971,7 @@ const Person = S.struct({
});

// $ExpectType Equivalence<{ readonly name: string; readonly age: number; }>
const PersonEquivalence = Equivalence.to(Person);
const PersonEquivalence = Equivalence.make(Person);

const john = { name: "John", age: 23 };
const alice = { name: "Alice", age: 30 };
Expand Down
13 changes: 9 additions & 4 deletions packages/schema/src/Arbitrary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import * as AST from "./AST.js"
import * as Internal from "./internal/ast.js"
import * as filters from "./internal/filters.js"
import * as hooks from "./internal/hooks.js"
import * as InternalSchema from "./internal/schema.js"
import * as Parser from "./Parser.js"
import type * as Schema from "./Schema.js"

Expand All @@ -33,10 +34,14 @@ export const ArbitraryHookId: unique symbol = hooks.ArbitraryHookId
*/
export type ArbitraryHookId = typeof ArbitraryHookId

/** @internal */
export const unsafe = <I, A>(
schema: Schema.Schema<I, A>
): Arbitrary<A> => go(schema.ast, {})
/**
* @category annotations
* @since 1.0.0
*/
export const arbitrary =
<A>(handler: (...args: ReadonlyArray<Arbitrary<any>>) => Arbitrary<A>) =>
<I>(self: Schema.Schema<I, A>): Schema.Schema<I, A> =>
InternalSchema.make(AST.setAnnotation(self.ast, ArbitraryHookId, handler))

/**
* Returns a fast-check Arbitrary for the `A` type of the provided schema.
Expand Down
17 changes: 13 additions & 4 deletions packages/schema/src/Equivalence.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import * as ReadonlyArray from "effect/ReadonlyArray"
import * as AST from "./AST.js"
import * as Internal from "./internal/ast.js"
import * as hooks from "./internal/hooks.js"
import * as InternalSchema from "./internal/schema.js"
import * as Parser from "./Parser.js"
import type * as Schema from "./Schema.js"

Expand All @@ -26,16 +27,19 @@ export const EquivalenceHookId: unique symbol = hooks.EquivalenceHookId
export type EquivalenceHookId = typeof EquivalenceHookId

/**
* @category Equivalence
* @category annotations
* @since 1.0.0
*/
export const to = <I, A>(schema: Schema.Schema<I, A>): Equivalence.Equivalence<A> => go(AST.to(schema.ast))
export const equivalence =
<A>(handler: (...args: ReadonlyArray<Equivalence.Equivalence<any>>) => Equivalence.Equivalence<A>) =>
<I>(self: Schema.Schema<I, A>): Schema.Schema<I, A> =>
InternalSchema.make(AST.setAnnotation(self.ast, EquivalenceHookId, handler))

/**
* @category Equivalence
* @since 1.0.0
*/
export const from = <I, A>(schema: Schema.Schema<I, A>): Equivalence.Equivalence<I> => go(AST.from(schema.ast))
export const make = <I, A>(schema: Schema.Schema<I, A>): Equivalence.Equivalence<A> => go(schema.ast)

const getHook = AST.getAnnotation<
(...args: ReadonlyArray<Equivalence.Equivalence<any>>) => Equivalence.Equivalence<any>
Expand All @@ -51,7 +55,12 @@ const is = (ast: AST.AST) => {
const go = (ast: AST.AST): Equivalence.Equivalence<any> => {
const hook = getHook(ast)
if (Option.isSome(hook)) {
return AST.isDeclaration(ast) ? hook.value(...ast.typeParameters.map(go)) : hook.value()
switch (ast._tag) {
case "Declaration":
return hook.value(...ast.typeParameters.map(go))
default:
return hook.value()
}
}
switch (ast._tag) {
case "NeverKeyword":
Expand Down
54 changes: 24 additions & 30 deletions packages/schema/src/JSONSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -208,13 +208,7 @@ export type JsonSchema7Root = JsonSchema7 & {
* @category encoding
* @since 1.0.0
*/
export const to = <I, A>(schema: Schema.Schema<I, A>): JsonSchema7Root => goRoot(AST.to(schema.ast))

/**
* @category encoding
* @since 1.0.0
*/
export const from = <I, A>(schema: Schema.Schema<I, A>): JsonSchema7Root => goRoot(AST.from(schema.ast))
export const make = <I, A>(schema: Schema.Schema<I, A>): JsonSchema7Root => goRoot(schema.ast)

const anyJsonSchema: JsonSchema7 = { $id: "/schemas/any" }

Expand Down Expand Up @@ -276,9 +270,8 @@ const getMetaData = (annotated: AST.Annotated) =>
})

const goWithMetaData = (ast: AST.AST, $defs: Record<string, JsonSchema7>): JsonSchema7 => {
const jsonSchema = go(ast, $defs)
return {
...jsonSchema,
...go(ast, $defs),
...getMetaData(ast)
}
}
Expand All @@ -287,9 +280,17 @@ const goWithMetaData = (ast: AST.AST, $defs: Record<string, JsonSchema7>): JsonS
export const DEFINITION_PREFIX = "#/$defs/"

const go = (ast: AST.AST, $defs: Record<string, JsonSchema7>): JsonSchema7 => {
const hook = AST.getJSONSchemaAnnotation(ast)
if (Option.isSome(hook)) {
switch (ast._tag) {
case "Refinement":
return { ...goWithIdentifier(ast.from, $defs), ...hook.value }
}
return hook.value as any
}
switch (ast._tag) {
case "Declaration": {
throw new Error("cannot convert a declaration to JSON Schema")
throw new Error("cannot build a JSON Schema for a declaration without a JSON Schema annotation")
}
case "Literal": {
const literal = ast.literal
Expand All @@ -302,16 +303,16 @@ const go = (ast: AST.AST, $defs: Record<string, JsonSchema7>): JsonSchema7 => {
} else if (Predicate.isBoolean(literal)) {
return { const: literal }
}
throw new Error("cannot convert `bigint` to JSON Schema")
throw new Error("cannot build a JSON Schema for a bigint literal without a JSON Schema annotation")
}
case "UniqueSymbol":
throw new Error("cannot convert a unique symbol to JSON Schema")
throw new Error("cannot build a JSON Schema for a unique symbol without a JSON Schema annotation")
case "UndefinedKeyword":
throw new Error("cannot convert `undefined` to JSON Schema")
throw new Error("cannot build a JSON Schema for `undefined` without a JSON Schema annotation")
case "VoidKeyword":
throw new Error("cannot convert `void` to JSON Schema")
throw new Error("cannot build a JSON Schema for `void` without a JSON Schema annotation")
case "NeverKeyword":
throw new Error("cannot convert `never` to JSON Schema")
throw new Error("cannot build a JSON Schema for `never` without a JSON Schema annotation")
case "UnknownKeyword":
return { ...unknownJsonSchema }
case "AnyKeyword":
Expand All @@ -325,9 +326,9 @@ const go = (ast: AST.AST, $defs: Record<string, JsonSchema7>): JsonSchema7 => {
case "BooleanKeyword":
return { type: "boolean" }
case "BigIntKeyword":
throw new Error("cannot convert `bigint` to JSON Schema")
throw new Error("cannot build a JSON Schema for `bigint` without a JSON Schema annotation")
case "SymbolKeyword":
throw new Error("cannot convert `symbol` to JSON Schema")
throw new Error("cannot build a JSON Schema for `symbol` without a JSON Schema annotation")
case "Tuple": {
const elements = ast.elements.map((e) => goWithIdentifier(e.type, $defs))
const rest = Option.map(
Expand Down Expand Up @@ -395,13 +396,13 @@ const go = (ast: AST.AST, $defs: Record<string, JsonSchema7>): JsonSchema7 => {
break
}
case "Refinement": {
const annotation = AST.getJSONSchemaAnnotation(parameter)
const hook = AST.getJSONSchemaAnnotation(parameter)
if (
Option.isSome(annotation) && "pattern" in annotation.value &&
Predicate.isString(annotation.value.pattern)
Option.isSome(hook) && "pattern" in hook.value &&
Predicate.isString(hook.value.pattern)
) {
patternProperties = {
[annotation.value.pattern]: goWithIdentifier(
[hook.value.pattern]: goWithIdentifier(
is.type,
$defs
)
Expand Down Expand Up @@ -489,14 +490,7 @@ const go = (ast: AST.AST, $defs: Record<string, JsonSchema7>): JsonSchema7 => {
}
}
case "Refinement": {
const from = goWithIdentifier(ast.from, $defs)
const annotation = AST.getJSONSchemaAnnotation(ast)
if (Option.isSome(annotation)) {
return { ...from, ...annotation.value }
}
throw new Error(
"cannot build a JSON Schema for refinements without a JSON Schema annotation"
)
throw new Error("cannot build a JSON Schema for a refinement without a JSON Schema annotation")
}
case "TemplateLiteral": {
const regex = Parser.getTemplateLiteralRegex(ast)
Expand All @@ -516,6 +510,6 @@ const go = (ast: AST.AST, $defs: Record<string, JsonSchema7>): JsonSchema7 => {
return goWithIdentifier(ast.f(), $defs)
}
case "Transform":
throw new Error("cannot build a JSON Schema for transformations")
return goWithIdentifier(ast.to, $defs)
}
}
Loading

0 comments on commit c4b84f7

Please sign in to comment.