From af288f36326b64cd0eb8d5fdade56480fa3a2192 Mon Sep 17 00:00:00 2001 From: Andrew M Date: Thu, 10 Oct 2024 14:35:57 -0400 Subject: [PATCH 1/8] add TSubscriptionRef (#2725) Co-authored-by: Michael Arnaldi Co-authored-by: Tim --- .changeset/cold-cougars-pretend.md | 5 + .changeset/shiny-squids-sell.md | 5 + packages/effect/src/Stream.ts | 18 ++ packages/effect/src/TPubSub.ts | 9 + packages/effect/src/TQueue.ts | 14 +- packages/effect/src/TRef.ts | 3 +- packages/effect/src/TSubscriptionRef.ts | 192 ++++++++++++ packages/effect/src/index.ts | 5 + packages/effect/src/internal/stm/core.ts | 3 +- packages/effect/src/internal/stm/tPubSub.ts | 1 + packages/effect/src/internal/stm/tQueue.ts | 4 +- packages/effect/src/internal/stm/tRef.ts | 9 +- .../src/internal/stm/tSubscriptionRef.ts | 286 ++++++++++++++++++ packages/effect/src/internal/stream.ts | 28 ++ packages/effect/test/TSubscriptionRef.test.ts | 148 +++++++++ 15 files changed, 716 insertions(+), 14 deletions(-) create mode 100644 .changeset/cold-cougars-pretend.md create mode 100644 .changeset/shiny-squids-sell.md create mode 100644 packages/effect/src/TSubscriptionRef.ts create mode 100644 packages/effect/src/internal/stm/tSubscriptionRef.ts create mode 100644 packages/effect/test/TSubscriptionRef.test.ts diff --git a/.changeset/cold-cougars-pretend.md b/.changeset/cold-cougars-pretend.md new file mode 100644 index 0000000000..df705b7505 --- /dev/null +++ b/.changeset/cold-cougars-pretend.md @@ -0,0 +1,5 @@ +--- +"effect": minor +--- + +add TSubscriptionRef diff --git a/.changeset/shiny-squids-sell.md b/.changeset/shiny-squids-sell.md new file mode 100644 index 0000000000..0e68f8a95f --- /dev/null +++ b/.changeset/shiny-squids-sell.md @@ -0,0 +1,5 @@ +--- +"effect": minor +--- + +add Stream.fromTQueue & Stream.fromTPubSub diff --git a/packages/effect/src/Stream.ts b/packages/effect/src/Stream.ts index 9a4dc08439..bbcf0bd702 100644 --- a/packages/effect/src/Stream.ts +++ b/packages/effect/src/Stream.ts @@ -29,6 +29,8 @@ import type * as Sink from "./Sink.js" import type * as Emit from "./StreamEmit.js" import type * as HaltStrategy from "./StreamHaltStrategy.js" import type * as Take from "./Take.js" +import type { TPubSub } from "./TPubSub.js" +import type { TDequeue } from "./TQueue.js" import type * as Tracer from "./Tracer.js" import type { Covariant, NoInfer, TupleOf } from "./Types.js" import type * as Unify from "./Unify.js" @@ -2013,6 +2015,14 @@ export const fromPubSub: { ): Stream } = internal.fromPubSub +/** + * Creates a stream from a subscription to a `TPubSub`. + * + * @since 3.10.0 + * @category constructors + */ +export const fromTPubSub: (pubsub: TPubSub) => Stream = internal.fromTPubSub + /** * Creates a new `Stream` from an iterable collection of values. * @@ -2094,6 +2104,14 @@ export const fromQueue: ( } ) => Stream = internal.fromQueue +/** + * Creates a stream from a TQueue of values + * + * @since 3.10.0 + * @category constructors + */ +export const fromTQueue: (queue: TDequeue) => Stream = internal.fromTQueue + /** * Creates a stream from a `ReadableStream`. * diff --git a/packages/effect/src/TPubSub.ts b/packages/effect/src/TPubSub.ts index 1a15cfa1b6..f6b7b045ce 100644 --- a/packages/effect/src/TPubSub.ts +++ b/packages/effect/src/TPubSub.ts @@ -107,6 +107,15 @@ export const isEmpty: (self: TPubSub) => STM.STM = internal.isEmp */ export const isFull: (self: TPubSub) => STM.STM = internal.isFull +/** + * Interrupts any fibers that are suspended on `offer` or `take`. Future calls + * to `offer*` and `take*` will be interrupted immediately. + * + * @since 2.0.0 + * @category utils + */ +export const shutdown: (self: TPubSub) => STM.STM = internal.shutdown + /** * Returns `true` if `shutdown` has been called, otherwise returns `false`. * diff --git a/packages/effect/src/TQueue.ts b/packages/effect/src/TQueue.ts index 800555b2c8..e8b9b465fa 100644 --- a/packages/effect/src/TQueue.ts +++ b/packages/effect/src/TQueue.ts @@ -206,7 +206,7 @@ export const isTEnqueue: (u: unknown) => u is TEnqueue = internal.isTEn * @since 2.0.0 * @category mutations */ -export const awaitShutdown: (self: TQueue) => STM.STM = internal.awaitShutdown +export const awaitShutdown: (self: TDequeue | TEnqueue) => STM.STM = internal.awaitShutdown /** * Creates a bounded queue with the back pressure strategy. The queue will @@ -226,7 +226,7 @@ export const bounded: (requestedCapacity: number) => STM.STM> = int * @since 2.0.0 * @category getters */ -export const capacity: (self: TQueue) => number = internal.capacity +export const capacity: (self: TDequeue | TEnqueue) => number = internal.capacity /** * Creates a bounded queue with the dropping strategy. The queue will drop new @@ -245,7 +245,7 @@ export const dropping: (requestedCapacity: number) => STM.STM> = in * @since 2.0.0 * @category getters */ -export const isEmpty: (self: TQueue) => STM.STM = internal.isEmpty +export const isEmpty: (self: TDequeue | TEnqueue) => STM.STM = internal.isEmpty /** * Returns `true` if the `TQueue` contains at least one element, `false` @@ -254,7 +254,7 @@ export const isEmpty: (self: TQueue) => STM.STM = internal.isEmpt * @since 2.0.0 * @category getters */ -export const isFull: (self: TQueue) => STM.STM = internal.isFull +export const isFull: (self: TDequeue | TEnqueue) => STM.STM = internal.isFull /** * Returns `true` if `shutdown` has been called, otherwise returns `false`. @@ -262,7 +262,7 @@ export const isFull: (self: TQueue) => STM.STM = internal.isFull * @since 2.0.0 * @category getters */ -export const isShutdown: (self: TQueue) => STM.STM = internal.isShutdown +export const isShutdown: (self: TDequeue | TEnqueue) => STM.STM = internal.isShutdown /** * Places one value in the queue. @@ -345,7 +345,7 @@ export const seek: { * @since 2.0.0 * @category mutations */ -export const shutdown: (self: TQueue) => STM.STM = internal.shutdown +export const shutdown: (self: TDequeue | TEnqueue) => STM.STM = internal.shutdown /** * Retrieves the size of the queue, which is equal to the number of elements @@ -355,7 +355,7 @@ export const shutdown: (self: TQueue) => STM.STM = internal.shutdown * @since 2.0.0 * @category getters */ -export const size: (self: TQueue) => STM.STM = internal.size +export const size: (self: TDequeue | TEnqueue) => STM.STM = internal.size /** * Creates a bounded queue with the sliding strategy. The queue will add new diff --git a/packages/effect/src/TRef.ts b/packages/effect/src/TRef.ts index 5b98a7c653..1dd83e9c4e 100644 --- a/packages/effect/src/TRef.ts +++ b/packages/effect/src/TRef.ts @@ -7,6 +7,7 @@ import type * as TxnId from "./internal/stm/stm/txnId.js" import type * as Versioned from "./internal/stm/stm/versioned.js" import * as internal from "./internal/stm/tRef.js" import type * as Option from "./Option.js" +import type { Pipeable } from "./Pipeable.js" import type * as STM from "./STM.js" import type * as Types from "./Types.js" @@ -34,7 +35,7 @@ export type TRefTypeId = typeof TRefTypeId * @since 2.0.0 * @category models */ -export interface TRef extends TRef.Variance { +export interface TRef extends TRef.Variance, Pipeable { /** * Note: the method is unbound, exposed only for potential extensions. */ diff --git a/packages/effect/src/TSubscriptionRef.ts b/packages/effect/src/TSubscriptionRef.ts new file mode 100644 index 0000000000..dfc6ccb5ff --- /dev/null +++ b/packages/effect/src/TSubscriptionRef.ts @@ -0,0 +1,192 @@ +/** + * @since 3.10.0 + */ +import type * as Effect from "./Effect.js" +import * as internal from "./internal/stm/tSubscriptionRef.js" +import type * as Option from "./Option.js" +import type * as Scope from "./Scope.js" +import type * as STM from "./STM.js" +import type * as Stream from "./Stream.js" +import type * as TPubSub from "./TPubSub.js" +import type * as TQueue from "./TQueue.js" +import type * as TRef from "./TRef.js" +import type * as Types from "./Types.js" + +/** + * @since 3.10.0 + * @category symbols + */ +export const TSubscriptionRefTypeId: unique symbol = internal.TSubscriptionRefTypeId + +/** + * @since 3.10.0 + * @category symbols + */ +export type TSubscriptionRefTypeId = typeof TSubscriptionRefTypeId + +/** + * A `TSubscriptionRef` is a `TRef` that can be subscribed to in order to + * receive a `TDequeue` of the current value and all committed changes to the value. + * + * @since 3.10.0 + * @category models + */ +export interface TSubscriptionRef extends TSubscriptionRef.Variance, TRef.TRef { + /** @internal */ + readonly ref: TRef.TRef + /** @internal */ + readonly pubsub: TPubSub.TPubSub + /** @internal */ + modify(f: (a: A) => readonly [B, A]): STM.STM + + /** + * A TDequeue containing the current value of the `Ref` as well as all changes + * to that value. + */ + readonly changes: STM.STM> +} + +/** + * @since 3.10.0 + */ +export declare namespace TSubscriptionRef { + /** + * @since 3.10.0 + * @category models + */ + export interface Variance { + readonly [TSubscriptionRefTypeId]: { + readonly _A: Types.Invariant + } + } +} + +/** + * @since 3.10.0 + * @category mutations + */ +export const get: (self: TSubscriptionRef) => STM.STM = internal.get + +/** + * @since 3.10.0 + * @category mutations + */ +export const getAndSet: { + (value: A): (self: TSubscriptionRef) => STM.STM + (self: TSubscriptionRef, value: A): STM.STM +} = internal.getAndSet + +/** + * @since 3.10.0 + * @category mutations + */ +export const getAndUpdate: { + (f: (a: A) => A): (self: TSubscriptionRef) => STM.STM + (self: TSubscriptionRef, f: (a: A) => A): STM.STM +} = internal.getAndUpdate + +/** + * @since 3.10.0 + * @category mutations + */ +export const getAndUpdateSome: { + (f: (a: A) => Option.Option): (self: TSubscriptionRef) => STM.STM + (self: TSubscriptionRef, f: (a: A) => Option.Option): STM.STM +} = internal.getAndUpdateSome + +/** + * @since 3.10.0 + * @category constructors + */ +export const make: (value: A) => STM.STM> = internal.make + +/** + * @since 3.10.0 + * @category mutations + */ +export const modify: { + (f: (a: A) => readonly [B, A]): (self: TSubscriptionRef) => STM.STM + (self: TSubscriptionRef, f: (a: A) => readonly [B, A]): STM.STM +} = internal.modify + +/** + * @since 3.10.0 + * @category mutations + */ +export const modifySome: { + (fallback: B, f: (a: A) => Option.Option): (self: TSubscriptionRef) => STM.STM + (self: TSubscriptionRef, fallback: B, f: (a: A) => Option.Option): STM.STM +} = internal.modifySome + +/** + * @since 3.10.0 + * @category mutations + */ +export const set: { + (value: A): (self: TSubscriptionRef) => STM.STM + (self: TSubscriptionRef, value: A): STM.STM +} = internal.set + +/** + * @since 3.10.0 + * @category mutations + */ +export const setAndGet: { + (value: A): (self: TSubscriptionRef) => STM.STM + (self: TSubscriptionRef, value: A): STM.STM +} = internal.setAndGet + +/** + * @since 3.10.0 + * @category mutations + */ +export const update: { + (f: (a: A) => A): (self: TSubscriptionRef) => STM.STM + (self: TSubscriptionRef, f: (a: A) => A): STM.STM +} = internal.update + +/** + * @since 3.10.0 + * @category mutations + */ +export const updateAndGet: { + (f: (a: A) => A): (self: TSubscriptionRef) => STM.STM + (self: TSubscriptionRef, f: (a: A) => A): STM.STM +} = internal.updateAndGet + +/** + * @since 3.10.0 + * @category mutations + */ +export const updateSome: { + (f: (a: A) => Option.Option): (self: TSubscriptionRef) => STM.STM + (self: TSubscriptionRef, f: (a: A) => Option.Option): STM.STM +} = internal.updateSome + +/** + * @since 3.10.0 + * @category mutations + */ +export const updateSomeAndGet: { + (f: (a: A) => Option.Option): (self: TSubscriptionRef) => STM.STM + (self: TSubscriptionRef, f: (a: A) => Option.Option): STM.STM +} = internal.updateSomeAndGet + +/** + * @since 3.10.0 + * @category mutations + */ +export const changesScoped: (self: TSubscriptionRef) => Effect.Effect, never, Scope.Scope> = + internal.changesScoped + +/** + * @since 3.10.0 + * @category mutations + */ +export const changesStream: (self: TSubscriptionRef) => Stream.Stream = internal.changesStream + +/** + * @since 3.10.0 + * @category mutations + */ +export const changes: (self: TSubscriptionRef) => STM.STM> = (self) => self.changes diff --git a/packages/effect/src/index.ts b/packages/effect/src/index.ts index cb90a4ac72..a57bd513ed 100644 --- a/packages/effect/src/index.ts +++ b/packages/effect/src/index.ts @@ -895,6 +895,11 @@ export * as TSemaphore from "./TSemaphore.js" */ export * as TSet from "./TSet.js" +/** + * @since 3.10.0 + */ +export * as TSubscriptionRef from "./TSubscriptionRef.js" + /** * @since 2.0.0 */ diff --git a/packages/effect/src/internal/stm/core.ts b/packages/effect/src/internal/stm/core.ts index 7c0f558715..1203090752 100644 --- a/packages/effect/src/internal/stm/core.ts +++ b/packages/effect/src/internal/stm/core.ts @@ -15,11 +15,10 @@ import { pipeArguments } from "../../Pipeable.js" import { hasProperty } from "../../Predicate.js" import type * as Scheduler from "../../Scheduler.js" import type * as STM from "../../STM.js" -import { StreamTypeId } from "../../Stream.js" import { YieldWrap } from "../../Utils.js" import { ChannelTypeId } from "../core-stream.js" import { withFiberRuntime } from "../core.js" -import { effectVariance } from "../effectable.js" +import { effectVariance, StreamTypeId } from "../effectable.js" import { OP_COMMIT } from "../opCodes/effect.js" import { SingleShotGen } from "../singleShotGen.js" import { SinkTypeId } from "../sink.js" diff --git a/packages/effect/src/internal/stm/tPubSub.ts b/packages/effect/src/internal/stm/tPubSub.ts index 089be12ce5..b838ddb90a 100644 --- a/packages/effect/src/internal/stm/tPubSub.ts +++ b/packages/effect/src/internal/stm/tPubSub.ts @@ -201,6 +201,7 @@ class TPubSubSubscriptionImpl implements TQueue.TDequeue { capacity(): number { return this.requestedCapacity } + size: STM.STM = core.withSTMRuntime((runtime) => { let currentSubscriberHead = tRef.unsafeGet(this.subscriberHead, runtime.journal) if (currentSubscriberHead === undefined) { diff --git a/packages/effect/src/internal/stm/tQueue.ts b/packages/effect/src/internal/stm/tQueue.ts index 90039374f3..8ca27b9865 100644 --- a/packages/effect/src/internal/stm/tQueue.ts +++ b/packages/effect/src/internal/stm/tQueue.ts @@ -3,7 +3,7 @@ import * as Chunk from "../../Chunk.js" import { dual, pipe } from "../../Function.js" import * as Option from "../../Option.js" import { hasProperty, type Predicate } from "../../Predicate.js" -import * as STM from "../../STM.js" +import type * as STM from "../../STM.js" import type * as TQueue from "../../TQueue.js" import type * as TRef from "../../TRef.js" import * as core from "./core.js" @@ -99,7 +99,7 @@ class TQueueImpl implements TQueue.TQueue { size: STM.STM = core.withSTMRuntime((runtime) => { const queue = tRef.unsafeGet(this.ref, runtime.journal) if (queue === undefined) { - return STM.interruptAs(runtime.fiberId) + return core.interruptAs(runtime.fiberId) } return core.succeed(queue.length) }) diff --git a/packages/effect/src/internal/stm/tRef.ts b/packages/effect/src/internal/stm/tRef.ts index c780509360..3162fc252b 100644 --- a/packages/effect/src/internal/stm/tRef.ts +++ b/packages/effect/src/internal/stm/tRef.ts @@ -1,5 +1,7 @@ import { dual } from "../../Function.js" import * as Option from "../../Option.js" +import type { Pipeable } from "../../Pipeable.js" +import { pipeArguments } from "../../Pipeable.js" import type * as STM from "../../STM.js" import type * as TRef from "../../TRef.js" import * as core from "./core.js" @@ -16,13 +18,13 @@ export const TRefTypeId: TRef.TRefTypeId = Symbol.for( TRefSymbolKey ) as TRef.TRefTypeId -const tRefVariance = { +export const tRefVariance = { /* c8 ignore next */ _A: (_: any) => _ } /** @internal */ -export class TRefImpl implements TRef.TRef { +export class TRefImpl implements TRef.TRef, Pipeable { readonly [TRefTypeId] = tRefVariance /** @internal */ todos: Map @@ -40,6 +42,9 @@ export class TRefImpl implements TRef.TRef { return retValue }) } + pipe() { + return pipeArguments(this, arguments) + } } /** @internal */ diff --git a/packages/effect/src/internal/stm/tSubscriptionRef.ts b/packages/effect/src/internal/stm/tSubscriptionRef.ts new file mode 100644 index 0000000000..94a4924055 --- /dev/null +++ b/packages/effect/src/internal/stm/tSubscriptionRef.ts @@ -0,0 +1,286 @@ +import * as Effect from "../../Effect.js" +import { dual, pipe } from "../../Function.js" +import * as Option from "../../Option.js" +import { pipeArguments } from "../../Pipeable.js" +import * as STM from "../../STM.js" +import * as TPubSub from "../../TPubSub.js" +import * as TQueue from "../../TQueue.js" +import * as TRef from "../../TRef.js" +import type * as TSubscriptionRef from "../../TSubscriptionRef.js" +import * as stream from "../stream.js" +import { tDequeueVariance } from "./tQueue.js" +import { tRefVariance } from "./tRef.js" + +/** @internal */ +const TSubscriptionRefSymbolKey = "effect/TSubscriptionRef" + +/** @internal */ +export const TSubscriptionRefTypeId: TSubscriptionRef.TSubscriptionRefTypeId = Symbol.for( + TSubscriptionRefSymbolKey +) as TSubscriptionRef.TSubscriptionRefTypeId + +const TSubscriptionRefVariance = { + /* c8 ignore next */ + _A: (_: any) => _ +} + +class TDequeueMerge implements TQueue.TDequeue { + [TQueue.TDequeueTypeId] = tDequeueVariance + + constructor( + readonly first: TQueue.TDequeue, + readonly second: TQueue.TDequeue + ) {} + + peek: STM.STM = STM.gen(this, function*() { + const first = yield* this.peekOption + if (first._tag === "Some") { + return first.value + } + return yield* STM.retry + }) + + peekOption: STM.STM> = STM.gen(this, function*() { + const first = yield* this.first.peekOption + if (first._tag === "Some") { + return first + } + const second = yield* this.second.peekOption + if (second._tag === "Some") { + return second + } + return Option.none() + }) + + take: STM.STM = STM.gen(this, function*() { + if (!(yield* this.first.isEmpty)) { + return yield* this.first.take + } + if (!(yield* this.second.isEmpty)) { + return yield* this.second.take + } + return yield* STM.retry + }) + + takeAll: STM.STM> = STM.gen(this, function*() { + return [...yield* this.first.takeAll, ...yield* this.second.takeAll] + }) + + takeUpTo(max: number): STM.STM> { + return STM.gen(this, function*() { + const first = yield* this.first.takeUpTo(max) + if (first.length >= max) { + return first + } + return [...first, ...yield* this.second.takeUpTo(max - first.length)] + }) + } + + capacity(): number { + return this.first.capacity() + this.second.capacity() + } + + size: STM.STM = STM.gen(this, function*() { + return (yield* this.first.size) + (yield* this.second.size) + }) + + isFull: STM.STM = STM.gen(this, function*() { + return (yield* this.first.isFull) && (yield* this.second.isFull) + }) + + isEmpty: STM.STM = STM.gen(this, function*() { + return (yield* this.first.isEmpty) && (yield* this.second.isEmpty) + }) + + shutdown: STM.STM = STM.gen(this, function*() { + yield* this.first.shutdown + yield* this.second.shutdown + }) + + isShutdown: STM.STM = STM.gen(this, function*() { + return (yield* this.first.isShutdown) && (yield* this.second.isShutdown) + }) + + awaitShutdown: STM.STM = STM.gen(this, function*() { + yield* this.first.awaitShutdown + yield* this.second.awaitShutdown + }) +} + +/** @internal */ +class TSubscriptionRefImpl implements TSubscriptionRef.TSubscriptionRef { + readonly [TSubscriptionRefTypeId] = TSubscriptionRefVariance + readonly [TRef.TRefTypeId] = tRefVariance + + constructor( + readonly ref: TRef.TRef, + readonly pubsub: TPubSub.TPubSub + ) {} + + get todos() { + return this.ref.todos + } + + get versioned() { + return this.ref.versioned + } + + pipe() { + return pipeArguments(this, arguments) + } + + get changes(): STM.STM> { + return STM.gen(this, function*() { + const first = yield* TQueue.unbounded() + yield* TQueue.offer(first, yield* TRef.get(this.ref)) + return new TDequeueMerge(first, yield* TPubSub.subscribe(this.pubsub)) + }) + } + + modify(f: (a: A) => readonly [B, A]): STM.STM { + return pipe( + TRef.get(this.ref), + STM.map(f), + STM.flatMap(([b, a]) => + pipe( + TRef.set(this.ref, a), + STM.as(b), + STM.zipLeft(TPubSub.publish(this.pubsub, a)) + ) + ) + ) + } +} + +/** @internal */ +export const make = (value: A): STM.STM> => + pipe( + STM.all([ + TPubSub.unbounded(), + TRef.make(value) + ]), + STM.map(([pubsub, ref]) => new TSubscriptionRefImpl(ref, pubsub)) + ) + +/** @internal */ +export const get = (self: TSubscriptionRef.TSubscriptionRef) => TRef.get(self.ref) + +/** @internal */ +export const set = dual< + (value: A) => (self: TSubscriptionRef.TSubscriptionRef) => STM.STM, + (self: TSubscriptionRef.TSubscriptionRef, value: A) => STM.STM +>( + 2, + (self: TSubscriptionRef.TSubscriptionRef, value: A): STM.STM => + self.modify((): [void, A] => [void 0, value]) +) + +/** @internal */ +export const getAndSet = dual< + (value: A) => (self: TSubscriptionRef.TSubscriptionRef) => STM.STM, + (self: TSubscriptionRef.TSubscriptionRef, value: A) => STM.STM +>(2, (self, value) => self.modify((a) => [a, value])) + +/** @internal */ +export const getAndUpdate = dual< + (f: (a: A) => A) => (self: TSubscriptionRef.TSubscriptionRef) => STM.STM, + (self: TSubscriptionRef.TSubscriptionRef, f: (a: A) => A) => STM.STM +>(2, (self, f) => self.modify((a) => [a, f(a)])) + +/** @internal */ +export const getAndUpdateSome = dual< + (f: (a: A) => Option.Option) => (self: TSubscriptionRef.TSubscriptionRef) => STM.STM, + (self: TSubscriptionRef.TSubscriptionRef, f: (a: A) => Option.Option) => STM.STM +>(2, (self, f) => + self.modify((a) => + Option.match(f(a), { + onNone: () => [a, a], + onSome: (b) => [a, b] + }) + )) + +/** @internal */ +export const setAndGet = dual< + (value: A) => (self: TSubscriptionRef.TSubscriptionRef) => STM.STM, + (self: TSubscriptionRef.TSubscriptionRef, value: A) => STM.STM +>(2, (self, value) => self.modify(() => [value, value])) + +/** @internal */ +export const modify = dual< + (f: (a: A) => readonly [B, A]) => (self: TSubscriptionRef.TSubscriptionRef) => STM.STM, + (self: TSubscriptionRef.TSubscriptionRef, f: (a: A) => readonly [B, A]) => STM.STM +>(2, (self, f) => self.modify(f)) + +/** @internal */ +export const modifySome = dual< + ( + fallback: B, + f: (a: A) => Option.Option + ) => (self: TSubscriptionRef.TSubscriptionRef) => STM.STM, + ( + self: TSubscriptionRef.TSubscriptionRef, + fallback: B, + f: (a: A) => Option.Option + ) => STM.STM +>(3, (self, fallback, f) => + self.modify((a) => + Option.match(f(a), { + onNone: () => [fallback, a], + onSome: (b) => b + }) + )) + +/** @internal */ +export const update = dual< + (f: (a: A) => A) => (self: TSubscriptionRef.TSubscriptionRef) => STM.STM, + (self: TSubscriptionRef.TSubscriptionRef, f: (a: A) => A) => STM.STM +>(2, (self, f) => self.modify((a) => [void 0, f(a)])) + +/** @internal */ +export const updateAndGet = dual< + (f: (a: A) => A) => (self: TSubscriptionRef.TSubscriptionRef) => STM.STM, + (self: TSubscriptionRef.TSubscriptionRef, f: (a: A) => A) => STM.STM +>(2, (self, f) => + self.modify((a) => { + const b = f(a) + return [b, b] + })) + +/** @internal */ +export const updateSome = dual< + (f: (a: A) => Option.Option) => (self: TSubscriptionRef.TSubscriptionRef) => STM.STM, + (self: TSubscriptionRef.TSubscriptionRef, f: (a: A) => Option.Option) => STM.STM +>( + 2, + (self, f) => + self.modify((a) => [ + void 0, + Option.match(f(a), { + onNone: () => a, + onSome: (b) => b + }) + ]) +) + +/** @internal */ +export const updateSomeAndGet = dual< + (f: (a: A) => Option.Option) => (self: TSubscriptionRef.TSubscriptionRef) => STM.STM, + (self: TSubscriptionRef.TSubscriptionRef, f: (a: A) => Option.Option) => STM.STM +>( + 2, + (self, f) => + self.modify((a) => + Option.match(f(a), { + onNone: () => [a, a], + onSome: (b) => [b, b] + }) + ) +) + +/** @internal */ +export const changesScoped = (self: TSubscriptionRef.TSubscriptionRef) => + Effect.acquireRelease(self.changes, TQueue.shutdown) + +/** @internal */ +export const changesStream = (self: TSubscriptionRef.TSubscriptionRef) => + stream.unwrap(Effect.map(self.changes, stream.fromTQueue)) diff --git a/packages/effect/src/internal/stream.ts b/packages/effect/src/internal/stream.ts index 3e677bfac9..7680583983 100644 --- a/packages/effect/src/internal/stream.ts +++ b/packages/effect/src/internal/stream.ts @@ -31,6 +31,8 @@ import type * as Stream from "../Stream.js" import type * as Emit from "../StreamEmit.js" import * as HaltStrategy from "../StreamHaltStrategy.js" import type * as Take from "../Take.js" +import * as TPubSub from "../TPubSub.js" +import * as TQueue from "../TQueue.js" import type * as Tracer from "../Tracer.js" import * as Tuple from "../Tuple.js" import type { NoInfer, TupleOf } from "../Types.js" @@ -3133,6 +3135,14 @@ export const fromPubSub: { return options?.shutdown ? ensuring(stream, PubSub.shutdown(pubsub)) : stream } +/** @internal */ +export const fromTPubSub = (pubsub: TPubSub.TPubSub): Stream.Stream => { + return unwrapScoped(Effect.map( + TPubSub.subscribeScoped(pubsub), + (queue) => fromTQueue(queue) + )) +} + /** @internal */ export const fromIterable = (iterable: Iterable): Stream.Stream => suspend(() => @@ -3224,6 +3234,24 @@ export const fromQueue = ( options?.shutdown ? ensuring(Queue.shutdown(queue)) : identity ) +/** @internal */ +export const fromTQueue = (queue: TQueue.TDequeue): Stream.Stream => + pipe( + TQueue.take(queue), + Effect.map(Chunk.of), + Effect.catchAllCause((cause) => + pipe( + TQueue.isShutdown(queue), + Effect.flatMap((isShutdown) => + isShutdown && Cause.isInterrupted(cause) ? + pull.end() : + pull.failCause(cause) + ) + ) + ), + repeatEffectChunkOption + ) + /** @internal */ export const fromSchedule = (schedule: Schedule.Schedule): Stream.Stream => pipe( diff --git a/packages/effect/test/TSubscriptionRef.test.ts b/packages/effect/test/TSubscriptionRef.test.ts new file mode 100644 index 0000000000..2cc54e89b9 --- /dev/null +++ b/packages/effect/test/TSubscriptionRef.test.ts @@ -0,0 +1,148 @@ +import { Chunk, Deferred, Effect, Equal, Exit, Fiber, pipe, Random, STM, Stream } from "effect" +import * as Number from "effect/Number" +import * as it from "effect/test/utils/extend" +import * as TSubscriptionRef from "effect/TSubscriptionRef" +import { assert, describe } from "vitest" + +describe.concurrent("TSubscriptionRef", () => { + it.effect("only emits comitted values", () => + Effect.gen(function*($) { + const subscriptionRef = yield* $(TSubscriptionRef.make(0)) + + const transaction = pipe( + TSubscriptionRef.update(subscriptionRef, (n) => n + 1), + STM.tap(() => TSubscriptionRef.update(subscriptionRef, (n) => n + 1)) + ) + + const subscriber = yield* $(pipe( + TSubscriptionRef.changesStream(subscriptionRef), + Stream.take(1), + Stream.runCollect, + Effect.fork + )) + // stream doesn't work properly without a yield, it will drop values + yield* $(Effect.yieldNow()) + yield* $(STM.commit(transaction)) + yield* $(Effect.yieldNow()) + const result = yield* $(Fiber.join(subscriber)) + + assert.deepStrictEqual(Array.from(result), [2]) + })) + + it.effect("emits every comitted value", () => + Effect.gen(function*($) { + const subscriptionRef = yield* $(TSubscriptionRef.make(0)) + + const transaction = pipe( + TSubscriptionRef.update(subscriptionRef, (n) => n + 1), + STM.commit, + // stream doesn't work properly without a yield, it will drop the first value without this + Effect.tap(() => Effect.yieldNow()), + Effect.flatMap(() => TSubscriptionRef.update(subscriptionRef, (n) => n + 1)) + ) + + const subscriber = yield* $(pipe( + TSubscriptionRef.changesStream(subscriptionRef), + Stream.take(2), + Stream.runCollect, + Effect.fork + )) + // stream doesn't work properly without a yield, it will drop the first value without this + yield* $(Effect.yieldNow()) + yield* $(transaction) + const result = yield* $(Fiber.join(subscriber)) + + assert.deepStrictEqual(Array.from(result), [1, 2]) + })) + + it.effect("multiple subscribers can receive committed values", () => + Effect.gen(function*($) { + const subscriptionRef = yield* $(TSubscriptionRef.make(0)) + const deferred1 = yield* $(Deferred.make()) + const deferred2 = yield* $(Deferred.make()) + const subscriber1 = yield* $(pipe( + TSubscriptionRef.changesStream(subscriptionRef), + Stream.tap(() => Deferred.succeed(deferred1, void 0)), + Stream.take(3), + Stream.runCollect, + Effect.fork + )) + yield* $(Deferred.await(deferred1)) + yield* $(TSubscriptionRef.update(subscriptionRef, (n) => n + 1)) + const subscriber2 = yield* $(pipe( + TSubscriptionRef.changesStream(subscriptionRef), + Stream.tap(() => Deferred.succeed(deferred2, void 0)), + Stream.take(2), + Stream.runCollect, + Effect.fork + )) + yield* $(Deferred.await(deferred2)) + yield* $(TSubscriptionRef.update(subscriptionRef, (n) => n + 1)) + const result1 = yield* $(Fiber.join(subscriber1)) + const result2 = yield* $(Fiber.join(subscriber2)) + assert.deepStrictEqual(Array.from(result1), [0, 1, 2]) + assert.deepStrictEqual(Array.from(result2), [1, 2]) + })) + + it.effect("subscriptions are interruptible", () => + Effect.gen(function*($) { + const ref = yield* $(TSubscriptionRef.make(0)) + const deferred1 = yield* $(Deferred.make()) + const deferred2 = yield* $(Deferred.make()) + const subscriber1 = yield* $( + TSubscriptionRef.changesStream(ref), + Stream.tap(() => Deferred.succeed(deferred1, void 0)), + Stream.take(5), + Stream.runCollect, + Effect.fork + ) + yield* $(Deferred.await(deferred1)) + yield* $(TSubscriptionRef.update(ref, (n) => n + 1)) + const subscriber2 = yield* $( + TSubscriptionRef.changesStream(ref), + Stream.tap(() => Deferred.succeed(deferred2, void 0)), + Stream.take(2), + Stream.runCollect, + Effect.fork + ) + yield* $(Deferred.await(deferred2)) + yield* $(TSubscriptionRef.update(ref, (n) => n + 1)) + const result1 = yield* $(Fiber.interrupt(subscriber1)) + const result2 = yield* $(Fiber.join(subscriber2)) + assert.isTrue(Exit.isInterrupted(result1)) + assert.deepStrictEqual(Array.from(result2), [1, 2]) + })) + + it.effect("concurrent subscribes and unsubscribes are handled correctly", () => + Effect.gen(function*($) { + const subscriber = (subscriptionRef: TSubscriptionRef.TSubscriptionRef) => + pipe( + Random.nextIntBetween(0, 200), + Effect.flatMap((n) => + pipe( + TSubscriptionRef.changesStream(subscriptionRef), + Stream.take(n), + Stream.runCollect + ) + ) + ) + const ref = yield* $(TSubscriptionRef.make(0)) + const fiber = yield* $( + TSubscriptionRef.update(ref, (n) => n + 1), + Effect.forever, + Effect.fork + ) + const result = yield* $( + Effect.map( + Effect.all( + Array.from({ length: 2 }, () => subscriber(ref)), + { concurrency: 2 } + ), + Chunk.unsafeFromArray + ) + ) + yield* $(Fiber.interrupt(fiber)) + const isSorted = Chunk.every(result, (chunk) => Equal.equals(chunk, Chunk.sort(chunk, Number.Order))) + assert.isTrue(isSorted) + })) +}) From 5bf55c1c576052da60e0c7c7f93f00d8390ab045 Mon Sep 17 00:00:00 2001 From: Tim Date: Tue, 15 Oct 2024 08:51:58 +1300 Subject: [PATCH 2/8] add option to .releaseLock a ReadableStream on finalization (#3771) --- .changeset/tough-lobsters-guess.md | 5 ++ packages/effect/src/Stream.ts | 34 +++++-- packages/effect/src/internal/stream.ts | 89 ++++++++++++++----- .../effect/test/Stream/constructors.test.ts | 8 +- 4 files changed, 103 insertions(+), 33 deletions(-) create mode 100644 .changeset/tough-lobsters-guess.md diff --git a/.changeset/tough-lobsters-guess.md b/.changeset/tough-lobsters-guess.md new file mode 100644 index 0000000000..50a130bd18 --- /dev/null +++ b/.changeset/tough-lobsters-guess.md @@ -0,0 +1,5 @@ +--- +"effect": minor +--- + +add option to .releaseLock a ReadableStream on finalization diff --git a/packages/effect/src/Stream.ts b/packages/effect/src/Stream.ts index bbcf0bd702..b06fd6ca74 100644 --- a/packages/effect/src/Stream.ts +++ b/packages/effect/src/Stream.ts @@ -2120,10 +2120,16 @@ export const fromTQueue: (queue: TDequeue) => Stream = internal.fromTQu * @since 2.0.0 * @category constructors */ -export const fromReadableStream: ( - evaluate: LazyArg>, - onError: (error: unknown) => E -) => Stream = internal.fromReadableStream +export const fromReadableStream: { + ( + options: { + readonly evaluate: LazyArg> + readonly onError: (error: unknown) => E + readonly releaseLockOnEnd?: boolean | undefined + } + ): Stream + (evaluate: LazyArg>, onError: (error: unknown) => E): Stream +} = internal.fromReadableStream /** * Creates a stream from a `ReadableStreamBYOBReader`. @@ -2134,11 +2140,21 @@ export const fromReadableStream: ( * @since 2.0.0 * @category constructors */ -export const fromReadableStreamByob: ( - evaluate: LazyArg>, - onError: (error: unknown) => E, - allocSize?: number -) => Stream = internal.fromReadableStreamByob +export const fromReadableStreamByob: { + ( + options: { + readonly evaluate: LazyArg> + readonly onError: (error: unknown) => E + readonly bufferSize?: number | undefined + readonly releaseLockOnEnd?: boolean | undefined + } + ): Stream + ( + evaluate: LazyArg>, + onError: (error: unknown) => E, + allocSize?: number + ): Stream +} = internal.fromReadableStreamByob /** * Creates a stream from a `Schedule` that does not require any further diff --git a/packages/effect/src/internal/stream.ts b/packages/effect/src/internal/stream.ts index 7680583983..76bc6bbbf4 100644 --- a/packages/effect/src/internal/stream.ts +++ b/packages/effect/src/internal/stream.ts @@ -18,7 +18,7 @@ import * as MergeDecision from "../MergeDecision.js" import * as Option from "../Option.js" import type * as Order from "../Order.js" import { pipeArguments } from "../Pipeable.js" -import { hasProperty, isTagged, type Predicate, type Refinement } from "../Predicate.js" +import { hasProperty, type Predicate, type Refinement } from "../Predicate.js" import * as PubSub from "../PubSub.js" import * as Queue from "../Queue.js" import * as RcRef from "../RcRef.js" @@ -3261,14 +3261,38 @@ export const fromSchedule = (schedule: Schedule.Schedule): ) /** @internal */ -export const fromReadableStream = ( - evaluate: LazyArg>, - onError: (error: unknown) => E -): Stream.Stream => - unwrapScoped(Effect.map( +export const fromReadableStream: { + ( + options: { + readonly evaluate: LazyArg> + readonly onError: (error: unknown) => E + readonly releaseLockOnEnd?: boolean | undefined + } + ): Stream.Stream + ( + evaluate: LazyArg>, + onError: (error: unknown) => E + ): Stream.Stream +} = ( + ...args: [options: { + readonly evaluate: LazyArg> + readonly onError: (error: unknown) => E + readonly releaseLockOnEnd?: boolean | undefined + }] | [ + evaluate: LazyArg>, + onError: (error: unknown) => E + ] +): Stream.Stream => { + const evaluate = args.length === 1 ? args[0].evaluate : args[0] + const onError = args.length === 1 ? args[0].onError : args[1] + const releaseLockOnEnd = args.length === 1 ? args[0].releaseLockOnEnd === true : false + return unwrapScoped(Effect.map( Effect.acquireRelease( Effect.sync(() => evaluate().getReader()), - (reader) => Effect.promise(() => reader.cancel()) + (reader) => + releaseLockOnEnd + ? Effect.sync(() => reader.releaseLock()) + : Effect.promise(() => reader.cancel()) ), (reader) => repeatEffectOption( @@ -3281,34 +3305,59 @@ export const fromReadableStream = ( ) ) )) +} /** @internal */ -export const fromReadableStreamByob = ( - evaluate: LazyArg>, - onError: (error: unknown) => E, - allocSize = 4096 -): Stream.Stream => - unwrapScoped(Effect.map( +export const fromReadableStreamByob: { + ( + options: { + readonly evaluate: LazyArg> + readonly onError: (error: unknown) => E + readonly bufferSize?: number | undefined + readonly releaseLockOnEnd?: boolean | undefined + } + ): Stream.Stream + ( + evaluate: LazyArg>, + onError: (error: unknown) => E, + allocSize?: number + ): Stream.Stream +} = ( + ...args: [options: { + readonly evaluate: LazyArg> + readonly onError: (error: unknown) => E + readonly bufferSize?: number | undefined + readonly releaseLockOnEnd?: boolean | undefined + }] | [ + evaluate: LazyArg>, + onError: (error: unknown) => E, + allocSize?: number | undefined + ] +): Stream.Stream => { + const evaluate = args.length === 1 ? args[0].evaluate : args[0] + const onError = args.length === 1 ? args[0].onError : args[1] + const allocSize = (args.length === 1 ? args[0].bufferSize : args[2]) ?? 4096 + const releaseLockOnEnd = args.length === 1 ? args[0].releaseLockOnEnd === true : false + return unwrapScoped(Effect.map( Effect.acquireRelease( Effect.sync(() => evaluate().getReader({ mode: "byob" })), - (reader) => Effect.promise(() => reader.cancel()) + (reader) => releaseLockOnEnd ? Effect.sync(() => reader.releaseLock()) : Effect.promise(() => reader.cancel()) ), (reader) => catchAll( forever(readChunkStreamByobReader(reader, onError, allocSize)), - (error) => isTagged(error, "EOF") ? empty : fail(error as E) + (error) => error === EOF ? empty : fail(error) ) )) - -interface EOF { - readonly _tag: "EOF" } +const EOF = Symbol.for("effect/Stream/EOF") + const readChunkStreamByobReader = ( reader: ReadableStreamBYOBReader, onError: (error: unknown) => E, size: number -): Stream.Stream => { +): Stream.Stream => { const buffer = new ArrayBuffer(size) return paginateEffect(0, (offset) => Effect.flatMap( @@ -3318,7 +3367,7 @@ const readChunkStreamByobReader = ( }), ({ done, value }) => { if (done) { - return Effect.fail({ _tag: "EOF" }) + return Effect.fail(EOF) } const newOffset = offset + value.byteLength return Effect.succeed([ diff --git a/packages/effect/test/Stream/constructors.test.ts b/packages/effect/test/Stream/constructors.test.ts index 15926537f8..f5aea08fec 100644 --- a/packages/effect/test/Stream/constructors.test.ts +++ b/packages/effect/test/Stream/constructors.test.ts @@ -229,10 +229,10 @@ describe("Stream", () => { } const result = yield* $( - Stream.fromReadableStream( - () => new ReadableStream(new NumberSource()), - (error) => new FromReadableStreamError(error) - ), + Stream.fromReadableStream({ + evaluate: () => new ReadableStream(new NumberSource()), + onError: (error) => new FromReadableStreamError(error) + }), Stream.take(10), Stream.runCollect ) From bc65bffbd87ab120ebe5c60e9249f65f3b1f1c34 Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Wed, 16 Oct 2024 08:33:27 +0200 Subject: [PATCH 3/8] Merge Schema into Effect (#3772) --- .changeset/six-crabs-itch.md | 75 + .github/CODEOWNERS | 1 - packages/ai/ai/docgen.json | 48 +- packages/ai/ai/package.json | 2 - packages/ai/ai/src/AiChat.ts | 4 +- packages/ai/ai/src/AiError.ts | 2 +- packages/ai/ai/src/AiInput.ts | 4 +- packages/ai/ai/src/AiResponse.ts | 2 +- packages/ai/ai/src/AiRole.ts | 2 +- packages/ai/ai/src/AiToolkit.ts | 11 +- packages/ai/ai/src/Completions.ts | 4 +- packages/ai/ai/tsconfig.build.json | 3 +- packages/ai/ai/tsconfig.src.json | 6 +- packages/ai/ai/tsconfig.test.json | 1 - packages/ai/openai/docgen.json | 57 +- packages/ai/openai/package.json | 2 - packages/ai/openai/src/Generated.ts | 4 +- packages/ai/openai/tsconfig.build.json | 3 +- packages/ai/openai/tsconfig.src.json | 3 +- packages/ai/openai/tsconfig.test.json | 1 - packages/cli/docgen.json | 63 +- packages/cli/examples/naval-fate/domain.ts | 2 +- packages/cli/examples/naval-fate/store.ts | 2 +- packages/cli/package.json | 2 - packages/cli/src/Args.ts | 2 +- packages/cli/src/Options.ts | 2 +- packages/cli/src/internal/args.ts | 8 +- packages/cli/src/internal/options.ts | 9 +- packages/cli/src/internal/primitive.ts | 2 +- packages/cli/src/internal/prompt/number.ts | 2 +- packages/cli/test/Args.test.ts | 2 +- packages/cli/test/Options.test.ts | 2 +- packages/cli/tsconfig.build.json | 3 +- packages/cli/tsconfig.examples.json | 3 +- packages/cli/tsconfig.src.json | 3 +- packages/cli/tsconfig.test.json | 3 +- packages/cluster-browser/package.json | 2 - .../src/RpcBroadcastChannel.ts | 5 +- packages/cluster-browser/tsconfig.build.json | 3 +- packages/cluster-browser/tsconfig.src.json | 6 +- .../cluster-node/examples/sample-common.ts | 2 +- packages/cluster-node/package.json | 2 - .../cluster-node/src/ShardManagerProtocol.ts | 2 +- packages/cluster-node/src/ShardingProtocol.ts | 2 +- packages/cluster-node/src/StorageFile.ts | 16 +- packages/cluster-node/tsconfig.build.json | 3 +- packages/cluster-node/tsconfig.src.json | 7 +- packages/cluster-workflow/package.json | 2 - packages/cluster-workflow/src/Activity.ts | 2 +- .../src/DurableExecutionEvent.ts | 2 +- .../src/DurableExecutionJournal.ts | 2 +- packages/cluster-workflow/src/Workflow.ts | 2 +- .../test/DurableExecutionJournal.test.ts | 2 +- .../cluster-workflow/test/Workflow.test.ts | 2 +- packages/cluster-workflow/test/utils.ts | 2 +- packages/cluster-workflow/tsconfig.build.json | 3 +- packages/cluster-workflow/tsconfig.src.json | 10 +- packages/cluster/package.json | 2 - packages/cluster/src/Message.ts | 8 +- packages/cluster/src/MessageState.ts | 2 +- packages/cluster/src/Pod.ts | 2 +- packages/cluster/src/PodAddress.ts | 2 +- packages/cluster/src/PoisonPill.ts | 2 +- packages/cluster/src/RecipientAddress.ts | 2 +- packages/cluster/src/RecipientType.ts | 2 +- packages/cluster/src/Serialization.ts | 2 +- packages/cluster/src/SerializedEnvelope.ts | 7 +- packages/cluster/src/SerializedMessage.ts | 2 +- packages/cluster/src/ShardId.ts | 2 +- packages/cluster/src/ShardingException.ts | 2 +- .../src/internal/atLeastOnceStorage.ts | 2 +- packages/cluster/src/internal/message.ts | 11 +- packages/cluster/src/internal/messageState.ts | 2 +- .../cluster/src/internal/serialization.ts | 16 +- packages/cluster/src/internal/utils.ts | 2 +- packages/cluster/test/AtLeastOnce.test.ts | 2 +- .../cluster/test/RecipientBehaviour.test.ts | 2 +- packages/cluster/test/RecipientType.test.ts | 2 +- packages/cluster/test/Sharding.test.ts | 2 +- packages/cluster/tsconfig.build.json | 1 - packages/cluster/tsconfig.src.json | 5 +- packages/cluster/tsconfig.test.json | 7 +- .../benchmark/SchemaArray.ts} | 6 +- .../benchmark/SchemaFilters.ts} | 6 +- .../benchmark/SchemaIndex.ts} | 6 +- .../benchmark/SchemaPropertyOrder.ts} | 4 +- .../benchmark/SchemaStruct.ts} | 4 +- .../benchmark/SchemaToString.ts} | 7 +- .../benchmark/SchemaTreeFormatter.ts} | 7 +- .../benchmark/SchemaUnion.ts} | 6 +- .../benchmark/tsconfig.json | 2 - packages/effect/docgen.json | 55 +- packages/{schema => effect}/dtslint/Schema.ts | 17 +- .../AST.ts => effect/dtslint/SchemaAST.ts} | 6 +- .../dtslint/SchemaBrand.ts} | 2 +- .../dtslint/SchemaClass.ts} | 4 +- .../dtslint/SchemaContext.ts} | 7 +- .../dtslint/SchemaGeneric.ts} | 3 +- .../dtslint/SchemaParseResult.ts} | 2 +- .../dtslint/SchemaPropertySignature.ts} | 2 +- .../dtslint/SchemaSerializable.ts} | 28 +- .../dtslint/SchemaTaggedError.ts} | 3 +- .../dtslint/SchemaTaggedRequest.ts} | 2 +- .../dtslint/SchemaUserland.ts} | 2 +- packages/effect/package.json | 8 +- packages/{schema => effect}/src/Arbitrary.ts | 101 +- packages/{schema => effect}/src/FastCheck.ts | 4 +- packages/{schema => effect}/src/JSONSchema.ts | 55 +- .../{schema => effect}/src/ParseResult.ts | 456 ++- packages/{schema => effect}/src/Pretty.ts | 62 +- packages/{schema => effect}/src/Schema.ts | 2621 ++++++++++------- .../src/AST.ts => effect/src/SchemaAST.ts} | 608 ++-- packages/effect/src/index.ts | 35 + .../src/internal/schema}/errors.ts | 2 +- .../effect/src/internal/schema/filters.ts | 86 + .../src/internal/schema}/util.ts | 4 +- .../test/Schema}/Arbitrary/Arbitrary.test.ts | 12 +- .../test/Schema}/Arbitrary/Class.test.ts | 6 +- .../Schema}/Arbitrary/getConstraints.test.ts | 6 +- .../test/Schema}/JSONSchema.test.ts | 16 +- .../test/Schema}/ParseResult.test.ts | 6 +- .../test/Schema/ParseResultFormatter.test.ts} | 24 +- .../test/Schema}/Pretty.test.ts | 16 +- .../test/Schema}/Schema/Any/Any.test.ts | 4 +- .../test/Schema}/Schema/Array/Array.test.ts | 6 +- .../test/Schema}/Schema/Array/head.test.ts | 4 +- .../Schema}/Schema/Array/headOrElse.test.ts | 4 +- .../Schema}/Schema/Array/itemsCount.test.ts | 4 +- .../Schema}/Schema/Array/maxItems.test.ts | 4 +- .../Schema}/Schema/Array/minItems.test.ts | 4 +- .../test/Schema}/Schema/ArrayEnsure.test.ts | 4 +- .../Schema/BigDecimal/BigDecimal.test.ts | 4 +- .../BigDecimal/BigDecimalFromNumber.test.ts | 4 +- .../BigDecimal/BigDecimalFromSelf.test.ts | 9 +- .../NegativeBigDecimalFromSelf.test.ts | 4 +- .../NonNegativeBigDecimalFromSelf.test.ts | 4 +- .../NonPositiveBigDecimalFromSelf.test.ts | 4 +- .../PositiveBigDecimalFromSelf.test.ts | 4 +- .../BigDecimal/betweenBigDecimal.test.ts | 4 +- .../Schema/BigDecimal/clampBigDecimal.test.ts | 4 +- .../BigDecimal/greaterThanBigDecimal.test.ts | 4 +- .../greaterThanOrEqualToBigDecimal.test.ts | 4 +- .../BigDecimal/lessThanBigDecimal.test.ts | 4 +- .../lessThanOrEqualToBigDecimal.test.ts | 4 +- .../test/Schema}/Schema/BigInt/BigInt.test.ts | 4 +- .../Schema/BigInt/BigIntFromNumber.test.ts | 4 +- .../Schema/BigInt/BigIntFromSelf.test.ts | 4 +- .../BigInt/NegativeBigIntFromSelf.test.ts | 4 +- .../BigInt/NonNegativeBigIntFromSelf.test.ts | 4 +- .../BigInt/NonPositiveBigIntFromSelf.test.ts | 4 +- .../BigInt/PositiveBigIntFromSelf.test.ts | 4 +- .../Schema/BigInt/betweenBigInt.test.ts | 4 +- .../Schema}/Schema/BigInt/clampBigInt.test.ts | 4 +- .../Schema/BigInt/greaterThanBigInt.test.ts | 4 +- .../BigInt/greaterThanOrEqualToBigInt.test.ts | 4 +- .../Schema/BigInt/lessThanBigInt.test.ts | 4 +- .../BigInt/lessThanOrEqualToBigInt.test.ts | 4 +- .../Schema}/Schema/Boolean/Boolean.test.ts | 4 +- .../Schema/Boolean/BooleanFromUnknown.test.ts | 4 +- .../test/Schema}/Schema/Boolean/Not.test.ts | 4 +- .../test/Schema}/Schema/Cause/Cause.test.ts | 4 +- .../Schema/Cause/CauseFromSelf.test.ts | 6 +- .../test/Schema}/Schema/Chunk/Chunk.test.ts | 4 +- .../Schema/Chunk/ChunkFromSelf.test.ts | 10 +- .../Schema/Chunk/NonEmptyChunk.test.ts | 4 +- .../Chunk/NonEmptyChunkFromSelf.test.ts | 13 +- .../test/Schema}/Schema/Class/Class.test.ts | 10 +- .../Schema}/Schema/Class/TaggedClass.test.ts | 9 +- .../Schema}/Schema/Class/TaggedError.test.ts | 7 +- .../Schema/Class/TaggedRequest.test.ts | 27 +- .../test/Schema}/Schema/Class/extend.test.ts | 4 +- .../Schema/Class/transformOrFail.test.ts | 6 +- .../Schema/Class/transformOrFailFrom.test.ts | 6 +- .../test/Schema}/Schema/Config/Config.test.ts | 2 +- .../test/Schema}/Schema/Data/Data.test.ts | 4 +- .../Schema}/Schema/Data/DataFromSelf.test.ts | 8 +- .../test/Schema}/Schema/Date/Date.test.ts | 4 +- .../Schema/Date/DateFromNumber.test.ts | 4 +- .../Schema}/Schema/Date/DateFromSelf.test.ts | 6 +- .../Schema}/Schema/Date/betweenDate.test.ts | 4 +- .../Schema/Date/greaterThanDate.test.ts | 4 +- .../Date/greaterThanOrEqualToDate.test.ts | 4 +- .../Schema}/Schema/Date/lessThanDate.test.ts | 4 +- .../Schema/Date/lessThanOrEqualToDate.test.ts | 4 +- .../Schema}/Schema/DateTime/DateTime.test.ts | 4 +- .../Schema/DecodingFallbackAnnotation.test.ts | 4 +- .../test/Schema}/Schema/Defect/Defect.test.ts | 4 +- .../Schema}/Schema/Duration/Duration.test.ts | 4 +- .../Duration/DurationFromMillis.test.ts | 4 +- .../Schema/Duration/DurationFromNanos.test.ts | 4 +- .../Schema/Duration/DurationFromSelf.test.ts | 6 +- .../Schema/Duration/betweenDuration.test.ts | 4 +- .../Schema/Duration/clampDuration.test.ts | 4 +- .../Duration/greaterThanDuration.test.ts | 4 +- .../greaterThanOrEqualToDuration.test.ts | 4 +- .../Schema/Duration/lessThanDuration.test.ts | 4 +- .../lessThanOrEqualToDuration.test.ts | 4 +- .../test/Schema}/Schema/Either/Either.test.ts | 4 +- .../Schema/Either/EitherFromSelf.test.ts | 8 +- .../Schema/Either/EitherFromUnion.test.ts | 4 +- .../test/Schema}/Schema/Enums/Enums.test.ts | 4 +- .../test/Schema}/Schema/Exit/Exit.test.ts | 4 +- .../Schema}/Schema/Exit/ExitFromSelf.test.ts | 4 +- .../Schema}/Schema/FiberId/FiberId.test.ts | 4 +- .../Schema/FiberId/FiberIdFromSelf.test.ts | 6 +- .../Schema}/Schema/HashMap/HashMap.test.ts | 4 +- .../Schema/HashMap/HashMapFromSelf.test.ts | 8 +- .../Schema}/Schema/HashSet/HashSet.test.ts | 4 +- .../Schema/HashSet/HashSetFromSelf.test.ts | 10 +- .../test/Schema}/Schema/List/List.test.ts | 4 +- .../Schema}/Schema/List/ListFromSelf.test.ts | 10 +- .../Schema}/Schema/Literal/Literal.test.ts | 6 +- .../test/Schema}/Schema/Map/Map.test.ts | 2 +- .../Schema}/Schema/Map/MapFromRecord.test.ts | 4 +- .../Schema}/Schema/Map/MapFromSelf.test.ts | 2 +- .../test/Schema}/Schema/Never/Never.test.ts | 4 +- .../Schema/NonEmptyArrayEnsure.test.ts | 4 +- .../Schema}/Schema/Number/JsonNumber.test.ts | 4 +- .../test/Schema}/Schema/Number/Number.test.ts | 4 +- .../Schema}/Schema/Number/between.test.ts | 4 +- .../test/Schema}/Schema/Number/clamp.test.ts | 4 +- .../test/Schema}/Schema/Number/finite.test.ts | 4 +- .../Schema}/Schema/Number/greaterThan.test.ts | 8 +- .../Number/greaterThanOrEqualTo.test.ts | 8 +- .../test/Schema}/Schema/Number/int.test.ts | 8 +- .../Schema}/Schema/Number/lessThan.test.ts | 8 +- .../Schema/Number/lessThanOrEqualTo.test.ts | 8 +- .../Schema}/Schema/Number/multipleOf.test.ts | 6 +- .../Schema}/Schema/Number/negative.test.ts | 4 +- .../test/Schema}/Schema/Number/nonNaN.test.ts | 8 +- .../Schema}/Schema/Number/nonNegative.test.ts | 4 +- .../Schema}/Schema/Number/nonPositive.test.ts | 4 +- .../Schema/Number/numberFromString.test.ts | 4 +- .../Schema}/Schema/Number/positive.test.ts | 4 +- .../test/Schema}/Schema/Object/Object.test.ts | 4 +- .../test/Schema}/Schema/Option/Option.test.ts | 4 +- .../OptionFromNonEmptyTrimmedString.test.ts | 4 +- .../Schema/Option/OptionFromNullOr.test.ts | 4 +- .../Schema/Option/OptionFromNullishOr.test.ts | 4 +- .../Schema/Option/OptionFromSelf.test.ts | 8 +- .../Option/OptionFromUndefinedOr.test.ts | 4 +- .../Schema/ParseOptions-errors.test.ts | 4 +- .../Schema}/Schema/ParseOptions-exact.test.ts | 4 +- .../ParseOptions-onExcessProperty.test.ts | 16 +- .../ParseOptions-preserveKeyOrder.test.ts | 6 +- .../Schema/ParseOptionsAnnotation.test.ts | 4 +- .../Schema}/Schema/PropertySignature.test.ts | 12 +- .../Schema/ReadonlyMap/ReadonlyMap.test.ts | 4 +- .../ReadonlyMap/ReadonlyMapFromRecord.test.ts | 4 +- .../ReadonlyMap/ReadonlyMapFromSelf.test.ts | 8 +- .../Schema/ReadonlySet/ReadonlySet.test.ts | 4 +- .../ReadonlySet/ReadonlySetFromSelf.test.ts | 8 +- .../test/Schema}/Schema/Record/Record.test.ts | 32 +- .../Schema}/Schema/Redacted/Redacted.test.ts | 6 +- .../Schema/Redacted/RedactedFromSelf.test.ts | 6 +- .../test/Schema}/Schema/Set/Set.test.ts | 2 +- .../Schema}/Schema/Set/SetFromSelf.test.ts | 2 +- .../Schema/SortedSet/SortedSet.test.ts | 4 +- .../SortedSet/SortedSetFromSelf.test.ts | 11 +- .../String/NonEmptyTrimmedString.test.ts | 4 +- .../test/Schema}/Schema/String/String.test.ts | 4 +- .../Schema/String/StringFromBase64.test.ts | 4 +- .../Schema/String/StringFromBase64Url.test.ts | 4 +- .../Schema/String/StringFromHex.test.ts | 4 +- .../Schema}/Schema/String/capitalize.test.ts | 4 +- .../Schema}/Schema/String/endsWith.test.ts | 6 +- .../Schema}/Schema/String/includes.test.ts | 8 +- .../test/Schema}/Schema/String/length.test.ts | 4 +- .../Schema}/Schema/String/lowercase.test.ts | 4 +- .../Schema}/Schema/String/maxLength.test.ts | 8 +- .../Schema}/Schema/String/minLength.test.ts | 8 +- .../Schema/String/nonEmptyString.test.ts | 4 +- .../Schema}/Schema/String/pattern.test.ts | 4 +- .../test/Schema}/Schema/String/split.test.ts | 4 +- .../Schema}/Schema/String/startsWith.test.ts | 6 +- .../test/Schema}/Schema/String/trim.test.ts | 4 +- .../Schema/String/uncapitalize.test.ts | 4 +- .../Schema}/Schema/String/uppercase.test.ts | 4 +- .../test/Schema}/Schema/Struct/Struct.test.ts | 10 +- .../test/Schema}/Schema/Struct/make.test.ts | 4 +- .../test/Schema}/Schema/Struct/omit.test.ts | 2 +- .../test/Schema}/Schema/Struct/pick.test.ts | 2 +- .../test/Schema}/Schema/Symbol/Symbol.test.ts | 4 +- .../Schema/Symbol/SymbolFromSelf.test.ts | 8 +- .../Schema}/Schema/TaggedStruct/make.test.ts | 4 +- .../TemplateLiteral/TemplateLiteral.test.ts | 6 +- .../Schema/TemplateLiteralParser.test.ts | 4 +- .../Schema}/Schema/Trimmed/Trimmed.test.ts | 10 +- .../test/Schema}/Schema/Tuple/Tuple.test.ts | 6 +- .../test/Schema}/Schema/ULID.test.ts | 4 +- .../test/Schema}/Schema/UUID.test.ts | 4 +- .../Schema/Uint8Array/Uint8Array.test.ts | 4 +- .../Uint8Array/Uint8ArrayFromBase64.test.ts | 4 +- .../Uint8ArrayFromBase64Url.test.ts | 4 +- .../Uint8Array/Uint8ArrayFromHex.test.ts | 4 +- .../Uint8Array/Uint8ArrayFromSelf.test.ts | 6 +- .../test/Schema}/Schema/Union/Union.test.ts | 6 +- .../UniqueSymbol/UniqueSymbolFromSelf.test.ts | 17 + .../Schema}/Schema/Unknown/Unknown.test.ts | 4 +- .../test/Schema}/Schema/Void/Void.test.ts | 4 +- .../test/Schema}/Schema/annotations.test.ts | 23 +- .../test/Schema}/Schema/asserts.test.ts | 6 +- .../Schema/attachPropertySignature.test.ts | 18 +- .../test/Schema}/Schema/brand.test.ts | 12 +- .../test/Schema}/Schema/compose.test.ts | 4 +- .../test/Schema}/Schema/decode.test.ts | 4 +- .../test/Schema}/Schema/decodeEither.test.ts | 4 +- .../test/Schema}/Schema/decodeOption.test.ts | 4 +- .../test/Schema}/Schema/decodePromise.test.ts | 4 +- .../test/Schema}/Schema/decodeSync.test.ts | 4 +- .../Schema/decodeUnknownEither.test.ts | 4 +- .../Schema/decodeUnknownOption.test.ts | 4 +- .../Schema}/Schema/decodeUnknownSync.test.ts | 6 +- .../test/Schema}/Schema/encode.test.ts | 4 +- .../test/Schema}/Schema/encodeEither.test.ts | 4 +- .../test/Schema}/Schema/encodeOption.test.ts | 4 +- .../test/Schema}/Schema/encodePromise.test.ts | 4 +- .../test/Schema}/Schema/encodeSync.test.ts | 4 +- .../Schema/encodeUnknownEither.test.ts | 4 +- .../Schema/encodeUnknownOption.test.ts | 4 +- .../Schema}/Schema/encodeUnknownSync.test.ts | 4 +- .../Schema}/Schema/encodedBoundSchema.test.ts | 4 +- .../test/Schema}/Schema/encodedSchema.test.ts | 4 +- .../test/Schema/Schema/equivalence.test.ts} | 109 +- .../effect/test/Schema/Schema/exports.test.ts | 51 + .../test/Schema}/Schema/extend.test.ts | 10 +- .../test/Schema}/Schema/filter.test.ts | 12 +- .../test/Schema}/Schema/filterEffect.test.ts | 6 +- .../test/Schema}/Schema/format.test.ts | 4 +- .../test/Schema}/Schema/fromBrand.test.ts | 4 +- .../Schema/getNumberIndexedAccess.test.ts | 4 +- .../test/Schema}/Schema/instanceOf.test.ts | 12 +- .../test/Schema}/Schema/is.test.ts | 26 +- .../test/Schema}/Schema/isSchema.test.ts | 2 +- .../test/Schema}/Schema/keyof.test.ts | 12 +- .../test/Schema}/Schema/mutable.test.ts | 4 +- .../test/Schema}/Schema/nonEmptyArray.test.ts | 4 +- .../test/Schema}/Schema/omit.test.ts | 14 +- .../test/Schema}/Schema/optional.test.ts | 4 +- .../Schema}/Schema/optionalToRequired.test.ts | 4 +- .../test/Schema}/Schema/optionalWith.test.ts | 6 +- .../test/Schema}/Schema/parseJson.test.ts | 4 +- .../test/Schema}/Schema/partial.test.ts | 4 +- .../test/Schema}/Schema/partialWith.test.ts | 4 +- .../test/Schema}/Schema/pick.test.ts | 18 +- .../test/Schema}/Schema/pickLiteral.test.ts | 6 +- .../test/Schema}/Schema/pipe.test.ts | 2 +- .../test/Schema}/Schema/pluck.test.ts | 4 +- .../test/Schema}/Schema/rename.test.ts | 12 +- .../test/Schema}/Schema/required.test.ts | 4 +- .../Schema}/Schema/requiredToOptional.test.ts | 4 +- .../test/Schema}/Schema/suspend.test.ts | 4 +- .../test/Schema}/Schema/toString.test.ts | 2 +- .../test/Schema}/Schema/transform.test.ts | 4 +- .../Schema}/Schema/transformLiterals.test.ts | 4 +- .../Schema}/Schema/transformOrFail.test.ts | 6 +- .../test/Schema}/Schema/typeSchema.test.ts | 4 +- .../test/Schema}/Schema/validate.test.ts | 4 +- .../Schema}/Schema/validateEither.test.ts | 4 +- .../Schema}/Schema/validateOption.test.ts | 4 +- .../Schema}/Schema/validatePromise.test.ts | 4 +- .../test/Schema}/Schema/validateSync.test.ts | 4 +- .../Schema/withConstructorDefault.test.ts | 2 +- .../Schema/withDecodingDefault.test.ts | 4 +- .../Schema/SchemaAST}/IndexSignature.test.ts | 2 +- .../test/Schema/SchemaAST}/Tuple.test.ts | 2 +- .../Schema/SchemaAST}/TypeLiteral.test.ts | 4 +- .../TypeLiteralTransformation.test.ts | 2 +- .../test/Schema/SchemaAST}/Union.test.ts | 4 +- .../Schema/SchemaAST}/annotations.test.ts | 4 +- .../test/Schema/SchemaAST}/encodedAST.test.ts | 4 +- .../Schema/SchemaAST}/encodedBoundAST.test.ts | 4 +- .../SchemaAST}/getPropertySignatures.test.ts | 4 +- .../test/Schema/SchemaAST}/guards.test.ts | 6 +- .../test/Schema/SchemaAST}/mutable.test.ts | 4 +- .../test/Schema/SchemaAST}/partial.test.ts | 4 +- .../test/Schema/SchemaAST}/pick.test.ts | 4 +- .../test/Schema/SchemaAST}/record.test.ts | 2 +- .../test/Schema/SchemaAST}/suspend.test.ts | 6 +- .../test/Schema/SchemaAST}/toString.test.ts | 2 +- .../test/Schema/SchemaAST}/typeAST.test.ts | 4 +- .../test/Schema/SchemaAST}/unify.test.ts | 4 +- .../effect/test/Schema/SchemaInternal.test.ts | 39 + .../test/Schema/SchemaUserland.test.ts} | 7 +- .../test/Schema}/Serializable.test.ts | 27 +- .../test => effect/test/Schema}/TestUtils.ts | 22 +- .../experimental/examples/redis/resolver.ts | 3 +- .../examples/serializable-machine.ts | 3 +- packages/experimental/package.json | 1 - packages/experimental/src/ChannelSchema.ts | 4 +- packages/experimental/src/DevTools/Domain.ts | 2 +- packages/experimental/src/Machine.ts | 7 +- .../experimental/src/Machine/Procedure.ts | 5 +- .../src/Machine/SerializableProcedureList.ts | 15 +- packages/experimental/src/MsgPack.ts | 4 +- packages/experimental/src/Ndjson.ts | 4 +- packages/experimental/src/PersistedCache.ts | 16 +- packages/experimental/src/Persistence.ts | 13 +- packages/experimental/src/RequestResolver.ts | 12 +- packages/experimental/src/VariantSchema.ts | 6 +- packages/experimental/test/Machine.test.ts | 3 +- .../experimental/test/PersistedCache.test.ts | 3 +- .../experimental/test/RequestResolver.test.ts | 3 +- packages/experimental/tsconfig.build.json | 1 - packages/experimental/tsconfig.src.json | 1 - packages/experimental/tsconfig.test.json | 1 - packages/platform-browser/package.json | 1 - .../platform-browser/test/fixtures/schema.ts | 2 +- packages/platform-browser/tsconfig.build.json | 3 +- .../platform-browser/tsconfig.examples.json | 6 +- packages/platform-browser/tsconfig.src.json | 6 +- packages/platform-browser/tsconfig.test.json | 1 - packages/platform-bun/examples/http-client.ts | 4 +- packages/platform-bun/examples/http-router.ts | 3 +- packages/platform-bun/package.json | 1 - packages/platform-node-shared/package.json | 1 - .../platform-node-shared/tsconfig.build.json | 3 +- .../platform-node-shared/tsconfig.src.json | 6 +- .../platform-node-shared/tsconfig.test.json | 3 +- packages/platform-node/docgen.json | 4 +- packages/platform-node/examples/api.ts | 3 +- .../platform-node/examples/http-client.ts | 4 +- .../platform-node/examples/http-router.ts | 2 +- packages/platform-node/package.json | 1 - packages/platform-node/test/HttpApi.test.ts | 3 +- .../platform-node/test/HttpClient.test.ts | 2 +- .../platform-node/test/HttpServer.test.ts | 2 +- packages/platform-node/tsconfig.build.json | 3 +- packages/platform-node/tsconfig.src.json | 3 +- packages/platform-node/tsconfig.test.json | 1 - packages/platform/README.md | 26 +- packages/platform/docgen.json | 48 +- packages/platform/package.json | 2 - packages/platform/src/Headers.ts | 2 +- packages/platform/src/HttpApi.ts | 4 +- packages/platform/src/HttpApiBuilder.ts | 9 +- packages/platform/src/HttpApiClient.ts | 4 +- packages/platform/src/HttpApiEndpoint.ts | 2 +- packages/platform/src/HttpApiError.ts | 10 +- packages/platform/src/HttpApiGroup.ts | 2 +- packages/platform/src/HttpApiSchema.ts | 4 +- packages/platform/src/HttpBody.ts | 4 +- packages/platform/src/HttpClientRequest.ts | 4 +- packages/platform/src/HttpClientResponse.ts | 6 +- packages/platform/src/HttpIncomingMessage.ts | 6 +- packages/platform/src/HttpRouter.ts | 6 +- packages/platform/src/HttpServerRequest.ts | 6 +- .../platform/src/HttpServerRespondable.ts | 2 +- packages/platform/src/HttpServerResponse.ts | 4 +- packages/platform/src/KeyValueStore.ts | 4 +- packages/platform/src/Multipart.ts | 6 +- packages/platform/src/OpenApi.ts | 4 +- packages/platform/src/OpenApiJsonSchema.ts | 24 +- packages/platform/src/Transferable.ts | 4 +- packages/platform/src/UrlParams.ts | 6 +- packages/platform/src/Worker.ts | 15 +- packages/platform/src/WorkerError.ts | 2 +- packages/platform/src/WorkerRunner.ts | 5 +- packages/platform/src/internal/httpBody.ts | 4 +- .../src/internal/httpClientRequest.ts | 4 +- .../src/internal/httpClientResponse.ts | 6 +- packages/platform/src/internal/httpRouter.ts | 4 +- .../src/internal/httpServerRequest.ts | 6 +- .../src/internal/httpServerResponse.ts | 4 +- .../platform/src/internal/keyValueStore.ts | 2 +- packages/platform/src/internal/multipart.ts | 6 +- packages/platform/src/internal/worker.ts | 13 +- .../platform/src/internal/workerRunner.ts | 7 +- packages/platform/test/HttpClient.test.ts | 2 +- packages/platform/test/KeyValueStore.test.ts | 2 +- .../platform/test/OpenApiJsonSchema.test.ts | 12 +- packages/platform/test/Transferable.test.ts | 3 +- packages/platform/tsconfig.build.json | 5 +- packages/platform/tsconfig.src.json | 5 +- packages/platform/tsconfig.test.json | 1 - packages/rpc-http/examples/schema.ts | 2 +- packages/rpc-http/package.json | 2 - packages/rpc-http/src/HttpRpcResolver.ts | 6 +- .../rpc-http/src/HttpRpcResolverNoStream.ts | 6 +- .../rpc-http/src/HttpRpcRouterNoStream.ts | 2 +- packages/rpc-http/tsconfig.build.json | 1 - packages/rpc-http/tsconfig.examples.json | 1 - packages/rpc-http/tsconfig.src.json | 1 - packages/rpc-http/tsconfig.test.json | 1 - packages/rpc/README.md | 6 +- packages/rpc/package.json | 2 - packages/rpc/src/Rpc.ts | 33 +- packages/rpc/src/RpcResolver.ts | 15 +- packages/rpc/src/RpcResolverNoStream.ts | 11 +- packages/rpc/src/RpcRouter.ts | 21 +- packages/rpc/src/internal/rpc.ts | 11 +- packages/rpc/test/Router.test.ts | 79 +- packages/rpc/tsconfig.build.json | 3 +- packages/rpc/tsconfig.examples.json | 3 +- packages/rpc/tsconfig.src.json | 6 +- packages/rpc/tsconfig.test.json | 3 +- packages/schema/LICENSE | 21 - packages/schema/README.md | 271 -- packages/schema/docgen.json | 26 - packages/schema/dtslint/tsconfig.json | 9 - packages/schema/package.json | 60 - packages/schema/serializable.md | 355 --- packages/schema/src/ArrayFormatter.ts | 82 - packages/schema/src/Equivalence.ts | 222 -- packages/schema/src/Serializable.ts | 385 --- packages/schema/src/TreeFormatter.ts | 215 -- packages/schema/src/index.ts | 54 - packages/schema/src/internal/filters.ts | 89 - packages/schema/src/internal/serializable.ts | 9 - .../UniqueSymbol/UniqueSymbolFromSelf.test.ts | 17 - packages/schema/test/Schema/exports.test.ts | 51 - packages/schema/test/formatUnknown.test.ts | 27 - packages/schema/test/util.test.ts | 14 - packages/schema/tsconfig.build.json | 12 - packages/schema/tsconfig.json | 8 - packages/schema/tsconfig.src.json | 12 - packages/schema/tsconfig.test.json | 13 - packages/schema/vitest.config.ts | 6 - packages/sql-d1/test/Resolver.test.ts | 2 +- packages/sql-kysely/test/Sqlite.test.ts | 3 +- packages/sql-libsql/test/Resolver.test.ts | 2 +- packages/sql-mysql2/test/Model.test.ts | 3 +- packages/sql-pg/examples/resolver.ts | 2 +- .../sql-sqlite-node/test/Resolver.test.ts | 2 +- packages/sql/README.md | 16 +- packages/sql/package.json | 2 - packages/sql/src/Model.ts | 6 +- packages/sql/src/SqlResolver.ts | 4 +- packages/sql/src/SqlSchema.ts | 4 +- packages/sql/tsconfig.build.json | 3 +- packages/sql/tsconfig.examples.json | 3 +- packages/sql/tsconfig.src.json | 3 +- packages/sql/tsconfig.test.json | 3 +- pnpm-lock.yaml | 81 +- {packages/schema => schema}/CHANGELOG.md | 0 {packages/schema => schema}/comparisons.md | 20 +- tsconfig.base.json | 3 - tsconfig.build.json | 1 - tsconfig.json | 2 - vitest.shared.ts | 1 - 540 files changed, 4057 insertions(+), 5229 deletions(-) create mode 100644 .changeset/six-crabs-itch.md rename packages/{schema/benchmark/array.ts => effect/benchmark/SchemaArray.ts} (94%) rename packages/{schema/benchmark/filters.ts => effect/benchmark/SchemaFilters.ts} (96%) rename packages/{schema/benchmark/index.ts => effect/benchmark/SchemaIndex.ts} (96%) rename packages/{schema/benchmark/propertyOrder.ts => effect/benchmark/SchemaPropertyOrder.ts} (96%) rename packages/{schema/benchmark/Struct.ts => effect/benchmark/SchemaStruct.ts} (95%) rename packages/{schema/benchmark/toString.ts => effect/benchmark/SchemaToString.ts} (90%) rename packages/{schema/benchmark/TreeFormatter.formatIssueSync.ts => effect/benchmark/SchemaTreeFormatter.ts} (90%) rename packages/{schema/benchmark/union.ts => effect/benchmark/SchemaUnion.ts} (95%) rename packages/{schema => effect}/benchmark/tsconfig.json (69%) rename packages/{schema => effect}/dtslint/Schema.ts (99%) rename packages/{schema/dtslint/AST.ts => effect/dtslint/SchemaAST.ts} (57%) rename packages/{schema/dtslint/Brand.errors.ts => effect/dtslint/SchemaBrand.ts} (90%) rename packages/{schema/dtslint/Class.ts => effect/dtslint/SchemaClass.ts} (98%) rename packages/{schema/dtslint/Context.ts => effect/dtslint/SchemaContext.ts} (98%) rename packages/{schema/dtslint/generic.ts => effect/dtslint/SchemaGeneric.ts} (93%) rename packages/{schema/dtslint/ParseResult.ts => effect/dtslint/SchemaParseResult.ts} (78%) rename packages/{schema/dtslint/PropertySignature.ts => effect/dtslint/SchemaPropertySignature.ts} (95%) rename packages/{schema/dtslint/Serializable.ts => effect/dtslint/SchemaSerializable.ts} (68%) rename packages/{schema/dtslint/TaggedError.ts => effect/dtslint/SchemaTaggedError.ts} (79%) rename packages/{schema/dtslint/TaggedRequest.ts => effect/dtslint/SchemaTaggedRequest.ts} (88%) rename packages/{schema/dtslint/userland.ts => effect/dtslint/SchemaUserland.ts} (95%) rename packages/{schema => effect}/src/Arbitrary.ts (89%) rename packages/{schema => effect}/src/FastCheck.ts (66%) rename packages/{schema => effect}/src/JSONSchema.ts (96%) rename packages/{schema => effect}/src/ParseResult.ts (82%) rename packages/{schema => effect}/src/Pretty.ts (82%) rename packages/{schema => effect}/src/Schema.ts (84%) rename packages/{schema/src/AST.ts => effect/src/SchemaAST.ts} (89%) rename packages/{schema/src/internal => effect/src/internal/schema}/errors.ts (99%) create mode 100644 packages/effect/src/internal/schema/filters.ts rename packages/{schema/src/internal => effect/src/internal/schema}/util.ts (96%) rename packages/{schema/test => effect/test/Schema}/Arbitrary/Arbitrary.test.ts (97%) rename packages/{schema/test => effect/test/Schema}/Arbitrary/Class.test.ts (87%) rename packages/{schema/test => effect/test/Schema}/Arbitrary/getConstraints.test.ts (97%) rename packages/{schema/test => effect/test/Schema}/JSONSchema.test.ts (99%) rename packages/{schema/test => effect/test/Schema}/ParseResult.test.ts (99%) rename packages/{schema/test/Formatter.test.ts => effect/test/Schema/ParseResultFormatter.test.ts} (97%) rename packages/{schema/test => effect/test/Schema}/Pretty.test.ts (97%) rename packages/{schema/test => effect/test/Schema}/Schema/Any/Any.test.ts (84%) rename packages/{schema/test => effect/test/Schema}/Schema/Array/Array.test.ts (90%) rename packages/{schema/test => effect/test/Schema}/Schema/Array/head.test.ts (90%) rename packages/{schema/test => effect/test/Schema}/Schema/Array/headOrElse.test.ts (95%) rename packages/{schema/test => effect/test/Schema}/Schema/Array/itemsCount.test.ts (89%) rename packages/{schema/test => effect/test/Schema}/Schema/Array/maxItems.test.ts (83%) rename packages/{schema/test => effect/test/Schema}/Schema/Array/minItems.test.ts (88%) rename packages/{schema/test => effect/test/Schema}/Schema/ArrayEnsure.test.ts (96%) rename packages/{schema/test => effect/test/Schema}/Schema/BigDecimal/BigDecimal.test.ts (91%) rename packages/{schema/test => effect/test/Schema}/Schema/BigDecimal/BigDecimalFromNumber.test.ts (91%) rename packages/{schema/test => effect/test/Schema}/Schema/BigDecimal/BigDecimalFromSelf.test.ts (86%) rename packages/{schema/test => effect/test/Schema}/Schema/BigDecimal/NegativeBigDecimalFromSelf.test.ts (90%) rename packages/{schema/test => effect/test/Schema}/Schema/BigDecimal/NonNegativeBigDecimalFromSelf.test.ts (89%) rename packages/{schema/test => effect/test/Schema}/Schema/BigDecimal/NonPositiveBigDecimalFromSelf.test.ts (89%) rename packages/{schema/test => effect/test/Schema}/Schema/BigDecimal/PositiveBigDecimalFromSelf.test.ts (90%) rename packages/{schema/test => effect/test/Schema}/Schema/BigDecimal/betweenBigDecimal.test.ts (92%) rename packages/{schema/test => effect/test/Schema}/Schema/BigDecimal/clampBigDecimal.test.ts (86%) rename packages/{schema/test => effect/test/Schema}/Schema/BigDecimal/greaterThanBigDecimal.test.ts (89%) rename packages/{schema/test => effect/test/Schema}/Schema/BigDecimal/greaterThanOrEqualToBigDecimal.test.ts (88%) rename packages/{schema/test => effect/test/Schema}/Schema/BigDecimal/lessThanBigDecimal.test.ts (89%) rename packages/{schema/test => effect/test/Schema}/Schema/BigDecimal/lessThanOrEqualToBigDecimal.test.ts (88%) rename packages/{schema/test => effect/test/Schema}/Schema/BigInt/BigInt.test.ts (94%) rename packages/{schema/test => effect/test/Schema}/Schema/BigInt/BigIntFromNumber.test.ts (94%) rename packages/{schema/test => effect/test/Schema}/Schema/BigInt/BigIntFromSelf.test.ts (85%) rename packages/{schema/test => effect/test/Schema}/Schema/BigInt/NegativeBigIntFromSelf.test.ts (86%) rename packages/{schema/test => effect/test/Schema}/Schema/BigInt/NonNegativeBigIntFromSelf.test.ts (83%) rename packages/{schema/test => effect/test/Schema}/Schema/BigInt/NonPositiveBigIntFromSelf.test.ts (84%) rename packages/{schema/test => effect/test/Schema}/Schema/BigInt/PositiveBigIntFromSelf.test.ts (86%) rename packages/{schema/test => effect/test/Schema}/Schema/BigInt/betweenBigInt.test.ts (88%) rename packages/{schema/test => effect/test/Schema}/Schema/BigInt/clampBigInt.test.ts (78%) rename packages/{schema/test => effect/test/Schema}/Schema/BigInt/greaterThanBigInt.test.ts (86%) rename packages/{schema/test => effect/test/Schema}/Schema/BigInt/greaterThanOrEqualToBigInt.test.ts (84%) rename packages/{schema/test => effect/test/Schema}/Schema/BigInt/lessThanBigInt.test.ts (86%) rename packages/{schema/test => effect/test/Schema}/Schema/BigInt/lessThanOrEqualToBigInt.test.ts (84%) rename packages/{schema/test => effect/test/Schema}/Schema/Boolean/Boolean.test.ts (83%) rename packages/{schema/test => effect/test/Schema}/Schema/Boolean/BooleanFromUnknown.test.ts (89%) rename packages/{schema/test => effect/test/Schema}/Schema/Boolean/Not.test.ts (80%) rename packages/{schema/test => effect/test/Schema}/Schema/Cause/Cause.test.ts (98%) rename packages/{schema/test => effect/test/Schema}/Schema/Cause/CauseFromSelf.test.ts (95%) rename packages/{schema/test => effect/test/Schema}/Schema/Chunk/Chunk.test.ts (91%) rename packages/{schema/test => effect/test/Schema}/Schema/Chunk/ChunkFromSelf.test.ts (86%) rename packages/{schema/test => effect/test/Schema}/Schema/Chunk/NonEmptyChunk.test.ts (91%) rename packages/{schema/test => effect/test/Schema}/Schema/Chunk/NonEmptyChunkFromSelf.test.ts (85%) rename packages/{schema/test => effect/test/Schema}/Schema/Class/Class.test.ts (98%) rename packages/{schema/test => effect/test/Schema}/Schema/Class/TaggedClass.test.ts (97%) rename packages/{schema/test => effect/test/Schema}/Schema/Class/TaggedError.test.ts (95%) rename packages/{schema/test => effect/test/Schema}/Schema/Class/TaggedRequest.test.ts (83%) rename packages/{schema/test => effect/test/Schema}/Schema/Class/extend.test.ts (97%) rename packages/{schema/test => effect/test/Schema}/Schema/Class/transformOrFail.test.ts (94%) rename packages/{schema/test => effect/test/Schema}/Schema/Class/transformOrFailFrom.test.ts (94%) rename packages/{schema/test => effect/test/Schema}/Schema/Config/Config.test.ts (97%) rename packages/{schema/test => effect/test/Schema}/Schema/Data/Data.test.ts (91%) rename packages/{schema/test => effect/test/Schema}/Schema/Data/DataFromSelf.test.ts (90%) rename packages/{schema/test => effect/test/Schema}/Schema/Date/Date.test.ts (88%) rename packages/{schema/test => effect/test/Schema}/Schema/Date/DateFromNumber.test.ts (91%) rename packages/{schema/test => effect/test/Schema}/Schema/Date/DateFromSelf.test.ts (85%) rename packages/{schema/test => effect/test/Schema}/Schema/Date/betweenDate.test.ts (91%) rename packages/{schema/test => effect/test/Schema}/Schema/Date/greaterThanDate.test.ts (88%) rename packages/{schema/test => effect/test/Schema}/Schema/Date/greaterThanOrEqualToDate.test.ts (86%) rename packages/{schema/test => effect/test/Schema}/Schema/Date/lessThanDate.test.ts (88%) rename packages/{schema/test => effect/test/Schema}/Schema/Date/lessThanOrEqualToDate.test.ts (86%) rename packages/{schema/test => effect/test/Schema}/Schema/DateTime/DateTime.test.ts (94%) rename packages/{schema/test => effect/test/Schema}/Schema/DecodingFallbackAnnotation.test.ts (95%) rename packages/{schema/test => effect/test/Schema}/Schema/Defect/Defect.test.ts (94%) rename packages/{schema/test => effect/test/Schema}/Schema/Duration/Duration.test.ts (95%) rename packages/{schema/test => effect/test/Schema}/Schema/Duration/DurationFromMillis.test.ts (88%) rename packages/{schema/test => effect/test/Schema}/Schema/Duration/DurationFromNanos.test.ts (85%) rename packages/{schema/test => effect/test/Schema}/Schema/Duration/DurationFromSelf.test.ts (88%) rename packages/{schema/test => effect/test/Schema}/Schema/Duration/betweenDuration.test.ts (91%) rename packages/{schema/test => effect/test/Schema}/Schema/Duration/clampDuration.test.ts (86%) rename packages/{schema/test => effect/test/Schema}/Schema/Duration/greaterThanDuration.test.ts (91%) rename packages/{schema/test => effect/test/Schema}/Schema/Duration/greaterThanOrEqualToDuration.test.ts (90%) rename packages/{schema/test => effect/test/Schema}/Schema/Duration/lessThanDuration.test.ts (91%) rename packages/{schema/test => effect/test/Schema}/Schema/Duration/lessThanOrEqualToDuration.test.ts (90%) rename packages/{schema/test => effect/test/Schema}/Schema/Either/Either.test.ts (89%) rename packages/{schema/test => effect/test/Schema}/Schema/Either/EitherFromSelf.test.ts (91%) rename packages/{schema/test => effect/test/Schema}/Schema/Either/EitherFromUnion.test.ts (98%) rename packages/{schema/test => effect/test/Schema}/Schema/Enums/Enums.test.ts (96%) rename packages/{schema/test => effect/test/Schema}/Schema/Exit/Exit.test.ts (94%) rename packages/{schema/test => effect/test/Schema}/Schema/Exit/ExitFromSelf.test.ts (95%) rename packages/{schema/test => effect/test/Schema}/Schema/FiberId/FiberId.test.ts (92%) rename packages/{schema/test => effect/test/Schema}/Schema/FiberId/FiberIdFromSelf.test.ts (88%) rename packages/{schema/test => effect/test/Schema}/Schema/HashMap/HashMap.test.ts (94%) rename packages/{schema/test => effect/test/Schema}/Schema/HashMap/HashMapFromSelf.test.ts (93%) rename packages/{schema/test => effect/test/Schema}/Schema/HashSet/HashSet.test.ts (92%) rename packages/{schema/test => effect/test/Schema}/Schema/HashSet/HashSetFromSelf.test.ts (87%) rename packages/{schema/test => effect/test/Schema}/Schema/List/List.test.ts (91%) rename packages/{schema/test => effect/test/Schema}/Schema/List/ListFromSelf.test.ts (86%) rename packages/{schema/test => effect/test/Schema}/Schema/Literal/Literal.test.ts (93%) rename packages/{schema/test => effect/test/Schema}/Schema/Map/Map.test.ts (86%) rename packages/{schema/test => effect/test/Schema}/Schema/Map/MapFromRecord.test.ts (95%) rename packages/{schema/test => effect/test/Schema}/Schema/Map/MapFromSelf.test.ts (83%) rename packages/{schema/test => effect/test/Schema}/Schema/Never/Never.test.ts (77%) rename packages/{schema/test => effect/test/Schema}/Schema/NonEmptyArrayEnsure.test.ts (97%) rename packages/{schema/test => effect/test/Schema}/Schema/Number/JsonNumber.test.ts (93%) rename packages/{schema/test => effect/test/Schema}/Schema/Number/Number.test.ts (85%) rename packages/{schema/test => effect/test/Schema}/Schema/Number/between.test.ts (87%) rename packages/{schema/test => effect/test/Schema}/Schema/Number/clamp.test.ts (86%) rename packages/{schema/test => effect/test/Schema}/Schema/Number/finite.test.ts (86%) rename packages/{schema/test => effect/test/Schema}/Schema/Number/greaterThan.test.ts (82%) rename packages/{schema/test => effect/test/Schema}/Schema/Number/greaterThanOrEqualTo.test.ts (80%) rename packages/{schema/test => effect/test/Schema}/Schema/Number/int.test.ts (81%) rename packages/{schema/test => effect/test/Schema}/Schema/Number/lessThan.test.ts (83%) rename packages/{schema/test => effect/test/Schema}/Schema/Number/lessThanOrEqualTo.test.ts (81%) rename packages/{schema/test => effect/test/Schema}/Schema/Number/multipleOf.test.ts (89%) rename packages/{schema/test => effect/test/Schema}/Schema/Number/negative.test.ts (84%) rename packages/{schema/test => effect/test/Schema}/Schema/Number/nonNaN.test.ts (77%) rename packages/{schema/test => effect/test/Schema}/Schema/Number/nonNegative.test.ts (82%) rename packages/{schema/test => effect/test/Schema}/Schema/Number/nonPositive.test.ts (82%) rename packages/{schema/test => effect/test/Schema}/Schema/Number/numberFromString.test.ts (95%) rename packages/{schema/test => effect/test/Schema}/Schema/Number/positive.test.ts (84%) rename packages/{schema/test => effect/test/Schema}/Schema/Object/Object.test.ts (90%) rename packages/{schema/test => effect/test/Schema}/Schema/Option/Option.test.ts (87%) rename packages/{schema/test => effect/test/Schema}/Schema/Option/OptionFromNonEmptyTrimmedString.test.ts (93%) rename packages/{schema/test => effect/test/Schema}/Schema/Option/OptionFromNullOr.test.ts (94%) rename packages/{schema/test => effect/test/Schema}/Schema/Option/OptionFromNullishOr.test.ts (94%) rename packages/{schema/test => effect/test/Schema}/Schema/Option/OptionFromSelf.test.ts (86%) rename packages/{schema/test => effect/test/Schema}/Schema/Option/OptionFromUndefinedOr.test.ts (94%) rename packages/{schema/test => effect/test/Schema}/Schema/ParseOptions-errors.test.ts (98%) rename packages/{schema/test => effect/test/Schema}/Schema/ParseOptions-exact.test.ts (92%) rename packages/{schema/test => effect/test/Schema}/Schema/ParseOptions-onExcessProperty.test.ts (94%) rename packages/{schema/test => effect/test/Schema}/Schema/ParseOptions-preserveKeyOrder.test.ts (95%) rename packages/{schema/test => effect/test/Schema}/Schema/ParseOptionsAnnotation.test.ts (94%) rename packages/{schema/test => effect/test/Schema}/Schema/PropertySignature.test.ts (96%) rename packages/{schema/test => effect/test/Schema}/Schema/ReadonlyMap/ReadonlyMap.test.ts (93%) rename packages/{schema/test => effect/test/Schema}/Schema/ReadonlyMap/ReadonlyMapFromRecord.test.ts (95%) rename packages/{schema/test => effect/test/Schema}/Schema/ReadonlyMap/ReadonlyMapFromSelf.test.ts (92%) rename packages/{schema/test => effect/test/Schema}/Schema/ReadonlySet/ReadonlySet.test.ts (91%) rename packages/{schema/test => effect/test/Schema}/Schema/ReadonlySet/ReadonlySetFromSelf.test.ts (90%) rename packages/{schema/test => effect/test/Schema}/Schema/Record/Record.test.ts (93%) rename packages/{schema/test => effect/test/Schema}/Schema/Redacted/Redacted.test.ts (86%) rename packages/{schema/test => effect/test/Schema}/Schema/Redacted/RedactedFromSelf.test.ts (86%) rename packages/{schema/test => effect/test/Schema}/Schema/Set/Set.test.ts (82%) rename packages/{schema/test => effect/test/Schema}/Schema/Set/SetFromSelf.test.ts (81%) rename packages/{schema/test => effect/test/Schema}/Schema/SortedSet/SortedSet.test.ts (93%) rename packages/{schema/test => effect/test/Schema}/Schema/SortedSet/SortedSetFromSelf.test.ts (90%) rename packages/{schema/test => effect/test/Schema}/Schema/String/NonEmptyTrimmedString.test.ts (93%) rename packages/{schema/test => effect/test/Schema}/Schema/String/String.test.ts (78%) rename packages/{schema/test => effect/test/Schema}/Schema/String/StringFromBase64.test.ts (91%) rename packages/{schema/test => effect/test/Schema}/Schema/String/StringFromBase64Url.test.ts (91%) rename packages/{schema/test => effect/test/Schema}/Schema/String/StringFromHex.test.ts (93%) rename packages/{schema/test => effect/test/Schema}/Schema/String/capitalize.test.ts (90%) rename packages/{schema/test => effect/test/Schema}/Schema/String/endsWith.test.ts (86%) rename packages/{schema/test => effect/test/Schema}/Schema/String/includes.test.ts (83%) rename packages/{schema/test => effect/test/Schema}/Schema/String/length.test.ts (96%) rename packages/{schema/test => effect/test/Schema}/Schema/String/lowercase.test.ts (89%) rename packages/{schema/test => effect/test/Schema}/Schema/String/maxLength.test.ts (81%) rename packages/{schema/test => effect/test/Schema}/Schema/String/minLength.test.ts (81%) rename packages/{schema/test => effect/test/Schema}/Schema/String/nonEmptyString.test.ts (87%) rename packages/{schema/test => effect/test/Schema}/Schema/String/pattern.test.ts (92%) rename packages/{schema/test => effect/test/Schema}/Schema/String/split.test.ts (91%) rename packages/{schema/test => effect/test/Schema}/Schema/String/startsWith.test.ts (86%) rename packages/{schema/test => effect/test/Schema}/Schema/String/trim.test.ts (96%) rename packages/{schema/test => effect/test/Schema}/Schema/String/uncapitalize.test.ts (90%) rename packages/{schema/test => effect/test/Schema}/Schema/String/uppercase.test.ts (89%) rename packages/{schema/test => effect/test/Schema}/Schema/Struct/Struct.test.ts (97%) rename packages/{schema/test => effect/test/Schema}/Schema/Struct/make.test.ts (97%) rename packages/{schema/test => effect/test/Schema}/Schema/Struct/omit.test.ts (85%) rename packages/{schema/test => effect/test/Schema}/Schema/Struct/pick.test.ts (86%) rename packages/{schema/test => effect/test/Schema}/Schema/Symbol/Symbol.test.ts (88%) rename packages/{schema/test => effect/test/Schema}/Schema/Symbol/SymbolFromSelf.test.ts (66%) rename packages/{schema/test => effect/test/Schema}/Schema/TaggedStruct/make.test.ts (89%) rename packages/{schema/test => effect/test/Schema}/Schema/TemplateLiteral/TemplateLiteral.test.ts (98%) rename packages/{schema/test => effect/test/Schema}/Schema/TemplateLiteralParser.test.ts (97%) rename packages/{schema/test => effect/test/Schema}/Schema/Trimmed/Trimmed.test.ts (92%) rename packages/{schema/test => effect/test/Schema}/Schema/Tuple/Tuple.test.ts (99%) rename packages/{schema/test => effect/test/Schema}/Schema/ULID.test.ts (81%) rename packages/{schema/test => effect/test/Schema}/Schema/UUID.test.ts (82%) rename packages/{schema/test => effect/test/Schema}/Schema/Uint8Array/Uint8Array.test.ts (90%) rename packages/{schema/test => effect/test/Schema}/Schema/Uint8Array/Uint8ArrayFromBase64.test.ts (91%) rename packages/{schema/test => effect/test/Schema}/Schema/Uint8Array/Uint8ArrayFromBase64Url.test.ts (92%) rename packages/{schema/test => effect/test/Schema}/Schema/Uint8Array/Uint8ArrayFromHex.test.ts (93%) rename packages/{schema/test => effect/test/Schema}/Schema/Uint8Array/Uint8ArrayFromSelf.test.ts (84%) rename packages/{schema/test => effect/test/Schema}/Schema/Union/Union.test.ts (98%) create mode 100644 packages/effect/test/Schema/Schema/UniqueSymbol/UniqueSymbolFromSelf.test.ts rename packages/{schema/test => effect/test/Schema}/Schema/Unknown/Unknown.test.ts (84%) rename packages/{schema/test => effect/test/Schema}/Schema/Void/Void.test.ts (85%) rename packages/{schema/test => effect/test/Schema}/Schema/annotations.test.ts (89%) rename packages/{schema/test => effect/test/Schema}/Schema/asserts.test.ts (93%) rename packages/{schema/test => effect/test/Schema}/Schema/attachPropertySignature.test.ts (91%) rename packages/{schema/test => effect/test/Schema}/Schema/brand.test.ts (94%) rename packages/{schema/test => effect/test/Schema}/Schema/compose.test.ts (96%) rename packages/{schema/test => effect/test/Schema}/Schema/decode.test.ts (92%) rename packages/{schema/test => effect/test/Schema}/Schema/decodeEither.test.ts (93%) rename packages/{schema/test => effect/test/Schema}/Schema/decodeOption.test.ts (89%) rename packages/{schema/test => effect/test/Schema}/Schema/decodePromise.test.ts (92%) rename packages/{schema/test => effect/test/Schema}/Schema/decodeSync.test.ts (93%) rename packages/{schema/test => effect/test/Schema}/Schema/decodeUnknownEither.test.ts (78%) rename packages/{schema/test => effect/test/Schema}/Schema/decodeUnknownOption.test.ts (67%) rename packages/{schema/test => effect/test/Schema}/Schema/decodeUnknownSync.test.ts (84%) rename packages/{schema/test => effect/test/Schema}/Schema/encode.test.ts (92%) rename packages/{schema/test => effect/test/Schema}/Schema/encodeEither.test.ts (93%) rename packages/{schema/test => effect/test/Schema}/Schema/encodeOption.test.ts (89%) rename packages/{schema/test => effect/test/Schema}/Schema/encodePromise.test.ts (92%) rename packages/{schema/test => effect/test/Schema}/Schema/encodeSync.test.ts (93%) rename packages/{schema/test => effect/test/Schema}/Schema/encodeUnknownEither.test.ts (78%) rename packages/{schema/test => effect/test/Schema}/Schema/encodeUnknownOption.test.ts (67%) rename packages/{schema/test => effect/test/Schema}/Schema/encodeUnknownSync.test.ts (79%) rename packages/{schema/test => effect/test/Schema}/Schema/encodedBoundSchema.test.ts (97%) rename packages/{schema/test => effect/test/Schema}/Schema/encodedSchema.test.ts (92%) rename packages/{schema/test/Equivalence.test.ts => effect/test/Schema/Schema/equivalence.test.ts} (89%) create mode 100644 packages/effect/test/Schema/Schema/exports.test.ts rename packages/{schema/test => effect/test/Schema}/Schema/extend.test.ts (98%) rename packages/{schema/test => effect/test/Schema}/Schema/filter.test.ts (96%) rename packages/{schema/test => effect/test/Schema}/Schema/filterEffect.test.ts (97%) rename packages/{schema/test => effect/test/Schema}/Schema/format.test.ts (90%) rename packages/{schema/test => effect/test/Schema}/Schema/fromBrand.test.ts (95%) rename packages/{schema/test => effect/test/Schema}/Schema/getNumberIndexedAccess.test.ts (94%) rename packages/{schema/test => effect/test/Schema}/Schema/instanceOf.test.ts (80%) rename packages/{schema/test => effect/test/Schema}/Schema/is.test.ts (96%) rename packages/{schema/test => effect/test/Schema}/Schema/isSchema.test.ts (92%) rename packages/{schema/test => effect/test/Schema}/Schema/keyof.test.ts (93%) rename packages/{schema/test => effect/test/Schema}/Schema/mutable.test.ts (96%) rename packages/{schema/test => effect/test/Schema}/Schema/nonEmptyArray.test.ts (85%) rename packages/{schema/test => effect/test/Schema}/Schema/omit.test.ts (89%) rename packages/{schema/test => effect/test/Schema}/Schema/optional.test.ts (96%) rename packages/{schema/test => effect/test/Schema}/Schema/optionalToRequired.test.ts (87%) rename packages/{schema/test => effect/test/Schema}/Schema/optionalWith.test.ts (99%) rename packages/{schema/test => effect/test/Schema}/Schema/parseJson.test.ts (97%) rename packages/{schema/test => effect/test/Schema}/Schema/partial.test.ts (97%) rename packages/{schema/test => effect/test/Schema}/Schema/partialWith.test.ts (98%) rename packages/{schema/test => effect/test/Schema}/Schema/pick.test.ts (89%) rename packages/{schema/test => effect/test/Schema}/Schema/pickLiteral.test.ts (90%) rename packages/{schema/test => effect/test/Schema}/Schema/pipe.test.ts (92%) rename packages/{schema/test => effect/test/Schema}/Schema/pluck.test.ts (97%) rename packages/{schema/test => effect/test/Schema}/Schema/rename.test.ts (92%) rename packages/{schema/test => effect/test/Schema}/Schema/required.test.ts (98%) rename packages/{schema/test => effect/test/Schema}/Schema/requiredToOptional.test.ts (87%) rename packages/{schema/test => effect/test/Schema}/Schema/suspend.test.ts (97%) rename packages/{schema/test => effect/test/Schema}/Schema/toString.test.ts (95%) rename packages/{schema/test => effect/test/Schema}/Schema/transform.test.ts (86%) rename packages/{schema/test => effect/test/Schema}/Schema/transformLiterals.test.ts (92%) rename packages/{schema/test => effect/test/Schema}/Schema/transformOrFail.test.ts (81%) rename packages/{schema/test => effect/test/Schema}/Schema/typeSchema.test.ts (93%) rename packages/{schema/test => effect/test/Schema}/Schema/validate.test.ts (96%) rename packages/{schema/test => effect/test/Schema}/Schema/validateEither.test.ts (93%) rename packages/{schema/test => effect/test/Schema}/Schema/validateOption.test.ts (89%) rename packages/{schema/test => effect/test/Schema}/Schema/validatePromise.test.ts (92%) rename packages/{schema/test => effect/test/Schema}/Schema/validateSync.test.ts (93%) rename packages/{schema/test => effect/test/Schema}/Schema/withConstructorDefault.test.ts (95%) rename packages/{schema/test => effect/test/Schema}/Schema/withDecodingDefault.test.ts (94%) rename packages/{schema/test/AST => effect/test/Schema/SchemaAST}/IndexSignature.test.ts (92%) rename packages/{schema/test/AST => effect/test/Schema/SchemaAST}/Tuple.test.ts (95%) rename packages/{schema/test/AST => effect/test/Schema/SchemaAST}/TypeLiteral.test.ts (84%) rename packages/{schema/test/AST => effect/test/Schema/SchemaAST}/TypeLiteralTransformation.test.ts (95%) rename packages/{schema/test/AST => effect/test/Schema/SchemaAST}/Union.test.ts (95%) rename packages/{schema/test/AST => effect/test/Schema/SchemaAST}/annotations.test.ts (88%) rename packages/{schema/test/AST => effect/test/Schema/SchemaAST}/encodedAST.test.ts (96%) rename packages/{schema/test/AST => effect/test/Schema/SchemaAST}/encodedBoundAST.test.ts (96%) rename packages/{schema/test/AST => effect/test/Schema/SchemaAST}/getPropertySignatures.test.ts (92%) rename packages/{schema/test/AST => effect/test/Schema/SchemaAST}/guards.test.ts (96%) rename packages/{schema/test/AST => effect/test/Schema/SchemaAST}/mutable.test.ts (92%) rename packages/{schema/test/AST => effect/test/Schema/SchemaAST}/partial.test.ts (97%) rename packages/{schema/test/AST => effect/test/Schema/SchemaAST}/pick.test.ts (97%) rename packages/{schema/test/AST => effect/test/Schema/SchemaAST}/record.test.ts (94%) rename packages/{schema/test/AST => effect/test/Schema/SchemaAST}/suspend.test.ts (85%) rename packages/{schema/test/AST => effect/test/Schema/SchemaAST}/toString.test.ts (95%) rename packages/{schema/test/AST => effect/test/Schema/SchemaAST}/typeAST.test.ts (96%) rename packages/{schema/test/AST => effect/test/Schema/SchemaAST}/unify.test.ts (96%) create mode 100644 packages/effect/test/Schema/SchemaInternal.test.ts rename packages/{schema/test/userland.test.ts => effect/test/Schema/SchemaUserland.test.ts} (94%) rename packages/{schema/test => effect/test/Schema}/Serializable.test.ts (71%) rename packages/{schema/test => effect/test/Schema}/TestUtils.ts (95%) delete mode 100644 packages/schema/LICENSE delete mode 100644 packages/schema/README.md delete mode 100644 packages/schema/docgen.json delete mode 100644 packages/schema/dtslint/tsconfig.json delete mode 100644 packages/schema/package.json delete mode 100644 packages/schema/serializable.md delete mode 100644 packages/schema/src/ArrayFormatter.ts delete mode 100644 packages/schema/src/Equivalence.ts delete mode 100644 packages/schema/src/Serializable.ts delete mode 100644 packages/schema/src/TreeFormatter.ts delete mode 100644 packages/schema/src/index.ts delete mode 100644 packages/schema/src/internal/filters.ts delete mode 100644 packages/schema/src/internal/serializable.ts delete mode 100644 packages/schema/test/Schema/UniqueSymbol/UniqueSymbolFromSelf.test.ts delete mode 100644 packages/schema/test/Schema/exports.test.ts delete mode 100644 packages/schema/test/formatUnknown.test.ts delete mode 100644 packages/schema/test/util.test.ts delete mode 100644 packages/schema/tsconfig.build.json delete mode 100644 packages/schema/tsconfig.json delete mode 100644 packages/schema/tsconfig.src.json delete mode 100644 packages/schema/tsconfig.test.json delete mode 100644 packages/schema/vitest.config.ts rename {packages/schema => schema}/CHANGELOG.md (100%) rename {packages/schema => schema}/comparisons.md (97%) diff --git a/.changeset/six-crabs-itch.md b/.changeset/six-crabs-itch.md new file mode 100644 index 0000000000..49eb2c240f --- /dev/null +++ b/.changeset/six-crabs-itch.md @@ -0,0 +1,75 @@ +--- +"effect": minor +--- + +Merge Schema into Effect. + +### Modules + +Before + +```ts +import { + Arbitrary, + AST, + FastCheck, + JSONSchema, + ParseResult, + Pretty, + Schema +} from "@effect/schema" +``` + +After + +```ts +import { + Arbitrary, + SchemaAST, // changed + FastCheck, + JSONSchema, + ParseResult, + Pretty, + Schema +} from "effect" +``` + +### Formatters + +`ArrayFormatter` / `TreeFormatter` merged into `ParseResult` module. + +Before + +```ts +import { ArrayFormatter, TreeFormatter } from "@effect/schema" +``` + +After + +```ts +import { ArrayFormatter, TreeFormatter } from "effect/ParseResult" +``` + +### Serializable + +Merged into `Schema` module. + +### Equivalence + +Merged into `Schema` module. + +Before + +```ts +import { Equivalence } from "@effect/schema" + +Equivalence.make(myschema) +``` + +After + +```ts +import { Schema } from "@effect/schema" + +Schema.equivalence(myschema) +``` diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 4ee8222af8..6d1efe9bb3 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -15,7 +15,6 @@ /packages/printer-ansi/ @IMax153 /packages/rpc/ @tim-smart /packages/rpc-http/ @tim-smart -/packages/schema/ @gcanti /packages/sql/ @tim-smart /packages/sql-mssql/ @tim-smart /packages/sql-mysql2/ @tim-smart diff --git a/packages/ai/ai/docgen.json b/packages/ai/ai/docgen.json index a728e1818f..2525a36595 100644 --- a/packages/ai/ai/docgen.json +++ b/packages/ai/ai/docgen.json @@ -1,8 +1,6 @@ { "$schema": "../../../node_modules/@effect/docgen/schema.json", - "exclude": [ - "src/internal/**/*.ts" - ], + "exclude": ["src/internal/**/*.ts"], "examplesCompilerOptions": { "noEmit": true, "strict": true, @@ -10,42 +8,16 @@ "moduleResolution": "Bundler", "module": "ES2022", "target": "ES2022", - "lib": [ - "ES2022", - "DOM", - "DOM.Iterable" - ], + "lib": ["ES2022", "DOM", "DOM.Iterable"], "paths": { - "effect": [ - "../../../../effect/src/index.js" - ], - "effect/*": [ - "../../../../effect/src/*.js" - ], - "@effect/platform": [ - "../../../../platform/src/index.js" - ], - "@effect/platform/*": [ - "../../../../platform/src/*.js" - ], - "@effect/schema": [ - "../../../../schema/src/index.js" - ], - "@effect/schema/*": [ - "../../../../schema/src/*.js" - ], - "@effect/ai": [ - "../../../ai/src/index.js" - ], - "@effect/ai/*": [ - "../../../ai/src/*.js" - ], - "@effect/ai-openai": [ - "../../../ai-openai/src/index.js" - ], - "@effect/ai-openai/*": [ - "../../../ai-openai/src/*.js" - ] + "effect": ["../../../../effect/src/index.js"], + "effect/*": ["../../../../effect/src/*.js"], + "@effect/platform": ["../../../../platform/src/index.js"], + "@effect/platform/*": ["../../../../platform/src/*.js"], + "@effect/ai": ["../../../ai/src/index.js"], + "@effect/ai/*": ["../../../ai/src/*.js"], + "@effect/ai-openai": ["../../../ai-openai/src/index.js"], + "@effect/ai-openai/*": ["../../../ai-openai/src/*.js"] } } } diff --git a/packages/ai/ai/package.json b/packages/ai/ai/package.json index d3c578db82..bae99e82ed 100644 --- a/packages/ai/ai/package.json +++ b/packages/ai/ai/package.json @@ -41,12 +41,10 @@ "dependencies": {}, "peerDependencies": { "@effect/platform": "workspace:^", - "@effect/schema": "workspace:^", "effect": "workspace:^" }, "devDependencies": { "@effect/platform": "workspace:^", - "@effect/schema": "workspace:^", "effect": "workspace:^" } } diff --git a/packages/ai/ai/src/AiChat.ts b/packages/ai/ai/src/AiChat.ts index 5a47f4600f..da90dfaabb 100644 --- a/packages/ai/ai/src/AiChat.ts +++ b/packages/ai/ai/src/AiChat.ts @@ -1,12 +1,12 @@ /** * @since 1.0.0 */ -import type { ParseError } from "@effect/schema/ParseResult" -import * as Schema from "@effect/schema/Schema" import * as Channel from "effect/Channel" import * as Chunk from "effect/Chunk" import * as Effect from "effect/Effect" +import type { ParseError } from "effect/ParseResult" import * as Ref from "effect/Ref" +import * as Schema from "effect/Schema" import * as Stream from "effect/Stream" import type { Concurrency } from "effect/Types" import type { AiError } from "./AiError.js" diff --git a/packages/ai/ai/src/AiError.ts b/packages/ai/ai/src/AiError.ts index 83a6e15931..30bf1d77fc 100644 --- a/packages/ai/ai/src/AiError.ts +++ b/packages/ai/ai/src/AiError.ts @@ -1,7 +1,7 @@ /** * @since 1.0.0 */ -import * as Schema from "@effect/schema/Schema" +import * as Schema from "effect/Schema" /** * @since 1.0.0 diff --git a/packages/ai/ai/src/AiInput.ts b/packages/ai/ai/src/AiInput.ts index cf95f00a4f..6cbad1bf87 100644 --- a/packages/ai/ai/src/AiInput.ts +++ b/packages/ai/ai/src/AiInput.ts @@ -4,15 +4,15 @@ import type { PlatformError } from "@effect/platform/Error" import * as FileSystem from "@effect/platform/FileSystem" import * as Path from "@effect/platform/Path" -import * as ParseResult from "@effect/schema/ParseResult" -import * as Schema_ from "@effect/schema/Schema" import * as Chunk from "effect/Chunk" import * as Context from "effect/Context" import * as Effect from "effect/Effect" import * as Encoding from "effect/Encoding" import { dual } from "effect/Function" import * as Option from "effect/Option" +import * as ParseResult from "effect/ParseResult" import * as Predicate from "effect/Predicate" +import * as Schema_ from "effect/Schema" import { AiResponse, ToolCallId, WithResolved } from "./AiResponse.js" import * as AiRole from "./AiRole.js" diff --git a/packages/ai/ai/src/AiResponse.ts b/packages/ai/ai/src/AiResponse.ts index 20a0ef03bb..78bbb311f0 100644 --- a/packages/ai/ai/src/AiResponse.ts +++ b/packages/ai/ai/src/AiResponse.ts @@ -1,13 +1,13 @@ /** * @since 1.0.0 */ -import * as Schema from "@effect/schema/Schema" import * as Chunk from "effect/Chunk" import * as Data from "effect/Data" import * as Effect from "effect/Effect" import * as Iterable from "effect/Iterable" import * as Option from "effect/Option" import * as Predicate from "effect/Predicate" +import * as Schema from "effect/Schema" import { AiError } from "./AiError.js" import * as AiRole from "./AiRole.js" diff --git a/packages/ai/ai/src/AiRole.ts b/packages/ai/ai/src/AiRole.ts index 557a34fefa..af2ec4ae20 100644 --- a/packages/ai/ai/src/AiRole.ts +++ b/packages/ai/ai/src/AiRole.ts @@ -1,8 +1,8 @@ /** * @since 1.0.0 */ -import * as Schema from "@effect/schema/Schema" import * as Option from "effect/Option" +import * as Schema from "effect/Schema" /** * @since 1.0.0 diff --git a/packages/ai/ai/src/AiToolkit.ts b/packages/ai/ai/src/AiToolkit.ts index a4f3387319..6d1aaf2e8b 100644 --- a/packages/ai/ai/src/AiToolkit.ts +++ b/packages/ai/ai/src/AiToolkit.ts @@ -1,8 +1,6 @@ /** * @since 1.0.0 */ -import type * as Schema from "@effect/schema/Schema" -import type * as Serializable from "@effect/schema/Serializable" import * as Context from "effect/Context" import * as Effect from "effect/Effect" import * as Effectable from "effect/Effectable" @@ -11,6 +9,7 @@ import * as HashMap from "effect/HashMap" import * as Inspectable from "effect/Inspectable" import * as Layer from "effect/Layer" import { pipeArguments } from "effect/Pipeable" +import type * as Schema from "effect/Schema" import type { Scope } from "effect/Scope" import type * as Types from "effect/Types" @@ -82,7 +81,7 @@ export declare namespace Tool { export interface AnySchema { readonly [Schema.TypeId]: any readonly _tag: string - readonly Type: Serializable.SerializableWithResult.All + readonly Type: Schema.SerializableWithResult.All readonly success: Schema.Schema.Any } @@ -90,19 +89,19 @@ export declare namespace Tool { * @since 1.0.0 * @category tool */ - export type Success = Serializable.WithResult.Success + export type Success = Schema.WithResult.Success /** * @since 1.0.0 * @category tool */ - export type Failure = Serializable.WithResult.Failure + export type Failure = Schema.WithResult.Failure /** * @since 1.0.0 * @category tool */ - export type Context = Serializable.WithResult.Context + export type Context = Schema.WithResult.Context /** * @since 1.0.0 diff --git a/packages/ai/ai/src/Completions.ts b/packages/ai/ai/src/Completions.ts index 31cdf7adc2..0f3e5cfa1b 100644 --- a/packages/ai/ai/src/Completions.ts +++ b/packages/ai/ai/src/Completions.ts @@ -2,13 +2,13 @@ * @since 1.0.0 */ import * as JsonSchema from "@effect/platform/OpenApiJsonSchema" -import * as AST from "@effect/schema/AST" -import * as Schema from "@effect/schema/Schema" import * as Chunk from "effect/Chunk" import * as Context from "effect/Context" import * as Effect from "effect/Effect" import * as HashMap from "effect/HashMap" import * as Option from "effect/Option" +import * as Schema from "effect/Schema" +import * as AST from "effect/SchemaAST" import * as Stream from "effect/Stream" import type { Concurrency } from "effect/Types" import { AiError } from "./AiError.js" diff --git a/packages/ai/ai/tsconfig.build.json b/packages/ai/ai/tsconfig.build.json index be5cca2ee7..e28d885dba 100644 --- a/packages/ai/ai/tsconfig.build.json +++ b/packages/ai/ai/tsconfig.build.json @@ -2,8 +2,7 @@ "extends": "./tsconfig.src.json", "references": [ { "path": "../../effect/tsconfig.build.json" }, - { "path": "../../platform/tsconfig.build.json" }, - { "path": "../../schema/tsconfig.build.json" } + { "path": "../../platform/tsconfig.build.json" } ], "compilerOptions": { "tsBuildInfoFile": ".tsbuildinfo/build.tsbuildinfo", diff --git a/packages/ai/ai/tsconfig.src.json b/packages/ai/ai/tsconfig.src.json index 127e58a359..be27b3befb 100644 --- a/packages/ai/ai/tsconfig.src.json +++ b/packages/ai/ai/tsconfig.src.json @@ -1,11 +1,7 @@ { "extends": "../../../tsconfig.base.json", "include": ["src"], - "references": [ - { "path": "../../effect" }, - { "path": "../../platform" }, - { "path": "../../schema" } - ], + "references": [{ "path": "../../effect" }, { "path": "../../platform" }], "compilerOptions": { "tsBuildInfoFile": ".tsbuildinfo/src.tsbuildinfo", "rootDir": "src", diff --git a/packages/ai/ai/tsconfig.test.json b/packages/ai/ai/tsconfig.test.json index 892b49082e..4781a0a2a5 100644 --- a/packages/ai/ai/tsconfig.test.json +++ b/packages/ai/ai/tsconfig.test.json @@ -5,7 +5,6 @@ { "path": "tsconfig.src.json" }, { "path": "../../effect" }, { "path": "../../platform" }, - { "path": "../../schema" }, { "path": "../../vitest" } ], "compilerOptions": { diff --git a/packages/ai/openai/docgen.json b/packages/ai/openai/docgen.json index 7fdfa91f86..5fa5696a71 100644 --- a/packages/ai/openai/docgen.json +++ b/packages/ai/openai/docgen.json @@ -1,9 +1,6 @@ { "$schema": "../../../node_modules/@effect/docgen/schema.json", - "exclude": [ - "src/Generated.ts", - "src/internal/**/*.ts" - ], + "exclude": ["src/Generated.ts", "src/internal/**/*.ts"], "examplesCompilerOptions": { "noEmit": true, "strict": true, @@ -11,48 +8,18 @@ "moduleResolution": "Bundler", "module": "ES2022", "target": "ES2022", - "lib": [ - "ES2022", - "DOM", - "DOM.Iterable" - ], + "lib": ["ES2022", "DOM", "DOM.Iterable"], "paths": { - "effect": [ - "../../../../effect/src/index.js" - ], - "effect/*": [ - "../../../../effect/src/*.js" - ], - "@effect/experimental": [ - "../../../../experimental/src/index.js" - ], - "@effect/experimental/*": [ - "../../../../experimental/src/*.js" - ], - "@effect/platform": [ - "../../../../platform/src/index.js" - ], - "@effect/platform/*": [ - "../../../../platform/src/*.js" - ], - "@effect/schema": [ - "../../../../schema/src/index.js" - ], - "@effect/schema/*": [ - "../../../../schema/src/*.js" - ], - "@effect/ai": [ - "../../../ai/src/index.js" - ], - "@effect/ai/*": [ - "../../../ai/src/*.js" - ], - "@effect/ai-openai": [ - "../../../ai-openai/src/index.js" - ], - "@effect/ai-openai/*": [ - "../../../ai-openai/src/*.js" - ] + "effect": ["../../../../effect/src/index.js"], + "effect/*": ["../../../../effect/src/*.js"], + "@effect/experimental": ["../../../../experimental/src/index.js"], + "@effect/experimental/*": ["../../../../experimental/src/*.js"], + "@effect/platform": ["../../../../platform/src/index.js"], + "@effect/platform/*": ["../../../../platform/src/*.js"], + "@effect/ai": ["../../../ai/src/index.js"], + "@effect/ai/*": ["../../../ai/src/*.js"], + "@effect/ai-openai": ["../../../ai-openai/src/index.js"], + "@effect/ai-openai/*": ["../../../ai-openai/src/*.js"] } } } diff --git a/packages/ai/openai/package.json b/packages/ai/openai/package.json index 8b8a25a688..fc32c8b59d 100644 --- a/packages/ai/openai/package.json +++ b/packages/ai/openai/package.json @@ -42,7 +42,6 @@ "@effect/ai": "workspace:^", "@effect/experimental": "workspace:^", "@effect/platform": "workspace:^", - "@effect/schema": "workspace:^", "effect": "workspace:^" }, "devDependencies": { @@ -50,7 +49,6 @@ "@effect/experimental": "workspace:^", "@effect/platform": "workspace:^", "@effect/platform-node": "workspace:^", - "@effect/schema": "workspace:^", "@tim-smart/openapi-gen": "^0.2.0", "effect": "workspace:^" }, diff --git a/packages/ai/openai/src/Generated.ts b/packages/ai/openai/src/Generated.ts index 0773e22119..f9d4bc4b12 100644 --- a/packages/ai/openai/src/Generated.ts +++ b/packages/ai/openai/src/Generated.ts @@ -5,9 +5,9 @@ import type * as HttpClient from "@effect/platform/HttpClient" import * as HttpClientError from "@effect/platform/HttpClientError" import * as HttpClientRequest from "@effect/platform/HttpClientRequest" import * as HttpClientResponse from "@effect/platform/HttpClientResponse" -import type { ParseError } from "@effect/schema/ParseResult" -import * as S from "@effect/schema/Schema" import * as Effect from "effect/Effect" +import type { ParseError } from "effect/ParseResult" +import * as S from "effect/Schema" export class ChatCompletionRequestMessageContentPartText extends S.Struct({ "type": S.Literal("text"), diff --git a/packages/ai/openai/tsconfig.build.json b/packages/ai/openai/tsconfig.build.json index 05f1fccc7a..48f83a4721 100644 --- a/packages/ai/openai/tsconfig.build.json +++ b/packages/ai/openai/tsconfig.build.json @@ -4,8 +4,7 @@ { "path": "../../effect/tsconfig.build.json" }, { "path": "../ai/tsconfig.build.json" }, { "path": "../../experimental/tsconfig.build.json" }, - { "path": "../../platform/tsconfig.build.json" }, - { "path": "../../schema/tsconfig.build.json" } + { "path": "../../platform/tsconfig.build.json" } ], "compilerOptions": { "tsBuildInfoFile": ".tsbuildinfo/build.tsbuildinfo", diff --git a/packages/ai/openai/tsconfig.src.json b/packages/ai/openai/tsconfig.src.json index f570f4485b..354a8aec05 100644 --- a/packages/ai/openai/tsconfig.src.json +++ b/packages/ai/openai/tsconfig.src.json @@ -5,8 +5,7 @@ { "path": "../../effect" }, { "path": "../ai" }, { "path": "../../experimental" }, - { "path": "../../platform" }, - { "path": "../../schema" } + { "path": "../../platform" } ], "compilerOptions": { "tsBuildInfoFile": ".tsbuildinfo/src.tsbuildinfo", diff --git a/packages/ai/openai/tsconfig.test.json b/packages/ai/openai/tsconfig.test.json index 7af6a56bea..dba1449e95 100644 --- a/packages/ai/openai/tsconfig.test.json +++ b/packages/ai/openai/tsconfig.test.json @@ -7,7 +7,6 @@ { "path": "../ai" }, { "path": "../../experimental" }, { "path": "../../platform" }, - { "path": "../../schema" }, { "path": "../../vitest" } ], "compilerOptions": { diff --git a/packages/cli/docgen.json b/packages/cli/docgen.json index f0bf704bf2..dffc506f60 100644 --- a/packages/cli/docgen.json +++ b/packages/cli/docgen.json @@ -1,8 +1,6 @@ { "$schema": "../../node_modules/@effect/docgen/schema.json", - "exclude": [ - "src/internal/**/*.ts" - ], + "exclude": ["src/internal/**/*.ts"], "examplesCompilerOptions": { "noEmit": true, "strict": true, @@ -10,59 +8,26 @@ "moduleResolution": "Bundler", "module": "ES2022", "target": "ES2022", - "lib": [ - "ES2022", - "DOM" - ], + "lib": ["ES2022", "DOM"], "paths": { - "effect": [ - "../../../effect/src/index.js" - ], - "effect/*": [ - "../../../effect/src/*.js" - ], - "@effect/platform": [ - "../../../platform/src/index.js" - ], - "@effect/platform/*": [ - "../../../platform/src/*.js" - ], - "@effect/platform-node": [ - "../../../platform-node/src/index.js" - ], - "@effect/platform-node/*": [ - "../../../platform-node/src/*.js" - ], + "effect": ["../../../effect/src/index.js"], + "effect/*": ["../../../effect/src/*.js"], + "@effect/platform": ["../../../platform/src/index.js"], + "@effect/platform/*": ["../../../platform/src/*.js"], + "@effect/platform-node": ["../../../platform-node/src/index.js"], + "@effect/platform-node/*": ["../../../platform-node/src/*.js"], "@effect/platform-node-shared": [ "../../../platform-node-shared/src/index.js" ], "@effect/platform-node-shared/*": [ "../../../platform-node-shared/src/*.js" ], - "@effect/printer": [ - "../../../printer/src/index.js" - ], - "@effect/printer/*": [ - "../../../printer/src/*.js" - ], - "@effect/printer-ansi": [ - "../../../printer-ansi/src/index.js" - ], - "@effect/printer-ansi/*": [ - "../../../printer-ansi/src/*.js" - ], - "@effect/schema": [ - "../../../schema/src/index.js" - ], - "@effect/schema/*": [ - "../../../schema/src/*.js" - ], - "@effect/typeclass": [ - "../../../typeclass/src/index.js" - ], - "@effect/typeclass/*": [ - "../../../typeclass/src/*.js" - ] + "@effect/printer": ["../../../printer/src/index.js"], + "@effect/printer/*": ["../../../printer/src/*.js"], + "@effect/printer-ansi": ["../../../printer-ansi/src/index.js"], + "@effect/printer-ansi/*": ["../../../printer-ansi/src/*.js"], + "@effect/typeclass": ["../../../typeclass/src/index.js"], + "@effect/typeclass/*": ["../../../typeclass/src/*.js"] } } } diff --git a/packages/cli/examples/naval-fate/domain.ts b/packages/cli/examples/naval-fate/domain.ts index 27e914dc58..7cec03f100 100644 --- a/packages/cli/examples/naval-fate/domain.ts +++ b/packages/cli/examples/naval-fate/domain.ts @@ -1,5 +1,5 @@ -import * as Schema from "@effect/schema/Schema" import * as Data from "effect/Data" +import * as Schema from "effect/Schema" /** * An error that occurs when attempting to create a Naval Fate ship that already diff --git a/packages/cli/examples/naval-fate/store.ts b/packages/cli/examples/naval-fate/store.ts index b4348374d3..f043a9146f 100644 --- a/packages/cli/examples/naval-fate/store.ts +++ b/packages/cli/examples/naval-fate/store.ts @@ -1,11 +1,11 @@ import * as KeyValueStore from "@effect/platform/KeyValueStore" -import * as Schema from "@effect/schema/Schema" import * as Arr from "effect/Array" import * as Context from "effect/Context" import * as Effect from "effect/Effect" import { pipe } from "effect/Function" import * as Layer from "effect/Layer" import * as Option from "effect/Option" +import * as Schema from "effect/Schema" import { CoordinatesOccupiedError, Mine, Ship, ShipExistsError, ShipNotFoundError } from "./domain.js" /** diff --git a/packages/cli/package.json b/packages/cli/package.json index 7b39e6bf06..2743babbfe 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -44,7 +44,6 @@ "@effect/platform": "workspace:^", "@effect/printer": "workspace:^", "@effect/printer-ansi": "workspace:^", - "@effect/schema": "workspace:^", "effect": "workspace:^" }, "devDependencies": { @@ -52,7 +51,6 @@ "@effect/platform-node": "workspace:^", "@effect/printer": "workspace:^", "@effect/printer-ansi": "workspace:^", - "@effect/schema": "workspace:^", "@types/ini": "^4.1.1", "@types/node": "^20.14.10", "effect": "workspace:^" diff --git a/packages/cli/src/Args.ts b/packages/cli/src/Args.ts index dd2e7aca7a..28b88652b7 100644 --- a/packages/cli/src/Args.ts +++ b/packages/cli/src/Args.ts @@ -4,13 +4,13 @@ import type { FileSystem } from "@effect/platform/FileSystem" import type { Path } from "@effect/platform/Path" import type { QuitException, Terminal } from "@effect/platform/Terminal" -import type { Schema } from "@effect/schema/Schema" import type { NonEmptyArray } from "effect/Array" import type { Config } from "effect/Config" import type { Effect } from "effect/Effect" import type { Option } from "effect/Option" import type { Pipeable } from "effect/Pipeable" import type { Redacted } from "effect/Redacted" +import type { Schema } from "effect/Schema" import type { Secret } from "effect/Secret" import type { CliConfig } from "./CliConfig.js" import type { HelpDoc } from "./HelpDoc.js" diff --git a/packages/cli/src/Options.ts b/packages/cli/src/Options.ts index 4d68c3bdc5..68f296ef52 100644 --- a/packages/cli/src/Options.ts +++ b/packages/cli/src/Options.ts @@ -4,7 +4,6 @@ import type { FileSystem } from "@effect/platform/FileSystem" import type { Path } from "@effect/platform/Path" import type { QuitException, Terminal } from "@effect/platform/Terminal" -import type { Schema } from "@effect/schema/Schema" import type { NonEmptyArray } from "effect/Array" import type { Config } from "effect/Config" import type { Effect } from "effect/Effect" @@ -13,6 +12,7 @@ import type { HashMap } from "effect/HashMap" import type { Option } from "effect/Option" import type { Pipeable } from "effect/Pipeable" import type { Redacted } from "effect/Redacted" +import type { Schema } from "effect/Schema" import type { Secret } from "effect/Secret" import type { CliConfig } from "./CliConfig.js" import type { HelpDoc } from "./HelpDoc.js" diff --git a/packages/cli/src/internal/args.ts b/packages/cli/src/internal/args.ts index c7f404ee4f..ace998a793 100644 --- a/packages/cli/src/internal/args.ts +++ b/packages/cli/src/internal/args.ts @@ -1,8 +1,6 @@ import type * as FileSystem from "@effect/platform/FileSystem" import type * as Path from "@effect/platform/Path" import type * as Terminal from "@effect/platform/Terminal" -import * as Schema from "@effect/schema/Schema" -import * as TreeFormatter from "@effect/schema/TreeFormatter" import * as Arr from "effect/Array" import type * as Config from "effect/Config" import * as Console from "effect/Console" @@ -10,9 +8,11 @@ import * as Effect from "effect/Effect" import * as Either from "effect/Either" import { dual, pipe } from "effect/Function" import * as Option from "effect/Option" +import * as ParseResult from "effect/ParseResult" import { pipeArguments } from "effect/Pipeable" import type * as Redacted from "effect/Redacted" import * as Ref from "effect/Ref" +import type * as Schema from "effect/Schema" import type * as Secret from "effect/Secret" import type * as Args from "../Args.js" import type * as CliConfig from "../CliConfig.js" @@ -436,11 +436,11 @@ export const withSchema = dual< schema: Schema.Schema ) => Args.Args >(2, (self, schema) => { - const decode = Schema.decode(schema) + const decode = ParseResult.decode(schema) return mapEffect(self, (_) => Effect.mapError( decode(_ as any), - (error) => InternalHelpDoc.p(TreeFormatter.formatErrorSync(error)) + (issue) => InternalHelpDoc.p(ParseResult.TreeFormatter.formatIssueSync(issue)) )) }) diff --git a/packages/cli/src/internal/options.ts b/packages/cli/src/internal/options.ts index 3151ff4371..7e47a51ec1 100644 --- a/packages/cli/src/internal/options.ts +++ b/packages/cli/src/internal/options.ts @@ -1,8 +1,6 @@ import type * as FileSystem from "@effect/platform/FileSystem" import type * as Path from "@effect/platform/Path" import type * as Terminal from "@effect/platform/Terminal" -import * as Schema from "@effect/schema/Schema" -import * as TreeFormatter from "@effect/schema/TreeFormatter" import * as Arr from "effect/Array" import * as Config from "effect/Config" import * as Console from "effect/Console" @@ -12,10 +10,12 @@ import { dual, pipe } from "effect/Function" import * as HashMap from "effect/HashMap" import * as Option from "effect/Option" import * as Order from "effect/Order" +import * as ParseResult from "effect/ParseResult" import { pipeArguments } from "effect/Pipeable" import * as Predicate from "effect/Predicate" import type * as Redacted from "effect/Redacted" import * as Ref from "effect/Ref" +import type * as Schema from "effect/Schema" import type * as Secret from "effect/Secret" import type * as CliConfig from "../CliConfig.js" import type * as HelpDoc from "../HelpDoc.js" @@ -671,11 +671,12 @@ export const withSchema = dual< schema: Schema.Schema ) => Options.Options >(2, (self, schema) => { - const decode = Schema.decode(schema) + const decode = ParseResult.decode(schema) return mapEffect(self, (_) => Effect.mapError( decode(_ as any), - (error) => InternalValidationError.invalidValue(InternalHelpDoc.p(TreeFormatter.formatErrorSync(error))) + (issue) => + InternalValidationError.invalidValue(InternalHelpDoc.p(ParseResult.TreeFormatter.formatIssueSync(issue))) )) }) diff --git a/packages/cli/src/internal/primitive.ts b/packages/cli/src/internal/primitive.ts index ccd033eb2a..d3fb2f6308 100644 --- a/packages/cli/src/internal/primitive.ts +++ b/packages/cli/src/internal/primitive.ts @@ -1,11 +1,11 @@ import * as FileSystem from "@effect/platform/FileSystem" -import * as Schema from "@effect/schema/Schema" import * as Arr from "effect/Array" import * as Effect from "effect/Effect" import { dual, pipe } from "effect/Function" import * as Option from "effect/Option" import { pipeArguments } from "effect/Pipeable" import * as EffectRedacted from "effect/Redacted" +import * as Schema from "effect/Schema" import * as EffectSecret from "effect/Secret" import type * as CliConfig from "../CliConfig.js" import type * as HelpDoc from "../HelpDoc.js" diff --git a/packages/cli/src/internal/prompt/number.ts b/packages/cli/src/internal/prompt/number.ts index f2d69334bf..8726aaaad3 100644 --- a/packages/cli/src/internal/prompt/number.ts +++ b/packages/cli/src/internal/prompt/number.ts @@ -2,11 +2,11 @@ import * as Terminal from "@effect/platform/Terminal" import * as Ansi from "@effect/printer-ansi/Ansi" import * as Doc from "@effect/printer-ansi/AnsiDoc" import * as Optimize from "@effect/printer/Optimize" -import * as Schema from "@effect/schema/Schema" import * as Arr from "effect/Array" import * as Effect from "effect/Effect" import * as EffectNumber from "effect/Number" import * as Option from "effect/Option" +import * as Schema from "effect/Schema" import type * as Prompt from "../../Prompt.js" import * as InternalPrompt from "../prompt.js" import { Action } from "./action.js" diff --git a/packages/cli/test/Args.test.ts b/packages/cli/test/Args.test.ts index 9fdaf394d2..fd16393f60 100644 --- a/packages/cli/test/Args.test.ts +++ b/packages/cli/test/Args.test.ts @@ -4,10 +4,10 @@ import * as HelpDoc from "@effect/cli/HelpDoc" import * as ValidationError from "@effect/cli/ValidationError" import { FileSystem, Path } from "@effect/platform" import { NodeContext } from "@effect/platform-node" -import * as Schema from "@effect/schema/Schema" import * as Array from "effect/Array" import * as Effect from "effect/Effect" import * as Option from "effect/Option" +import * as Schema from "effect/Schema" import { describe, expect, it } from "vitest" const runEffect = ( diff --git a/packages/cli/test/Options.test.ts b/packages/cli/test/Options.test.ts index f493f2e91a..8402450dc4 100644 --- a/packages/cli/test/Options.test.ts +++ b/packages/cli/test/Options.test.ts @@ -5,7 +5,6 @@ import * as ValidationError from "@effect/cli/ValidationError" import * as NodeContext from "@effect/platform-node/NodeContext" import * as FileSystem from "@effect/platform/FileSystem" import * as Path from "@effect/platform/Path" -import * as Schema from "@effect/schema/Schema" import { BigDecimal } from "effect" import * as Array from "effect/Array" import * as Data from "effect/Data" @@ -14,6 +13,7 @@ import * as Either from "effect/Either" import { identity } from "effect/Function" import * as HashMap from "effect/HashMap" import * as Option from "effect/Option" +import * as Schema from "effect/Schema" import { assert, describe, expect, it } from "vitest" const firstName = Options.text("firstName").pipe(Options.withAlias("f")) diff --git a/packages/cli/tsconfig.build.json b/packages/cli/tsconfig.build.json index fadf00be97..1a36eb89df 100644 --- a/packages/cli/tsconfig.build.json +++ b/packages/cli/tsconfig.build.json @@ -2,11 +2,10 @@ "extends": "./tsconfig.src.json", "references": [ { "path": "../effect/tsconfig.build.json" }, - { "path": "../schema/tsconfig.build.json" }, { "path": "../printer/tsconfig.build.json" }, { "path": "../printer-ansi/tsconfig.build.json" }, { "path": "../platform/tsconfig.build.json" }, - { "path": "../platform-node/tsconfig.build.json" }, + { "path": "../platform-node/tsconfig.build.json" } ], "compilerOptions": { "types": ["node"], diff --git a/packages/cli/tsconfig.examples.json b/packages/cli/tsconfig.examples.json index c8ed2bd93a..b244aaebd1 100644 --- a/packages/cli/tsconfig.examples.json +++ b/packages/cli/tsconfig.examples.json @@ -4,11 +4,10 @@ "references": [ { "path": "tsconfig.src.json" }, { "path": "../effect" }, - { "path": "../schema" }, { "path": "../printer" }, { "path": "../printer-ansi" }, { "path": "../platform" }, - { "path": "../platform-node" }, + { "path": "../platform-node" } ], "compilerOptions": { "types": ["node"], diff --git a/packages/cli/tsconfig.src.json b/packages/cli/tsconfig.src.json index 2115a3effb..d6e3c3ae5f 100644 --- a/packages/cli/tsconfig.src.json +++ b/packages/cli/tsconfig.src.json @@ -3,11 +3,10 @@ "include": ["src"], "references": [ { "path": "../effect" }, - { "path": "../schema" }, { "path": "../printer" }, { "path": "../printer-ansi" }, { "path": "../platform" }, - { "path": "../platform-node" }, + { "path": "../platform-node" } ], "compilerOptions": { "types": ["node"], diff --git a/packages/cli/tsconfig.test.json b/packages/cli/tsconfig.test.json index d751ab5910..b0f22e2d30 100644 --- a/packages/cli/tsconfig.test.json +++ b/packages/cli/tsconfig.test.json @@ -4,11 +4,10 @@ "references": [ { "path": "tsconfig.src.json" }, { "path": "../effect" }, - { "path": "../schema" }, { "path": "../printer" }, { "path": "../printer-ansi" }, { "path": "../platform" }, - { "path": "../platform-node" }, + { "path": "../platform-node" } ], "compilerOptions": { "types": ["node"], diff --git a/packages/cluster-browser/package.json b/packages/cluster-browser/package.json index 3c448a1c64..19020b5fd1 100644 --- a/packages/cluster-browser/package.json +++ b/packages/cluster-browser/package.json @@ -27,12 +27,10 @@ }, "peerDependencies": { "@effect/rpc": "workspace:^", - "@effect/schema": "workspace:^", "effect": "workspace:^" }, "devDependencies": { "@effect/rpc": "workspace:^", - "@effect/schema": "workspace:^", "effect": "workspace:^" } } diff --git a/packages/cluster-browser/src/RpcBroadcastChannel.ts b/packages/cluster-browser/src/RpcBroadcastChannel.ts index 31b89f091a..6fa78d3ae8 100644 --- a/packages/cluster-browser/src/RpcBroadcastChannel.ts +++ b/packages/cluster-browser/src/RpcBroadcastChannel.ts @@ -4,12 +4,11 @@ import type * as Rpc from "@effect/rpc/Rpc" import * as RpcResolver from "@effect/rpc/RpcResolver" import * as RpcRouter from "@effect/rpc/RpcRouter" -import * as Schema from "@effect/schema/Schema" -import type * as Serializable from "@effect/schema/Serializable" import * as Effect from "effect/Effect" import { pipe } from "effect/Function" import * as Queue from "effect/Queue" import type * as RequestResolver from "effect/RequestResolver" +import * as Schema from "effect/Schema" import * as Stream from "effect/Stream" class ClientRequest extends Schema.TaggedClass()("ClientRequest", { @@ -73,7 +72,7 @@ export const make = >( channelId: string ): RequestResolver.RequestResolver< Rpc.Request>, - Serializable.SerializableWithResult.Context> + Schema.SerializableWithResult.Context> > => RpcResolver.make((requests) => { return Effect.gen(function*($) { diff --git a/packages/cluster-browser/tsconfig.build.json b/packages/cluster-browser/tsconfig.build.json index 36692e627e..f0ff2e3e55 100644 --- a/packages/cluster-browser/tsconfig.build.json +++ b/packages/cluster-browser/tsconfig.build.json @@ -2,8 +2,7 @@ "extends": "./tsconfig.src.json", "references": [ { "path": "../effect/tsconfig.build.json" }, - { "path": "../rpc/tsconfig.build.json" }, - { "path": "../schema/tsconfig.build.json" } + { "path": "../rpc/tsconfig.build.json" } ], "compilerOptions": { "tsBuildInfoFile": ".tsbuildinfo/build.tsbuildinfo", diff --git a/packages/cluster-browser/tsconfig.src.json b/packages/cluster-browser/tsconfig.src.json index 9d467a9551..2d72ee5c02 100644 --- a/packages/cluster-browser/tsconfig.src.json +++ b/packages/cluster-browser/tsconfig.src.json @@ -1,11 +1,7 @@ { "extends": "../../tsconfig.base.json", "include": ["src"], - "references": [ - { "path": "../effect" }, - { "path": "../rpc" }, - { "path": "../schema" } - ], + "references": [{ "path": "../effect" }, { "path": "../rpc" }], "compilerOptions": { "tsBuildInfoFile": ".tsbuildinfo/src.tsbuildinfo", "rootDir": "src", diff --git a/packages/cluster-node/examples/sample-common.ts b/packages/cluster-node/examples/sample-common.ts index 828fda62ca..1b2928f94b 100644 --- a/packages/cluster-node/examples/sample-common.ts +++ b/packages/cluster-node/examples/sample-common.ts @@ -1,6 +1,6 @@ import * as Message from "@effect/cluster/Message" import * as RecipientType from "@effect/cluster/RecipientType" -import * as Schema from "@effect/schema/Schema" +import * as Schema from "effect/Schema" export class GetCurrent extends Message.TaggedMessage()("GetCurrent", Schema.Never, Schema.Number, { messageId: Schema.String diff --git a/packages/cluster-node/package.json b/packages/cluster-node/package.json index 09335637a6..1a8c6364e1 100644 --- a/packages/cluster-node/package.json +++ b/packages/cluster-node/package.json @@ -28,7 +28,6 @@ "peerDependencies": { "@effect/cluster": "workspace:^", "@effect/rpc": "workspace:^", - "@effect/schema": "workspace:^", "effect": "workspace:^" }, "devDependencies": { @@ -36,7 +35,6 @@ "@effect/platform-node": "workspace:^", "@effect/rpc": "workspace:^", "@effect/rpc-http": "workspace:^", - "@effect/schema": "workspace:^", "@types/node": "^20.14.10", "effect": "workspace:^" } diff --git a/packages/cluster-node/src/ShardManagerProtocol.ts b/packages/cluster-node/src/ShardManagerProtocol.ts index f5d5d8b8ac..d48edf8846 100644 --- a/packages/cluster-node/src/ShardManagerProtocol.ts +++ b/packages/cluster-node/src/ShardManagerProtocol.ts @@ -4,7 +4,7 @@ import * as Pod from "@effect/cluster/Pod" import * as PodAddress from "@effect/cluster/PodAddress" import * as ShardId from "@effect/cluster/ShardId" -import * as Schema from "@effect/schema/Schema" +import * as Schema from "effect/Schema" /** * @since 1.0.0 diff --git a/packages/cluster-node/src/ShardingProtocol.ts b/packages/cluster-node/src/ShardingProtocol.ts index 684484f78d..8ce4de0c49 100644 --- a/packages/cluster-node/src/ShardingProtocol.ts +++ b/packages/cluster-node/src/ShardingProtocol.ts @@ -6,7 +6,7 @@ import * as SerializedEnvelope from "@effect/cluster/SerializedEnvelope" import * as SerializedMessage from "@effect/cluster/SerializedMessage" import * as ShardId from "@effect/cluster/ShardId" import * as ShardingException from "@effect/cluster/ShardingException" -import * as Schema from "@effect/schema/Schema" +import * as Schema from "effect/Schema" /** * @since 1.0.0 diff --git a/packages/cluster-node/src/StorageFile.ts b/packages/cluster-node/src/StorageFile.ts index 6e9e3fa03e..67ab625799 100644 --- a/packages/cluster-node/src/StorageFile.ts +++ b/packages/cluster-node/src/StorageFile.ts @@ -6,14 +6,14 @@ import * as PodAddress from "@effect/cluster/PodAddress" import * as ShardId from "@effect/cluster/ShardId" import * as ShardingException from "@effect/cluster/ShardingException" import * as Storage from "@effect/cluster/Storage" -import * as Schema from "@effect/schema/Schema" -import * as TreeFormatter from "@effect/schema/TreeFormatter" import * as Effect from "effect/Effect" import { pipe } from "effect/Function" import * as HashMap from "effect/HashMap" import * as Layer from "effect/Layer" import type * as Option from "effect/Option" +import * as ParseResult from "effect/ParseResult" import * as Queue from "effect/Queue" +import * as Schema from "effect/Schema" import * as Stream from "effect/Stream" import * as fs from "node:fs" @@ -21,8 +21,10 @@ import * as fs from "node:fs" export function jsonStringify(value: A, schema: Schema.Schema) { return pipe( value, - Schema.encode(schema), - Effect.mapError((e) => new ShardingException.SerializationException({ error: TreeFormatter.formatError(e) })), + ParseResult.encode(schema), + Effect.mapError((issue) => + new ShardingException.SerializationException({ error: ParseResult.TreeFormatter.formatIssue(issue) }) + ), Effect.map((_) => JSON.stringify(_)) ) } @@ -31,8 +33,10 @@ export function jsonStringify(value: A, schema: Schema.Schema) { export function jsonParse(value: string, schema: Schema.Schema) { return pipe( Effect.sync(() => JSON.parse(value)), - Effect.flatMap(Schema.decode(schema)), - Effect.mapError((e) => new ShardingException.SerializationException({ error: TreeFormatter.formatError(e) })) + Effect.flatMap(ParseResult.decode(schema)), + Effect.mapError((issue) => + new ShardingException.SerializationException({ error: ParseResult.TreeFormatter.formatIssue(issue) }) + ) ) } diff --git a/packages/cluster-node/tsconfig.build.json b/packages/cluster-node/tsconfig.build.json index 8f81d8e387..8b1286c662 100644 --- a/packages/cluster-node/tsconfig.build.json +++ b/packages/cluster-node/tsconfig.build.json @@ -3,8 +3,7 @@ "references": [ { "path": "../effect/tsconfig.build.json" }, { "path": "../cluster/tsconfig.build.json" }, - { "path": "../rpc/tsconfig.build.json" }, - { "path": "../schema/tsconfig.build.json" } + { "path": "../rpc/tsconfig.build.json" } ], "compilerOptions": { "types": ["node"], diff --git a/packages/cluster-node/tsconfig.src.json b/packages/cluster-node/tsconfig.src.json index 9a899d00a6..a0dbf713b3 100644 --- a/packages/cluster-node/tsconfig.src.json +++ b/packages/cluster-node/tsconfig.src.json @@ -1,13 +1,10 @@ { "extends": "../../tsconfig.base.json", - "include": [ - "src" - ], + "include": ["src"], "references": [ { "path": "../effect" }, { "path": "../cluster" }, - { "path": "../rpc" }, - { "path": "../schema" } + { "path": "../rpc" } ], "compilerOptions": { "types": ["node"], diff --git a/packages/cluster-workflow/package.json b/packages/cluster-workflow/package.json index 6db76c71d6..0e59c4e373 100644 --- a/packages/cluster-workflow/package.json +++ b/packages/cluster-workflow/package.json @@ -27,13 +27,11 @@ }, "peerDependencies": { "@effect/cluster": "workspace:^", - "@effect/schema": "workspace:^", "@effect/sql": "workspace:^", "effect": "workspace:^" }, "devDependencies": { "@effect/cluster": "workspace:^", - "@effect/schema": "workspace:^", "@effect/platform": "workspace:^", "@effect/platform-node": "workspace:^", "@effect/sql": "workspace:^", diff --git a/packages/cluster-workflow/src/Activity.ts b/packages/cluster-workflow/src/Activity.ts index d40b2a4745..229da333ca 100644 --- a/packages/cluster-workflow/src/Activity.ts +++ b/packages/cluster-workflow/src/Activity.ts @@ -1,11 +1,11 @@ /** * @since 1.0.0 */ -import type * as Schema from "@effect/schema/Schema" import * as Effect from "effect/Effect" import type * as Exit from "effect/Exit" import { pipe } from "effect/Function" import * as Option from "effect/Option" +import type * as Schema from "effect/Schema" import * as Stream from "effect/Stream" import * as ActivityContext from "./ActivityContext.js" import * as DurableExecutionEvent from "./DurableExecutionEvent.js" diff --git a/packages/cluster-workflow/src/DurableExecutionEvent.ts b/packages/cluster-workflow/src/DurableExecutionEvent.ts index 7de0b6f2e6..09e816cc27 100644 --- a/packages/cluster-workflow/src/DurableExecutionEvent.ts +++ b/packages/cluster-workflow/src/DurableExecutionEvent.ts @@ -1,8 +1,8 @@ /** * @since 1.0.0 */ -import * as Schema from "@effect/schema/Schema" import type * as Exit from "effect/Exit" +import * as Schema from "effect/Schema" const ATTEMPTED = "@effect/cluster-workflow/DurableExecutionEvent/Attempted" diff --git a/packages/cluster-workflow/src/DurableExecutionJournal.ts b/packages/cluster-workflow/src/DurableExecutionJournal.ts index 7dd5a631f0..d10e360214 100644 --- a/packages/cluster-workflow/src/DurableExecutionJournal.ts +++ b/packages/cluster-workflow/src/DurableExecutionJournal.ts @@ -2,11 +2,11 @@ * @since 1.0.0 */ import * as DurableExecutionEvent from "@effect/cluster-workflow/DurableExecutionEvent" -import * as Schema from "@effect/schema/Schema" import * as SqlClient from "@effect/sql/SqlClient" import * as Context from "effect/Context" import * as Effect from "effect/Effect" import * as Layer from "effect/Layer" +import * as Schema from "effect/Schema" import * as Stream from "effect/Stream" const SymbolKey = "@effect/cluster-workflow/DurableExecutionJournal" diff --git a/packages/cluster-workflow/src/Workflow.ts b/packages/cluster-workflow/src/Workflow.ts index 8e76c670c3..c451a2b88d 100644 --- a/packages/cluster-workflow/src/Workflow.ts +++ b/packages/cluster-workflow/src/Workflow.ts @@ -2,13 +2,13 @@ * @since 1.0.0 */ import type * as Message from "@effect/cluster/Message" -import * as Schema from "@effect/schema/Schema" import * as Array from "effect/Array" import * as Clock from "effect/Clock" import * as Duration from "effect/Duration" import * as Effect from "effect/Effect" import { pipe } from "effect/Function" import * as Option from "effect/Option" +import * as Schema from "effect/Schema" import * as Activity from "./Activity.js" import * as WorkflowContext from "./WorkflowContext.js" diff --git a/packages/cluster-workflow/test/DurableExecutionJournal.test.ts b/packages/cluster-workflow/test/DurableExecutionJournal.test.ts index b3c263b1f0..8fbcd8cfad 100644 --- a/packages/cluster-workflow/test/DurableExecutionJournal.test.ts +++ b/packages/cluster-workflow/test/DurableExecutionJournal.test.ts @@ -2,12 +2,12 @@ import * as DurableExecutionEvent from "@effect/cluster-workflow/DurableExecutio import * as DurableExecutionJournal from "@effect/cluster-workflow/DurableExecutionJournal" import * as NodeFileSystem from "@effect/platform-node/NodeFileSystem" import * as FileSystem from "@effect/platform/FileSystem" -import * as Schema from "@effect/schema/Schema" import * as Sqlite from "@effect/sql-sqlite-node/SqliteClient" import * as SqlClient from "@effect/sql/SqlClient" import * as Chunk from "effect/Chunk" import * as Effect from "effect/Effect" import * as Layer from "effect/Layer" +import * as Schema from "effect/Schema" import * as Stream from "effect/Stream" import { describe, expect, it } from "vitest" diff --git a/packages/cluster-workflow/test/Workflow.test.ts b/packages/cluster-workflow/test/Workflow.test.ts index 31102c9a38..7c018cc577 100644 --- a/packages/cluster-workflow/test/Workflow.test.ts +++ b/packages/cluster-workflow/test/Workflow.test.ts @@ -8,7 +8,6 @@ import * as utils from "@effect/cluster-workflow/test/utils" import * as Workflow from "@effect/cluster-workflow/Workflow" import * as WorkflowEngine from "@effect/cluster-workflow/WorkflowEngine" import * as Message from "@effect/cluster/Message" -import * as Schema from "@effect/schema/Schema" import * as Chunk from "effect/Chunk" import * as Deferred from "effect/Deferred" import * as Effect from "effect/Effect" @@ -17,6 +16,7 @@ import { pipe } from "effect/Function" import * as Logger from "effect/Logger" import * as LogLevel from "effect/LogLevel" import * as Ref from "effect/Ref" +import * as Schema from "effect/Schema" import * as Stream from "effect/Stream" import { describe, expect, it } from "vitest" diff --git a/packages/cluster-workflow/test/utils.ts b/packages/cluster-workflow/test/utils.ts index 0efe645720..4c2183c0b2 100644 --- a/packages/cluster-workflow/test/utils.ts +++ b/packages/cluster-workflow/test/utils.ts @@ -1,8 +1,8 @@ import * as Activity from "@effect/cluster-workflow/Activity" -import type * as Schema from "@effect/schema/Schema" import * as Effect from "effect/Effect" import type * as Exit from "effect/Exit" import { pipe } from "effect/Function" +import type * as Schema from "effect/Schema" import { vi } from "vitest" import type { Mock } from "vitest" diff --git a/packages/cluster-workflow/tsconfig.build.json b/packages/cluster-workflow/tsconfig.build.json index 39e0efb897..8f6e6ec87d 100644 --- a/packages/cluster-workflow/tsconfig.build.json +++ b/packages/cluster-workflow/tsconfig.build.json @@ -2,8 +2,7 @@ "extends": "./tsconfig.src.json", "references": [ { "path": "../effect/tsconfig.build.json" }, - { "path": "../cluster/tsconfig.build.json" }, - { "path": "../schema/tsconfig.build.json" } + { "path": "../cluster/tsconfig.build.json" } ], "compilerOptions": { "tsBuildInfoFile": ".tsbuildinfo/build.tsbuildinfo", diff --git a/packages/cluster-workflow/tsconfig.src.json b/packages/cluster-workflow/tsconfig.src.json index 5f417a08f2..bfe4147871 100644 --- a/packages/cluster-workflow/tsconfig.src.json +++ b/packages/cluster-workflow/tsconfig.src.json @@ -1,13 +1,7 @@ { "extends": "../../tsconfig.base.json", - "include": [ - "src" - ], - "references": [ - { "path": "../effect" }, - { "path": "../cluster" }, - { "path": "../schema" } - ], + "include": ["src"], + "references": [{ "path": "../effect" }, { "path": "../cluster" }], "compilerOptions": { "tsBuildInfoFile": ".tsbuildinfo/src.tsbuildinfo", "rootDir": "src", diff --git a/packages/cluster/package.json b/packages/cluster/package.json index 84bd3f0777..43f88368d1 100644 --- a/packages/cluster/package.json +++ b/packages/cluster/package.json @@ -26,14 +26,12 @@ "coverage": "vitest --coverage" }, "peerDependencies": { - "@effect/schema": "workspace:^", "@effect/sql": "workspace:^", "effect": "workspace:^" }, "devDependencies": { "@effect/platform": "workspace:^", "@effect/platform-node": "workspace:^", - "@effect/schema": "workspace:^", "@effect/sql": "workspace:^", "@effect/sql-sqlite-node": "workspace:^", "effect": "workspace:^" diff --git a/packages/cluster/src/Message.ts b/packages/cluster/src/Message.ts index ad67e73162..8767e9d539 100644 --- a/packages/cluster/src/Message.ts +++ b/packages/cluster/src/Message.ts @@ -1,10 +1,9 @@ /** * @since 1.0.0 */ -import type * as Schema from "@effect/schema/Schema" -import type * as Serializable from "@effect/schema/Serializable" import type * as Exit_ from "effect/Exit" import type * as PrimaryKey from "effect/PrimaryKey" +import type * as Schema from "effect/Schema" import type * as Types from "effect/Types" import * as internal from "./internal/message.js" @@ -16,7 +15,7 @@ import * as internal from "./internal/message.js" * @category models */ export interface Message - extends Serializable.SerializableWithResult, PrimaryKey.PrimaryKey + extends Schema.SerializableWithResult, PrimaryKey.PrimaryKey {} /** @@ -70,8 +69,7 @@ export namespace Message { * @since 1.0.0 * @category utils */ - export type Exit = S extends Serializable.WithResult ? - Exit_.Exit + export type Exit = S extends Schema.WithResult ? Exit_.Exit : never } diff --git a/packages/cluster/src/MessageState.ts b/packages/cluster/src/MessageState.ts index 0f0393f629..4d4c16be69 100644 --- a/packages/cluster/src/MessageState.ts +++ b/packages/cluster/src/MessageState.ts @@ -1,8 +1,8 @@ /** * @since 1.0.0 */ -import type * as Schema from "@effect/schema/Schema" import type * as Effect from "effect/Effect" +import type * as Schema from "effect/Schema" import * as internal from "./internal/messageState.js" /** diff --git a/packages/cluster/src/Pod.ts b/packages/cluster/src/Pod.ts index a03146c467..8833b52230 100644 --- a/packages/cluster/src/Pod.ts +++ b/packages/cluster/src/Pod.ts @@ -1,7 +1,7 @@ /** * @since 1.0.0 */ -import * as Schema from "@effect/schema/Schema" +import * as Schema from "effect/Schema" import { TypeIdSchema } from "./internal/utils.js" import * as PodAddress from "./PodAddress.js" diff --git a/packages/cluster/src/PodAddress.ts b/packages/cluster/src/PodAddress.ts index ce49383848..69929b7bf6 100644 --- a/packages/cluster/src/PodAddress.ts +++ b/packages/cluster/src/PodAddress.ts @@ -1,7 +1,7 @@ /** * @since 1.0.0 */ -import * as Schema from "@effect/schema/Schema" +import * as Schema from "effect/Schema" import { TypeIdSchema } from "./internal/utils.js" /** @internal */ diff --git a/packages/cluster/src/PoisonPill.ts b/packages/cluster/src/PoisonPill.ts index d87b71c5a7..81d99cf18a 100644 --- a/packages/cluster/src/PoisonPill.ts +++ b/packages/cluster/src/PoisonPill.ts @@ -1,10 +1,10 @@ /** * @since 1.0.0 */ -import * as Schema from "@effect/schema/Schema" import * as Effect from "effect/Effect" import { pipe } from "effect/Function" import * as Queue from "effect/Queue" +import * as Schema from "effect/Schema" import { TypeIdSchema } from "./internal/utils.js" /** @internal */ diff --git a/packages/cluster/src/RecipientAddress.ts b/packages/cluster/src/RecipientAddress.ts index a5806489ca..36ac78f2e3 100644 --- a/packages/cluster/src/RecipientAddress.ts +++ b/packages/cluster/src/RecipientAddress.ts @@ -1,9 +1,9 @@ /** * @since 1.0.0 */ -import * as Schema from "@effect/schema/Schema" import * as Equal from "effect/Equal" import * as Hash from "effect/Hash" +import * as Schema from "effect/Schema" import { TypeIdSchema } from "./internal/utils.js" const RecipientAddressSymbolKey = "@effect/cluster/RecipientAddress" diff --git a/packages/cluster/src/RecipientType.ts b/packages/cluster/src/RecipientType.ts index cb0c48b443..2b20ac38aa 100644 --- a/packages/cluster/src/RecipientType.ts +++ b/packages/cluster/src/RecipientType.ts @@ -1,10 +1,10 @@ /** * @since 1.0.0 */ -import type * as Schema from "@effect/schema/Schema" import * as Data from "effect/Data" import * as Equal from "effect/Equal" import * as Hash from "effect/Hash" +import type * as Schema from "effect/Schema" import type * as Message from "./Message.js" import * as ShardId from "./ShardId.js" diff --git a/packages/cluster/src/Serialization.ts b/packages/cluster/src/Serialization.ts index 7285a6dbbf..4250f7e31e 100644 --- a/packages/cluster/src/Serialization.ts +++ b/packages/cluster/src/Serialization.ts @@ -1,10 +1,10 @@ /** * @since 1.0.0 */ -import type * as Schema from "@effect/schema/Schema" import type * as Context from "effect/Context" import type * as Effect from "effect/Effect" import type * as Layer from "effect/Layer" +import type * as Schema from "effect/Schema" import * as internal from "./internal/serialization.js" import type * as SerializedMessage from "./SerializedMessage.js" import type * as ShardingException from "./ShardingException.js" diff --git a/packages/cluster/src/SerializedEnvelope.ts b/packages/cluster/src/SerializedEnvelope.ts index 0e3dc294e5..41c605ee36 100644 --- a/packages/cluster/src/SerializedEnvelope.ts +++ b/packages/cluster/src/SerializedEnvelope.ts @@ -1,9 +1,8 @@ /** * @since 1.0.0 */ -import * as Schema from "@effect/schema/Schema" -import * as Serializable from "@effect/schema/Serializable" import * as PrimaryKey from "effect/PrimaryKey" +import * as Schema from "effect/Schema" import { TypeIdSchema } from "./internal/utils.js" import * as RecipientAddress from "./RecipientAddress.js" import * as SerializedMessage from "./SerializedMessage.js" @@ -41,10 +40,10 @@ export class SerializedEnvelope extends Schema.Class(Seriali messageId: Schema.String, body: SerializedMessage.schema }) { - get [Serializable.symbol]() { + get [Schema.symbolSerializable]() { return this.constructor } - get [Serializable.symbolResult]() { + get [Schema.symbolWithResult]() { return { Success: Schema.Void, Failure: Schema.Never } } get [PrimaryKey.symbol]() { diff --git a/packages/cluster/src/SerializedMessage.ts b/packages/cluster/src/SerializedMessage.ts index 3dcedd83c1..c7e3d797e6 100644 --- a/packages/cluster/src/SerializedMessage.ts +++ b/packages/cluster/src/SerializedMessage.ts @@ -1,7 +1,7 @@ /** * @since 1.0.0 */ -import * as Schema from "@effect/schema/Schema" +import * as Schema from "effect/Schema" import { TypeIdSchema } from "./internal/utils.js" /** @internal */ diff --git a/packages/cluster/src/ShardId.ts b/packages/cluster/src/ShardId.ts index baeb49c625..25902a2866 100644 --- a/packages/cluster/src/ShardId.ts +++ b/packages/cluster/src/ShardId.ts @@ -1,7 +1,7 @@ /** * @since 1.0.0 */ -import * as Schema from "@effect/schema/Schema" +import * as Schema from "effect/Schema" import { TypeIdSchema } from "./internal/utils.js" /** @internal */ diff --git a/packages/cluster/src/ShardingException.ts b/packages/cluster/src/ShardingException.ts index 7f23d95032..656679f06d 100644 --- a/packages/cluster/src/ShardingException.ts +++ b/packages/cluster/src/ShardingException.ts @@ -1,7 +1,7 @@ /** * @since 1.0.0 */ -import * as Schema from "@effect/schema/Schema" +import * as Schema from "effect/Schema" import * as PodAddress from "./PodAddress.js" import * as RecipientAddress from "./RecipientAddress.js" diff --git a/packages/cluster/src/internal/atLeastOnceStorage.ts b/packages/cluster/src/internal/atLeastOnceStorage.ts index f0c29688af..eecef554ad 100644 --- a/packages/cluster/src/internal/atLeastOnceStorage.ts +++ b/packages/cluster/src/internal/atLeastOnceStorage.ts @@ -1,4 +1,3 @@ -import * as Schema from "@effect/schema/Schema" import * as SqlClient from "@effect/sql/SqlClient" import type * as SqlError from "@effect/sql/SqlError" import * as SqlResolver from "@effect/sql/SqlResolver" @@ -6,6 +5,7 @@ import * as Context from "effect/Context" import * as Effect from "effect/Effect" import * as Layer from "effect/Layer" import * as PrimaryKey from "effect/PrimaryKey" +import * as Schema from "effect/Schema" import * as Stream from "effect/Stream" import type * as AtLeastOnceStorage from "../AtLeastOnceStorage.js" import * as RecipientAddress from "../RecipientAddress.js" diff --git a/packages/cluster/src/internal/message.ts b/packages/cluster/src/internal/message.ts index d099076d33..f662f72e08 100644 --- a/packages/cluster/src/internal/message.ts +++ b/packages/cluster/src/internal/message.ts @@ -1,6 +1,5 @@ -import * as Schema from "@effect/schema/Schema" -import * as Serializable from "@effect/schema/Serializable" import * as PrimaryKey from "effect/PrimaryKey" +import * as Schema from "effect/Schema" import type * as Types from "effect/Types" import type * as Message from "../Message.js" @@ -8,7 +7,7 @@ import type * as Message from "../Message.js" export function isMessageWithResult(value: unknown): value is Message.Message { return ( typeof value === "object" && value !== null && - Serializable.symbolResult in value + Schema.symbolWithResult in value ) } @@ -16,21 +15,21 @@ export function isMessageWithResult(value: unknown): value is Message.Message( message: A ): Schema.Schema, unknown> { - return Serializable.exitSchema(message as any) as any + return Schema.exitSchema(message as any) as any } /** @internal */ export function successSchema( message: A ): Schema.Schema, unknown> { - return Serializable.successSchema(message as any) as any + return Schema.successSchema(message as any) as any } /** @internal */ export function failureSchema( message: A ): Schema.Schema, unknown> { - return Serializable.failureSchema(message as any) as any + return Schema.failureSchema(message as any) as any } /** diff --git a/packages/cluster/src/internal/messageState.ts b/packages/cluster/src/internal/messageState.ts index 811131386e..0f04f112e1 100644 --- a/packages/cluster/src/internal/messageState.ts +++ b/packages/cluster/src/internal/messageState.ts @@ -1,6 +1,6 @@ -import * as Schema from "@effect/schema/Schema" import * as Effect from "effect/Effect" import { pipe } from "effect/Function" +import * as Schema from "effect/Schema" import type * as MessageState from "../MessageState.js" /** @internal */ diff --git a/packages/cluster/src/internal/serialization.ts b/packages/cluster/src/internal/serialization.ts index 6ff8dc9851..c031a1e957 100644 --- a/packages/cluster/src/internal/serialization.ts +++ b/packages/cluster/src/internal/serialization.ts @@ -1,9 +1,9 @@ -import * as Schema from "@effect/schema/Schema" -import * as TreeFormatter from "@effect/schema/TreeFormatter" import * as Context from "effect/Context" import * as Effect from "effect/Effect" import { pipe } from "effect/Function" import * as Layer from "effect/Layer" +import * as ParseResult from "effect/ParseResult" +import type * as Schema from "effect/Schema" import type * as Serialization from "../Serialization.js" import * as SerializedMessage from "../SerializedMessage.js" import * as ShardingException from "../ShardingException.js" @@ -23,8 +23,10 @@ export const serializationTag = Context.GenericTag( function jsonStringify(value: A, schema: Schema.Schema) { return pipe( value, - Schema.encode(schema), - Effect.mapError((e) => new ShardingException.SerializationException({ error: TreeFormatter.formatError(e) })), + ParseResult.encode(schema), + Effect.mapError((issue) => + new ShardingException.SerializationException({ error: ParseResult.TreeFormatter.formatIssue(issue) }) + ), Effect.map((_) => JSON.stringify(_)) ) } @@ -33,8 +35,10 @@ function jsonStringify(value: A, schema: Schema.Schema) { function jsonParse(value: string, schema: Schema.Schema) { return pipe( Effect.sync(() => JSON.parse(value)), - Effect.flatMap(Schema.decode(schema)), - Effect.mapError((e) => new ShardingException.SerializationException({ error: TreeFormatter.formatError(e) })) + Effect.flatMap(ParseResult.decode(schema)), + Effect.mapError((issue) => + new ShardingException.SerializationException({ error: ParseResult.TreeFormatter.formatIssue(issue) }) + ) ) } diff --git a/packages/cluster/src/internal/utils.ts b/packages/cluster/src/internal/utils.ts index f604f3cd56..b7d632da8b 100644 --- a/packages/cluster/src/internal/utils.ts +++ b/packages/cluster/src/internal/utils.ts @@ -1,7 +1,7 @@ -import * as Schema from "@effect/schema/Schema" import * as HashMap from "effect/HashMap" import * as HashSet from "effect/HashSet" import * as Option from "effect/Option" +import * as Schema from "effect/Schema" /** @internal */ export function NotAMessageWithReplierDefect(message: unknown): unknown { diff --git a/packages/cluster/test/AtLeastOnce.test.ts b/packages/cluster/test/AtLeastOnce.test.ts index 404b5fb2d5..72daa85465 100644 --- a/packages/cluster/test/AtLeastOnce.test.ts +++ b/packages/cluster/test/AtLeastOnce.test.ts @@ -12,7 +12,6 @@ import * as ShardManagerClient from "@effect/cluster/ShardManagerClient" import * as Storage from "@effect/cluster/Storage" import * as NodeFileSystem from "@effect/platform-node/NodeFileSystem" import * as FileSystem from "@effect/platform/FileSystem" -import * as Schema from "@effect/schema/Schema" import * as Sqlite from "@effect/sql-sqlite-node/SqliteClient" import * as SqlClient from "@effect/sql/SqlClient" import * as Duration from "effect/Duration" @@ -21,6 +20,7 @@ import * as Exit from "effect/Exit" import { pipe } from "effect/Function" import * as Layer from "effect/Layer" import * as PrimaryKey from "effect/PrimaryKey" +import * as Schema from "effect/Schema" import { describe, expect, it } from "vitest" class SampleMessage extends Schema.TaggedRequest()( diff --git a/packages/cluster/test/RecipientBehaviour.test.ts b/packages/cluster/test/RecipientBehaviour.test.ts index b425431d9a..b34a0ea505 100644 --- a/packages/cluster/test/RecipientBehaviour.test.ts +++ b/packages/cluster/test/RecipientBehaviour.test.ts @@ -5,7 +5,6 @@ import * as RecipientBehaviour from "@effect/cluster/RecipientBehaviour" import * as RecipientBehaviourContext from "@effect/cluster/RecipientBehaviourContext" import * as RecipientType from "@effect/cluster/RecipientType" import * as ShardId from "@effect/cluster/ShardId" -import * as Schema from "@effect/schema/Schema" import * as Deferred from "effect/Deferred" import * as Effect from "effect/Effect" import * as Exit from "effect/Exit" @@ -14,6 +13,7 @@ import { pipe } from "effect/Function" import * as Logger from "effect/Logger" import * as LogLevel from "effect/LogLevel" import * as Queue from "effect/Queue" +import * as Schema from "effect/Schema" import * as Scope from "effect/Scope" import { describe, expect, it } from "vitest" diff --git a/packages/cluster/test/RecipientType.test.ts b/packages/cluster/test/RecipientType.test.ts index 71a522b411..59b11d38a5 100644 --- a/packages/cluster/test/RecipientType.test.ts +++ b/packages/cluster/test/RecipientType.test.ts @@ -1,8 +1,8 @@ import * as Message from "@effect/cluster/Message" import * as RecipientType from "@effect/cluster/RecipientType" -import * as Schema from "@effect/schema/Schema" import { equals } from "effect/Equal" import * as Hash from "effect/Hash" +import * as Schema from "effect/Schema" import { describe, expect, it } from "vitest" class Sample extends Message.TaggedMessage()("Sample", Schema.Never, Schema.Number, { diff --git a/packages/cluster/test/Sharding.test.ts b/packages/cluster/test/Sharding.test.ts index e6735cd6ac..20600c6411 100644 --- a/packages/cluster/test/Sharding.test.ts +++ b/packages/cluster/test/Sharding.test.ts @@ -11,7 +11,6 @@ import * as ShardingConfig from "@effect/cluster/ShardingConfig" import * as ShardingException from "@effect/cluster/ShardingException" import * as ShardManagerClient from "@effect/cluster/ShardManagerClient" import * as Storage from "@effect/cluster/Storage" -import * as Schema from "@effect/schema/Schema" import * as Cause from "effect/Cause" import * as Context from "effect/Context" import * as Deferred from "effect/Deferred" @@ -28,6 +27,7 @@ import * as Option from "effect/Option" import * as PrimaryKey from "effect/PrimaryKey" import * as Queue from "effect/Queue" import * as Ref from "effect/Ref" +import * as Schema from "effect/Schema" import { describe, expect, it } from "vitest" interface SampleService { diff --git a/packages/cluster/tsconfig.build.json b/packages/cluster/tsconfig.build.json index 7d15eaf85f..b5bfec4204 100644 --- a/packages/cluster/tsconfig.build.json +++ b/packages/cluster/tsconfig.build.json @@ -3,7 +3,6 @@ "references": [ { "path": "../effect/tsconfig.build.json" }, { "path": "../platform/tsconfig.build.json" }, - { "path": "../schema/tsconfig.build.json" }, { "path": "../sql/tsconfig.build.json" } ], "compilerOptions": { diff --git a/packages/cluster/tsconfig.src.json b/packages/cluster/tsconfig.src.json index 04ca6812aa..5636abbdfa 100644 --- a/packages/cluster/tsconfig.src.json +++ b/packages/cluster/tsconfig.src.json @@ -1,12 +1,9 @@ { "extends": "../../tsconfig.base.json", - "include": [ - "src" - ], + "include": ["src"], "references": [ { "path": "../effect" }, { "path": "../platform" }, - { "path": "../schema" }, { "path": "../sql" } ], "compilerOptions": { diff --git a/packages/cluster/tsconfig.test.json b/packages/cluster/tsconfig.test.json index 6a3d8ee79d..671911fe3c 100644 --- a/packages/cluster/tsconfig.test.json +++ b/packages/cluster/tsconfig.test.json @@ -1,16 +1,13 @@ { "extends": "../../tsconfig.base.json", - "include": [ - "test", - ], + "include": ["test"], "references": [ { "path": "tsconfig.src.json" }, { "path": "../effect" }, { "path": "../platform" }, { "path": "../platform-node" }, - { "path": "../schema" }, { "path": "../sql" }, - { "path": "../sql-sqlite-node" }, + { "path": "../sql-sqlite-node" } ], "compilerOptions": { "tsBuildInfoFile": ".tsbuildinfo/test.tsbuildinfo", diff --git a/packages/schema/benchmark/array.ts b/packages/effect/benchmark/SchemaArray.ts similarity index 94% rename from packages/schema/benchmark/array.ts rename to packages/effect/benchmark/SchemaArray.ts index ea57d31de3..8ac4aa4237 100644 --- a/packages/schema/benchmark/array.ts +++ b/packages/effect/benchmark/SchemaArray.ts @@ -1,6 +1,6 @@ -import type { ParseOptions } from "@effect/schema/AST" -import * as ParseResult from "@effect/schema/ParseResult" -import * as S from "@effect/schema/Schema" +import * as ParseResult from "effect/ParseResult" +import * as S from "effect/Schema" +import type { ParseOptions } from "effect/SchemaAST" import { Bench } from "tinybench" /* diff --git a/packages/schema/benchmark/filters.ts b/packages/effect/benchmark/SchemaFilters.ts similarity index 96% rename from packages/schema/benchmark/filters.ts rename to packages/effect/benchmark/SchemaFilters.ts index f1aff6696f..83fe3c795b 100644 --- a/packages/schema/benchmark/filters.ts +++ b/packages/effect/benchmark/SchemaFilters.ts @@ -1,6 +1,6 @@ -import type { ParseOptions } from "@effect/schema/AST" -import * as ParseResult from "@effect/schema/ParseResult" -import * as S from "@effect/schema/Schema" +import * as ParseResult from "effect/ParseResult" +import * as S from "effect/Schema" +import type { ParseOptions } from "effect/SchemaAST" import { Bench } from "tinybench" import { z } from "zod" diff --git a/packages/schema/benchmark/index.ts b/packages/effect/benchmark/SchemaIndex.ts similarity index 96% rename from packages/schema/benchmark/index.ts rename to packages/effect/benchmark/SchemaIndex.ts index fb38103666..a37145866e 100644 --- a/packages/schema/benchmark/index.ts +++ b/packages/effect/benchmark/SchemaIndex.ts @@ -1,6 +1,6 @@ -import type { ParseOptions } from "@effect/schema/AST" -import * as ParseResult from "@effect/schema/ParseResult" -import * as S from "@effect/schema/Schema" +import * as ParseResult from "effect/ParseResult" +import * as S from "effect/Schema" +import type { ParseOptions } from "effect/SchemaAST" import { Bench } from "tinybench" import { z } from "zod" diff --git a/packages/schema/benchmark/propertyOrder.ts b/packages/effect/benchmark/SchemaPropertyOrder.ts similarity index 96% rename from packages/schema/benchmark/propertyOrder.ts rename to packages/effect/benchmark/SchemaPropertyOrder.ts index 37440a9a90..65d9aea4d3 100644 --- a/packages/schema/benchmark/propertyOrder.ts +++ b/packages/effect/benchmark/SchemaPropertyOrder.ts @@ -1,5 +1,5 @@ -import * as ParseResult from "@effect/schema/ParseResult" -import * as S from "@effect/schema/Schema" +import * as ParseResult from "effect/ParseResult" +import * as S from "effect/Schema" import { Bench } from "tinybench" /* diff --git a/packages/schema/benchmark/Struct.ts b/packages/effect/benchmark/SchemaStruct.ts similarity index 95% rename from packages/schema/benchmark/Struct.ts rename to packages/effect/benchmark/SchemaStruct.ts index 20e4b3eb9c..35a86d0740 100644 --- a/packages/schema/benchmark/Struct.ts +++ b/packages/effect/benchmark/SchemaStruct.ts @@ -1,5 +1,5 @@ -import * as ParseResult from "@effect/schema/ParseResult" -import * as S from "@effect/schema/Schema" +import * as ParseResult from "effect/ParseResult" +import * as S from "effect/Schema" import { Bench } from "tinybench" /* diff --git a/packages/schema/benchmark/toString.ts b/packages/effect/benchmark/SchemaToString.ts similarity index 90% rename from packages/schema/benchmark/toString.ts rename to packages/effect/benchmark/SchemaToString.ts index 998927eea7..b2f229bf8c 100644 --- a/packages/schema/benchmark/toString.ts +++ b/packages/effect/benchmark/SchemaToString.ts @@ -1,6 +1,5 @@ -import * as ParseResult from "@effect/schema/ParseResult" -import * as S from "@effect/schema/Schema" -import * as TreeFormatter from "@effect/schema/TreeFormatter" +import * as ParseResult from "effect/ParseResult" +import * as S from "effect/Schema" import { Bench } from "tinybench" /* @@ -37,7 +36,7 @@ bench schema.ast.toJSON() }) .add("TreeFormatter.formatIssueSync", function() { - TreeFormatter.formatIssueSync(result.left) + ParseResult.TreeFormatter.formatIssueSync(result.left) }) await bench.run() diff --git a/packages/schema/benchmark/TreeFormatter.formatIssueSync.ts b/packages/effect/benchmark/SchemaTreeFormatter.ts similarity index 90% rename from packages/schema/benchmark/TreeFormatter.formatIssueSync.ts rename to packages/effect/benchmark/SchemaTreeFormatter.ts index e22a6d4e7b..6f65134880 100644 --- a/packages/schema/benchmark/TreeFormatter.formatIssueSync.ts +++ b/packages/effect/benchmark/SchemaTreeFormatter.ts @@ -1,7 +1,6 @@ -import type * as ParseResult from "@effect/schema/ParseResult" -import * as S from "@effect/schema/Schema" -import * as TreeFormatter from "@effect/schema/TreeFormatter" import type * as Either from "effect/Either" +import * as ParseResult from "effect/ParseResult" +import * as S from "effect/Schema" import { Bench } from "tinybench" /* @@ -35,7 +34,7 @@ bench decodeUnknownEither(input) }) .add("TreeFormatter.formatIssueSync(issue)", function() { - TreeFormatter.formatIssueSync(issue) + ParseResult.TreeFormatter.formatIssueSync(issue) }) await bench.run() diff --git a/packages/schema/benchmark/union.ts b/packages/effect/benchmark/SchemaUnion.ts similarity index 95% rename from packages/schema/benchmark/union.ts rename to packages/effect/benchmark/SchemaUnion.ts index 35d2603904..306c8c760f 100644 --- a/packages/schema/benchmark/union.ts +++ b/packages/effect/benchmark/SchemaUnion.ts @@ -1,7 +1,7 @@ -import type { ParseOptions } from "@effect/schema/AST" -import * as ParseResult from "@effect/schema/ParseResult" -import * as S from "@effect/schema/Schema" import * as RA from "effect/Array" +import * as ParseResult from "effect/ParseResult" +import * as S from "effect/Schema" +import type { ParseOptions } from "effect/SchemaAST" import { Bench } from "tinybench" import { z } from "zod" diff --git a/packages/schema/benchmark/tsconfig.json b/packages/effect/benchmark/tsconfig.json similarity index 69% rename from packages/schema/benchmark/tsconfig.json rename to packages/effect/benchmark/tsconfig.json index 095be3dcfe..754e674d82 100644 --- a/packages/schema/benchmark/tsconfig.json +++ b/packages/effect/benchmark/tsconfig.json @@ -5,8 +5,6 @@ "moduleResolution": "NodeNext", "target": "ES2022", "paths": { - "@effect/schema": ["../src/index.js"], - "@effect/schema/*": ["../src/*.js"], "effect/*": ["../../effect/src/*.js"] } } diff --git a/packages/effect/docgen.json b/packages/effect/docgen.json index 341f13106d..5c4b045527 100644 --- a/packages/effect/docgen.json +++ b/packages/effect/docgen.json @@ -1,8 +1,6 @@ { "$schema": "../../node_modules/@effect/docgen/schema.json", - "exclude": [ - "src/internal/**/*.ts" - ], + "exclude": ["src/internal/**/*.ts"], "examplesCompilerOptions": { "noEmit": true, "strict": true, @@ -10,47 +8,18 @@ "moduleResolution": "Bundler", "module": "ES2022", "target": "ES2022", - "lib": [ - "ES2022", - "DOM" - ], + "lib": ["ES2022", "DOM"], "paths": { - "effect": [ - "../../../effect/src/index.js" - ], - "effect/*": [ - "../../../effect/src/*.js" - ], - "@effect/platform": [ - "../../../platform/src/index.js" - ], - "@effect/platform/*": [ - "../../../platform/src/*.js" - ], - "@effect/printer": [ - "../../../printer/src/index.js" - ], - "@effect/printer/*": [ - "../../../printer/src/*.js" - ], - "@effect/printer-ansi": [ - "../../../printer-ansi/src/index.js" - ], - "@effect/printer-ansi/*": [ - "../../../printer-ansi/src/*.js" - ], - "@effect/schema": [ - "../../../schema/src/index.js" - ], - "@effect/schema/*": [ - "../../../schema/src/*.js" - ], - "@effect/typeclass": [ - "../../../typeclass/src/index.js" - ], - "@effect/typeclass/*": [ - "../../../typeclass/src/*.js" - ] + "effect": ["../../../effect/src/index.js"], + "effect/*": ["../../../effect/src/*.js"], + "@effect/platform": ["../../../platform/src/index.js"], + "@effect/platform/*": ["../../../platform/src/*.js"], + "@effect/printer": ["../../../printer/src/index.js"], + "@effect/printer/*": ["../../../printer/src/*.js"], + "@effect/printer-ansi": ["../../../printer-ansi/src/index.js"], + "@effect/printer-ansi/*": ["../../../printer-ansi/src/*.js"], + "@effect/typeclass": ["../../../typeclass/src/index.js"], + "@effect/typeclass/*": ["../../../typeclass/src/*.js"] } } } diff --git a/packages/schema/dtslint/Schema.ts b/packages/effect/dtslint/Schema.ts similarity index 99% rename from packages/schema/dtslint/Schema.ts rename to packages/effect/dtslint/Schema.ts index 8c8dd4b97b..0910294c33 100644 --- a/packages/schema/dtslint/Schema.ts +++ b/packages/effect/dtslint/Schema.ts @@ -1,8 +1,8 @@ -import type * as AST from "@effect/schema/AST" -import * as ParseResult from "@effect/schema/ParseResult" -import * as S from "@effect/schema/Schema" import { Brand, Context, Effect, Number as N, Option, String as Str } from "effect" import { hole, identity, pipe } from "effect/Function" +import * as ParseResult from "effect/ParseResult" +import * as S from "effect/Schema" +import type * as AST from "effect/SchemaAST" import type { Simplify } from "effect/Types" declare const anyNever: S.Schema @@ -62,9 +62,14 @@ hole>>() // S.annotations // --------------------------------------------- -// @ts-expect-error +// should allow to add custom string annotations to a schema +// $ExpectType SchemaClass S.String.annotations({ a: 1 }) +// should allow to add custom symbol annotations to a schema +// $ExpectType SchemaClass +S.String.annotations({ [Symbol.for("a")]: 1 }) + /** * @category api interface * @since 1.0.0 @@ -1122,7 +1127,7 @@ S.rename(S.Struct({ a: S.String, b: S.Number }), { a: "c" }) // $ExpectType SchemaClass<{ readonly c: string; readonly d: number; }, { readonly a: string; readonly b: number; }, never> S.rename(S.Struct({ a: S.String, b: S.Number }), { a: "c", b: "d" }) -const a = Symbol.for("@effect/schema/dtslint/a") +const a = Symbol.for("effect/Schema/dtslint/a") // $ExpectType SchemaClass<{ readonly [a]: string; readonly b: number; }, { readonly a: string; readonly b: number; }, never> S.rename(S.Struct({ a: S.String, b: S.Number }), { a }) @@ -1175,7 +1180,7 @@ S.TemplateLiteral(S.String, null) // $ExpectType TemplateLiteral<`${string}1`> S.TemplateLiteral(S.String, 1n) -// $ExpectType TemplateLiteral<`${string}0` | `${string}a`> +// $ExpectType TemplateLiteral<`${string}a` | `${string}0`> S.TemplateLiteral(S.String, S.Literal("a", 0)) // $ExpectType TemplateLiteral<`a${string}`> diff --git a/packages/schema/dtslint/AST.ts b/packages/effect/dtslint/SchemaAST.ts similarity index 57% rename from packages/schema/dtslint/AST.ts rename to packages/effect/dtslint/SchemaAST.ts index 2b67d9d80e..794554af31 100644 --- a/packages/schema/dtslint/AST.ts +++ b/packages/effect/dtslint/SchemaAST.ts @@ -1,11 +1,13 @@ -import * as AST from "@effect/schema/AST" +import * as AST from "effect/SchemaAST" // --------------------------------------------- // annotations // --------------------------------------------- -// @ts-expect-error +// should allow to add custom string annotations to a schema +// $ExpectType AST AST.annotations(AST.stringKeyword, { a: 1 }) +// should allow to add custom symbol annotations to a schema // $ExpectType AST AST.annotations(AST.stringKeyword, { [Symbol.for("a")]: 1 }) diff --git a/packages/schema/dtslint/Brand.errors.ts b/packages/effect/dtslint/SchemaBrand.ts similarity index 90% rename from packages/schema/dtslint/Brand.errors.ts rename to packages/effect/dtslint/SchemaBrand.ts index 9630738374..40f79241eb 100644 --- a/packages/schema/dtslint/Brand.errors.ts +++ b/packages/effect/dtslint/SchemaBrand.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" import { pipe } from "effect/Function" +import * as S from "effect/Schema" const Int1 = Symbol.for("Int") const Int2 = Symbol.for("Int") diff --git a/packages/schema/dtslint/Class.ts b/packages/effect/dtslint/SchemaClass.ts similarity index 98% rename from packages/schema/dtslint/Class.ts rename to packages/effect/dtslint/SchemaClass.ts index f12de50cd9..1198c34d4f 100644 --- a/packages/schema/dtslint/Class.ts +++ b/packages/effect/dtslint/SchemaClass.ts @@ -1,12 +1,12 @@ -import * as S from "@effect/schema/Schema" import { hole } from "effect/Function" +import * as S from "effect/Schema" // --------------------------------------------- // check that there are no conflicts with the `fields` and `from` fields // --------------------------------------------- type HasFields = S.Struct | { - readonly [S.refineTypeId]: HasFields + readonly [S.RefineSchemaId]: HasFields } declare const checkForConflicts: ( diff --git a/packages/schema/dtslint/Context.ts b/packages/effect/dtslint/SchemaContext.ts similarity index 98% rename from packages/schema/dtslint/Context.ts rename to packages/effect/dtslint/SchemaContext.ts index f55122c003..a8dee05306 100644 --- a/packages/schema/dtslint/Context.ts +++ b/packages/effect/dtslint/SchemaContext.ts @@ -1,8 +1,7 @@ -import * as ParseResult from "@effect/schema/ParseResult" -import * as S from "@effect/schema/Schema" -import * as Serializable from "@effect/schema/Serializable" import { Context, Effect, Option } from "effect" import { hole } from "effect/Function" +import * as ParseResult from "effect/ParseResult" +import * as S from "effect/Schema" interface aContext extends S.Schema {} interface bContext extends S.Schema {} @@ -414,7 +413,7 @@ MyRequest.fields declare const myRequest: MyRequest // $ExpectType Schema, ExitEncoded, "bContext" | "cContext"> -Serializable.exitSchema(myRequest) +S.exitSchema(myRequest) // --------------------------------------------- // TemplateLiteralParser diff --git a/packages/schema/dtslint/generic.ts b/packages/effect/dtslint/SchemaGeneric.ts similarity index 93% rename from packages/schema/dtslint/generic.ts rename to packages/effect/dtslint/SchemaGeneric.ts index 20700b3f06..d2e593c045 100644 --- a/packages/schema/dtslint/generic.ts +++ b/packages/effect/dtslint/SchemaGeneric.ts @@ -1,5 +1,4 @@ -import { Schema } from "@effect/schema" -import { Either } from "effect" +import { Either, Schema } from "effect" export const f1 = ( resultSchema: Schema.Schema diff --git a/packages/schema/dtslint/ParseResult.ts b/packages/effect/dtslint/SchemaParseResult.ts similarity index 78% rename from packages/schema/dtslint/ParseResult.ts rename to packages/effect/dtslint/SchemaParseResult.ts index 00469d019a..652655181d 100644 --- a/packages/schema/dtslint/ParseResult.ts +++ b/packages/effect/dtslint/SchemaParseResult.ts @@ -1,4 +1,4 @@ -import type * as ParseResult from "@effect/schema/ParseResult" +import type * as ParseResult from "effect/ParseResult" // --------------------------------------------- // a ParseIssue should always have an `actual` field diff --git a/packages/schema/dtslint/PropertySignature.ts b/packages/effect/dtslint/SchemaPropertySignature.ts similarity index 95% rename from packages/schema/dtslint/PropertySignature.ts rename to packages/effect/dtslint/SchemaPropertySignature.ts index 8ae00bab07..6596cae6df 100644 --- a/packages/schema/dtslint/PropertySignature.ts +++ b/packages/effect/dtslint/SchemaPropertySignature.ts @@ -1,4 +1,4 @@ -import { Schema } from "@effect/schema" +import { Schema } from "effect" // $ExpectType propertySignature const A = Schema.propertySignature(Schema.String) diff --git a/packages/schema/dtslint/Serializable.ts b/packages/effect/dtslint/SchemaSerializable.ts similarity index 68% rename from packages/schema/dtslint/Serializable.ts rename to packages/effect/dtslint/SchemaSerializable.ts index 2184b470e2..7e12e3fd59 100644 --- a/packages/schema/dtslint/Serializable.ts +++ b/packages/effect/dtslint/SchemaSerializable.ts @@ -1,4 +1,4 @@ -import { Schema, Serializable } from "@effect/schema" +import { Schema } from "effect" import { hole } from "effect/Function" class TR extends Schema.TaggedRequest()("TR", { @@ -9,20 +9,18 @@ class TR extends Schema.TaggedRequest()("TR", { } }) {} -const successSchema = (req: Req) => - Serializable.successSchema(Serializable.asWithResult(req)) +const successSchema = (req: Req) => Schema.successSchema(Schema.asWithResult(req)) // $ExpectType Schema successSchema(new TR({ id: 1 })) -const failureSchema = (req: Req) => - Serializable.failureSchema(Serializable.asWithResult(req)) +const failureSchema = (req: Req) => Schema.failureSchema(Schema.asWithResult(req)) // $ExpectType Schema failureSchema(new TR({ id: 1 })) const selfSchema = (req: Req) => - Serializable.selfSchema(Serializable.asSerializable(req)) + Schema.serializableSchema(Schema.asSerializable(req)) // $ExpectType Schema; } & { id: typeof NumberFromString; }>, never> selfSchema(new TR({ id: 1 })) @@ -44,36 +42,36 @@ class Foo extends Schema.TaggedRequest()("A", { // --------------------------------------------- // $ExpectType Foo -hole>>() +hole>>() // $ExpectType Encoded<{ readonly _tag: tag<"A">; } & { a: Schema<"payload", "payload-encoded", "payload-context">; }> -hole>>() +hole>>() // $ExpectType "payload-context" -hole>>() +hole>>() // --------------------------------------------- // WithResult type-level helpers // --------------------------------------------- // $ExpectType "success" -hole>>() +hole>>() // $ExpectType "success-encoded" -hole>>() +hole>>() // $ExpectType "failure" -hole>>() +hole>>() // $ExpectType "failure-encoded" -hole>>() +hole>>() // $ExpectType "failure-context" | "success-context" -hole>>() +hole>>() // --------------------------------------------- // SerializableWithResult type-level helpers // --------------------------------------------- // $ExpectType "failure-context" | "success-context" | "payload-context" -hole>>() +hole>>() diff --git a/packages/schema/dtslint/TaggedError.ts b/packages/effect/dtslint/SchemaTaggedError.ts similarity index 79% rename from packages/schema/dtslint/TaggedError.ts rename to packages/effect/dtslint/SchemaTaggedError.ts index 33f6efb899..2232e69479 100644 --- a/packages/schema/dtslint/TaggedError.ts +++ b/packages/effect/dtslint/SchemaTaggedError.ts @@ -1,6 +1,5 @@ -import { Schema } from "@effect/schema" import type { Unify } from "effect" -import { Effect } from "effect" +import { Effect, Schema } from "effect" class Err extends Schema.TaggedError()("Err", {}) {} diff --git a/packages/schema/dtslint/TaggedRequest.ts b/packages/effect/dtslint/SchemaTaggedRequest.ts similarity index 88% rename from packages/schema/dtslint/TaggedRequest.ts rename to packages/effect/dtslint/SchemaTaggedRequest.ts index ac8829b08e..cf956f8b03 100644 --- a/packages/schema/dtslint/TaggedRequest.ts +++ b/packages/effect/dtslint/SchemaTaggedRequest.ts @@ -1,4 +1,4 @@ -import * as S from "@effect/schema/Schema" +import * as S from "effect/Schema" class TRA extends S.TaggedRequest()("TRA", { failure: S.String, diff --git a/packages/schema/dtslint/userland.ts b/packages/effect/dtslint/SchemaUserland.ts similarity index 95% rename from packages/schema/dtslint/userland.ts rename to packages/effect/dtslint/SchemaUserland.ts index 0b15e3e4f4..3c2f2d74c2 100644 --- a/packages/schema/dtslint/userland.ts +++ b/packages/effect/dtslint/SchemaUserland.ts @@ -1,4 +1,4 @@ -import { Schema as S } from "@effect/schema" +import { Schema as S } from "effect" // Discord: https://discordapp.com/channels/795981131316985866/847382157861060618/1268580485412556883 // goal: pass a Schema Class as a parameter to a function diff --git a/packages/effect/package.json b/packages/effect/package.json index a52bda6423..7f12c6b86f 100644 --- a/packages/effect/package.json +++ b/packages/effect/package.json @@ -44,7 +44,13 @@ "devDependencies": { "@types/jscodeshift": "^0.11.11", "@types/node": "^20.14.10", + "ajv": "^8.17.1", "ast-types": "^0.14.2", - "jscodeshift": "^0.16.1" + "jscodeshift": "^0.16.1", + "tinybench": "^2.9.0", + "zod": "^3.23.5" + }, + "dependencies": { + "fast-check": "^3.21.0" } } diff --git a/packages/schema/src/Arbitrary.ts b/packages/effect/src/Arbitrary.ts similarity index 89% rename from packages/schema/src/Arbitrary.ts rename to packages/effect/src/Arbitrary.ts index 9d9343643c..5f98b93f26 100644 --- a/packages/schema/src/Arbitrary.ts +++ b/packages/effect/src/Arbitrary.ts @@ -1,67 +1,50 @@ /** - * @since 0.67.0 + * @since 3.10.0 */ -import * as Arr from "effect/Array" -import * as Option from "effect/Option" -import * as Predicate from "effect/Predicate" -import * as AST from "./AST.js" +import * as Arr from "./Array.js" import * as FastCheck from "./FastCheck.js" -import * as errors_ from "./internal/errors.js" -import * as filters_ from "./internal/filters.js" -import * as util_ from "./internal/util.js" +import * as errors_ from "./internal/schema/errors.js" +import * as filters_ from "./internal/schema/filters.js" +import * as util_ from "./internal/schema/util.js" +import * as Option from "./Option.js" +import * as Predicate from "./Predicate.js" import type * as Schema from "./Schema.js" +import * as AST from "./SchemaAST.js" /** * @category model - * @since 0.67.0 + * @since 3.10.0 */ export interface LazyArbitrary { (fc: typeof FastCheck): FastCheck.Arbitrary } /** - * @category hooks - * @since 0.67.0 - */ -export const ArbitraryHookId: unique symbol = Symbol.for("@effect/schema/ArbitraryHookId") - -/** - * @category hooks - * @since 0.67.0 - */ -export type ArbitraryHookId = typeof ArbitraryHookId - -/** - * @category hooks - * @since 0.72.3 + * @category annotations + * @since 3.10.0 */ -export interface GenerationContext { +export interface ArbitraryGenerationContext { readonly depthIdentifier?: string readonly maxDepth: number } -/** - * @category hooks - * @since 0.72.3 - */ -export type ArbitraryAnnotation = ( - ...args: [...ReadonlyArray>, GenerationContext] -) => LazyArbitrary - /** * @category annotations - * @since 0.67.0 + * @since 3.10.0 */ -export const arbitrary = - (annotation: ArbitraryAnnotation) => (self: Schema.Schema): Schema.Schema => - self.annotations({ [ArbitraryHookId]: annotation }) +export type ArbitraryAnnotation = readonly []> = ( + ...arbitraries: [ + ...{ readonly [K in keyof TypeParameters]: LazyArbitrary }, + ctx: ArbitraryGenerationContext + ] +) => LazyArbitrary /** * Returns a LazyArbitrary for the `A` type of the provided schema. * * @category arbitrary - * @since 0.67.0 + * @since 3.10.0 */ export const makeLazy = (schema: Schema.Schema): LazyArbitrary => go(schema.ast, { maxDepth: 2 }, []) @@ -70,11 +53,11 @@ export const makeLazy = (schema: Schema.Schema): LazyArbitrary * Returns a fast-check Arbitrary for the `A` type of the provided schema. * * @category arbitrary - * @since 0.67.0 + * @since 3.10.0 */ export const make = (schema: Schema.Schema): FastCheck.Arbitrary => makeLazy(schema)(FastCheck) -const getHook = AST.getAnnotation>(ArbitraryHookId) +const getArbitraryAnnotation = AST.getAnnotation>(AST.ArbitraryAnnotationId) const getRefinementFromArbitrary = ( ast: AST.Refinement, @@ -121,7 +104,7 @@ const getSuspendedArray = ( ) } -interface Context extends GenerationContext { +interface Context extends ArbitraryGenerationContext { readonly constraints?: Constraints } @@ -130,7 +113,7 @@ const go = ( ctx: Context, path: ReadonlyArray ): LazyArbitrary => { - const hook = getHook(ast) + const hook = getArbitraryAnnotation(ast) if (Option.isSome(hook)) { switch (ast._tag) { case "Declaration": @@ -442,40 +425,40 @@ export type Constraints = /** @internal */ export const getConstraints = (ast: AST.Refinement): Constraints | undefined => { - const TypeAnnotationId = ast.annotations[AST.TypeAnnotationId] + const TypeAnnotationId = ast.annotations[AST.SchemaIdAnnotationId] const jsonSchema: any = ast.annotations[AST.JSONSchemaAnnotationId] switch (TypeAnnotationId) { // int - case filters_.IntTypeId: + case filters_.IntSchemaId: return new IntegerConstraints({}) // number - case filters_.GreaterThanTypeId: - case filters_.GreaterThanOrEqualToTypeId: - case filters_.LessThanTypeId: - case filters_.LessThanOrEqualToTypeId: - case filters_.BetweenTypeId: + case filters_.GreaterThanSchemaId: + case filters_.GreaterThanOrEqualToSchemaId: + case filters_.LessThanSchemaId: + case filters_.LessThanOrEqualToSchemaId: + case filters_.BetweenSchemaId: return new NumberConstraints({ min: jsonSchema.exclusiveMinimum ?? jsonSchema.minimum, max: jsonSchema.exclusiveMaximum ?? jsonSchema.maximum }) // bigint - case filters_.GreaterThanBigintTypeId: - case filters_.GreaterThanOrEqualToBigIntTypeId: - case filters_.LessThanBigIntTypeId: - case filters_.LessThanOrEqualToBigIntTypeId: - case filters_.BetweenBigintTypeId: { + case filters_.GreaterThanBigintSchemaId: + case filters_.GreaterThanOrEqualToBigIntSchemaId: + case filters_.LessThanBigIntSchemaId: + case filters_.LessThanOrEqualToBigIntSchemaId: + case filters_.BetweenBigintSchemaId: { const constraints: any = ast.annotations[TypeAnnotationId] return new BigIntConstraints(constraints) } // string - case filters_.MinLengthTypeId: - case filters_.MaxLengthTypeId: - case filters_.LengthTypeId: + case filters_.MinLengthSchemaId: + case filters_.MaxLengthSchemaId: + case filters_.LengthSchemaId: return new StringConstraints(jsonSchema) // array - case filters_.MinItemsTypeId: - case filters_.MaxItemsTypeId: - case filters_.ItemsCountTypeId: + case filters_.MinItemsSchemaId: + case filters_.MaxItemsSchemaId: + case filters_.ItemsCountSchemaId: return new ArrayConstraints({ minLength: jsonSchema.minItems, maxLength: jsonSchema.maxItems diff --git a/packages/schema/src/FastCheck.ts b/packages/effect/src/FastCheck.ts similarity index 66% rename from packages/schema/src/FastCheck.ts rename to packages/effect/src/FastCheck.ts index f11dad7043..b5a3803d15 100644 --- a/packages/schema/src/FastCheck.ts +++ b/packages/effect/src/FastCheck.ts @@ -1,9 +1,9 @@ /** - * @since 0.67.0 + * @since 3.10.0 */ /** * @category re-exports - * @since 0.67.0 + * @since 3.10.0 */ export * from "fast-check" diff --git a/packages/schema/src/JSONSchema.ts b/packages/effect/src/JSONSchema.ts similarity index 96% rename from packages/schema/src/JSONSchema.ts rename to packages/effect/src/JSONSchema.ts index 4cfa214f09..a6e138db81 100644 --- a/packages/schema/src/JSONSchema.ts +++ b/packages/effect/src/JSONSchema.ts @@ -1,18 +1,17 @@ /** - * @since 0.67.0 + * @since 3.10.0 */ -import * as Option from "effect/Option" -import * as Predicate from "effect/Predicate" -import * as Record from "effect/Record" -import * as AST from "./AST.js" -import * as errors_ from "./internal/errors.js" -import * as filters_ from "./internal/filters.js" +import * as errors_ from "./internal/schema/errors.js" +import * as Option from "./Option.js" +import * as Predicate from "./Predicate.js" +import * as Record from "./Record.js" import type * as Schema from "./Schema.js" +import * as AST from "./SchemaAST.js" /** * @category model - * @since 0.67.0 + * @since 3.10.0 */ export interface JsonSchemaAnnotations { title?: string @@ -23,7 +22,7 @@ export interface JsonSchemaAnnotations { /** * @category model - * @since 0.67.0 + * @since 3.10.0 */ export interface JsonSchema7Any extends JsonSchemaAnnotations { $id: "/schemas/any" @@ -31,7 +30,7 @@ export interface JsonSchema7Any extends JsonSchemaAnnotations { /** * @category model - * @since 0.67.0 + * @since 3.10.0 */ export interface JsonSchema7Unknown extends JsonSchemaAnnotations { $id: "/schemas/unknown" @@ -39,7 +38,7 @@ export interface JsonSchema7Unknown extends JsonSchemaAnnotations { /** * @category model - * @since 0.69.0 + * @since 3.10.0 */ export interface JsonSchema7Void extends JsonSchemaAnnotations { $id: "/schemas/void" @@ -47,7 +46,7 @@ export interface JsonSchema7Void extends JsonSchemaAnnotations { /** * @category model - * @since 0.71.0 + * @since 3.10.0 */ export interface JsonSchema7object extends JsonSchemaAnnotations { $id: "/schemas/object" @@ -59,7 +58,7 @@ export interface JsonSchema7object extends JsonSchemaAnnotations { /** * @category model - * @since 0.71.0 + * @since 3.10.0 */ export interface JsonSchema7empty extends JsonSchemaAnnotations { $id: "/schemas/{}" @@ -71,7 +70,7 @@ export interface JsonSchema7empty extends JsonSchemaAnnotations { /** * @category model - * @since 0.67.0 + * @since 3.10.0 */ export interface JsonSchema7Ref extends JsonSchemaAnnotations { $ref: string @@ -79,7 +78,7 @@ export interface JsonSchema7Ref extends JsonSchemaAnnotations { /** * @category model - * @since 0.67.0 + * @since 3.10.0 */ export interface JsonSchema7String extends JsonSchemaAnnotations { type: "string" @@ -90,7 +89,7 @@ export interface JsonSchema7String extends JsonSchemaAnnotations { /** * @category model - * @since 0.67.0 + * @since 3.10.0 */ export interface JsonSchema7Numeric extends JsonSchemaAnnotations { minimum?: number @@ -101,7 +100,7 @@ export interface JsonSchema7Numeric extends JsonSchemaAnnotations { /** * @category model - * @since 0.67.0 + * @since 3.10.0 */ export interface JsonSchema7Number extends JsonSchema7Numeric { type: "number" @@ -109,7 +108,7 @@ export interface JsonSchema7Number extends JsonSchema7Numeric { /** * @category model - * @since 0.67.0 + * @since 3.10.0 */ export interface JsonSchema7Integer extends JsonSchema7Numeric { type: "integer" @@ -117,7 +116,7 @@ export interface JsonSchema7Integer extends JsonSchema7Numeric { /** * @category model - * @since 0.67.0 + * @since 3.10.0 */ export interface JsonSchema7Boolean extends JsonSchemaAnnotations { type: "boolean" @@ -125,7 +124,7 @@ export interface JsonSchema7Boolean extends JsonSchemaAnnotations { /** * @category model - * @since 0.67.0 + * @since 3.10.0 */ export interface JsonSchema7Array extends JsonSchemaAnnotations { type: "array" @@ -137,7 +136,7 @@ export interface JsonSchema7Array extends JsonSchemaAnnotations { /** * @category model - * @since 0.67.0 + * @since 3.10.0 */ export interface JsonSchema7Enum extends JsonSchemaAnnotations { enum: Array @@ -145,7 +144,7 @@ export interface JsonSchema7Enum extends JsonSchemaAnnotations { /** * @category model - * @since 0.71.0 + * @since 3.10.0 */ export interface JsonSchema7Enums extends JsonSchemaAnnotations { $comment: "/schemas/enums" @@ -157,7 +156,7 @@ export interface JsonSchema7Enums extends JsonSchemaAnnotations { /** * @category model - * @since 0.67.0 + * @since 3.10.0 */ export interface JsonSchema7AnyOf extends JsonSchemaAnnotations { anyOf: Array @@ -165,7 +164,7 @@ export interface JsonSchema7AnyOf extends JsonSchemaAnnotations { /** * @category model - * @since 0.67.0 + * @since 3.10.0 */ export interface JsonSchema7Object extends JsonSchemaAnnotations { type: "object" @@ -178,7 +177,7 @@ export interface JsonSchema7Object extends JsonSchemaAnnotations { /** * @category model - * @since 0.71.0 + * @since 3.10.0 */ export type JsonSchema7 = | JsonSchema7Any @@ -199,7 +198,7 @@ export type JsonSchema7 = /** * @category model - * @since 0.67.0 + * @since 3.10.0 */ export type JsonSchema7Root = JsonSchema7 & { $schema?: string @@ -208,7 +207,7 @@ export type JsonSchema7Root = JsonSchema7 & { /** * @category encoding - * @since 0.67.0 + * @since 3.10.0 */ export const make = (schema: Schema.Schema): JsonSchema7Root => { const $defs: Record = {} @@ -319,7 +318,7 @@ const getRefinementInnerTransformation = (ast: AST.Refinement): AST.AST | undefi } const isParseJsonTransformation = (ast: AST.AST): boolean => - ast.annotations[AST.TypeAnnotationId] === filters_.ParseJsonTypeId + ast.annotations[AST.SchemaIdAnnotationId] === AST.ParseJsonSchemaId function merge(a: JsonSchemaAnnotations, b: JsonSchema7): JsonSchema7 function merge(a: JsonSchema7, b: JsonSchemaAnnotations): JsonSchema7 diff --git a/packages/schema/src/ParseResult.ts b/packages/effect/src/ParseResult.ts similarity index 82% rename from packages/schema/src/ParseResult.ts rename to packages/effect/src/ParseResult.ts index 48397c9495..1339939f65 100644 --- a/packages/schema/src/ParseResult.ts +++ b/packages/effect/src/ParseResult.ts @@ -1,28 +1,28 @@ /** - * @since 0.67.0 + * @since 3.10.0 */ -import * as array_ from "effect/Array" -import { TaggedError } from "effect/Data" -import * as Effect from "effect/Effect" -import * as Either from "effect/Either" -import type { LazyArg } from "effect/Function" -import { dual } from "effect/Function" -import { globalValue } from "effect/GlobalValue" -import * as Inspectable from "effect/Inspectable" -import * as Option from "effect/Option" -import * as Predicate from "effect/Predicate" -import type { Concurrency } from "effect/Types" -import * as AST from "./AST.js" -import * as util_ from "./internal/util.js" +import * as array_ from "./Array.js" +import type * as cause_ from "./Cause.js" +import { TaggedError } from "./Data.js" +import * as Effect from "./Effect.js" +import * as Either from "./Either.js" +import type { LazyArg } from "./Function.js" +import { dual } from "./Function.js" +import { globalValue } from "./GlobalValue.js" +import * as Inspectable from "./Inspectable.js" +import * as util_ from "./internal/schema/util.js" +import * as Option from "./Option.js" +import * as Predicate from "./Predicate.js" import type * as Schema from "./Schema.js" -import * as TreeFormatter from "./TreeFormatter.js" +import * as AST from "./SchemaAST.js" +import type { Concurrency } from "./Types.js" /** * `ParseIssue` is a type that represents the different types of errors that can occur when decoding/encoding a value. * * @category model - * @since 0.67.0 + * @since 3.10.0 */ export type ParseIssue = // leaf @@ -38,23 +38,23 @@ export type ParseIssue = /** * @category model - * @since 0.68.0 + * @since 3.10.0 */ export type SingleOrNonEmpty = A | array_.NonEmptyReadonlyArray /** * @category model - * @since 0.68.0 + * @since 3.10.0 */ export type Path = SingleOrNonEmpty /** * @category model - * @since 0.68.0 + * @since 3.10.0 */ export class Pointer { /** - * @since 0.68.0 + * @since 3.10.0 */ readonly _tag = "Pointer" constructor( @@ -68,17 +68,17 @@ export class Pointer { * Error that occurs when an unexpected key or index is present. * * @category model - * @since 0.67.0 + * @since 3.10.0 */ export class Unexpected { /** - * @since 0.67.0 + * @since 3.10.0 */ readonly _tag = "Unexpected" constructor( readonly actual: unknown, /** - * @since 0.68.0 + * @since 3.10.0 */ readonly message?: string ) {} @@ -88,24 +88,24 @@ export class Unexpected { * Error that occurs when a required key or index is missing. * * @category model - * @since 0.67.0 + * @since 3.10.0 */ export class Missing { /** - * @since 0.67.0 + * @since 3.10.0 */ readonly _tag = "Missing" /** - * @since 0.68.0 + * @since 3.10.0 */ readonly actual = undefined constructor( /** - * @since 0.68.0 + * @since 3.10.0 */ readonly ast: AST.Type, /** - * @since 0.68.0 + * @since 3.10.0 */ readonly message?: string ) {} @@ -115,11 +115,11 @@ export class Missing { * Error that contains multiple issues. * * @category model - * @since 0.68.0 + * @since 3.10.0 */ export class Composite { /** - * @since 0.68.0 + * @since 3.10.0 */ readonly _tag = "Composite" constructor( @@ -130,23 +130,15 @@ export class Composite { ) {} } -/** - * Returns `true` if the value is a `Composite`. - * - * @category guards - * @since 0.68.0 - */ -export const isComposite = (u: unknown): u is Composite => Predicate.hasProperty(u, "_tag") - /** * Error that occurs when a refinement has an error. * * @category model - * @since 0.67.0 + * @since 3.10.0 */ export class Refinement { /** - * @since 0.67.0 + * @since 3.10.0 */ readonly _tag = "Refinement" constructor( @@ -161,11 +153,11 @@ export class Refinement { * Error that occurs when a transformation has an error. * * @category model - * @since 0.67.0 + * @since 3.10.0 */ export class Transformation { /** - * @since 0.67.0 + * @since 3.10.0 */ readonly _tag = "Transformation" constructor( @@ -181,11 +173,11 @@ export class Transformation { * The `ast` field specifies the expected type, and the `actual` field contains the value that caused the error. * * @category model - * @since 0.67.0 + * @since 3.10.0 */ export class Type { /** - * @since 0.67.0 + * @since 3.10.0 */ readonly _tag = "Type" constructor( @@ -199,11 +191,11 @@ export class Type { * The `Forbidden` variant of the `ParseIssue` type represents a forbidden operation, such as when encountering an Effect that is not allowed to execute (e.g., using `runSync`). * * @category model - * @since 0.67.0 + * @since 3.10.0 */ export class Forbidden { /** - * @since 0.67.0 + * @since 3.10.0 */ readonly _tag = "Forbidden" constructor( @@ -215,27 +207,27 @@ export class Forbidden { /** * @category type id - * @since 0.68.0 + * @since 3.10.0 */ -export const ParseErrorTypeId: unique symbol = Symbol.for("@effect/schema/ParseErrorTypeId") +export const ParseErrorTypeId: unique symbol = Symbol.for("effect/Schema/ParseErrorTypeId") /** * @category type id - * @since 0.68.0 + * @since 3.10.0 */ export type ParseErrorTypeId = typeof ParseErrorTypeId /** - * @since 0.68.0 + * @since 3.10.0 */ export const isParseError = (u: unknown): u is ParseError => Predicate.hasProperty(u, ParseErrorTypeId) /** - * @since 0.67.0 + * @since 3.10.0 */ export class ParseError extends TaggedError("ParseError")<{ readonly issue: ParseIssue }> { /** - * @since 0.68.0 + * @since 3.10.0 */ readonly [ParseErrorTypeId] = ParseErrorTypeId @@ -243,13 +235,13 @@ export class ParseError extends TaggedError("ParseError")<{ readonly issue: Pars return this.toString() } /** - * @since 0.67.0 + * @since 3.10.0 */ toString() { return TreeFormatter.formatIssueSync(this.issue) } /** - * @since 0.67.0 + * @since 3.10.0 */ toJSON() { return { @@ -258,7 +250,7 @@ export class ParseError extends TaggedError("ParseError")<{ readonly issue: Pars } } /** - * @since 0.67.0 + * @since 3.10.0 */ [Inspectable.NodeInspectSymbol]() { return this.toJSON() @@ -267,19 +259,19 @@ export class ParseError extends TaggedError("ParseError")<{ readonly issue: Pars /** * @category constructors - * @since 0.67.0 + * @since 3.10.0 */ export const parseError = (issue: ParseIssue): ParseError => new ParseError({ issue }) /** * @category constructors - * @since 0.67.0 + * @since 3.10.0 */ export const succeed: (a: A) => Either.Either = Either.right /** * @category constructors - * @since 0.67.0 + * @since 3.10.0 */ export const fail: (issue: ParseIssue) => Either.Either = Either.left @@ -291,14 +283,14 @@ const _try: (options: { export { /** * @category constructors - * @since 0.67.0 + * @since 3.10.0 */ _try as try } /** * @category constructors - * @since 0.67.0 + * @since 3.10.0 */ export const fromOption: { (onNone: () => ParseIssue): (self: Option.Option) => Either.Either @@ -307,7 +299,7 @@ export const fromOption: { /** * @category optimisation - * @since 0.67.0 + * @since 3.10.0 */ export const flatMap: { ( @@ -333,7 +325,7 @@ export const flatMap: { /** * @category optimisation - * @since 0.67.0 + * @since 3.10.0 */ export const map: { (f: (a: A) => B): (self: Effect.Effect) => Effect.Effect @@ -351,7 +343,7 @@ export const map: { /** * @category optimisation - * @since 0.67.0 + * @since 3.10.0 */ export const mapError: { (f: (e: E) => E2): (self: Effect.Effect) => Effect.Effect @@ -369,7 +361,7 @@ export const mapError: { /** * @category optimisation - * @since 0.67.0 + * @since 3.10.0 */ export const eitherOrUndefined = ( self: Effect.Effect @@ -382,7 +374,7 @@ export const eitherOrUndefined = ( /** * @category optimisation - * @since 0.67.0 + * @since 3.10.0 */ export const mapBoth: { ( @@ -408,7 +400,7 @@ export const mapBoth: { /** * @category optimisation - * @since 0.67.0 + * @since 3.10.0 */ export const orElse: { ( @@ -433,12 +425,12 @@ export const orElse: { }) /** - * @since 0.67.0 + * @since 3.10.0 */ export type DecodeUnknown = (u: unknown, options?: AST.ParseOptions) => Effect.Effect /** - * @since 0.67.0 + * @since 3.10.0 */ export type DeclarationDecodeUnknown = ( u: unknown, @@ -487,7 +479,7 @@ const getEffect = (ast: AST.AST, isDecoding: boolean, options?: AST.ParseOpti /** * @throws `ParseError` * @category decoding - * @since 0.67.0 + * @since 3.10.0 */ export const decodeUnknownSync = ( schema: Schema.Schema, @@ -496,7 +488,7 @@ export const decodeUnknownSync = ( /** * @category decoding - * @since 0.67.0 + * @since 3.10.0 */ export const decodeUnknownOption = ( schema: Schema.Schema, @@ -505,7 +497,7 @@ export const decodeUnknownOption = ( /** * @category decoding - * @since 0.67.0 + * @since 3.10.0 */ export const decodeUnknownEither = ( schema: Schema.Schema, @@ -515,7 +507,7 @@ export const decodeUnknownEither = ( /** * @category decoding - * @since 0.67.0 + * @since 3.10.0 */ export const decodeUnknownPromise = ( schema: Schema.Schema, @@ -527,7 +519,7 @@ export const decodeUnknownPromise = ( /** * @category decoding - * @since 0.67.0 + * @since 3.10.0 */ export const decodeUnknown = ( schema: Schema.Schema, @@ -538,7 +530,7 @@ export const decodeUnknown = ( /** * @throws `ParseError` * @category encoding - * @since 0.67.0 + * @since 3.10.0 */ export const encodeUnknownSync = ( schema: Schema.Schema, @@ -547,7 +539,7 @@ export const encodeUnknownSync = ( /** * @category encoding - * @since 0.67.0 + * @since 3.10.0 */ export const encodeUnknownOption = ( schema: Schema.Schema, @@ -556,7 +548,7 @@ export const encodeUnknownOption = ( /** * @category encoding - * @since 0.67.0 + * @since 3.10.0 */ export const encodeUnknownEither = ( schema: Schema.Schema, @@ -566,7 +558,7 @@ export const encodeUnknownEither = ( /** * @category encoding - * @since 0.67.0 + * @since 3.10.0 */ export const encodeUnknownPromise = ( schema: Schema.Schema, @@ -578,7 +570,7 @@ export const encodeUnknownPromise = ( /** * @category encoding - * @since 0.67.0 + * @since 3.10.0 */ export const encodeUnknown = ( schema: Schema.Schema, @@ -588,7 +580,7 @@ export const encodeUnknown = ( /** * @category decoding - * @since 0.67.0 + * @since 3.10.0 */ export const decodeSync: ( schema: Schema.Schema, @@ -597,7 +589,7 @@ export const decodeSync: ( /** * @category decoding - * @since 0.67.0 + * @since 3.10.0 */ export const decodeOption: ( schema: Schema.Schema, @@ -606,7 +598,7 @@ export const decodeOption: ( /** * @category decoding - * @since 0.67.0 + * @since 3.10.0 */ export const decodeEither: ( schema: Schema.Schema, @@ -615,7 +607,7 @@ export const decodeEither: ( /** * @category decoding - * @since 0.67.0 + * @since 3.10.0 */ export const decodePromise: ( schema: Schema.Schema, @@ -624,7 +616,7 @@ export const decodePromise: ( /** * @category decoding - * @since 0.67.0 + * @since 3.10.0 */ export const decode: ( schema: Schema.Schema, @@ -634,7 +626,7 @@ export const decode: ( /** * @throws `ParseError` * @category validation - * @since 0.67.0 + * @since 3.10.0 */ export const validateSync = ( schema: Schema.Schema, @@ -643,7 +635,7 @@ export const validateSync = ( /** * @category validation - * @since 0.67.0 + * @since 3.10.0 */ export const validateOption = ( schema: Schema.Schema, @@ -653,7 +645,7 @@ export const validateOption = ( /** * @category validation - * @since 0.67.0 + * @since 3.10.0 */ export const validateEither = ( schema: Schema.Schema, @@ -663,7 +655,7 @@ export const validateEither = ( /** * @category validation - * @since 0.67.0 + * @since 3.10.0 */ export const validatePromise = ( schema: Schema.Schema, @@ -675,7 +667,7 @@ export const validatePromise = ( /** * @category validation - * @since 0.67.0 + * @since 3.10.0 */ export const validate = ( schema: Schema.Schema, @@ -687,7 +679,7 @@ export const validate = ( * By default the option `exact` is set to `true`. * * @category validation - * @since 0.67.0 + * @since 3.10.0 */ export const is = (schema: Schema.Schema, options?: AST.ParseOptions) => { const parser = goMemo(AST.typeAST(schema.ast), true) @@ -700,7 +692,7 @@ export const is = (schema: Schema.Schema, options?: AST.ParseO * * @throws `ParseError` * @category validation - * @since 0.67.0 + * @since 3.10.0 */ export const asserts = (schema: Schema.Schema, options?: AST.ParseOptions) => { const parser = goMemo(AST.typeAST(schema.ast), true) @@ -717,7 +709,7 @@ export const asserts = (schema: Schema.Schema, options?: AST.P /** * @category encoding - * @since 0.67.0 + * @since 3.10.0 */ export const encodeSync: ( schema: Schema.Schema, @@ -726,7 +718,7 @@ export const encodeSync: ( /** * @category encoding - * @since 0.67.0 + * @since 3.10.0 */ export const encodeOption: ( schema: Schema.Schema, @@ -735,7 +727,7 @@ export const encodeOption: ( /** * @category encoding - * @since 0.67.0 + * @since 3.10.0 */ export const encodeEither: ( schema: Schema.Schema, @@ -744,7 +736,7 @@ export const encodeEither: ( /** * @category encoding - * @since 0.67.0 + * @since 3.10.0 */ export const encodePromise: ( schema: Schema.Schema, @@ -753,7 +745,7 @@ export const encodePromise: ( /** * @category encoding - * @since 0.67.0 + * @since 3.10.0 */ export const encode: ( schema: Schema.Schema, @@ -769,11 +761,11 @@ interface Parser { } const decodeMemoMap = globalValue( - Symbol.for("@effect/schema/Parser/decodeMemoMap"), + Symbol.for("effect/Schema/Parser/decodeMemoMap"), () => new WeakMap() ) const encodeMemoMap = globalValue( - Symbol.for("@effect/schema/Parser/encodeMemoMap"), + Symbol.for("effect/Schema/Parser/encodeMemoMap"), () => new WeakMap() ) @@ -1718,3 +1710,273 @@ export const getFinalTransformation = ( } } } + +// ---------------- +// Formatters +// ---------------- + +interface Forest extends ReadonlyArray> {} + +interface Tree { + readonly value: A + readonly forest: Forest +} + +const makeTree = (value: A, forest: Forest = []): Tree => ({ + value, + forest +}) + +/** + * @category formatting + * @since 3.10.0 + */ +export interface ParseResultFormatter { + readonly formatIssue: (issue: ParseIssue) => Effect.Effect + readonly formatIssueSync: (issue: ParseIssue) => A + readonly formatError: (error: ParseError) => Effect.Effect + readonly formatErrorSync: (error: ParseError) => A +} + +/** + * @category formatting + * @since 3.10.0 + */ +export const TreeFormatter: ParseResultFormatter = { + formatIssue: (issue) => Effect.map(formatTree(issue), drawTree), + formatIssueSync: (issue) => Effect.runSync(TreeFormatter.formatIssue(issue)), + formatError: (error) => TreeFormatter.formatIssue(error.issue), + formatErrorSync: (error) => TreeFormatter.formatIssueSync(error.issue) +} + +const drawTree = (tree: Tree): string => tree.value + draw("\n", tree.forest) + +const draw = (indentation: string, forest: Forest): string => { + let r = "" + const len = forest.length + let tree: Tree + for (let i = 0; i < len; i++) { + tree = forest[i] + const isLast = i === len - 1 + r += indentation + (isLast ? "└" : "├") + "─ " + tree.value + r += draw(indentation + (len > 1 && !isLast ? "│ " : " "), tree.forest) + } + return r +} + +const formatTransformationKind = (kind: Transformation["kind"]): string => { + switch (kind) { + case "Encoded": + return "Encoded side transformation failure" + case "Transformation": + return "Transformation process failure" + case "Type": + return "Type side transformation failure" + } +} + +const formatRefinementKind = (kind: Refinement["kind"]): string => { + switch (kind) { + case "From": + return "From side refinement failure" + case "Predicate": + return "Predicate refinement failure" + } +} + +const getAnnotated = (issue: ParseIssue): Option.Option => + "ast" in issue ? Option.some(issue.ast) : Option.none() + +interface CurrentMessage { + readonly message: string + readonly override: boolean +} + +const getCurrentMessage = ( + issue: ParseIssue +): Effect.Effect => + getAnnotated(issue).pipe( + Option.flatMap(AST.getMessageAnnotation), + Effect.flatMap((annotation) => { + const out = annotation(issue) + return Predicate.isString(out) + ? Effect.succeed({ message: out, override: false }) + : Effect.isEffect(out) + ? Effect.map(out, (message) => ({ message, override: false })) + : Predicate.isString(out.message) + ? Effect.succeed({ message: out.message, override: out.override }) + : Effect.map(out.message, (message) => ({ message, override: out.override })) + }) + ) + +const createParseIssueGuard = + (tag: T) => (issue: ParseIssue): issue is Extract => + issue._tag === tag + +/** + * Returns `true` if the value is a `Composite`. + * + * @category guards + * @since 3.10.0 + */ +export const isComposite = createParseIssueGuard("Composite") + +const isRefinement = createParseIssueGuard("Refinement") +const isTransformation = createParseIssueGuard("Transformation") + +const getMessage: ( + issue: ParseIssue +) => Effect.Effect = (issue: ParseIssue) => + getCurrentMessage(issue).pipe( + Effect.flatMap((currentMessage) => { + const useInnerMessage = !currentMessage.override && ( + isComposite(issue) || + (isRefinement(issue) && issue.kind === "From") || + (isTransformation(issue) && issue.kind !== "Transformation") + ) + return useInnerMessage + ? isTransformation(issue) || isRefinement(issue) ? getMessage(issue.issue) : Option.none() + : Effect.succeed(currentMessage.message) + }) + ) + +const getParseIssueTitleAnnotation = (issue: ParseIssue): Option.Option => + getAnnotated(issue).pipe( + Option.flatMap(AST.getParseIssueTitleAnnotation), + Option.filterMap( + (annotation) => Option.fromNullable(annotation(issue)) + ) + ) + +const formatTypeMessage = (e: Type): Effect.Effect => + getMessage(e).pipe( + Effect.orElse(() => getParseIssueTitleAnnotation(e)), + Effect.catchAll(() => + Effect.succeed(e.message ?? `Expected ${String(e.ast)}, actual ${util_.formatUnknown(e.actual)}`) + ) + ) + +const getParseIssueTitle = ( + issue: Forbidden | Transformation | Refinement | Composite +): string => Option.getOrElse(getParseIssueTitleAnnotation(issue), () => String(issue.ast)) + +const formatForbiddenMessage = (e: Forbidden): string => e.message ?? "is forbidden" + +const formatUnexpectedMessage = (e: Unexpected): string => e.message ?? "is unexpected" + +const formatMissingMessage = (e: Missing): Effect.Effect => + AST.getMissingMessageAnnotation(e.ast).pipe( + Effect.flatMap((annotation) => { + const out = annotation() + return Predicate.isString(out) ? Effect.succeed(out) : out + }), + Effect.catchAll(() => Effect.succeed(e.message ?? "is missing")) + ) + +const getTree = (issue: ParseIssue, onFailure: () => Effect.Effect>) => + Effect.matchEffect(getMessage(issue), { + onFailure, + onSuccess: (message) => Effect.succeed(makeTree(message)) + }) + +const formatTree = ( + e: ParseIssue | Pointer +): Effect.Effect> => { + switch (e._tag) { + case "Type": + return Effect.map(formatTypeMessage(e), makeTree) + case "Forbidden": + return Effect.succeed(makeTree(getParseIssueTitle(e), [makeTree(formatForbiddenMessage(e))])) + case "Unexpected": + return Effect.succeed(makeTree(formatUnexpectedMessage(e))) + case "Missing": + return Effect.map(formatMissingMessage(e), makeTree) + case "Transformation": + return getTree(e, () => + Effect.map( + formatTree(e.issue), + (tree) => makeTree(getParseIssueTitle(e), [makeTree(formatTransformationKind(e.kind), [tree])]) + )) + case "Refinement": + return getTree( + e, + () => + Effect.map( + formatTree(e.issue), + (tree) => makeTree(getParseIssueTitle(e), [makeTree(formatRefinementKind(e.kind), [tree])]) + ) + ) + case "Pointer": + return Effect.map(formatTree(e.issue), (tree) => makeTree(util_.formatPath(e.path), [tree])) + case "Composite": { + const parseIssueTitle = getParseIssueTitle(e) + return getTree( + e, + () => + util_.isNonEmpty(e.issues) + ? Effect.map(Effect.forEach(e.issues, formatTree), (forest) => makeTree(parseIssueTitle, forest)) + : Effect.map(formatTree(e.issues), (tree) => makeTree(parseIssueTitle, [tree])) + ) + } + } +} + +/** + * @category model + * @since 3.10.0 + */ +export interface ArrayFormatterIssue { + readonly _tag: ParseIssue["_tag"] + readonly path: ReadonlyArray + readonly message: string +} + +/** + * @category formatting + * @since 3.10.0 + */ +export const ArrayFormatter: ParseResultFormatter> = { + formatIssue: (issue) => formatArray(issue), + formatIssueSync: (issue) => Effect.runSync(ArrayFormatter.formatIssue(issue)), + formatError: (error) => ArrayFormatter.formatIssue(error.issue), + formatErrorSync: (error) => ArrayFormatter.formatIssueSync(error.issue) +} + +const succeedArrayFormatterIssue = (issue: ArrayFormatterIssue) => Effect.succeed([issue]) + +const getArray = ( + issue: ParseIssue, + path: ReadonlyArray, + onFailure: () => Effect.Effect> +) => + Effect.matchEffect(getMessage(issue), { + onFailure, + onSuccess: (message) => succeedArrayFormatterIssue({ _tag: issue._tag, path, message }) + }) + +const formatArray = ( + e: ParseIssue | Pointer, + path: ReadonlyArray = [] +): Effect.Effect> => { + const _tag = e._tag + switch (_tag) { + case "Type": + return Effect.map(formatTypeMessage(e), (message) => [{ _tag, path, message }]) + case "Forbidden": + return succeedArrayFormatterIssue({ _tag, path, message: formatForbiddenMessage(e) }) + case "Unexpected": + return succeedArrayFormatterIssue({ _tag, path, message: formatUnexpectedMessage(e) }) + case "Missing": + return Effect.map(formatMissingMessage(e), (message) => [{ _tag, path, message }]) + case "Pointer": + return formatArray(e.issue, path.concat(e.path)) + case "Composite": + return getArray(e, path, () => + util_.isNonEmpty(e.issues) + ? Effect.map(Effect.forEach(e.issues, (issue) => formatArray(issue, path)), array_.flatten) + : formatArray(e.issues, path)) + case "Refinement": + case "Transformation": + return getArray(e, path, () => formatArray(e.issue, path)) + } +} diff --git a/packages/schema/src/Pretty.ts b/packages/effect/src/Pretty.ts similarity index 82% rename from packages/schema/src/Pretty.ts rename to packages/effect/src/Pretty.ts index bff905d33b..c301c0c938 100644 --- a/packages/schema/src/Pretty.ts +++ b/packages/effect/src/Pretty.ts @@ -1,54 +1,40 @@ /** - * @since 0.67.0 + * @since 3.10.0 */ -import * as Arr from "effect/Array" -import * as Option from "effect/Option" -import * as AST from "./AST.js" -import * as errors_ from "./internal/errors.js" -import * as util_ from "./internal/util.js" +import * as Arr from "./Array.js" +import * as errors_ from "./internal/schema/errors.js" +import * as util_ from "./internal/schema/util.js" +import * as Option from "./Option.js" import * as ParseResult from "./ParseResult.js" import type * as Schema from "./Schema.js" +import * as AST from "./SchemaAST.js" /** * @category model - * @since 0.67.0 + * @since 3.10.0 */ export interface Pretty { (a: To): string } -/** - * @category hooks - * @since 0.67.0 - */ -export const PrettyHookId: unique symbol = Symbol.for("@effect/schema/PrettyHookId") - -/** - * @category hooks - * @since 0.67.0 - */ -export type PrettyHookId = typeof PrettyHookId - /** * @category annotations - * @since 0.67.0 + * @since 3.10.0 */ -export const pretty = - (handler: (...args: ReadonlyArray>) => Pretty) => - (self: Schema.Schema): Schema.Schema => self.annotations({ [PrettyHookId]: handler }) +export type PrettyAnnotation = readonly []> = ( + ...pretties: { readonly [K in keyof TypeParameters]: Pretty } +) => Pretty /** * @category prettify - * @since 0.67.0 + * @since 3.10.0 */ export const make = (schema: Schema.Schema): (a: A) => string => compile(schema.ast, []) -const getHook = AST.getAnnotation<(...args: ReadonlyArray>) => Pretty>( - PrettyHookId -) +const getPrettyAnnotation = AST.getAnnotation>(AST.PrettyAnnotationId) const getMatcher = (defaultPretty: Pretty) => (ast: AST.AST): Pretty => - Option.match(getHook(ast), { + Option.match(getPrettyAnnotation(ast), { onNone: () => defaultPretty, onSome: (handler) => handler() }) @@ -60,13 +46,13 @@ const stringify = getMatcher((a) => JSON.stringify(a)) const formatUnknown = getMatcher(util_.formatUnknown) /** - * @since 0.67.0 + * @since 3.10.0 */ export const match: AST.Match> = { "Declaration": (ast, go, path) => { - const hook = getHook(ast) - if (Option.isSome(hook)) { - return hook.value(...ast.typeParameters.map((tp) => go(tp, path))) + const annotation = getPrettyAnnotation(ast) + if (Option.isSome(annotation)) { + return annotation.value(...ast.typeParameters.map((tp) => go(tp, path))) } throw new Error(errors_.getPrettyMissingAnnotationErrorMessage(path, ast)) }, @@ -92,7 +78,7 @@ export const match: AST.Match> = { "BigIntKeyword": getMatcher((a) => `${String(a)}n`), "Enums": stringify, "TupleType": (ast, go, path) => { - const hook = getHook(ast) + const hook = getPrettyAnnotation(ast) if (Option.isSome(hook)) { return hook.value() } @@ -134,7 +120,7 @@ export const match: AST.Match> = { } }, "TypeLiteral": (ast, go, path) => { - const hook = getHook(ast) + const hook = getPrettyAnnotation(ast) if (Option.isSome(hook)) { return hook.value() } @@ -179,7 +165,7 @@ export const match: AST.Match> = { } }, "Union": (ast, go, path) => { - const hook = getHook(ast) + const hook = getPrettyAnnotation(ast) if (Option.isSome(hook)) { return hook.value() } @@ -193,7 +179,7 @@ export const match: AST.Match> = { } }, "Suspend": (ast, go, path) => { - return Option.match(getHook(ast), { + return Option.match(getPrettyAnnotation(ast), { onNone: () => { const get = util_.memoizeThunk(() => go(ast.f(), path)) return (a) => get()(a) @@ -202,13 +188,13 @@ export const match: AST.Match> = { }) }, "Refinement": (ast, go, path) => { - return Option.match(getHook(ast), { + return Option.match(getPrettyAnnotation(ast), { onNone: () => go(ast.from, path), onSome: (handler) => handler() }) }, "Transformation": (ast, go, path) => { - return Option.match(getHook(ast), { + return Option.match(getPrettyAnnotation(ast), { onNone: () => go(ast.to, path), onSome: (handler) => handler() }) diff --git a/packages/schema/src/Schema.ts b/packages/effect/src/Schema.ts similarity index 84% rename from packages/schema/src/Schema.ts rename to packages/effect/src/Schema.ts index 32c7bd1fd9..512cd08b52 100644 --- a/packages/schema/src/Schema.ts +++ b/packages/effect/src/Schema.ts @@ -1,91 +1,86 @@ /** - * @since 0.67.0 - */ - -import * as array_ from "effect/Array" -import * as bigDecimal_ from "effect/BigDecimal" -import * as bigInt_ from "effect/BigInt" -import * as boolean_ from "effect/Boolean" -import type { Brand } from "effect/Brand" -import * as cause_ from "effect/Cause" -import * as chunk_ from "effect/Chunk" -import * as config_ from "effect/Config" -import * as configError_ from "effect/ConfigError" -import * as data_ from "effect/Data" -import * as dateTime from "effect/DateTime" -import * as duration_ from "effect/Duration" -import * as Effect from "effect/Effect" -import * as either_ from "effect/Either" -import * as Encoding from "effect/Encoding" -import * as Equal from "effect/Equal" -import * as Equivalence from "effect/Equivalence" -import * as exit_ from "effect/Exit" -import * as fiberId_ from "effect/FiberId" -import type { LazyArg } from "effect/Function" -import { dual, identity } from "effect/Function" -import * as hashMap_ from "effect/HashMap" -import * as hashSet_ from "effect/HashSet" -import * as list_ from "effect/List" -import * as number_ from "effect/Number" -import * as option_ from "effect/Option" -import type * as Order from "effect/Order" -import type { Pipeable } from "effect/Pipeable" -import { pipeArguments } from "effect/Pipeable" -import * as Predicate from "effect/Predicate" -import * as record_ from "effect/Record" -import * as redacted_ from "effect/Redacted" -import * as Request from "effect/Request" -import * as sortedSet_ from "effect/SortedSet" -import * as string_ from "effect/String" -import * as struct_ from "effect/Struct" -import type * as Types from "effect/Types" -import type { GenerationContext, LazyArbitrary } from "./Arbitrary.js" -import * as arbitrary_ from "./Arbitrary.js" -import type { ParseOptions } from "./AST.js" -import * as AST from "./AST.js" -import * as equivalence_ from "./Equivalence.js" + * @since 3.10.0 + */ + +import type { ArbitraryAnnotation, ArbitraryGenerationContext, LazyArbitrary } from "./Arbitrary.js" +import * as array_ from "./Array.js" +import * as bigDecimal_ from "./BigDecimal.js" +import * as bigInt_ from "./BigInt.js" +import * as boolean_ from "./Boolean.js" +import type { Brand } from "./Brand.js" +import * as cause_ from "./Cause.js" +import * as chunk_ from "./Chunk.js" +import * as config_ from "./Config.js" +import * as configError_ from "./ConfigError.js" +import * as data_ from "./Data.js" +import * as dateTime from "./DateTime.js" +import * as duration_ from "./Duration.js" +import * as Effect from "./Effect.js" +import * as either_ from "./Either.js" +import * as Encoding from "./Encoding.js" +import * as Equal from "./Equal.js" +import * as Equivalence from "./Equivalence.js" +import * as exit_ from "./Exit.js" import * as fastCheck_ from "./FastCheck.js" -import * as errors_ from "./internal/errors.js" -import * as filters_ from "./internal/filters.js" -import * as serializable_ from "./internal/serializable.js" -import * as util_ from "./internal/util.js" +import * as fiberId_ from "./FiberId.js" +import type { LazyArg } from "./Function.js" +import { dual, identity } from "./Function.js" +import { globalValue } from "./GlobalValue.js" +import * as hashMap_ from "./HashMap.js" +import * as hashSet_ from "./HashSet.js" +import * as errors_ from "./internal/schema/errors.js" +import * as filters_ from "./internal/schema/filters.js" +import * as util_ from "./internal/schema/util.js" +import * as list_ from "./List.js" +import * as number_ from "./Number.js" +import * as option_ from "./Option.js" +import type * as Order from "./Order.js" import * as ParseResult from "./ParseResult.js" -import * as pretty_ from "./Pretty.js" -import type * as Serializable from "./Serializable.js" -import * as TreeFormatter from "./TreeFormatter.js" - -/** - * @since 0.68.2 +import type { Pipeable } from "./Pipeable.js" +import { pipeArguments } from "./Pipeable.js" +import * as Predicate from "./Predicate.js" +import type * as pretty_ from "./Pretty.js" +import * as record_ from "./Record.js" +import * as redacted_ from "./Redacted.js" +import * as Request from "./Request.js" +import type { ParseOptions } from "./SchemaAST.js" +import * as AST from "./SchemaAST.js" +import * as sortedSet_ from "./SortedSet.js" +import * as string_ from "./String.js" +import * as struct_ from "./Struct.js" +import type * as Types from "./Types.js" + +/** + * @since 3.10.0 */ export type Simplify = { [K in keyof A]: A[K] } & {} /** - * @since 0.67.0 + * @since 3.10.0 */ export type SimplifyMutable = { -readonly [K in keyof A]: A[K] } extends infer B ? B : never /** - * @since 0.67.0 + * @since 3.10.0 * @category symbol */ -export const TypeId: unique symbol = Symbol.for("@effect/schema/Schema") +export const TypeId: unique symbol = Symbol.for("effect/Schema") /** - * @since 0.67.0 + * @since 3.10.0 * @category symbol */ export type TypeId = typeof TypeId /** * @category model - * @since 0.67.0 + * @since 3.10.0 */ export interface Schema extends Schema.Variance, Pipeable { readonly Type: A readonly Encoded: I - /** @since 0.69.3 */ readonly Context: R readonly ast: AST.AST /** @@ -97,13 +92,13 @@ export interface Schema extends Schema.Va /** * @category model - * @since 0.67.0 + * @since 3.10.0 */ export interface SchemaClass extends AnnotableClass, A, I, R> {} /** * @category constructors - * @since 0.67.0 + * @since 3.10.0 */ export const make = (ast: AST.AST): SchemaClass => class SchemaClass { @@ -137,52 +132,42 @@ interface AllAnnotations> extends Annotations.Schema, PropertySignature.Annotations {} +const builtInAnnotations = { + schemaId: AST.SchemaIdAnnotationId, + message: AST.MessageAnnotationId, + missingMessage: AST.MissingMessageAnnotationId, + identifier: AST.IdentifierAnnotationId, + title: AST.TitleAnnotationId, + description: AST.DescriptionAnnotationId, + examples: AST.ExamplesAnnotationId, + default: AST.DefaultAnnotationId, + documentation: AST.DocumentationAnnotationId, + jsonSchema: AST.JSONSchemaAnnotationId, + arbitrary: AST.ArbitraryAnnotationId, + pretty: AST.PrettyAnnotationId, + equivalence: AST.EquivalenceAnnotationId, + concurrency: AST.ConcurrencyAnnotationId, + batching: AST.BatchingAnnotationId, + parseIssueTitle: AST.ParseIssueTitleAnnotationId, + parseOptions: AST.ParseOptionsAnnotationId, + decodingFallback: AST.DecodingFallbackAnnotationId +} + const toASTAnnotations = >( annotations?: AllAnnotations ): AST.Annotations => { if (!annotations) { return {} } - const out: Types.Mutable = {} + const out: Types.Mutable = { ...annotations } - // symbols are reserved for custom annotations - const custom = Object.getOwnPropertySymbols(annotations) - for (const sym of custom) { - out[sym] = annotations[sym] - } - - // string keys are reserved as /schema namespace - if (annotations.typeId !== undefined) { - const typeId = annotations.typeId - if (typeof typeId === "object") { - out[AST.TypeAnnotationId] = typeId.id - out[typeId.id] = typeId.annotation - } else { - out[AST.TypeAnnotationId] = typeId + for (const key in builtInAnnotations) { + if (key in annotations) { + const id = builtInAnnotations[key as keyof typeof builtInAnnotations] + out[id] = annotations[key as keyof typeof annotations] + delete out[key] } } - const move = (from: keyof typeof annotations, to: symbol) => { - if (annotations[from] !== undefined) { - out[to] = annotations[from] - } - } - move("message", AST.MessageAnnotationId) - move("missingMessage", AST.MissingMessageAnnotationId) - move("identifier", AST.IdentifierAnnotationId) - move("title", AST.TitleAnnotationId) - move("description", AST.DescriptionAnnotationId) - move("examples", AST.ExamplesAnnotationId) - move("default", AST.DefaultAnnotationId) - move("documentation", AST.DocumentationAnnotationId) - move("jsonSchema", AST.JSONSchemaAnnotationId) - move("arbitrary", arbitrary_.ArbitraryHookId) - move("pretty", pretty_.PrettyHookId) - move("equivalence", equivalence_.EquivalenceHookId) - move("concurrency", AST.ConcurrencyAnnotationId) - move("batching", AST.BatchingAnnotationId) - move("parseIssueTitle", AST.ParseIssueTitleAnnotationId) - move("parseOptions", AST.ParseOptionsAnnotationId) - move("decodingFallback", AST.DecodingFallbackAnnotationId) return out } @@ -192,21 +177,21 @@ const mergeSchemaAnnotations = (ast: AST.AST, annotations: Annotations.Schema /** * @category annotations - * @since 0.67.0 + * @since 3.10.0 */ export declare namespace Annotable { /** - * @since 0.67.0 + * @since 3.10.0 */ export type Self = ReturnType /** - * @since 0.67.0 + * @since 3.10.0 */ export type Any = Annotable /** - * @since 0.67.0 + * @since 3.10.0 */ export type All = | Any @@ -217,7 +202,7 @@ export declare namespace Annotable { /** * @category annotations - * @since 0.67.0 + * @since 3.10.0 */ export interface Annotable, A, I = A, R = never> extends Schema { annotations(annotations: Annotations.Schema): Self @@ -225,14 +210,14 @@ export interface Annotable, A, I = A, R = never> ex /** * @category annotations - * @since 0.67.0 + * @since 3.10.0 */ export interface AnnotableClass, A, I = A, R = never> extends Annotable { new(_: never): Schema.Variance } /** - * @since 0.67.0 + * @since 3.10.0 */ export const asSchema = ( schema: S @@ -240,16 +225,16 @@ export const asSchema = ( /** * @category formatting - * @since 0.67.0 + * @since 3.10.0 */ export const format = (schema: S): string => String(schema.ast) /** - * @since 0.67.0 + * @since 3.10.0 */ export declare namespace Schema { /** - * @since 0.67.0 + * @since 3.10.0 */ export interface Variance { readonly [TypeId]: { @@ -260,22 +245,22 @@ export declare namespace Schema { } /** - * @since 0.67.0 + * @since 3.10.0 */ export type Type = S extends Schema.Variance ? A : never /** - * @since 0.67.0 + * @since 3.10.0 */ export type Encoded = S extends Schema.Variance ? I : never /** - * @since 0.67.0 + * @since 3.10.0 */ export type Context = S extends Schema.Variance ? R : never /** - * @since 0.67.0 + * @since 3.10.0 */ export type ToAsserts = ( input: unknown, @@ -285,21 +270,21 @@ export declare namespace Schema { /** * Any schema, except for `never`. * - * @since 0.67.0 + * @since 3.10.0 */ export type Any = Schema /** * Any schema with `Context = never`, except for `never`. * - * @since 0.67.0 + * @since 3.10.0 */ export type AnyNoContext = Schema /** * Any schema, including `never`. * - * @since 0.67.0 + * @since 3.10.0 */ export type All = | Any @@ -310,7 +295,7 @@ export declare namespace Schema { /** * Type-level counterpart of `Schema.asSchema` function. * - * @since 0.67.0 + * @since 3.10.0 */ export type AsSchema = Schema, Encoded, Context> } @@ -321,7 +306,7 @@ export declare namespace Schema { * original schema without retaining any refinements or transformations that * were applied previously. * - * @since 0.67.0 + * @since 3.10.0 */ export const encodedSchema = (schema: Schema): SchemaClass => make(AST.encodedAST(schema.ast)) @@ -329,7 +314,7 @@ export const encodedSchema = (schema: Schema): SchemaClass * The `encodedBoundSchema` function is similar to `encodedSchema` but preserves * the refinements up to the first transformation point in the original schema. * - * @since 0.67.17 + * @since 3.10.0 */ export const encodedBoundSchema = (schema: Schema): SchemaClass => make(AST.encodedBoundAST(schema.ast)) @@ -340,7 +325,7 @@ export const encodedBoundSchema = (schema: Schema): SchemaClas * original schema without considering the initial encoding or transformation * processes. * - * @since 0.67.0 + * @since 3.10.0 */ export const typeSchema = (schema: Schema): SchemaClass => make(AST.typeAST(schema.ast)) @@ -351,69 +336,69 @@ export { * * @throws `ParseError` * @category validation - * @since 0.67.0 + * @since 3.10.0 */ asserts, /** * @category decoding - * @since 0.67.0 + * @since 3.10.0 */ decodeOption, /** * @throws `ParseError` * @category decoding - * @since 0.67.0 + * @since 3.10.0 */ decodeSync, /** * @category decoding - * @since 0.67.0 + * @since 3.10.0 */ decodeUnknownOption, /** * @throws `ParseError` * @category decoding - * @since 0.67.0 + * @since 3.10.0 */ decodeUnknownSync, /** * @category encoding - * @since 0.67.0 + * @since 3.10.0 */ encodeOption, /** * @throws `ParseError` * @category encoding - * @since 0.67.0 + * @since 3.10.0 */ encodeSync, /** * @category encoding - * @since 0.67.0 + * @since 3.10.0 */ encodeUnknownOption, /** * @throws `ParseError` * @category encoding - * @since 0.67.0 + * @since 3.10.0 */ encodeUnknownSync, /** * By default the option `exact` is set to `true`. * * @category validation - * @since 0.67.0 + * @since 3.10.0 */ is, /** * @category validation - * @since 0.67.0 + * @since 3.10.0 */ validateOption, /** * @throws `ParseError` * @category validation - * @since 0.67.0 + * @since 3.10.0 */ validateSync } from "./ParseResult.js" @@ -421,7 +406,7 @@ export { /** * @category encoding - * @since 0.67.0 + * @since 3.10.0 */ export const encodeUnknown = ( schema: Schema, @@ -434,7 +419,7 @@ export const encodeUnknown = ( /** * @category encoding - * @since 0.67.0 + * @since 3.10.0 */ export const encodeUnknownEither = ( schema: Schema, @@ -447,7 +432,7 @@ export const encodeUnknownEither = ( /** * @category encoding - * @since 0.67.0 + * @since 3.10.0 */ export const encodeUnknownPromise = ( schema: Schema, @@ -459,7 +444,7 @@ export const encodeUnknownPromise = ( /** * @category encoding - * @since 0.67.0 + * @since 3.10.0 */ export const encode: ( schema: Schema, @@ -468,7 +453,7 @@ export const encode: ( /** * @category encoding - * @since 0.67.0 + * @since 3.10.0 */ export const encodeEither: ( schema: Schema, @@ -477,7 +462,7 @@ export const encodeEither: ( /** * @category encoding - * @since 0.67.0 + * @since 3.10.0 */ export const encodePromise: ( schema: Schema, @@ -486,7 +471,7 @@ export const encodePromise: ( /** * @category decoding - * @since 0.67.0 + * @since 3.10.0 */ export const decodeUnknown = ( schema: Schema, @@ -499,7 +484,7 @@ export const decodeUnknown = ( /** * @category decoding - * @since 0.67.0 + * @since 3.10.0 */ export const decodeUnknownEither = ( schema: Schema, @@ -512,7 +497,7 @@ export const decodeUnknownEither = ( /** * @category decoding - * @since 0.67.0 + * @since 3.10.0 */ export const decodeUnknownPromise = ( schema: Schema, @@ -524,7 +509,7 @@ export const decodeUnknownPromise = ( /** * @category decoding - * @since 0.67.0 + * @since 3.10.0 */ export const decode: ( schema: Schema, @@ -533,7 +518,7 @@ export const decode: ( /** * @category decoding - * @since 0.67.0 + * @since 3.10.0 */ export const decodeEither: ( schema: Schema, @@ -542,7 +527,7 @@ export const decodeEither: ( /** * @category decoding - * @since 0.67.0 + * @since 3.10.0 */ export const decodePromise: ( schema: Schema, @@ -551,7 +536,7 @@ export const decodePromise: ( /** * @category validation - * @since 0.67.0 + * @since 3.10.0 */ export const validate = ( schema: Schema, @@ -564,7 +549,7 @@ export const validate = ( /** * @category validation - * @since 0.67.0 + * @since 3.10.0 */ export const validateEither = ( schema: Schema, @@ -577,7 +562,7 @@ export const validateEither = ( /** * @category validation - * @since 0.67.0 + * @since 3.10.0 */ export const validatePromise = ( schema: Schema, @@ -591,14 +576,14 @@ export const validatePromise = ( * Tests if a value is a `Schema`. * * @category guards - * @since 0.67.0 + * @since 3.10.0 */ export const isSchema = (u: unknown): u is Schema.Any => Predicate.hasProperty(u, TypeId) && Predicate.isObject(u[TypeId]) /** * @category api interface - * @since 0.67.0 + * @since 3.10.0 */ export interface Literal> extends AnnotableClass, Literals[number]> @@ -626,7 +611,7 @@ const makeLiteralClass = >( ...literals: Literals @@ -645,17 +630,17 @@ export function Literal>( * Creates a new `Schema` from a literal schema. * * @example - * import * as S from "@effect/schema/Schema" + * import * as Schema from "effect/Schema" * import { Either } from "effect" * - * const schema = S.Literal("a", "b", "c").pipe(S.pickLiteral("a", "b")) + * const schema = Schema.Literal("a", "b", "c").pipe(Schema.pickLiteral("a", "b")) * - * assert.deepStrictEqual(S.decodeSync(schema)("a"), "a") - * assert.deepStrictEqual(S.decodeSync(schema)("b"), "b") - * assert.strictEqual(Either.isLeft(S.decodeUnknownEither(schema)("c")), true) + * assert.deepStrictEqual(Schema.decodeSync(schema)("a"), "a") + * assert.deepStrictEqual(Schema.decodeSync(schema)("b"), "b") + * assert.strictEqual(Either.isLeft(Schema.decodeUnknownEither(schema)("c")), true) * * @category constructors - * @since 0.67.0 + * @since 3.10.0 */ export const pickLiteral = >(...literals: L) => @@ -663,20 +648,20 @@ export const pickLiteral = /** * @category constructors - * @since 0.67.0 + * @since 3.10.0 */ export const UniqueSymbolFromSelf = (symbol: S): SchemaClass => make(new AST.UniqueSymbol(symbol)) /** * @category api interface - * @since 0.67.0 + * @since 3.10.0 */ export interface Enums extends AnnotableClass, A[keyof A]> { readonly enums: A } /** - * @since 0.67.0 + * @since 3.10.0 */ export type EnumsDefinition = { [x: string]: string | number } @@ -701,7 +686,7 @@ const makeEnumsClass = ( /** * @category constructors - * @since 0.67.0 + * @since 3.10.0 */ export const Enums = (enums: A): Enums => makeEnumsClass(enums) @@ -711,7 +696,7 @@ type Join = Params extends [infer Head, ...infer Tail] ? /** * @category API interface - * @since 0.67.17 + * @since 3.10.0 */ export interface TemplateLiteral extends SchemaClass {} @@ -719,7 +704,7 @@ type TemplateLiteralParameter = Schema.AnyNoContext | AST.LiteralValue /** * @category template literal - * @since 0.67.0 + * @since 3.10.0 */ export const TemplateLiteral = >( ...[head, ...tail]: Params @@ -797,7 +782,7 @@ type TemplateLiteralParserParametersEncoded = T extends [infer Head, ...infer /** * @category API interface - * @since 0.70.1 + * @since 3.10.0 */ export interface TemplateLiteralParser> extends @@ -812,7 +797,7 @@ export interface TemplateLiteralParser>( ...params: Params @@ -913,7 +898,7 @@ const declarePrimitive = ( * This ensures that when you call `Schema.to` or `Schema.from`, you receive a schema with a `never` context. * * @category constructors - * @since 0.67.0 + * @since 3.10.0 */ export const declare: { ( @@ -953,14 +938,14 @@ export const declare: { } as any /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export const BrandTypeId: unique symbol = Symbol.for("@effect/schema/TypeId/Brand") +export const BrandSchemaId: unique symbol = Symbol.for("effect/SchemaId/Brand") /** * @category constructors - * @since 0.67.0 + * @since 3.10.0 */ export const fromBrand = , A extends Brand.Unbranded>( constructor: Brand.Constructor, @@ -976,25 +961,29 @@ export const fromBrand = , A extends Brand.Unbr option_.some(new ParseResult.Type(ast, a, either.left.map((v) => v.message).join(", "))) : option_.none() }, - toASTAnnotations({ typeId: { id: BrandTypeId, annotation: { constructor } }, ...annotations }) + toASTAnnotations({ + schemaId: BrandSchemaId, + [BrandSchemaId]: { constructor }, + ...annotations + }) ) ) /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export const InstanceOfTypeId: unique symbol = Symbol.for("@effect/schema/TypeId/InstanceOf") +export const InstanceOfSchemaId: unique symbol = Symbol.for("effect/SchemaId/InstanceOf") /** * @category api interface - * @since 0.67.0 + * @since 3.10.0 */ export interface instanceOf extends AnnotableClass, A> {} /** * @category constructors - * @since 0.67.0 + * @since 3.10.0 */ export const instanceOf = any>( constructor: A, @@ -1006,56 +995,57 @@ export const instanceOf = any>( title: constructor.name, description: `an instance of ${constructor.name}`, pretty: (): pretty_.Pretty> => String, - typeId: { id: InstanceOfTypeId, annotation: { constructor } }, + schemaId: InstanceOfSchemaId, + [InstanceOfSchemaId]: { constructor }, ...annotations } ) /** * @category primitives - * @since 0.67.0 + * @since 3.10.0 */ export class Undefined extends make(AST.undefinedKeyword) {} /** * @category primitives - * @since 0.67.0 + * @since 3.10.0 */ export class Void extends make(AST.voidKeyword) {} /** * @category primitives - * @since 0.67.0 + * @since 3.10.0 */ export class Null extends make(AST.null) {} /** * @category primitives - * @since 0.67.0 + * @since 3.10.0 */ export class Never extends make(AST.neverKeyword) {} /** * @category primitives - * @since 0.67.0 + * @since 3.10.0 */ export class Unknown extends make(AST.unknownKeyword) {} /** * @category primitives - * @since 0.67.0 + * @since 3.10.0 */ export class Any extends make(AST.anyKeyword) {} /** * @category primitives - * @since 0.67.0 + * @since 3.10.0 */ export class BigIntFromSelf extends make(AST.bigIntKeyword) {} /** * @category primitives - * @since 0.67.0 + * @since 3.10.0 */ export class SymbolFromSelf extends make(AST.symbolKeyword) {} @@ -1074,29 +1064,29 @@ class Object$ extends make(AST.objectKeyword) {} export { /** * @category primitives - * @since 0.67.0 + * @since 3.10.0 */ Boolean$ as Boolean, /** * @category primitives - * @since 0.67.0 + * @since 3.10.0 */ Number$ as Number, /** * @category primitives - * @since 0.67.0 + * @since 3.10.0 */ Object$ as Object, /** * @category primitives - * @since 0.67.0 + * @since 3.10.0 */ String$ as String } /** * @category api interface - * @since 0.67.0 + * @since 3.10.0 */ export interface Union> extends AnnotableClass< @@ -1129,7 +1119,7 @@ const makeUnionClass = >( /** * @category combinators - * @since 0.67.0 + * @since 3.10.0 */ export function Union>(...members: Members): Union export function Union(member: Member): Member @@ -1149,7 +1139,7 @@ export function Union>( /** * @category api interface - * @since 0.67.0 + * @since 3.10.0 */ export interface NullOr extends Union<[S, typeof Null]> { annotations(annotations: Annotations.Schema | null>): NullOr @@ -1157,13 +1147,13 @@ export interface NullOr extends Union<[S, typeof Null]> { /** * @category combinators - * @since 0.67.0 + * @since 3.10.0 */ export const NullOr = (self: S): NullOr => Union(self, Null) /** * @category api interface - * @since 0.67.0 + * @since 3.10.0 */ export interface UndefinedOr extends Union<[S, typeof Undefined]> { annotations(annotations: Annotations.Schema | undefined>): UndefinedOr @@ -1171,13 +1161,13 @@ export interface UndefinedOr extends Union<[S, typeof Unde /** * @category combinators - * @since 0.67.0 + * @since 3.10.0 */ export const UndefinedOr = (self: S): UndefinedOr => Union(self, Undefined) /** * @category api interface - * @since 0.67.0 + * @since 3.10.0 */ export interface NullishOr extends Union<[S, typeof Null, typeof Undefined]> { annotations(annotations: Annotations.Schema | null | undefined>): NullishOr @@ -1185,36 +1175,36 @@ export interface NullishOr extends Union<[S, typeof Null, /** * @category combinators - * @since 0.67.0 + * @since 3.10.0 */ export const NullishOr = (self: S): NullishOr => Union(self, Null, Undefined) /** * @category combinators - * @since 0.67.0 + * @since 3.10.0 */ export const keyof = (self: Schema): SchemaClass => make(AST.keyof(self.ast)) /** - * @since 0.68.0 + * @since 3.10.0 */ export declare namespace Element { /** - * @since 0.68.0 + * @since 3.10.0 */ export interface Annotations extends Annotations.Doc { readonly missingMessage?: AST.MissingMessageAnnotation } /** - * @since 0.68.0 + * @since 3.10.0 */ export type Token = "" | "?" } /** * @category API interface - * @since 0.68.0 + * @since 3.10.0 */ export interface Element extends Schema.Variance, Schema.Encoded, Schema.Context> @@ -1226,13 +1216,13 @@ export interface Element } /** - * @since 0.68.0 + * @since 3.10.0 */ export const element = (self: S): Element => new ElementImpl(new AST.OptionalType(self.ast, false), self) /** - * @since 0.67.0 + * @since 3.10.0 */ export const optionalElement = (self: S): Element => new ElementImpl(new AST.OptionalType(self.ast, true), self) @@ -1262,7 +1252,7 @@ class ElementImpl implements } /** - * @since 0.67.0 + * @since 3.10.0 */ export declare namespace TupleType { type ElementsType< @@ -1282,17 +1272,17 @@ export declare namespace TupleType { : Out /** - * @since 0.67.0 + * @since 3.10.0 */ export type Elements = ReadonlyArray> /** - * @since 0.68.0 + * @since 3.10.0 */ export type Rest = ReadonlyArray> /** - * @since 0.67.0 + * @since 3.10.0 */ export type Type = Rest extends [infer Head, ...infer Tail] ? Readonly<[ @@ -1303,7 +1293,7 @@ export declare namespace TupleType { ElementsType /** - * @since 0.67.0 + * @since 3.10.0 */ export type Encoded = Rest extends [infer Head, ...infer Tail] ? Readonly<[ @@ -1316,7 +1306,7 @@ export declare namespace TupleType { /** * @category api interface - * @since 0.67.0 + * @since 3.10.0 */ export interface TupleType extends AnnotableClass< @@ -1363,7 +1353,7 @@ const makeTupleTypeClass = extends TupleType { annotations(annotations: Annotations.Schema>): Tuple @@ -1371,7 +1361,7 @@ export interface Tuple extends TupleType): any { /** * @category api interface - * @since 0.67.0 + * @since 3.10.0 */ export interface Array$ extends TupleType<[], [Value]> { readonly value: Value @@ -1407,14 +1397,14 @@ const Array$ = (value: Value): Array$ => makeAr export { /** * @category constructors - * @since 0.67.0 + * @since 3.10.0 */ Array$ as Array } /** * @category api interface - * @since 0.67.0 + * @since 3.10.0 */ export interface NonEmptyArray extends TupleType<[Value], [Value]> { readonly value: Value @@ -1432,14 +1422,14 @@ const makeNonEmptyArrayClass = (value: Value, ast?: AS /** * @category constructors - * @since 0.67.0 + * @since 3.10.0 */ export const NonEmptyArray = (value: Value): NonEmptyArray => makeNonEmptyArrayClass(value) /** * @category api interface - * @since 0.71.0 + * @since 3.10.0 */ export interface ArrayEnsure extends AnnotableClass< @@ -1452,7 +1442,7 @@ export interface ArrayEnsure extends /** * @category constructors - * @since 0.71.0 + * @since 3.10.0 */ export const ArrayEnsure = (value: Value): ArrayEnsure => { const value_ = asSchema(value) @@ -1465,7 +1455,7 @@ export const ArrayEnsure = (value: Value): ArrayEnsure /** * @category api interface - * @since 0.71.0 + * @since 3.10.0 */ export interface NonEmptyArrayEnsure extends AnnotableClass< @@ -1478,7 +1468,7 @@ export interface NonEmptyArrayEnsure extends /** * @category constructors - * @since 0.71.0 + * @since 3.10.0 */ export const NonEmptyArrayEnsure = (value: Value): NonEmptyArrayEnsure => { const value_ = asSchema(value) @@ -1492,16 +1482,16 @@ export const NonEmptyArrayEnsure = (value: Value): Non } /** - * @since 0.67.0 + * @since 3.10.0 */ export declare namespace PropertySignature { /** - * @since 0.67.0 + * @since 3.10.0 */ export type Token = "?:" | ":" /** - * @since 0.67.0 + * @since 3.10.0 */ export type Any = PropertySignature< Token, @@ -1514,7 +1504,7 @@ export declare namespace PropertySignature { > /** - * @since 0.67.0 + * @since 3.10.0 */ export type All = | Any @@ -1523,14 +1513,14 @@ export declare namespace PropertySignature { | PropertySignature /** - * @since 0.67.0 + * @since 3.10.0 */ export type AST = | PropertySignatureDeclaration | PropertySignatureTransformation /** - * @since 0.67.0 + * @since 3.10.0 */ export interface Annotations extends Annotations.Doc { readonly missingMessage?: AST.MissingMessageAnnotation @@ -1541,11 +1531,11 @@ const formatPropertySignatureToken = (isOptional: boolean): string => isOptional /** * @category PropertySignature - * @since 0.67.0 + * @since 3.10.0 */ export class PropertySignatureDeclaration extends AST.OptionalType { /** - * @since 0.67.0 + * @since 3.10.0 */ readonly _tag = "PropertySignatureDeclaration" constructor( @@ -1558,7 +1548,7 @@ export class PropertySignatureDeclaration extends AST.OptionalType { super(type, isOptional, annotations) } /** - * @since 0.67.0 + * @since 3.10.0 */ toString() { const token = formatPropertySignatureToken(this.isOptional) @@ -1569,7 +1559,7 @@ export class PropertySignatureDeclaration extends AST.OptionalType { /** * @category PropertySignature - * @since 0.67.0 + * @since 3.10.0 */ export class FromPropertySignature extends AST.OptionalType { constructor( @@ -1585,7 +1575,7 @@ export class FromPropertySignature extends AST.OptionalType { /** * @category PropertySignature - * @since 0.67.0 + * @since 3.10.0 */ export class ToPropertySignature extends AST.OptionalType { constructor( @@ -1611,11 +1601,11 @@ const formatPropertyKey = (p: PropertyKey | undefined): string => { /** * @category PropertySignature - * @since 0.67.0 + * @since 3.10.0 */ export class PropertySignatureTransformation { /** - * @since 0.67.0 + * @since 3.10.0 */ readonly _tag = "PropertySignatureTransformation" constructor( @@ -1625,7 +1615,7 @@ export class PropertySignatureTransformation { readonly encode: AST.PropertySignatureTransformation["encode"] ) {} /** - * @since 0.67.0 + * @since 3.10.0 */ toString() { return `PropertySignature<${formatPropertySignatureToken(this.to.isOptional)}, ${this.to.type}, ${ @@ -1668,19 +1658,19 @@ const mergeSignatureAnnotations = ( } /** - * @since 0.68.0 + * @since 3.10.0 * @category symbol */ -export const PropertySignatureTypeId: unique symbol = Symbol.for("@effect/schema/PropertySignature") +export const PropertySignatureTypeId: unique symbol = Symbol.for("effect/PropertySignature") /** - * @since 0.68.0 + * @since 3.10.0 * @category symbol */ export type PropertySignatureTypeId = typeof PropertySignatureTypeId /** - * @since 0.69.3 + * @since 3.10.0 * @category guards */ export const isPropertySignature = (u: unknown): u is PropertySignature.All => @@ -1688,7 +1678,7 @@ export const isPropertySignature = (u: unknown): u is PropertySignature.All => /** * @category PropertySignature - * @since 0.67.0 + * @since 3.10.0 */ export interface PropertySignature< TypeToken extends PropertySignature.Token, @@ -1748,7 +1738,7 @@ class PropertySignatureImpl< /** * @category PropertySignature - * @since 0.67.15 + * @since 3.10.0 */ export const makePropertySignature = < TypeToken extends PropertySignature.Token, @@ -1799,7 +1789,7 @@ export interface propertySignature * Lifts a `Schema` into a `PropertySignature`. * * @category PropertySignature - * @since 0.67.0 + * @since 3.10.0 */ export const propertySignature = ( self: S @@ -1813,7 +1803,7 @@ export const propertySignature = ( * Enhances a property signature with a default constructor value. * * @category PropertySignature - * @since 0.67.0 + * @since 3.10.0 */ export const withConstructorDefault: { (defaultValue: () => Types.NoInfer): < @@ -1875,7 +1865,7 @@ const applyDefaultValue = (o: option_.Option, defaultValue: () => A) => * Enhances a property signature with a default decoding value. * * @category PropertySignature - * @since 0.67.0 + * @since 3.10.0 */ export const withDecodingDefault: { (defaultValue: () => Types.NoInfer): < @@ -1932,7 +1922,7 @@ export const withDecodingDefault: { * Enhances a property signature with a default decoding value and a default constructor value. * * @category PropertySignature - * @since 0.67.0 + * @since 3.10.0 */ export const withDefaults: { (defaults: { @@ -1975,7 +1965,7 @@ export const withDefaults: { * Enhances a property signature by specifying a different key for it in the Encoded type. * * @category PropertySignature - * @since 0.67.0 + * @since 3.10.0 */ export const fromKey: { (key: Key): < @@ -2055,7 +2045,7 @@ export const fromKey: { * - `encode`: `none` as return value means the value will be missing in the output. * * @category PropertySignature - * @since 0.67.0 + * @since 3.10.0 */ export const optionalToRequired = ( from: Schema, @@ -2081,7 +2071,7 @@ export const optionalToRequired = ( * - `encode`: `none` as argument means the value is missing in the input. * * @category PropertySignature - * @since 0.67.15 + * @since 3.10.0 */ export const requiredToOptional = ( from: Schema, @@ -2111,7 +2101,7 @@ export const requiredToOptional = ( * - `none` as return value means the value will be missing in the output. * * @category PropertySignature - * @since 0.67.0 + * @since 3.10.0 */ export const optionalToOptional = ( from: Schema, @@ -2131,7 +2121,7 @@ export const optionalToOptional = ( ) /** - * @since 0.67.0 + * @since 3.10.0 */ export type OptionalOptions = { readonly default?: never @@ -2171,7 +2161,7 @@ export type OptionalOptions = { /** * @category api interface - * @since 0.67.10 + * @since 3.10.0 */ export interface optional extends PropertySignature< @@ -2190,7 +2180,7 @@ export interface optional extends /** * @category api interface - * @since 0.69.0 + * @since 3.10.0 */ export interface optionalWith extends PropertySignature< @@ -2346,7 +2336,7 @@ const optionalPropertySignatureAST = ( /** * @category PropertySignature - * @since 0.69.0 + * @since 3.10.0 */ export const optional = (self: S): optional => { const ast = self.ast === AST.undefinedKeyword || self.ast === AST.neverKeyword @@ -2357,7 +2347,7 @@ export const optional = (self: S): optional => { /** * @category PropertySignature - * @since 0.69.0 + * @since 3.10.0 */ export const optionalWith: { >>( @@ -2372,11 +2362,11 @@ export const optionalWith: { }) /** - * @since 0.67.0 + * @since 3.10.0 */ export declare namespace Struct { /** - * @since 0.67.0 + * @since 3.10.0 */ export type Fields = { readonly [x: PropertyKey]: @@ -2408,7 +2398,7 @@ export declare namespace Struct { | PropertySignature<"?:", never, PropertyKey, PropertySignature.Token, never, boolean, unknown> /** - * @since 0.67.0 + * @since 3.10.0 */ export type Type = Types.UnionToIntersection< { @@ -2418,14 +2408,14 @@ export declare namespace Struct { > extends infer Q ? Q : never /** - * @since 0.67.0 + * @since 3.10.0 */ export type Encoded = & { readonly [K in Exclude> as Key]: Schema.Encoded } & { readonly [K in EncodedTokenKeys as Key]?: Schema.Encoded } /** - * @since 0.67.0 + * @since 3.10.0 */ export type Context = Schema.Context @@ -2436,7 +2426,7 @@ export declare namespace Struct { | PropertySignature /** - * @since 0.67.0 + * @since 3.10.0 */ export type Constructor = Types.UnionToIntersection< { @@ -2448,26 +2438,26 @@ export declare namespace Struct { } /** - * @since 0.67.0 + * @since 3.10.0 */ export declare namespace IndexSignature { /** - * @since 0.67.0 + * @since 3.10.0 */ export type Record = { readonly key: Schema.All; readonly value: Schema.All } /** - * @since 0.67.0 + * @since 3.10.0 */ export type Records = ReadonlyArray /** - * @since 0.67.0 + * @since 3.10.0 */ export type NonEmptyRecords = array_.NonEmptyReadonlyArray /** - * @since 0.67.0 + * @since 3.10.0 */ export type Type< Records extends IndexSignature.Records @@ -2480,7 +2470,7 @@ export declare namespace IndexSignature { > /** - * @since 0.67.0 + * @since 3.10.0 */ export type Encoded< Records extends IndexSignature.Records @@ -2493,7 +2483,7 @@ export declare namespace IndexSignature { > /** - * @since 0.67.0 + * @since 3.10.0 */ export type Context = { [K in keyof Records]: Schema.Context | Schema.Context @@ -2501,25 +2491,25 @@ export declare namespace IndexSignature { } /** - * @since 0.67.0 + * @since 3.10.0 */ export declare namespace TypeLiteral { /** - * @since 0.67.0 + * @since 3.10.0 */ export type Type = & Struct.Type & IndexSignature.Type /** - * @since 0.67.0 + * @since 3.10.0 */ export type Encoded = & Struct.Encoded & IndexSignature.Encoded /** - * @since 0.67.0 + * @since 3.10.0 */ export type Constructor = & Struct.Constructor @@ -2528,7 +2518,7 @@ export declare namespace TypeLiteral { /** * @category api interface - * @since 0.67.0 + * @since 3.10.0 */ export interface TypeLiteral< Fields extends Struct.Fields, @@ -2694,19 +2684,17 @@ const makeTypeLiteralClass = < /** * @category api interface - * @since 0.67.0 + * @since 3.10.0 */ export interface Struct extends TypeLiteral { annotations(annotations: Annotations.Schema>>): Struct - /** @since 0.68.17 */ pick>(...keys: Keys): Struct>> - /** @since 0.68.17 */ omit>(...keys: Keys): Struct>> } /** * @category constructors - * @since 0.67.0 + * @since 3.10.0 */ export function Struct( fields: Fields, @@ -2722,7 +2710,7 @@ export function Struct extends PropertySignature<":", Tag, never, ":", Tag, true, never> {} @@ -2734,7 +2722,7 @@ export interface tag extends PropertySignature<":" * @see {@link TaggedStruct} * * @example - * import { Schema } from "@effect/schema" + * import { Schema } from "effect" * * const User = Schema.Struct({ * _tag: Schema.tag("User"), @@ -2744,14 +2732,14 @@ export interface tag extends PropertySignature<":" * * assert.deepStrictEqual(User.make({ name: "John", age: 44 }), { _tag: "User", name: "John", age: 44 }) * - * @since 0.67.14 + * @since 3.10.0 */ export const tag = (tag: Tag): tag => Literal(tag).pipe(propertySignature, withConstructorDefault(() => tag)) /** * @category api interface - * @since 0.67.14 + * @since 3.10.0 */ export type TaggedStruct = Struct< { _tag: tag } & Fields @@ -2763,7 +2751,7 @@ export type TaggedStruct( value: Tag, @@ -2782,7 +2770,7 @@ export const TaggedStruct = extends TypeLiteral<{}, [{ key: K; value: V }]> { readonly key: K @@ -2807,7 +2795,7 @@ const makeRecordClass = (key: K, val /** * @category constructors - * @since 0.67.0 + * @since 3.10.0 */ export const Record = ( options: { readonly key: K; readonly value: V } @@ -2815,7 +2803,7 @@ export const Record = ( /** * @category struct transformations - * @since 0.67.0 + * @since 3.10.0 */ export const pick = >(...keys: Keys) => ( @@ -2824,7 +2812,7 @@ export const pick = >(...key /** * @category struct transformations - * @since 0.67.0 + * @since 3.10.0 */ export const omit = >(...keys: Keys) => ( @@ -2836,28 +2824,28 @@ export const omit = >(...key * producing a new schema that represents a transformation from the `{ readonly [key]: I[K] }` type to `A[K]`. * * @example - * import * as S from "@effect/schema/Schema" + * import * as Schema from "effect/Schema" * * // --------------------------------------------- * // use case: pull out a single field from a * // struct through a transformation * // --------------------------------------------- * - * const mytable = S.Struct({ - * column1: S.NumberFromString, - * column2: S.Number + * const mytable = Schema.Struct({ + * column1: Schema.NumberFromString, + * column2: Schema.Number * }) * * // const pullOutColumn: S.Schema - * const pullOutColumn = mytable.pipe(S.pluck("column1")) + * const pullOutColumn = mytable.pipe(Schema.pluck("column1")) * - * console.log(S.decodeUnknownEither(S.Array(pullOutColumn))([{ column1: "1", column2: 100 }, { column1: "2", column2: 300 }])) + * console.log(Schema.decodeUnknownEither(Schema.Array(pullOutColumn))([{ column1: "1", column2: 100 }, { column1: "2", column2: 300 }])) * // Output: { _id: 'Either', _tag: 'Right', right: [ 1, 2 ] } * * @category struct transformations - * @since 0.67.0 + * @since 3.10.0 */ export const pluck: { ( @@ -2889,7 +2877,7 @@ export const pluck: { /** * @category branding - * @since 0.67.0 + * @since 3.10.0 */ export interface BrandSchema, I = A, R = never> extends AnnotableClass, A, I, R> @@ -2899,7 +2887,7 @@ export interface BrandSchema, I = A, R = never> /** * @category api interface - * @since 0.67.0 + * @since 3.10.0 */ export interface brand extends BrandSchema & Brand, Schema.Encoded, Schema.Context> @@ -2929,13 +2917,13 @@ const makeBrandClass = (ast: AS * @param brand - The brand to apply. * * @example - * import * as Schema from "@effect/schema/Schema" + * import * as Schema from "effect/Schema" * * const Int = Schema.Number.pipe(Schema.int(), Schema.brand("Int")) * type Int = Schema.Schema.Type // number & Brand<"Int"> * * @category branding - * @since 0.67.0 + * @since 3.10.0 */ export const brand = ( brand: B, @@ -2960,7 +2948,7 @@ export const brand = ( /** * @category combinators - * @since 0.69.0 + * @since 3.10.0 */ export const partial = ( self: Schema @@ -2969,7 +2957,7 @@ export const partial = ( /** * @category combinators - * @since 0.69.0 + * @since 3.10.0 */ export const partialWith: { (options: Options): ( @@ -2986,7 +2974,7 @@ export const partialWith: { /** * @category combinators - * @since 0.67.0 + * @since 3.10.0 */ export const required = ( self: Schema @@ -2994,7 +2982,7 @@ export const required = ( /** * @category api interface - * @since 0.67.0 + * @since 3.10.0 */ export interface mutable extends AnnotableClass< @@ -3011,7 +2999,7 @@ export interface mutable extends * @param schema - The original schema to make properties mutable (shallowly). * * @category combinators - * @since 0.67.0 + * @since 3.10.0 */ export const mutable = (schema: S): mutable => make(AST.mutable(schema.ast)) @@ -3193,7 +3181,7 @@ const intersectUnionMembers = ( /** * @category api interface - * @since 0.67.0 + * @since 3.10.0 */ export interface extend extends AnnotableClass< @@ -3220,14 +3208,14 @@ export interface extend extend * - A suspend of a struct with a supported schema * * @example - * import * as Schema from "@effect/schema/Schema" + * import * as Schema from "effect/Schema" * * const schema = Schema.Struct({ * a: Schema.String, * b: Schema.String * }) * - * // const extended: Schema.Schema< + * // const extended: Schema< * // { * // readonly a: string * // readonly b: string @@ -3243,7 +3231,7 @@ export interface extend extend * )) * * @category combinators - * @since 0.67.0 + * @since 3.10.0 */ export const extend: { (that: That): (self: Self) => extend @@ -3255,7 +3243,7 @@ export const extend: { /** * @category combinators - * @since 0.67.0 + * @since 3.10.0 */ export const compose: { ( @@ -3299,36 +3287,36 @@ export const compose: { /** * @category api interface - * @since 0.67.0 + * @since 3.10.0 */ export interface suspend extends AnnotableClass, A, I, R> {} /** * @category constructors - * @since 0.67.0 + * @since 3.10.0 */ export const suspend = (f: () => Schema): suspend => make(new AST.Suspend(() => f().ast)) /** - * @since 0.68.8 + * @since 3.10.0 * @category symbol */ -export const refineTypeId: unique symbol = Symbol.for("@effect/schema/refine") +export const RefineSchemaId: unique symbol = Symbol.for("effect/SchemaId/Refine") /** - * @since 0.68.8 + * @since 3.10.0 * @category symbol */ -export type refineTypeId = typeof refineTypeId +export type RefineSchemaId = typeof RefineSchemaId /** * @category api interface - * @since 0.67.0 + * @since 3.10.0 */ export interface refine extends AnnotableClass, A, Schema.Encoded, Schema.Context> { - readonly [refineTypeId]: From + readonly [RefineSchemaId]: From // required for `type HasFields = ...` readonly from: From readonly filter: ( a: Schema.Type, @@ -3352,7 +3340,7 @@ const makeRefineClass = ( return makeRefineClass(this.from, this.filter, mergeSchemaAnnotations(this.ast, annotations)) } - static [refineTypeId] = from + static [RefineSchemaId] = from static from = from @@ -3365,7 +3353,7 @@ const makeRefineClass = ( /** * @category api interface - * @since 0.67.0 + * @since 3.10.0 */ export interface filter extends refine, From> {} @@ -3413,7 +3401,7 @@ const toFilterParseIssue = ( /** * @category filtering - * @since 0.68.0 + * @since 3.10.0 */ export interface FilterIssue { readonly path: ReadonlyArray @@ -3422,7 +3410,7 @@ export interface FilterIssue { /** * @category filtering - * @since 0.68.0 + * @since 3.10.0 */ export type FilterOutput = undefined | boolean | string | ParseResult.ParseIssue | FilterIssue @@ -3430,7 +3418,7 @@ type FilterReturnType = FilterOutput | ReadonlyArray /** * @category filtering - * @since 0.67.0 + * @since 3.10.0 */ export function filter( refinement: (a: A, options: ParseOptions, self: AST.Refinement) => a is B, @@ -3471,7 +3459,7 @@ export function filter( /** * @category api interface - * @since 0.68.17 + * @since 3.10.0 */ export interface filterEffect extends transformOrFail>, FD> @@ -3479,7 +3467,7 @@ export interface filterEffect /** * @category transformations - * @since 0.68.17 + * @since 3.10.0 */ export const filterEffect: { ( @@ -3525,7 +3513,7 @@ export const filterEffect: { /** * @category api interface - * @since 0.67.0 + * @since 3.10.0 */ export interface transformOrFail extends AnnotableClass< @@ -3565,7 +3553,7 @@ const makeTransformationClass = ( @@ -3663,7 +3651,7 @@ export const transformOrFail: { /** * @category api interface - * @since 0.67.0 + * @since 3.10.0 */ export interface transform extends transformOrFail { annotations(annotations: Annotations.Schema>): transform @@ -3674,7 +3662,7 @@ export interface transform exten * using the provided mapping functions. * * @category transformations - * @since 0.67.0 + * @since 3.10.0 */ export const transform: { ( @@ -3725,7 +3713,7 @@ export const transform: { /** * @category api interface - * @since 0.67.0 + * @since 3.10.0 */ export interface transformLiteral extends Annotable, Type, Encoded> {} @@ -3733,14 +3721,14 @@ export interface transformLiteral extends Annotable( from: Encoded, @@ -3752,7 +3740,7 @@ export const transformLiteral = >( ...pairs: A @@ -3790,7 +3778,7 @@ export function transformLiterals< * @param value - The value of the property to add to the schema. * * @example - * import * as S from "@effect/schema/Schema" + * import * as S from "effect/Schema" * import { pipe } from "effect/Function" * * const Circle = S.Struct({ radius: S.Number }) @@ -3806,7 +3794,7 @@ export function transformLiterals< * }) * * @category combinators - * @since 0.67.0 + * @since 3.10.0 */ export const attachPropertySignature: { ( @@ -3855,12 +3843,12 @@ export const attachPropertySignature: { /** * @category annotations - * @since 0.67.0 + * @since 3.10.0 */ export declare namespace Annotations { /** * @category annotations - * @since 0.67.0 + * @since 3.10.0 */ export interface Doc extends AST.Annotations { readonly title?: AST.TitleAnnotation @@ -3871,25 +3859,16 @@ export declare namespace Annotations { } /** - * @since 0.67.0 + * @since 3.10.0 */ export interface Schema = readonly []> extends Doc { readonly identifier?: AST.IdentifierAnnotation readonly message?: AST.MessageAnnotation - readonly typeId?: AST.TypeAnnotation | { id: AST.TypeAnnotation; annotation: unknown } + readonly schemaId?: AST.SchemaIdAnnotation readonly jsonSchema?: AST.JSONSchemaAnnotation - readonly arbitrary?: ( - ...arbitraries: [ - ...{ readonly [K in keyof TypeParameters]: LazyArbitrary }, - ctx: GenerationContext - ] - ) => LazyArbitrary - readonly pretty?: ( - ...pretties: { readonly [K in keyof TypeParameters]: pretty_.Pretty } - ) => pretty_.Pretty - readonly equivalence?: ( - ...equivalences: { readonly [K in keyof TypeParameters]: Equivalence.Equivalence } - ) => Equivalence.Equivalence + readonly arbitrary?: ArbitraryAnnotation + readonly pretty?: pretty_.PrettyAnnotation + readonly equivalence?: AST.EquivalenceAnnotation readonly concurrency?: AST.ConcurrencyAnnotation readonly batching?: AST.BatchingAnnotation readonly parseIssueTitle?: AST.ParseIssueTitleAnnotation @@ -3898,7 +3877,7 @@ export declare namespace Annotations { } /** - * @since 0.67.0 + * @since 3.10.0 */ export interface Filter extends Schema {} } @@ -3908,7 +3887,7 @@ export declare namespace Annotations { * any duplicates. * * @category annotations - * @since 0.67.0 + * @since 3.10.0 */ export const annotations: { (annotations: Annotations.Schema>): (self: S) => Annotable.Self @@ -3928,7 +3907,7 @@ type Rename = { /** * @category renaming - * @since 0.67.0 + * @since 3.10.0 */ export const rename: { < @@ -3966,10 +3945,10 @@ export const rename: { ) /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export const TrimmedTypeId: unique symbol = Symbol.for("@effect/schema/TypeId/Trimmed") +export const TrimmedSchemaId: unique symbol = Symbol.for("effect/SchemaId/Trimmed") /** * Verifies that a string contains no leading or trailing whitespaces. @@ -3978,13 +3957,13 @@ export const TrimmedTypeId: unique symbol = Symbol.for("@effect/schema/TypeId/Tr * If what you were looking for was a combinator to trim strings, then check out the `trim` combinator. * * @category string filters - * @since 0.67.0 + * @since 3.10.0 */ export const trimmed = (annotations?: Annotations.Filter) => (self: Schema): filter> => self.pipe( filter((a) => a === a.trim(), { - typeId: TrimmedTypeId, + schemaId: TrimmedSchemaId, description: "a string with no leading or trailing whitespace", jsonSchema: { pattern: "^\\S[\\s\\S]*\\S$|^\\S$|^$" }, ...annotations @@ -3992,20 +3971,20 @@ export const trimmed = ) /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export const MaxLengthTypeId: unique symbol = filters_.MaxLengthTypeId +export const MaxLengthSchemaId: unique symbol = filters_.MaxLengthSchemaId /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export type MaxLengthTypeId = typeof MaxLengthTypeId +export type MaxLengthSchemaId = typeof MaxLengthSchemaId /** * @category string filters - * @since 0.67.0 + * @since 3.10.0 */ export const maxLength = ( maxLength: number, @@ -4016,7 +3995,7 @@ export const maxLength = ( filter( (a) => a.length <= maxLength, { - typeId: MaxLengthTypeId, + schemaId: MaxLengthSchemaId, description: `a string at most ${maxLength} character(s) long`, jsonSchema: { maxLength }, ...annotations @@ -4025,20 +4004,20 @@ export const maxLength = ( ) /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export const MinLengthTypeId: unique symbol = filters_.MinLengthTypeId +export const MinLengthSchemaId: unique symbol = filters_.MinLengthSchemaId /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export type MinLengthTypeId = typeof MinLengthTypeId +export type MinLengthSchemaId = typeof MinLengthSchemaId /** * @category string filters - * @since 0.67.0 + * @since 3.10.0 */ export const minLength = ( minLength: number, @@ -4049,7 +4028,7 @@ export const minLength = ( filter( (a) => a.length >= minLength, { - typeId: MinLengthTypeId, + schemaId: MinLengthSchemaId, description: `a string at least ${minLength} character(s) long`, jsonSchema: { minLength }, ...annotations @@ -4058,14 +4037,14 @@ export const minLength = ( ) /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export const PatternTypeId: unique symbol = Symbol.for("@effect/schema/TypeId/Pattern") +export const PatternSchemaId: unique symbol = Symbol.for("effect/SchemaId/Pattern") /** * @category string filters - * @since 0.67.0 + * @since 3.10.0 */ export const pattern = ( regex: RegExp, @@ -4081,7 +4060,8 @@ export const pattern = ( return regex.test(a) }, { - typeId: { id: PatternTypeId, annotation: { regex } }, + schemaId: PatternSchemaId, + [PatternSchemaId]: { regex }, description: `a string matching the pattern ${pattern}`, jsonSchema: { pattern }, arbitrary: () => (fc) => fc.stringMatching(regex) as any, @@ -4092,14 +4072,14 @@ export const pattern = ( } /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export const StartsWithTypeId: unique symbol = Symbol.for("@effect/schema/TypeId/StartsWith") +export const StartsWithSchemaId: unique symbol = Symbol.for("effect/SchemaId/StartsWith") /** * @category string filters - * @since 0.67.0 + * @since 3.10.0 */ export const startsWith = ( startsWith: string, @@ -4110,7 +4090,8 @@ export const startsWith = ( filter( (a) => a.startsWith(startsWith), { - typeId: { id: StartsWithTypeId, annotation: { startsWith } }, + schemaId: StartsWithSchemaId, + [StartsWithSchemaId]: { startsWith }, description: `a string starting with ${JSON.stringify(startsWith)}`, jsonSchema: { pattern: `^${startsWith}` }, ...annotations @@ -4119,14 +4100,14 @@ export const startsWith = ( ) /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export const EndsWithTypeId: unique symbol = Symbol.for("@effect/schema/TypeId/EndsWith") +export const EndsWithSchemaId: unique symbol = Symbol.for("effect/SchemaId/EndsWith") /** * @category string filters - * @since 0.67.0 + * @since 3.10.0 */ export const endsWith = ( endsWith: string, @@ -4137,7 +4118,8 @@ export const endsWith = ( filter( (a) => a.endsWith(endsWith), { - typeId: { id: EndsWithTypeId, annotation: { endsWith } }, + schemaId: EndsWithSchemaId, + [EndsWithSchemaId]: { endsWith }, description: `a string ending with ${JSON.stringify(endsWith)}`, jsonSchema: { pattern: `^.*${endsWith}$` }, ...annotations @@ -4146,14 +4128,14 @@ export const endsWith = ( ) /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export const IncludesTypeId: unique symbol = Symbol.for("@effect/schema/TypeId/Includes") +export const IncludesSchemaId: unique symbol = Symbol.for("effect/SchemaId/Includes") /** * @category string filters - * @since 0.67.0 + * @since 3.10.0 */ export const includes = ( searchString: string, @@ -4164,7 +4146,8 @@ export const includes = ( filter( (a) => a.includes(searchString), { - typeId: { id: IncludesTypeId, annotation: { includes: searchString } }, + schemaId: IncludesSchemaId, + [IncludesSchemaId]: { includes: searchString }, description: `a string including ${JSON.stringify(searchString)}`, jsonSchema: { pattern: `.*${searchString}.*` }, ...annotations @@ -4173,22 +4156,22 @@ export const includes = ( ) /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export const LowercasedTypeId: unique symbol = Symbol.for("@effect/schema/TypeId/Lowercased") +export const LowercasedSchemaId: unique symbol = Symbol.for("effect/SchemaId/Lowercased") /** * Verifies that a string is lowercased. * * @category string filters - * @since 0.67.0 + * @since 3.10.0 */ export const lowercased = (annotations?: Annotations.Filter) => (self: Schema): filter> => self.pipe( filter((a) => a === a.toLowerCase(), { - typeId: LowercasedTypeId, + schemaId: LowercasedSchemaId, description: "a lowercase string", ...annotations }) @@ -4196,29 +4179,29 @@ export const lowercased = /** * @category string constructors - * @since 0.67.0 + * @since 3.10.0 */ export class Lowercased extends String$.pipe( lowercased({ identifier: "Lowercased", title: "Lowercased" }) ) {} /** - * @category type id - * @since 0.68.18 + * @category schema id + * @since 3.10.0 */ -export const CapitalizedTypeId: unique symbol = Symbol.for("@effect/schema/TypeId/Capitalized") +export const CapitalizedSchemaId: unique symbol = Symbol.for("effect/SchemaId/Capitalized") /** * Verifies that a string is capitalized. * * @category string filters - * @since 0.68.18 + * @since 3.10.0 */ export const capitalized = (annotations?: Annotations.Filter) => (self: Schema): filter> => self.pipe( filter((a) => a[0]?.toUpperCase() === a[0], { - typeId: CapitalizedTypeId, + schemaId: CapitalizedSchemaId, description: "a capitalized string", ...annotations }) @@ -4226,29 +4209,29 @@ export const capitalized = /** * @category string constructors - * @since 0.68.18 + * @since 3.10.0 */ export class Capitalized extends String$.pipe( capitalized({ identifier: "Capitalized", title: "Capitalized" }) ) {} /** - * @category type id - * @since 0.68.18 + * @category schema id + * @since 3.10.0 */ -export const UncapitalizedTypeId: unique symbol = Symbol.for("@effect/schema/TypeId/Uncapitalized") +export const UncapitalizedSchemaId: unique symbol = Symbol.for("effect/SchemaId/Uncapitalized") /** * Verifies that a string is uncapitalized. * * @category string filters - * @since 0.68.18 + * @since 3.10.0 */ export const uncapitalized = (annotations?: Annotations.Filter) => (self: Schema): filter> => self.pipe( filter((a) => a[0]?.toLowerCase() === a[0], { - typeId: UncapitalizedTypeId, + schemaId: UncapitalizedSchemaId, description: "a uncapitalized string", ...annotations }) @@ -4256,29 +4239,29 @@ export const uncapitalized = /** * @category string constructors - * @since 0.68.18 + * @since 3.10.0 */ export class Uncapitalized extends String$.pipe( uncapitalized({ identifier: "Uncapitalized", title: "Uncapitalized" }) ) {} /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export const UppercasedTypeId: unique symbol = Symbol.for("@effect/schema/TypeId/Uppercased") +export const UppercasedSchemaId: unique symbol = Symbol.for("effect/SchemaId/Uppercased") /** * Verifies that a string is uppercased. * * @category string filters - * @since 0.67.0 + * @since 3.10.0 */ export const uppercased = (annotations?: Annotations.Filter) => (self: Schema): filter> => self.pipe( filter((a) => a === a.toUpperCase(), { - typeId: UppercasedTypeId, + schemaId: UppercasedSchemaId, description: "an uppercase string", ...annotations }) @@ -4286,27 +4269,27 @@ export const uppercased = /** * @category string constructors - * @since 0.67.0 + * @since 3.10.0 */ export class Uppercased extends String$.pipe( uppercased({ identifier: "Uppercased", title: "Uppercased" }) ) {} /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export const LengthTypeId: unique symbol = filters_.LengthTypeId +export const LengthSchemaId: unique symbol = filters_.LengthSchemaId /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export type LengthTypeId = typeof LengthTypeId +export type LengthSchemaId = typeof LengthSchemaId /** * @category string filters - * @since 0.67.0 + * @since 3.10.0 */ export const length = ( length: number | { readonly min: number; readonly max: number }, @@ -4318,7 +4301,7 @@ export const length = ( if (minLength !== maxLength) { return self.pipe( filter((a) => a.length >= minLength && a.length <= maxLength, { - typeId: LengthTypeId, + schemaId: LengthSchemaId, description: `a string at least ${minLength} character(s) and at most ${maxLength} character(s) long`, jsonSchema: { minLength, maxLength }, ...annotations @@ -4327,7 +4310,7 @@ export const length = ( } return self.pipe( filter((a) => a.length === minLength, { - typeId: LengthTypeId, + schemaId: LengthSchemaId, description: minLength === 1 ? `a single character` : `a string ${minLength} character(s) long`, jsonSchema: { minLength, maxLength: minLength }, ...annotations @@ -4339,13 +4322,13 @@ export const length = ( * A schema representing a single character. * * @category string constructors - * @since 0.67.0 + * @since 3.10.0 */ export class Char extends String$.pipe(length(1, { identifier: "Char" })) {} /** * @category string filters - * @since 0.69.0 + * @since 3.10.0 */ export const nonEmptyString = ( annotations?: Annotations.Filter @@ -4359,7 +4342,7 @@ export const nonEmptyString = ( * This schema converts a string to lowercase. * * @category string transformations - * @since 0.67.0 + * @since 3.10.0 */ export class Lowercase extends transform( String$.annotations({ description: "a string that will be converted to lowercase" }), @@ -4371,7 +4354,7 @@ export class Lowercase extends transform( * This schema converts a string to uppercase. * * @category string transformations - * @since 0.67.0 + * @since 3.10.0 */ export class Uppercase extends transform( String$.annotations({ description: "a string that will be converted to uppercase" }), @@ -4383,7 +4366,7 @@ export class Uppercase extends transform( * This schema converts a string to capitalized one. * * @category string transformations - * @since 0.68.18 + * @since 3.10.0 */ export class Capitalize extends transform( String$.annotations({ description: "a string that will be converted to a capitalized format" }), @@ -4395,7 +4378,7 @@ export class Capitalize extends transform( * This schema converts a string to uncapitalized one. * * @category string transformations - * @since 0.68.18 + * @since 3.10.0 */ export class Uncapitalize extends transform( String$.annotations({ description: "a string that will be converted to an uncapitalized format" }), @@ -4405,7 +4388,7 @@ export class Uncapitalize extends transform( /** * @category string constructors - * @since 0.67.0 + * @since 3.10.0 */ export class Trimmed extends String$.pipe( trimmed({ identifier: "Trimmed", title: "Trimmed" }) @@ -4416,14 +4399,14 @@ export class Trimmed extends String$.pipe( * leading or trailing whitespace. * * @example - * import { Schema } from "@effect/schema" + * import { Schema } from "effect" * * console.log(Schema.decodeOption(Schema.NonEmptyTrimmedString)("")) // Option.none() * console.log(Schema.decodeOption(Schema.NonEmptyTrimmedString)(" a ")) // Option.none() * console.log(Schema.decodeOption(Schema.NonEmptyTrimmedString)("a")) // Option.some("a") * * @category string constructors - * @since 0.69.3 + * @since 3.10.0 */ export class NonEmptyTrimmedString extends Trimmed.pipe( nonEmptyString({ identifier: "NonEmptyTrimmedString", title: "NonEmptyTrimmedString" }) @@ -4433,7 +4416,7 @@ export class NonEmptyTrimmedString extends Trimmed.pipe( * This schema allows removing whitespaces from the beginning and end of a string. * * @category string transformations - * @since 0.67.0 + * @since 3.10.0 */ export class Trim extends transform( String$.annotations({ description: "a string that will be trimmed" }), @@ -4445,7 +4428,7 @@ export class Trim extends transform( * Returns a schema that allows splitting a string into an array of strings. * * @category string transformations - * @since 0.67.0 + * @since 3.10.0 */ export const split = (separator: string): transform> => transform( @@ -4455,7 +4438,7 @@ export const split = (separator: string): transform[1] @@ -4486,7 +4469,7 @@ const getParseJsonTransformation = (options?: ParseJsonOptions) => catch: (e: any) => new ParseResult.Type(ast, u, e.message) }) } - ).annotations({ typeId: filters_.ParseJsonTypeId }) + ).annotations({ schemaId: AST.ParseJsonSchemaId }) /** * The `ParseJson` combinator provides a method to convert JSON strings into the `unknown` type using the underlying @@ -4497,35 +4480,35 @@ const getParseJsonTransformation = (options?: ParseJsonOptions) => * Optionally, you can pass a schema `Schema` to obtain an `A` type instead of `unknown`. * * @example - * import * as S from "@effect/schema/Schema" + * import * as Schema from "effect/Schema" * - * assert.deepStrictEqual(S.decodeUnknownSync(S.parseJson())(`{"a":"1"}`), { a: "1" }) - * assert.deepStrictEqual(S.decodeUnknownSync(S.parseJson(S.Struct({ a: S.NumberFromString })))(`{"a":"1"}`), { a: 1 }) + * assert.deepStrictEqual(Schema.decodeUnknownSync(Schema.parseJson())(`{"a":"1"}`), { a: "1" }) + * assert.deepStrictEqual(Schema.decodeUnknownSync(Schema.parseJson(Schema.Struct({ a: Schema.NumberFromString })))(`{"a":"1"}`), { a: 1 }) * * @category string transformations - * @since 0.67.0 + * @since 3.10.0 */ export const parseJson: { (schema: Schema, options?: ParseJsonOptions): SchemaClass (options?: ParseJsonOptions): SchemaClass -} = (schema?: Schema | ParseJsonOptions, o?: ParseJsonOptions) => - isSchema(schema) - ? compose(parseJson(o), schema) as any - : getParseJsonTransformation(schema as ParseJsonOptions | undefined) +} = (schemaOrOptions?: Schema | ParseJsonOptions, o?: ParseJsonOptions) => + isSchema(schemaOrOptions) + ? compose(parseJson(o), schemaOrOptions) as any + : getParseJsonTransformation(schemaOrOptions as ParseJsonOptions | undefined) /** * @category string constructors - * @since 0.69.0 + * @since 3.10.0 */ export class NonEmptyString extends String$.pipe( nonEmptyString({ identifier: "NonEmptyString", title: "NonEmptyString" }) ) {} /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export const UUIDTypeId: unique symbol = Symbol.for("@effect/schema/TypeId/UUID") +export const UUIDSchemaId: unique symbol = Symbol.for("effect/SchemaId/UUID") const uuidRegexp = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/i @@ -4535,11 +4518,11 @@ const uuidRegexp = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4} * This schema ensures that the provided string adheres to the standard UUID format. * * @category string constructors - * @since 0.67.0 + * @since 3.10.0 */ export class UUID extends String$.pipe( pattern(uuidRegexp, { - typeId: UUIDTypeId, + schemaId: UUIDSchemaId, identifier: "UUID", title: "UUID", description: "a Universally Unique Identifier", @@ -4548,10 +4531,10 @@ export class UUID extends String$.pipe( ) {} /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export const ULIDTypeId: unique symbol = Symbol.for("@effect/schema/TypeId/ULID") +export const ULIDSchemaId: unique symbol = Symbol.for("effect/SchemaId/ULID") const ulidRegexp = /^[0-7][0-9A-HJKMNP-TV-Z]{25}$/i @@ -4562,11 +4545,11 @@ const ulidRegexp = /^[0-7][0-9A-HJKMNP-TV-Z]{25}$/i * This schema ensures that the provided string adheres to the standard ULID format. * * @category string constructors - * @since 0.67.0 + * @since 3.10.0 */ export class ULID extends String$.pipe( pattern(ulidRegexp, { - typeId: ULIDTypeId, + schemaId: ULIDSchemaId, identifier: "ULID", title: "ULID", description: "a Universally Unique Lexicographically Sortable Identifier", @@ -4575,10 +4558,10 @@ export class ULID extends String$.pipe( ) {} /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export const FiniteTypeId: unique symbol = Symbol.for("@effect/schema/TypeId/Finite") +export const FiniteSchemaId: unique symbol = Symbol.for("effect/SchemaId/Finite") /** * Ensures that the provided value is a finite number. @@ -4586,35 +4569,35 @@ export const FiniteTypeId: unique symbol = Symbol.for("@effect/schema/TypeId/Fin * This schema filters out non-finite numeric values, allowing only finite numbers to pass through. * * @category number filters - * @since 0.67.0 + * @since 3.10.0 */ export const finite = (annotations?: Annotations.Filter) => (self: Schema): filter> => self.pipe( filter((a) => Number.isFinite(a), { - typeId: FiniteTypeId, + schemaId: FiniteSchemaId, description: "a finite number", ...annotations }) ) /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export const GreaterThanTypeId: unique symbol = filters_.GreaterThanTypeId +export const GreaterThanSchemaId: unique symbol = filters_.GreaterThanSchemaId /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export type GreaterThanTypeId = typeof GreaterThanTypeId +export type GreaterThanSchemaId = typeof GreaterThanSchemaId /** * This filter checks whether the provided number is greater than the specified minimum. * * @category number filters - * @since 0.67.0 + * @since 3.10.0 */ export const greaterThan = ( min: number, @@ -4623,7 +4606,7 @@ export const greaterThan = ( (self: Schema): filter> => self.pipe( filter((a) => a > min, { - typeId: GreaterThanTypeId, + schemaId: GreaterThanSchemaId, description: min === 0 ? "a positive number" : `a number greater than ${min}`, jsonSchema: { exclusiveMinimum: min }, ...annotations @@ -4631,22 +4614,22 @@ export const greaterThan = ( ) /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export const GreaterThanOrEqualToTypeId: unique symbol = filters_.GreaterThanOrEqualToTypeId +export const GreaterThanOrEqualToSchemaId: unique symbol = filters_.GreaterThanOrEqualToSchemaId /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export type GreaterThanOrEqualToTypeId = typeof GreaterThanOrEqualToTypeId +export type GreaterThanOrEqualToSchemaId = typeof GreaterThanOrEqualToSchemaId /** * This filter checks whether the provided number is greater than or equal to the specified minimum. * * @category number filters - * @since 0.67.0 + * @since 3.10.0 */ export const greaterThanOrEqualTo = ( min: number, @@ -4655,7 +4638,7 @@ export const greaterThanOrEqualTo = ( (self: Schema): filter> => self.pipe( filter((a) => a >= min, { - typeId: GreaterThanOrEqualToTypeId, + schemaId: GreaterThanOrEqualToSchemaId, description: min === 0 ? "a non-negative number" : `a number greater than or equal to ${min}`, jsonSchema: { minimum: min }, ...annotations @@ -4663,14 +4646,14 @@ export const greaterThanOrEqualTo = ( ) /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export const MultipleOfTypeId: unique symbol = Symbol.for("@effect/schema/TypeId/MultipleOf") +export const MultipleOfSchemaId: unique symbol = Symbol.for("effect/SchemaId/MultipleOf") /** * @category number filters - * @since 0.67.0 + * @since 3.10.0 */ export const multipleOf = ( divisor: number, @@ -4679,7 +4662,7 @@ export const multipleOf = ( (self: Schema): filter> => self.pipe( filter((a) => number_.remainder(a, divisor) === 0, { - typeId: MultipleOfTypeId, + schemaId: MultipleOfSchemaId, description: `a number divisible by ${divisor}`, jsonSchema: { multipleOf: Math.abs(divisor) }, // spec requires positive divisor ...annotations @@ -4687,26 +4670,26 @@ export const multipleOf = ( ) /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export const IntTypeId: unique symbol = filters_.IntTypeId +export const IntSchemaId: unique symbol = filters_.IntSchemaId /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export type IntTypeId = typeof IntTypeId +export type IntSchemaId = typeof IntSchemaId /** * @category number filters - * @since 0.67.0 + * @since 3.10.0 */ export const int = (annotations?: Annotations.Filter) => (self: Schema): filter> => self.pipe( filter((a) => Number.isSafeInteger(a), { - typeId: IntTypeId, + schemaId: IntSchemaId, title: "integer", description: "an integer", jsonSchema: { type: "integer" }, @@ -4715,29 +4698,29 @@ export const int = ) /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export const LessThanTypeId: unique symbol = filters_.LessThanTypeId +export const LessThanSchemaId: unique symbol = filters_.LessThanSchemaId /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export type LessThanTypeId = typeof LessThanTypeId +export type LessThanSchemaId = typeof LessThanSchemaId /** * This filter checks whether the provided number is less than the specified maximum. * * @category number filters - * @since 0.67.0 + * @since 3.10.0 */ export const lessThan = (max: number, annotations?: Annotations.Filter) => (self: Schema): filter> => self.pipe( filter((a) => a < max, { - typeId: LessThanTypeId, + schemaId: LessThanSchemaId, description: max === 0 ? "a negative number" : `a number less than ${max}`, jsonSchema: { exclusiveMaximum: max }, ...annotations @@ -4745,22 +4728,22 @@ export const lessThan = ) /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export const LessThanOrEqualToTypeId: unique symbol = filters_.LessThanOrEqualToTypeId +export const LessThanOrEqualToSchemaId: unique symbol = filters_.LessThanOrEqualToSchemaId /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export type LessThanOrEqualToTypeId = typeof LessThanOrEqualToTypeId +export type LessThanOrEqualToSchemaId = typeof LessThanOrEqualToSchemaId /** * This schema checks whether the provided number is less than or equal to the specified maximum. * * @category number filters - * @since 0.67.0 + * @since 3.10.0 */ export const lessThanOrEqualTo = ( max: number, @@ -4769,7 +4752,7 @@ export const lessThanOrEqualTo = ( (self: Schema): filter> => self.pipe( filter((a) => a <= max, { - typeId: LessThanOrEqualToTypeId, + schemaId: LessThanOrEqualToSchemaId, description: max === 0 ? "a non-positive number" : `a number less than or equal to ${max}`, jsonSchema: { maximum: max }, ...annotations @@ -4777,22 +4760,22 @@ export const lessThanOrEqualTo = ( ) /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export const BetweenTypeId: unique symbol = filters_.BetweenTypeId +export const BetweenSchemaId: unique symbol = filters_.BetweenSchemaId /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export type BetweenTypeId = typeof BetweenTypeId +export type BetweenSchemaId = typeof BetweenSchemaId /** * This filter checks whether the provided number falls within the specified minimum and maximum values. * * @category number filters - * @since 0.67.0 + * @since 3.10.0 */ export const between = ( min: number, @@ -4802,7 +4785,7 @@ export const between = ( (self: Schema): filter> => self.pipe( filter((a) => a >= min && a <= max, { - typeId: BetweenTypeId, + schemaId: BetweenSchemaId, description: `a number between ${min} and ${max}`, jsonSchema: { maximum: max, minimum: min }, ...annotations @@ -4810,20 +4793,20 @@ export const between = ( ) /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export const NonNaNTypeId: unique symbol = Symbol.for("@effect/schema/TypeId/NonNaN") +export const NonNaNSchemaId: unique symbol = Symbol.for("effect/SchemaId/NonNaN") /** * @category number filters - * @since 0.67.0 + * @since 3.10.0 */ export const nonNaN = (annotations?: Annotations.Filter) => (self: Schema): filter> => self.pipe( filter((a) => !Number.isNaN(a), { - typeId: NonNaNTypeId, + schemaId: NonNaNSchemaId, description: "a number excluding NaN", ...annotations }) @@ -4831,7 +4814,7 @@ export const nonNaN = /** * @category number filters - * @since 0.67.0 + * @since 3.10.0 */ export const positive = ( annotations?: Annotations.Filter @@ -4839,7 +4822,7 @@ export const positive = ( /** * @category number filters - * @since 0.67.0 + * @since 3.10.0 */ export const negative = ( annotations?: Annotations.Filter @@ -4847,7 +4830,7 @@ export const negative = ( /** * @category number filters - * @since 0.67.0 + * @since 3.10.0 */ export const nonPositive = ( annotations?: Annotations.Filter @@ -4855,7 +4838,7 @@ export const nonPositive = ( /** * @category number filters - * @since 0.67.0 + * @since 3.10.0 */ export const nonNegative = ( annotations?: Annotations.Filter @@ -4865,7 +4848,7 @@ export const nonNegative = ( * Clamps a number between a minimum and a maximum value. * * @category number transformations - * @since 0.67.0 + * @since 3.10.0 */ export const clamp = (minimum: number, maximum: number) => @@ -4884,7 +4867,7 @@ export const clamp = * The following special string values are supported: "NaN", "Infinity", "-Infinity". * * @category number transformations - * @since 0.67.0 + * @since 3.10.0 */ export const parseNumber = ( self: Schema @@ -4907,7 +4890,7 @@ export const parseNumber = ( * The following special string values are supported: "NaN", "Infinity", "-Infinity". * * @category number constructors - * @since 0.67.0 + * @since 3.10.0 */ export class NumberFromString extends parseNumber(String$.annotations({ description: "a string that will be parsed into a number" @@ -4915,25 +4898,25 @@ export class NumberFromString extends parseNumber(String$.annotations({ /** * @category number constructors - * @since 0.67.0 + * @since 3.10.0 */ export class Finite extends Number$.pipe(finite({ identifier: "Finite", title: "Finite" })) {} /** * @category number constructors - * @since 0.67.0 + * @since 3.10.0 */ export class Int extends Number$.pipe(int({ identifier: "Int", title: "Int" })) {} /** * @category number constructors - * @since 0.67.0 + * @since 3.10.0 */ export class NonNaN extends Number$.pipe(nonNaN({ identifier: "NonNaN", title: "NonNaN" })) {} /** * @category number constructors - * @since 0.67.0 + * @since 3.10.0 */ export class Positive extends Number$.pipe( positive({ identifier: "Positive", title: "Positive" }) @@ -4941,7 +4924,7 @@ export class Positive extends Number$.pipe( /** * @category number constructors - * @since 0.67.0 + * @since 3.10.0 */ export class Negative extends Number$.pipe( negative({ identifier: "Negative", title: "Negative" }) @@ -4949,7 +4932,7 @@ export class Negative extends Number$.pipe( /** * @category number constructors - * @since 0.67.0 + * @since 3.10.0 */ export class NonPositive extends Number$.pipe( nonPositive({ identifier: "NonPositive", title: "NonPositive" }) @@ -4957,17 +4940,17 @@ export class NonPositive extends Number$.pipe( /** * @category number constructors - * @since 0.67.0 + * @since 3.10.0 */ export class NonNegative extends Number$.pipe( nonNegative({ identifier: "NonNegative", title: "NonNegative" }) ) {} /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export const JsonNumberTypeId: unique symbol = Symbol.for("@effect/schema/TypeId/JsonNumber") +export const JsonNumberSchemaId: unique symbol = Symbol.for("effect/SchemaId/JsonNumber") /** * The `JsonNumber` is a schema for representing JSON numbers. It ensures that the provided value is a valid @@ -4975,9 +4958,9 @@ export const JsonNumberTypeId: unique symbol = Symbol.for("@effect/schema/TypeId * format. * * @example - * import * as S from "@effect/schema/Schema" + * import * as Schema from "effect/Schema" * - * const is = S.is(S.JsonNumber) + * const is = Schema.is(S.JsonNumber) * * assert.deepStrictEqual(is(42), true) * assert.deepStrictEqual(is(Number.NaN), false) @@ -4985,11 +4968,11 @@ export const JsonNumberTypeId: unique symbol = Symbol.for("@effect/schema/TypeId * assert.deepStrictEqual(is(Number.NEGATIVE_INFINITY), false) * * @category number constructors - * @since 0.67.0 + * @since 3.10.0 */ export class JsonNumber extends Number$.pipe( filter((n) => !Number.isNaN(n) && Number.isFinite(n), { - typeId: JsonNumberTypeId, + schemaId: JsonNumberSchemaId, identifier: "JsonNumber", title: "JSON-compatible number", description: "a JSON-compatible number, excluding NaN, +Infinity, and -Infinity", @@ -4999,7 +4982,7 @@ export class JsonNumber extends Number$.pipe( /** * @category boolean transformations - * @since 0.67.0 + * @since 3.10.0 */ export class Not extends transform(Boolean$.annotations({ description: "a boolean that will be negated" }), Boolean$, { strict: true, @@ -5019,26 +5002,26 @@ export { * This schema transforms a `string` into a `symbol`. * * @category symbol transformations - * @since 0.67.0 + * @since 3.10.0 */ Symbol$ as Symbol } /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export const GreaterThanBigIntTypeId: unique symbol = filters_.GreaterThanBigintTypeId +export const GreaterThanBigIntSchemaId: unique symbol = filters_.GreaterThanBigintSchemaId /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export type GreaterThanBigIntTypeId = typeof GreaterThanBigIntTypeId +export type GreaterThanBigIntSchemaId = typeof GreaterThanBigIntSchemaId /** * @category bigint filters - * @since 0.67.0 + * @since 3.10.0 */ export const greaterThanBigInt = ( min: bigint, @@ -5047,27 +5030,28 @@ export const greaterThanBigInt = ( (self: Schema): filter> => self.pipe( filter((a) => a > min, { - typeId: { id: GreaterThanBigIntTypeId, annotation: { min } }, + schemaId: GreaterThanBigIntSchemaId, + [GreaterThanBigIntSchemaId]: { min }, description: min === 0n ? "a positive bigint" : `a bigint greater than ${min}n`, ...annotations }) ) /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export const GreaterThanOrEqualToBigIntTypeId: unique symbol = filters_.GreaterThanOrEqualToBigIntTypeId +export const GreaterThanOrEqualToBigIntSchemaId: unique symbol = filters_.GreaterThanOrEqualToBigIntSchemaId /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export type GreaterThanOrEqualToBigIntTypeId = typeof GreaterThanOrEqualToBigIntTypeId +export type GreaterThanOrEqualToBigIntSchemaId = typeof GreaterThanOrEqualToBigIntSchemaId /** * @category bigint filters - * @since 0.67.0 + * @since 3.10.0 */ export const greaterThanOrEqualToBigInt = ( min: bigint, @@ -5076,7 +5060,8 @@ export const greaterThanOrEqualToBigInt = ( (self: Schema): filter> => self.pipe( filter((a) => a >= min, { - typeId: { id: GreaterThanOrEqualToBigIntTypeId, annotation: { min } }, + schemaId: GreaterThanOrEqualToBigIntSchemaId, + [GreaterThanOrEqualToBigIntSchemaId]: { min }, description: min === 0n ? "a non-negative bigint" : `a bigint greater than or equal to ${min}n`, @@ -5085,20 +5070,20 @@ export const greaterThanOrEqualToBigInt = ( ) /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export const LessThanBigIntTypeId: unique symbol = filters_.LessThanBigIntTypeId +export const LessThanBigIntSchemaId: unique symbol = filters_.LessThanBigIntSchemaId /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export type LessThanBigIntTypeId = typeof LessThanBigIntTypeId +export type LessThanBigIntSchemaId = typeof LessThanBigIntSchemaId /** * @category bigint filters - * @since 0.67.0 + * @since 3.10.0 */ export const lessThanBigInt = ( max: bigint, @@ -5107,27 +5092,28 @@ export const lessThanBigInt = ( (self: Schema): filter> => self.pipe( filter((a) => a < max, { - typeId: { id: LessThanBigIntTypeId, annotation: { max } }, + schemaId: LessThanBigIntSchemaId, + [LessThanBigIntSchemaId]: { max }, description: max === 0n ? "a negative bigint" : `a bigint less than ${max}n`, ...annotations }) ) /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export const LessThanOrEqualToBigIntTypeId: unique symbol = filters_.LessThanOrEqualToBigIntTypeId +export const LessThanOrEqualToBigIntSchemaId: unique symbol = filters_.LessThanOrEqualToBigIntSchemaId /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export type LessThanOrEqualToBigIntTypeId = typeof LessThanOrEqualToBigIntTypeId +export type LessThanOrEqualToBigIntSchemaId = typeof LessThanOrEqualToBigIntSchemaId /** * @category bigint filters - * @since 0.67.0 + * @since 3.10.0 */ export const lessThanOrEqualToBigInt = ( max: bigint, @@ -5136,27 +5122,28 @@ export const lessThanOrEqualToBigInt = ( (self: Schema): filter> => self.pipe( filter((a) => a <= max, { - typeId: { id: LessThanOrEqualToBigIntTypeId, annotation: { max } }, + schemaId: LessThanOrEqualToBigIntSchemaId, + [LessThanOrEqualToBigIntSchemaId]: { max }, description: max === 0n ? "a non-positive bigint" : `a bigint less than or equal to ${max}n`, ...annotations }) ) /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export const BetweenBigIntTypeId: unique symbol = filters_.BetweenBigintTypeId +export const BetweenBigIntSchemaId: unique symbol = filters_.BetweenBigintSchemaId /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export type BetweenBigIntTypeId = typeof BetweenBigIntTypeId +export type BetweenBigIntSchemaId = typeof BetweenBigIntSchemaId /** * @category bigint filters - * @since 0.67.0 + * @since 3.10.0 */ export const betweenBigInt = ( min: bigint, @@ -5166,7 +5153,8 @@ export const betweenBigInt = ( (self: Schema): filter> => self.pipe( filter((a) => a >= min && a <= max, { - typeId: { id: BetweenBigIntTypeId, annotation: { max, min } }, + schemaId: BetweenBigIntSchemaId, + [BetweenBigIntSchemaId]: { max, min }, description: `a bigint between ${min}n and ${max}n`, ...annotations }) @@ -5174,7 +5162,7 @@ export const betweenBigInt = ( /** * @category bigint filters - * @since 0.67.0 + * @since 3.10.0 */ export const positiveBigInt = ( annotations?: Annotations.Filter @@ -5182,7 +5170,7 @@ export const positiveBigInt = ( /** * @category bigint filters - * @since 0.67.0 + * @since 3.10.0 */ export const negativeBigInt = ( annotations?: Annotations.Filter @@ -5190,7 +5178,7 @@ export const negativeBigInt = ( /** * @category bigint filters - * @since 0.67.0 + * @since 3.10.0 */ export const nonNegativeBigInt = ( annotations?: Annotations.Filter @@ -5198,7 +5186,7 @@ export const nonNegativeBigInt = ( /** * @category bigint filters - * @since 0.67.0 + * @since 3.10.0 */ export const nonPositiveBigInt = ( annotations?: Annotations.Filter @@ -5208,7 +5196,7 @@ export const nonPositiveBigInt = ( * Clamps a bigint between a minimum and a maximum value. * * @category bigint transformations - * @since 0.67.0 + * @since 3.10.0 */ export const clampBigInt = (minimum: bigint, maximum: bigint) => @@ -5237,14 +5225,14 @@ export { * It returns an error if the value can't be converted (for example when non-numeric characters are provided). * * @category bigint transformations - * @since 0.67.0 + * @since 3.10.0 */ BigInt$ as BigInt } /** * @category bigint constructors - * @since 0.67.0 + * @since 3.10.0 */ export const PositiveBigIntFromSelf: filter> = BigIntFromSelf.pipe( positiveBigInt({ identifier: "PositiveBigintFromSelf", title: "PositiveBigintFromSelf" }) @@ -5252,7 +5240,7 @@ export const PositiveBigIntFromSelf: filter> = BigIntFromSelf.pip /** * @category bigint constructors - * @since 0.67.0 + * @since 3.10.0 */ export const PositiveBigInt: filter> = BigInt$.pipe( positiveBigInt({ identifier: "PositiveBigint", title: "PositiveBigint" }) @@ -5260,7 +5248,7 @@ export const PositiveBigInt: filter> = BigInt$.pipe( /** * @category bigint constructors - * @since 0.67.0 + * @since 3.10.0 */ export const NegativeBigIntFromSelf: filter> = BigIntFromSelf.pipe( negativeBigInt({ identifier: "NegativeBigintFromSelf", title: "NegativeBigintFromSelf" }) @@ -5268,7 +5256,7 @@ export const NegativeBigIntFromSelf: filter> = BigIntFromSelf.pip /** * @category bigint constructors - * @since 0.67.0 + * @since 3.10.0 */ export const NegativeBigInt: filter> = BigInt$.pipe( negativeBigInt({ identifier: "NegativeBigint", title: "NegativeBigint" }) @@ -5276,7 +5264,7 @@ export const NegativeBigInt: filter> = BigInt$.pipe( /** * @category bigint constructors - * @since 0.67.0 + * @since 3.10.0 */ export const NonPositiveBigIntFromSelf: filter> = BigIntFromSelf.pipe( nonPositiveBigInt({ identifier: "NonPositiveBigintFromSelf", title: "NonPositiveBigintFromSelf" }) @@ -5284,7 +5272,7 @@ export const NonPositiveBigIntFromSelf: filter> = BigIntFromSelf. /** * @category bigint constructors - * @since 0.67.0 + * @since 3.10.0 */ export const NonPositiveBigInt: filter> = BigInt$.pipe( nonPositiveBigInt({ identifier: "NonPositiveBigint", title: "NonPositiveBigint" }) @@ -5292,7 +5280,7 @@ export const NonPositiveBigInt: filter> = BigInt$.pipe( /** * @category bigint constructors - * @since 0.67.0 + * @since 3.10.0 */ export const NonNegativeBigIntFromSelf: filter> = BigIntFromSelf.pipe( nonNegativeBigInt({ identifier: "NonNegativeBigintFromSelf", title: "NonNegativeBigintFromSelf" }) @@ -5300,7 +5288,7 @@ export const NonNegativeBigIntFromSelf: filter> = BigIntFromSelf. /** * @category bigint constructors - * @since 0.67.0 + * @since 3.10.0 */ export const NonNegativeBigInt: filter> = BigInt$.pipe( nonNegativeBigInt({ identifier: "NonNegativeBigint", title: "NonNegativeBigint" }) @@ -5312,7 +5300,7 @@ export const NonNegativeBigInt: filter> = BigInt$.pipe( * It returns an error if the value can't be safely encoded as a `number` due to being out of range. * * @category bigint transformations - * @since 0.67.0 + * @since 3.10.0 */ export class BigIntFromNumber extends transformOrFail( Number$.annotations({ description: "a number that will be parsed into a bigint" }), @@ -5352,7 +5340,7 @@ const redactedParse = ( /** * @category api interface - * @since 0.67.21 + * @since 3.10.0 */ export interface RedactedFromSelf extends AnnotableClass< @@ -5365,7 +5353,7 @@ export interface RedactedFromSelf extends /** * @category Redacted constructors - * @since 0.67.21 + * @since 3.10.0 */ export const RedactedFromSelf = ( value: Value @@ -5386,7 +5374,7 @@ export const RedactedFromSelf = ( /** * @category api interface - * @since 0.67.21 + * @since 3.10.0 */ export interface Redacted extends AnnotableClass< @@ -5401,7 +5389,7 @@ export interface Redacted extends * A schema that transforms any type `A` into a `Redacted`. * * @category Redacted transformations - * @since 0.67.21 + * @since 3.10.0 */ export const Redacted = ( value: Value @@ -5419,7 +5407,7 @@ export const Redacted = ( /** * @category Duration constructors - * @since 0.67.0 + * @since 3.10.0 */ export class DurationFromSelf extends declare( duration_.isDuration, @@ -5447,7 +5435,7 @@ export class DurationFromSelf extends declare( * Treats the value as the number of nanoseconds. * * @category Duration transformations - * @since 0.67.0 + * @since 3.10.0 */ export class DurationFromNanos extends transformOrFail( BigIntFromSelf.annotations({ description: "a bigint that will be parsed into a Duration" }), @@ -5468,7 +5456,7 @@ export class DurationFromNanos extends transformOrFail( * Treats the value as the number of milliseconds. * * @category Duration transformations - * @since 0.67.0 + * @since 3.10.0 */ export class DurationFromMillis extends transform( Number$.annotations({ description: "a number that will be parsed into a Duration" }), @@ -5495,7 +5483,7 @@ const hrTime: Schema = Tuple( * A schema that transforms a `[number, number]` tuple into a `Duration`. * * @category Duration transformations - * @since 0.67.0 + * @since 3.10.0 */ export class Duration extends transform( hrTime.annotations({ description: "a tuple of seconds and nanos that will be parsed into a Duration" }), @@ -5511,7 +5499,7 @@ export class Duration extends transform( * Clamps a `Duration` between a minimum and a maximum value. * * @category Duration transformations - * @since 0.67.0 + * @since 3.10.0 */ export const clampDuration = (minimum: duration_.DurationInput, maximum: duration_.DurationInput) => @@ -5523,14 +5511,14 @@ export const clampDuration = ) /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export const LessThanDurationTypeId: unique symbol = Symbol.for("@effect/schema/TypeId/LessThanDuration") +export const LessThanDurationSchemaId: unique symbol = Symbol.for("effect/SchemaId/LessThanDuration") /** * @category Duration filters - * @since 0.67.0 + * @since 3.10.0 */ export const lessThanDuration = ( max: duration_.DurationInput, @@ -5539,23 +5527,24 @@ export const lessThanDuration = ( (self: Schema): filter> => self.pipe( filter((a) => duration_.lessThan(a, max), { - typeId: { id: LessThanDurationTypeId, annotation: { max } }, + schemaId: LessThanDurationSchemaId, + [LessThanDurationSchemaId]: { max }, description: `a Duration less than ${duration_.decode(max)}`, ...annotations }) ) /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export const LessThanOrEqualToDurationTypeId: unique symbol = Symbol.for( - "@effect/schema/TypeId/LessThanOrEqualToDuration" +export const LessThanOrEqualToDurationSchemaId: unique symbol = Symbol.for( + "effect/schema/LessThanOrEqualToDuration" ) /** * @category Duration filters - * @since 0.67.0 + * @since 3.10.0 */ export const lessThanOrEqualToDuration = ( max: duration_.DurationInput, @@ -5564,21 +5553,22 @@ export const lessThanOrEqualToDuration = ( (self: Schema): filter> => self.pipe( filter((a) => duration_.lessThanOrEqualTo(a, max), { - typeId: { id: LessThanDurationTypeId, annotation: { max } }, + schemaId: LessThanDurationSchemaId, + [LessThanDurationSchemaId]: { max }, description: `a Duration less than or equal to ${duration_.decode(max)}`, ...annotations }) ) /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export const GreaterThanDurationTypeId: unique symbol = Symbol.for("@effect/schema/TypeId/GreaterThanDuration") +export const GreaterThanDurationSchemaId: unique symbol = Symbol.for("effect/SchemaId/GreaterThanDuration") /** * @category Duration filters - * @since 0.67.0 + * @since 3.10.0 */ export const greaterThanDuration = ( min: duration_.DurationInput, @@ -5587,23 +5577,24 @@ export const greaterThanDuration = ( (self: Schema): filter> => self.pipe( filter((a) => duration_.greaterThan(a, min), { - typeId: { id: GreaterThanDurationTypeId, annotation: { min } }, + schemaId: GreaterThanDurationSchemaId, + [GreaterThanDurationSchemaId]: { min }, description: `a Duration greater than ${duration_.decode(min)}`, ...annotations }) ) /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export const GreaterThanOrEqualToDurationTypeId: unique symbol = Symbol.for( - "@effect/schema/TypeId/GreaterThanOrEqualToDuration" +export const GreaterThanOrEqualToDurationSchemaId: unique symbol = Symbol.for( + "effect/schema/GreaterThanOrEqualToDuration" ) /** * @category Duration filters - * @since 0.67.0 + * @since 3.10.0 */ export const greaterThanOrEqualToDuration = ( min: duration_.DurationInput, @@ -5612,21 +5603,22 @@ export const greaterThanOrEqualToDuration = ( (self: Schema): filter> => self.pipe( filter((a) => duration_.greaterThanOrEqualTo(a, min), { - typeId: { id: GreaterThanOrEqualToDurationTypeId, annotation: { min } }, + schemaId: GreaterThanOrEqualToDurationSchemaId, + [GreaterThanOrEqualToDurationSchemaId]: { min }, description: `a Duration greater than or equal to ${duration_.decode(min)}`, ...annotations }) ) /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export const BetweenDurationTypeId: unique symbol = Symbol.for("@effect/schema/TypeId/BetweenDuration") +export const BetweenDurationSchemaId: unique symbol = Symbol.for("effect/SchemaId/BetweenDuration") /** * @category Duration filters - * @since 0.67.0 + * @since 3.10.0 */ export const betweenDuration = ( minimum: duration_.DurationInput, @@ -5636,7 +5628,8 @@ export const betweenDuration = ( (self: Schema): filter> => self.pipe( filter((a) => duration_.between(a, { minimum, maximum }), { - typeId: { id: BetweenDurationTypeId, annotation: { maximum, minimum } }, + schemaId: BetweenDurationSchemaId, + [BetweenDurationSchemaId]: { maximum, minimum }, description: `a Duration between ${duration_.decode(minimum)} and ${duration_.decode(maximum)}`, ...annotations }) @@ -5644,7 +5637,7 @@ export const betweenDuration = ( /** * @category Uint8Array constructors - * @since 0.67.0 + * @since 3.10.0 */ export const Uint8ArrayFromSelf: Schema = declare( Predicate.isUint8Array, @@ -5672,7 +5665,7 @@ export { * A schema that transforms an array of numbers into a `Uint8Array`. * * @category Uint8Array transformations - * @since 0.67.0 + * @since 3.10.0 */ Uint8Array$ as Uint8Array } @@ -5700,7 +5693,7 @@ const makeUint8ArrayTransformation = ( * Decodes a base64 (RFC4648) encoded string into a `Uint8Array`. * * @category Uint8Array transformations - * @since 0.67.0 + * @since 3.10.0 */ export const Uint8ArrayFromBase64: Schema = makeUint8ArrayTransformation( "Uint8ArrayFromBase64", @@ -5712,7 +5705,7 @@ export const Uint8ArrayFromBase64: Schema = makeUint8ArrayTr * Decodes a base64 (URL) encoded string into a `Uint8Array`. * * @category Uint8Array transformations - * @since 0.67.0 + * @since 3.10.0 */ export const Uint8ArrayFromBase64Url: Schema = makeUint8ArrayTransformation( "Uint8ArrayFromBase64Url", @@ -5724,7 +5717,7 @@ export const Uint8ArrayFromBase64Url: Schema = makeUint8Arra * Decodes a hex encoded string into a `Uint8Array`. * * @category Uint8Array transformations - * @since 0.67.0 + * @since 3.10.0 */ export const Uint8ArrayFromHex: Schema = makeUint8ArrayTransformation( "Uint8ArrayFromHex", @@ -5757,7 +5750,7 @@ const makeEncodingTransformation = ( * Decodes a base64 (RFC4648) encoded string into a UTF-8 string. * * @category string transformations - * @since 0.67.0 + * @since 3.10.0 */ export const StringFromBase64: Schema = makeEncodingTransformation( "Base64", @@ -5769,7 +5762,7 @@ export const StringFromBase64: Schema = makeEncodingTransformation( * Decodes a base64 (URL) encoded string into a UTF-8 string. * * @category string transformations - * @since 0.67.0 + * @since 3.10.0 */ export const StringFromBase64Url: Schema = makeEncodingTransformation( "Base64Url", @@ -5781,7 +5774,7 @@ export const StringFromBase64Url: Schema = makeEncodingTransformation( * Decodes a hex encoded string into a UTF-8 string. * * @category string transformations - * @since 0.67.0 + * @since 3.10.0 */ export const StringFromHex: Schema = makeEncodingTransformation( "Hex", @@ -5790,20 +5783,20 @@ export const StringFromHex: Schema = makeEncodingTransformation( ) /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export const MinItemsTypeId: unique symbol = filters_.MinItemsTypeId +export const MinItemsSchemaId: unique symbol = filters_.MinItemsSchemaId /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export type MinItemsTypeId = typeof MinItemsTypeId +export type MinItemsSchemaId = typeof MinItemsSchemaId /** * @category ReadonlyArray filters - * @since 0.67.0 + * @since 3.10.0 */ export const minItems = ( n: number, @@ -5820,7 +5813,7 @@ export const minItems = ( filter( (a) => a.length >= minItems, { - typeId: MinItemsTypeId, + schemaId: MinItemsSchemaId, description: `an array of at least ${minItems} items`, jsonSchema: { minItems }, [AST.StableFilterAnnotationId]: true, @@ -5831,20 +5824,20 @@ export const minItems = ( } /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export const MaxItemsTypeId: unique symbol = filters_.MaxItemsTypeId +export const MaxItemsSchemaId: unique symbol = filters_.MaxItemsSchemaId /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export type MaxItemsTypeId = typeof MaxItemsTypeId +export type MaxItemsSchemaId = typeof MaxItemsSchemaId /** * @category ReadonlyArray filters - * @since 0.67.0 + * @since 3.10.0 */ export const maxItems = ( n: number, @@ -5853,7 +5846,7 @@ export const maxItems = ( (self: Schema, I, R>): filter, I, R>> => self.pipe( filter((a) => a.length <= n, { - typeId: MaxItemsTypeId, + schemaId: MaxItemsSchemaId, description: `an array of at most ${n} items`, jsonSchema: { maxItems: n }, [AST.StableFilterAnnotationId]: true, @@ -5862,20 +5855,20 @@ export const maxItems = ( ) /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export const ItemsCountTypeId: unique symbol = filters_.ItemsCountTypeId +export const ItemsCountSchemaId: unique symbol = filters_.ItemsCountSchemaId /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export type ItemsCountTypeId = typeof ItemsCountTypeId +export type ItemsCountSchemaId = typeof ItemsCountSchemaId /** * @category ReadonlyArray filters - * @since 0.67.0 + * @since 3.10.0 */ export const itemsCount = ( n: number, @@ -5884,7 +5877,7 @@ export const itemsCount = ( (self: Schema, I, R>): filter, I, R>> => self.pipe( filter((a) => a.length === n, { - typeId: ItemsCountTypeId, + schemaId: ItemsCountSchemaId, description: `an array of exactly ${n} item(s)`, jsonSchema: { minItems: n, maxItems: n }, [AST.StableFilterAnnotationId]: true, @@ -5894,7 +5887,7 @@ export const itemsCount = ( /** * @category ReadonlyArray transformations - * @since 0.67.0 + * @since 3.10.0 */ export const getNumberIndexedAccess = , I extends ReadonlyArray, R>( self: Schema @@ -5904,7 +5897,7 @@ export const getNumberIndexedAccess = , I extends R * Get the first element of a `ReadonlyArray`, or `None` if the array is empty. * * @category ReadonlyArray transformations - * @since 0.67.0 + * @since 3.10.0 */ export const head = (self: Schema, I, R>): SchemaClass, I, R> => transform( @@ -5919,7 +5912,7 @@ export const head = (self: Schema, I, R>): SchemaClass * If the array is empty, it returns the `fallback` argument if provided; otherwise, it fails. * * @category ReadonlyArray transformations - * @since 0.67.0 + * @since 3.10.0 */ export const headOrElse: { (fallback?: LazyArg): (self: Schema, I, R>) => SchemaClass @@ -5944,10 +5937,10 @@ export const headOrElse: { ) /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export const ValidDateTypeId: unique symbol = Symbol.for("@effect/schema/TypeId/ValidDate") +export const ValidDateSchemaId: unique symbol = Symbol.for("effect/SchemaId/ValidDate") /** * Defines a filter that specifically rejects invalid dates, such as `new @@ -5956,27 +5949,27 @@ export const ValidDateTypeId: unique symbol = Symbol.for("@effect/schema/TypeId/ * erroneous date values from being processed. * * @category Date filters - * @since 0.67.0 + * @since 3.10.0 */ export const validDate = (annotations?: Annotations.Filter) => (self: Schema): filter> => self.pipe( filter((a) => !Number.isNaN(a.getTime()), { - typeId: ValidDateTypeId, + schemaId: ValidDateSchemaId, description: "a valid Date", ...annotations }) ) /** - * @category type id - * @since 0.73.1 + * @category schema id + * @since 3.10.0 */ -export const LessThanDateTypeId: unique symbol = Symbol.for("@effect/schema/TypeId/LessThanDate") +export const LessThanDateSchemaId: unique symbol = Symbol.for("effect/SchemaId/LessThanDate") /** * @category Date filters - * @since 0.73.1 + * @since 3.10.0 */ export const lessThanDate = ( max: Date, @@ -5985,23 +5978,24 @@ export const lessThanDate = ( (self: Schema): filter> => self.pipe( filter((a) => a < max, { - typeId: { id: LessThanDateTypeId, annotation: { max } }, + schemaId: LessThanDateSchemaId, + [LessThanDateSchemaId]: { max }, description: `a date before ${util_.formatDate(max)}`, ...annotations }) ) /** - * @category type id - * @since 0.73.1 + * @category schema id + * @since 3.10.0 */ -export const LessThanOrEqualToDateTypeId: unique symbol = Symbol.for( - "@effect/schema/TypeId/LessThanOrEqualToDate" +export const LessThanOrEqualToDateSchemaId: unique symbol = Symbol.for( + "effect/schema/LessThanOrEqualToDate" ) /** * @category Date filters - * @since 0.73.1 + * @since 3.10.0 */ export const lessThanOrEqualToDate = ( max: Date, @@ -6010,21 +6004,22 @@ export const lessThanOrEqualToDate = ( (self: Schema): filter> => self.pipe( filter((a) => a <= max, { - typeId: { id: LessThanDateTypeId, annotation: { max } }, + schemaId: LessThanDateSchemaId, + [LessThanDateSchemaId]: { max }, description: `a date before or equal to ${util_.formatDate(max)}`, ...annotations }) ) /** - * @category type id - * @since 0.73.1 + * @category schema id + * @since 3.10.0 */ -export const GreaterThanDateTypeId: unique symbol = Symbol.for("@effect/schema/TypeId/GreaterThanDate") +export const GreaterThanDateSchemaId: unique symbol = Symbol.for("effect/SchemaId/GreaterThanDate") /** * @category Date filters - * @since 0.73.1 + * @since 3.10.0 */ export const greaterThanDate = ( min: Date, @@ -6033,23 +6028,24 @@ export const greaterThanDate = ( (self: Schema): filter> => self.pipe( filter((a) => a > min, { - typeId: { id: GreaterThanDateTypeId, annotation: { min } }, + schemaId: GreaterThanDateSchemaId, + [GreaterThanDateSchemaId]: { min }, description: `a date after ${util_.formatDate(min)}`, ...annotations }) ) /** - * @category type id - * @since 0.73.1 + * @category schema id + * @since 3.10.0 */ -export const GreaterThanOrEqualToDateTypeId: unique symbol = Symbol.for( - "@effect/schema/TypeId/GreaterThanOrEqualToDate" +export const GreaterThanOrEqualToDateSchemaId: unique symbol = Symbol.for( + "effect/schema/GreaterThanOrEqualToDate" ) /** * @category Date filters - * @since 0.73.1 + * @since 3.10.0 */ export const greaterThanOrEqualToDate = ( min: Date, @@ -6058,21 +6054,22 @@ export const greaterThanOrEqualToDate = ( (self: Schema): filter> => self.pipe( filter((a) => a >= min, { - typeId: { id: GreaterThanOrEqualToDateTypeId, annotation: { min } }, + schemaId: GreaterThanOrEqualToDateSchemaId, + [GreaterThanOrEqualToDateSchemaId]: { min }, description: `a date after or equal to ${util_.formatDate(min)}`, ...annotations }) ) /** - * @category type id - * @since 0.73.1 + * @category schema id + * @since 3.10.0 */ -export const BetweenDateTypeId: unique symbol = Symbol.for("@effect/schema/TypeId/BetweenDate") +export const BetweenDateSchemaId: unique symbol = Symbol.for("effect/SchemaId/BetweenDate") /** * @category Date filters - * @since 0.73.1 + * @since 3.10.0 */ export const betweenDate = ( minimum: Date, @@ -6082,7 +6079,8 @@ export const betweenDate = ( (self: Schema): filter> => self.pipe( filter((a) => a <= maximum && a >= minimum, { - typeId: { id: BetweenDateTypeId, annotation: { maximum, minimum } }, + schemaId: BetweenDateSchemaId, + [BetweenDateSchemaId]: { maximum, minimum }, description: `a date between ${util_.formatDate(minimum)} and ${util_.formatDate(maximum)}`, ...annotations }) @@ -6093,7 +6091,7 @@ export const betweenDate = ( * such as `new Date("Invalid Date")`, without rejection. * * @category Date constructors - * @since 0.67.0 + * @since 3.10.0 */ export class DateFromSelf extends declare( Predicate.isDate, @@ -6114,7 +6112,7 @@ export class DateFromSelf extends declare( * represent real dates. * * @category Date constructors - * @since 0.67.0 + * @since 3.10.0 */ export class ValidDateFromSelf extends DateFromSelf.pipe( validDate({ @@ -6130,7 +6128,7 @@ export class ValidDateFromSelf extends DateFromSelf.pipe( * Date")` results in a `Date` object, despite being invalid). * * @category Date transformations - * @since 0.67.0 + * @since 3.10.0 */ export class DateFromString extends transform( String$.annotations({ description: "a string that will be parsed into a Date" }), @@ -6151,7 +6149,7 @@ export { * Date("Invalid Date")`. * * @category Date transformations - * @since 0.67.0 + * @since 3.10.0 */ Date$ as Date } @@ -6164,7 +6162,7 @@ export { * any invalid `Date` object will be encoded to `NaN`. * * @category Date transformations - * @since 0.67.0 + * @since 3.10.0 */ export class DateFromNumber extends transform( Number$.annotations({ description: "a number that will be parsed into a Date" }), @@ -6176,7 +6174,7 @@ export class DateFromNumber extends transform( * Describes a schema that represents a `DateTime.Utc` instance. * * @category DateTime.Utc constructors - * @since 0.70.0 + * @since 3.10.0 */ export class DateTimeUtcFromSelf extends declare( (u) => dateTime.isDateTime(u) && dateTime.isUtc(u), @@ -6199,7 +6197,7 @@ const decodeDateTime = (input: A, _: ParseOpt * Defines a schema that attempts to convert a `number` to a `DateTime.Utc` instance using the `DateTime.unsafeMake` constructor. * * @category DateTime.Utc transformations - * @since 0.70.0 + * @since 3.10.0 */ export class DateTimeUtcFromNumber extends transformOrFail( Number$.annotations({ description: "a number that will be parsed into a DateTime.Utc" }), @@ -6215,7 +6213,7 @@ export class DateTimeUtcFromNumber extends transformOrFail( * Defines a schema that attempts to convert a `string` to a `DateTime.Utc` instance using the `DateTime.unsafeMake` constructor. * * @category DateTime.Utc transformations - * @since 0.70.0 + * @since 3.10.0 */ export class DateTimeUtc extends transformOrFail( String$.annotations({ description: "a string that will be parsed into a DateTime.Utc" }), @@ -6234,7 +6232,7 @@ const timeZoneOffsetArbitrary = (): LazyArbitrary => ( * Describes a schema that represents a `TimeZone.Offset` instance. * * @category TimeZone constructors - * @since 0.70.0 + * @since 3.10.0 */ export class TimeZoneOffsetFromSelf extends declare( dateTime.isTimeZoneOffset, @@ -6250,7 +6248,7 @@ export class TimeZoneOffsetFromSelf extends declare( * Defines a schema that converts a `number` to a `TimeZone.Offset` instance using the `DateTime.zoneMakeOffset` constructor. * * @category TimeZone transformations - * @since 0.70.0 + * @since 3.10.0 */ export class TimeZoneOffset extends transform( Number$.annotations({ description: "a number that will be parsed into a TimeZone.Offset" }), @@ -6265,7 +6263,7 @@ const timeZoneNamedArbitrary = (): LazyArbitrary => (fc * Describes a schema that represents a `TimeZone.Named` instance. * * @category TimeZone constructors - * @since 0.70.0 + * @since 3.10.0 */ export class TimeZoneNamedFromSelf extends declare( dateTime.isTimeZoneNamed, @@ -6281,7 +6279,7 @@ export class TimeZoneNamedFromSelf extends declare( * Defines a schema that attempts to convert a `string` to a `TimeZone.Named` instance using the `DateTime.zoneUnsafeMakeNamed` constructor. * * @category TimeZone transformations - * @since 0.70.0 + * @since 3.10.0 */ export class TimeZoneNamed extends transformOrFail( String$.annotations({ description: "a string that will be parsed into a TimeZone.Named" }), @@ -6299,7 +6297,7 @@ export class TimeZoneNamed extends transformOrFail( /** * @category api interface - * @since 0.70.0 + * @since 3.10.0 */ export interface TimeZoneFromSelf extends Union<[typeof TimeZoneOffsetFromSelf, typeof TimeZoneNamedFromSelf]> { annotations(annotations: Annotations.Schema): TimeZoneFromSelf @@ -6307,7 +6305,7 @@ export interface TimeZoneFromSelf extends Union<[typeof TimeZoneOffsetFromSelf, /** * @category TimeZone constructors - * @since 0.70.0 + * @since 3.10.0 */ export const TimeZoneFromSelf: TimeZoneFromSelf = Union(TimeZoneOffsetFromSelf, TimeZoneNamedFromSelf) @@ -6315,7 +6313,7 @@ export const TimeZoneFromSelf: TimeZoneFromSelf = Union(TimeZoneOffsetFromSelf, * Defines a schema that attempts to convert a `string` to a `TimeZone` using the `DateTime.zoneFromString` constructor. * * @category TimeZone transformations - * @since 0.70.0 + * @since 3.10.0 */ export class TimeZone extends transformOrFail( String$.annotations({ description: "a string that will be parsed into a TimeZone" }), @@ -6341,7 +6339,7 @@ const timeZoneArbitrary: LazyArbitrary = (fc) => * Describes a schema that represents a `DateTime.Zoned` instance. * * @category DateTime.Zoned constructors - * @since 0.70.0 + * @since 3.10.0 */ export class DateTimeZonedFromSelf extends declare( (u) => dateTime.isDateTime(u) && dateTime.isZoned(u), @@ -6359,7 +6357,7 @@ export class DateTimeZonedFromSelf extends declare( * Defines a schema that attempts to convert a `string` to a `DateTime.Zoned` instance. * * @category DateTime.Zoned transformations - * @since 0.70.0 + * @since 3.10.0 */ export class DateTimeZoned extends transformOrFail( String$.annotations({ description: "a string that will be parsed into a DateTime.Zoned" }), @@ -6377,7 +6375,7 @@ export class DateTimeZoned extends transformOrFail( /** * @category Option utils - * @since 0.67.0 + * @since 3.10.0 */ export type OptionEncoded = | { @@ -6410,7 +6408,7 @@ const optionDecode = (input: OptionEncoded): option_.Option => input._tag === "None" ? option_.none() : option_.some(input.value) const optionArbitrary = - (value: LazyArbitrary, ctx: GenerationContext): LazyArbitrary> => (fc) => + (value: LazyArbitrary, ctx: ArbitraryGenerationContext): LazyArbitrary> => (fc) => fc.oneof( ctx, fc.record({ _tag: fc.constant("None" as const) }), @@ -6434,7 +6432,7 @@ const optionParse = /** * @category api interface - * @since 0.67.0 + * @since 3.10.0 */ export interface OptionFromSelf extends AnnotableClass< @@ -6447,7 +6445,7 @@ export interface OptionFromSelf extends /** * @category Option transformations - * @since 0.67.0 + * @since 3.10.0 */ export const OptionFromSelf = ( value: Value @@ -6477,7 +6475,7 @@ const makeSomeEncoded = (value: A) => ({ /** * @category api interface - * @since 0.67.0 + * @since 3.10.0 */ export interface Option extends AnnotableClass< @@ -6490,7 +6488,7 @@ export interface Option extends /** * @category Option transformations - * @since 0.67.0 + * @since 3.10.0 */ export const Option = (value: Value): Option => { const value_ = asSchema(value) @@ -6510,7 +6508,7 @@ export const Option = (value: Value): Option => /** * @category api interface - * @since 0.67.0 + * @since 3.10.0 */ export interface OptionFromNullOr extends AnnotableClass< @@ -6523,7 +6521,7 @@ export interface OptionFromNullOr extends /** * @category Option transformations - * @since 0.67.0 + * @since 3.10.0 */ export const OptionFromNullOr = ( value: Value @@ -6538,7 +6536,7 @@ export const OptionFromNullOr = ( /** * @category api interface - * @since 0.67.0 + * @since 3.10.0 */ export interface OptionFromNullishOr extends AnnotableClass< @@ -6551,7 +6549,7 @@ export interface OptionFromNullishOr extends /** * @category Option transformations - * @since 0.67.0 + * @since 3.10.0 */ export const OptionFromNullishOr = ( value: Value, @@ -6571,7 +6569,7 @@ export const OptionFromNullishOr = ( /** * @category api interface - * @since 0.67.0 + * @since 3.10.0 */ export interface OptionFromUndefinedOr extends AnnotableClass< @@ -6584,7 +6582,7 @@ export interface OptionFromUndefinedOr extends /** * @category Option transformations - * @since 0.67.0 + * @since 3.10.0 */ export const OptionFromUndefinedOr = ( value: Value @@ -6603,14 +6601,14 @@ export const OptionFromUndefinedOr = ( * `none` for invalid inputs and `some` for valid non-empty strings. * * @example - * import { Schema } from "@effect/schema" + * import { Schema } from "effect" * * console.log(Schema.decodeSync(Schema.OptionFromNonEmptyTrimmedString)("")) // Option.none() * console.log(Schema.decodeSync(Schema.OptionFromNonEmptyTrimmedString)(" a ")) // Option.some("a") * console.log(Schema.decodeSync(Schema.OptionFromNonEmptyTrimmedString)("a")) // Option.some("a") * * @category Option transformations - * @since 0.69.3 + * @since 3.10.0 */ export const OptionFromNonEmptyTrimmedString = transform(String$, OptionFromSelf(NonEmptyTrimmedString), { strict: true, @@ -6623,7 +6621,7 @@ export const OptionFromNonEmptyTrimmedString = transform(String$, OptionFromSelf /** * @category Either utils - * @since 0.67.0 + * @since 3.10.0 */ export type RightEncoded = { readonly _tag: "Right" @@ -6632,7 +6630,7 @@ export type RightEncoded = { /** * @category Either utils - * @since 0.67.0 + * @since 3.10.0 */ export type LeftEncoded = { readonly _tag: "Left" @@ -6641,7 +6639,7 @@ export type LeftEncoded = { /** * @category Either utils - * @since 0.67.0 + * @since 3.10.0 */ export type EitherEncoded = RightEncoded | LeftEncoded @@ -6701,7 +6699,7 @@ const eitherParse = ( /** * @category api interface - * @since 0.67.0 + * @since 3.10.0 */ export interface EitherFromSelf extends AnnotableClass< @@ -6714,7 +6712,7 @@ export interface EitherFromSelf exte /** * @category Either transformations - * @since 0.67.0 + * @since 3.10.0 */ export const EitherFromSelf = ({ left, right }: { readonly left: L @@ -6746,7 +6744,7 @@ const makeRightEncoded = (right: A) => (({ /** * @category api interface - * @since 0.67.0 + * @since 3.10.0 */ export interface Either extends AnnotableClass< @@ -6759,7 +6757,7 @@ export interface Either extends /** * @category Either transformations - * @since 0.67.0 + * @since 3.10.0 */ export const Either = ({ left, right }: { readonly left: L @@ -6780,7 +6778,7 @@ export const Either = ({ left, right /** * @category api interface - * @since 0.67.0 + * @since 3.10.0 */ export interface EitherFromUnion extends AnnotableClass< @@ -6793,13 +6791,13 @@ export interface EitherFromUnion ext /** * @example - * import * as Schema from "@effect/schema/Schema" + * import * as Schema from "effect/Schema" * * // Schema> * Schema.EitherFromUnion({ left: Schema.String, right: Schema.Number }) * * @category Either transformations - * @since 0.67.0 + * @since 3.10.0 */ export const EitherFromUnion = ({ left, right }: { readonly left: L @@ -6833,7 +6831,7 @@ export const EitherFromUnion = ({ le const mapArbitrary = ( key: LazyArbitrary, value: LazyArbitrary, - ctx: GenerationContext + ctx: ArbitraryGenerationContext ): LazyArbitrary> => { return (fc) => { const items = fc.array(fc.tuple(key(fc), value(fc))) @@ -6872,7 +6870,7 @@ const readonlyMapParse = ( /** * @category api interface - * @since 0.67.0 + * @since 3.10.0 */ export interface ReadonlyMapFromSelf extends AnnotableClass< @@ -6904,7 +6902,7 @@ const mapFromSelf_ = ( /** * @category ReadonlyMap - * @since 0.67.0 + * @since 3.10.0 */ export const ReadonlyMapFromSelf = ({ key, value }: { readonly key: K @@ -6913,7 +6911,7 @@ export const ReadonlyMapFromSelf = ( /** * @category api interface - * @since 0.67.0 + * @since 3.10.0 */ export interface MapFromSelf extends AnnotableClass< @@ -6926,7 +6924,7 @@ export interface MapFromSelf extends /** * @category Map - * @since 0.67.0 + * @since 3.10.0 */ export const MapFromSelf = ({ key, value }: { readonly key: K @@ -6935,7 +6933,7 @@ export const MapFromSelf = ({ key, v /** * @category api interface - * @since 0.67.0 + * @since 3.10.0 */ export interface ReadonlyMap$ extends AnnotableClass< @@ -6948,7 +6946,7 @@ export interface ReadonlyMap$ extend /** * @category ReadonlyMap transformations - * @since 0.67.0 + * @since 3.10.0 */ export const ReadonlyMap = ({ key, value }: { readonly key: K @@ -6965,7 +6963,7 @@ export const ReadonlyMap = ({ key, v /** * @category api interface - * @since 0.67.0 + * @since 3.10.0 */ export interface Map$ extends AnnotableClass< @@ -6992,14 +6990,14 @@ const map = ({ key, value }: { export { /** * @category Map transformations - * @since 0.67.0 + * @since 3.10.0 */ map as Map } /** * @category ReadonlyMap transformations - * @since 0.68.15 + * @since 3.10.0 */ export const ReadonlyMapFromRecord = ({ key, value }: { key: Schema @@ -7019,7 +7017,7 @@ export const ReadonlyMapFromRecord = ({ key, value }: { /** * @category Map transformations - * @since 0.68.15 + * @since 3.10.0 */ export const MapFromRecord = ({ key, value }: { key: Schema @@ -7037,10 +7035,11 @@ export const MapFromRecord = ({ key, value }: { } ) -const setArbitrary = (item: LazyArbitrary, ctx: GenerationContext): LazyArbitrary> => (fc) => { - const items = fc.array(item(fc)) - return (ctx.depthIdentifier !== undefined ? fc.oneof(ctx, fc.constant([]), items) : items).map((as) => new Set(as)) -} +const setArbitrary = + (item: LazyArbitrary, ctx: ArbitraryGenerationContext): LazyArbitrary> => (fc) => { + const items = fc.array(item(fc)) + return (ctx.depthIdentifier !== undefined ? fc.oneof(ctx, fc.constant([]), items) : items).map((as) => new Set(as)) + } const readonlySetPretty = (item: pretty_.Pretty): pretty_.Pretty> => (set) => `new Set([${Array.from(set.values()).map((a) => item(a)).join(", ")}])` @@ -7062,7 +7061,7 @@ const readonlySetParse = ( /** * @category api interface - * @since 0.67.0 + * @since 3.10.0 */ export interface ReadonlySetFromSelf extends AnnotableClass< @@ -7090,14 +7089,14 @@ const setFromSelf_ = (value: Value, description: strin /** * @category ReadonlySet - * @since 0.67.0 + * @since 3.10.0 */ export const ReadonlySetFromSelf = (value: Value): ReadonlySetFromSelf => setFromSelf_(value, `ReadonlySet<${format(value)}>`) /** * @category api interface - * @since 0.67.0 + * @since 3.10.0 */ export interface SetFromSelf extends AnnotableClass< @@ -7110,14 +7109,14 @@ export interface SetFromSelf extends /** * @category Set - * @since 0.67.0 + * @since 3.10.0 */ export const SetFromSelf = (value: Value): SetFromSelf => setFromSelf_(value, `Set<${format(value)}>`) as any /** * @category api interface - * @since 0.67.0 + * @since 3.10.0 */ export interface ReadonlySet$ extends AnnotableClass< @@ -7130,7 +7129,7 @@ export interface ReadonlySet$ extends /** * @category ReadonlySet transformations - * @since 0.67.0 + * @since 3.10.0 */ export const ReadonlySet = (value: Value): ReadonlySet$ => { const value_ = asSchema(value) @@ -7143,7 +7142,7 @@ export const ReadonlySet = (value: Value): ReadonlySet /** * @category api interface - * @since 0.67.0 + * @since 3.10.0 */ export interface Set$ extends AnnotableClass< @@ -7166,7 +7165,7 @@ const set = (value: Value): Set$ => { export { /** * @category Set transformations - * @since 0.67.0 + * @since 3.10.0 */ set as Set } @@ -7179,7 +7178,7 @@ const bigDecimalArbitrary = (): LazyArbitrary => (fc) => /** * @category BigDecimal constructors - * @since 0.67.0 + * @since 3.10.0 */ export class BigDecimalFromSelf extends declare( bigDecimal_.isBigDecimal, @@ -7193,7 +7192,7 @@ export class BigDecimalFromSelf extends declare( /** * @category BigDecimal transformations - * @since 0.67.0 + * @since 3.10.0 */ export class BigDecimal extends transformOrFail( String$.annotations({ description: "a string that will be parsed into a BigDecimal" }), @@ -7214,7 +7213,7 @@ export class BigDecimal extends transformOrFail( * When encoding, this Schema will produce incorrect results if the BigDecimal exceeds the 64-bit range of a number. * * @category BigDecimal transformations - * @since 0.67.0 + * @since 3.10.0 */ export class BigDecimalFromNumber extends transformOrFail( Number$.annotations({ description: "a number that will be parsed into a BigDecimal" }), @@ -7227,14 +7226,14 @@ export class BigDecimalFromNumber extends transformOrFail( ).annotations({ identifier: "BigDecimalFromNumber" }) {} /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export const GreaterThanBigDecimalTypeId: unique symbol = Symbol.for("@effect/schema/TypeId/GreaterThanBigDecimal") +export const GreaterThanBigDecimalSchemaId: unique symbol = Symbol.for("effect/SchemaId/GreaterThanBigDecimal") /** * @category BigDecimal filters - * @since 0.67.0 + * @since 3.10.0 */ export const greaterThanBigDecimal = ( min: bigDecimal_.BigDecimal, @@ -7243,23 +7242,24 @@ export const greaterThanBigDecimal = ( (self: Schema): filter> => self.pipe( filter((a) => bigDecimal_.greaterThan(a, min), { - typeId: { id: GreaterThanBigDecimalTypeId, annotation: { min } }, + schemaId: GreaterThanBigDecimalSchemaId, + [GreaterThanBigDecimalSchemaId]: { min }, description: `a BigDecimal greater than ${bigDecimal_.format(min)}`, ...annotations }) ) /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export const GreaterThanOrEqualToBigDecimalTypeId: unique symbol = Symbol.for( - "@effect/schema/TypeId/GreaterThanOrEqualToBigDecimal" +export const GreaterThanOrEqualToBigDecimalSchemaId: unique symbol = Symbol.for( + "effect/schema/GreaterThanOrEqualToBigDecimal" ) /** * @category BigDecimal filters - * @since 0.67.0 + * @since 3.10.0 */ export const greaterThanOrEqualToBigDecimal = ( min: bigDecimal_.BigDecimal, @@ -7268,21 +7268,22 @@ export const greaterThanOrEqualToBigDecimal = (self: Schema): filter> => self.pipe( filter((a) => bigDecimal_.greaterThanOrEqualTo(a, min), { - typeId: { id: GreaterThanOrEqualToBigDecimalTypeId, annotation: { min } }, + schemaId: GreaterThanOrEqualToBigDecimalSchemaId, + [GreaterThanOrEqualToBigDecimalSchemaId]: { min }, description: `a BigDecimal greater than or equal to ${bigDecimal_.format(min)}`, ...annotations }) ) /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export const LessThanBigDecimalTypeId: unique symbol = Symbol.for("@effect/schema/TypeId/LessThanBigDecimal") +export const LessThanBigDecimalSchemaId: unique symbol = Symbol.for("effect/SchemaId/LessThanBigDecimal") /** * @category BigDecimal filters - * @since 0.67.0 + * @since 3.10.0 */ export const lessThanBigDecimal = ( max: bigDecimal_.BigDecimal, @@ -7291,23 +7292,24 @@ export const lessThanBigDecimal = ( (self: Schema): filter> => self.pipe( filter((a) => bigDecimal_.lessThan(a, max), { - typeId: { id: LessThanBigDecimalTypeId, annotation: { max } }, + schemaId: LessThanBigDecimalSchemaId, + [LessThanBigDecimalSchemaId]: { max }, description: `a BigDecimal less than ${bigDecimal_.format(max)}`, ...annotations }) ) /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export const LessThanOrEqualToBigDecimalTypeId: unique symbol = Symbol.for( - "@effect/schema/TypeId/LessThanOrEqualToBigDecimal" +export const LessThanOrEqualToBigDecimalSchemaId: unique symbol = Symbol.for( + "effect/schema/LessThanOrEqualToBigDecimal" ) /** * @category BigDecimal filters - * @since 0.67.0 + * @since 3.10.0 */ export const lessThanOrEqualToBigDecimal = ( max: bigDecimal_.BigDecimal, @@ -7316,23 +7318,24 @@ export const lessThanOrEqualToBigDecimal = ( (self: Schema): filter> => self.pipe( filter((a) => bigDecimal_.lessThanOrEqualTo(a, max), { - typeId: { id: LessThanOrEqualToBigDecimalTypeId, annotation: { max } }, + schemaId: LessThanOrEqualToBigDecimalSchemaId, + [LessThanOrEqualToBigDecimalSchemaId]: { max }, description: `a BigDecimal less than or equal to ${bigDecimal_.format(max)}`, ...annotations }) ) /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export const PositiveBigDecimalTypeId: unique symbol = Symbol.for( - "@effect/schema/TypeId/PositiveBigDecimal" +export const PositiveBigDecimalSchemaId: unique symbol = Symbol.for( + "effect/schema/PositiveBigDecimal" ) /** * @category BigDecimal filters - * @since 0.67.0 + * @since 3.10.0 */ export const positiveBigDecimal = ( annotations?: Annotations.Filter @@ -7340,7 +7343,7 @@ export const positiveBigDecimal = ( (self: Schema): filter> => self.pipe( filter((a) => bigDecimal_.isPositive(a), { - typeId: { id: PositiveBigDecimalTypeId, annotation: {} }, + schemaId: PositiveBigDecimalSchemaId, description: `a positive BigDecimal`, ...annotations }) @@ -7348,7 +7351,7 @@ export const positiveBigDecimal = ( /** * @category BigDecimal constructors - * @since 0.67.0 + * @since 3.10.0 */ export const PositiveBigDecimalFromSelf: filter> = BigDecimalFromSelf.pipe( positiveBigDecimal({ @@ -7358,16 +7361,16 @@ export const PositiveBigDecimalFromSelf: filter> ) /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export const NonNegativeBigDecimalTypeId: unique symbol = Symbol.for( - "@effect/schema/TypeId/NonNegativeBigDecimal" +export const NonNegativeBigDecimalSchemaId: unique symbol = Symbol.for( + "effect/schema/NonNegativeBigDecimal" ) /** * @category BigDecimal filters - * @since 0.67.0 + * @since 3.10.0 */ export const nonNegativeBigDecimal = ( annotations?: Annotations.Filter @@ -7375,7 +7378,7 @@ export const nonNegativeBigDecimal = ( (self: Schema): filter> => self.pipe( filter((a) => a.value >= 0n, { - typeId: { id: NonNegativeBigDecimalTypeId, annotation: {} }, + schemaId: NonNegativeBigDecimalSchemaId, description: `a non-negative BigDecimal`, ...annotations }) @@ -7383,7 +7386,7 @@ export const nonNegativeBigDecimal = ( /** * @category BigDecimal constructors - * @since 0.67.0 + * @since 3.10.0 */ export const NonNegativeBigDecimalFromSelf: filter> = BigDecimalFromSelf.pipe( nonNegativeBigDecimal({ @@ -7393,16 +7396,16 @@ export const NonNegativeBigDecimalFromSelf: filter( annotations?: Annotations.Filter @@ -7410,7 +7413,7 @@ export const negativeBigDecimal = ( (self: Schema): filter> => self.pipe( filter((a) => bigDecimal_.isNegative(a), { - typeId: { id: NegativeBigDecimalTypeId, annotation: {} }, + schemaId: NegativeBigDecimalSchemaId, description: `a negative BigDecimal`, ...annotations }) @@ -7418,7 +7421,7 @@ export const negativeBigDecimal = ( /** * @category BigDecimal constructors - * @since 0.67.0 + * @since 3.10.0 */ export const NegativeBigDecimalFromSelf: filter> = BigDecimalFromSelf.pipe( negativeBigDecimal({ @@ -7428,16 +7431,16 @@ export const NegativeBigDecimalFromSelf: filter> ) /** - * @category type id - * @since 0.67.0 + * @category schema id + * @since 3.10.0 */ -export const NonPositiveBigDecimalTypeId: unique symbol = Symbol.for( - "@effect/schema/TypeId/NonPositiveBigDecimal" +export const NonPositiveBigDecimalSchemaId: unique symbol = Symbol.for( + "effect/schema/NonPositiveBigDecimal" ) /** * @category BigDecimal filters - * @since 0.67.0 + * @since 3.10.0 */ export const nonPositiveBigDecimal = ( annotations?: Annotations.Filter @@ -7445,7 +7448,7 @@ export const nonPositiveBigDecimal = ( (self: Schema): filter> => self.pipe( filter((a) => a.value <= 0n, { - typeId: { id: NonPositiveBigDecimalTypeId, annotation: {} }, + schemaId: NonPositiveBigDecimalSchemaId, description: `a non-positive BigDecimal`, ...annotations }) @@ -7453,7 +7456,7 @@ export const nonPositiveBigDecimal = ( /** * @category BigDecimal constructors - * @since 0.67.0 + * @since 3.10.0 */ export const NonPositiveBigDecimalFromSelf: filter> = BigDecimalFromSelf.pipe( nonPositiveBigDecimal({ @@ -7463,14 +7466,14 @@ export const NonPositiveBigDecimalFromSelf: filter( minimum: bigDecimal_.BigDecimal, @@ -7480,7 +7483,8 @@ export const betweenBigDecimal = ( (self: Schema): filter> => self.pipe( filter((a) => bigDecimal_.between(a, { minimum, maximum }), { - typeId: { id: BetweenBigDecimalTypeId, annotation: { maximum, minimum } }, + schemaId: BetweenBigDecimalSchemaId, + [BetweenBigDecimalSchemaId]: { maximum, minimum }, description: `a BigDecimal between ${bigDecimal_.format(minimum)} and ${bigDecimal_.format(maximum)}`, ...annotations }) @@ -7490,7 +7494,7 @@ export const betweenBigDecimal = ( * Clamps a `BigDecimal` between a minimum and a maximum value. * * @category BigDecimal transformations - * @since 0.67.0 + * @since 3.10.0 */ export const clampBigDecimal = (minimum: bigDecimal_.BigDecimal, maximum: bigDecimal_.BigDecimal) => @@ -7501,10 +7505,11 @@ export const clampBigDecimal = { strict: false, decode: (self) => bigDecimal_.clamp(self, { minimum, maximum }), encode: identity } ) -const chunkArbitrary = (item: LazyArbitrary, ctx: GenerationContext): LazyArbitrary> => (fc) => { - const items = fc.array(item(fc)) - return (ctx.depthIdentifier !== undefined ? fc.oneof(ctx, fc.constant([]), items) : items).map(chunk_.fromIterable) -} +const chunkArbitrary = + (item: LazyArbitrary, ctx: ArbitraryGenerationContext): LazyArbitrary> => (fc) => { + const items = fc.array(item(fc)) + return (ctx.depthIdentifier !== undefined ? fc.oneof(ctx, fc.constant([]), items) : items).map(chunk_.fromIterable) + } const chunkPretty = (item: pretty_.Pretty): pretty_.Pretty> => (c) => `Chunk(${chunk_.toReadonlyArray(c).map(item).join(", ")})` @@ -7521,7 +7526,7 @@ const chunkParse = ( /** * @category api interface - * @since 0.67.0 + * @since 3.10.0 */ export interface ChunkFromSelf extends AnnotableClass< @@ -7534,7 +7539,7 @@ export interface ChunkFromSelf extends /** * @category Chunk - * @since 0.67.0 + * @since 3.10.0 */ export const ChunkFromSelf = (value: Value): ChunkFromSelf => { return declare( @@ -7554,7 +7559,7 @@ export const ChunkFromSelf = (value: Value): ChunkFrom /** * @category api interface - * @since 0.67.0 + * @since 3.10.0 */ export interface Chunk extends AnnotableClass< @@ -7567,7 +7572,7 @@ export interface Chunk extends /** * @category Chunk transformations - * @since 0.67.0 + * @since 3.10.0 */ export const Chunk = (value: Value): Chunk => { const value_ = asSchema(value) @@ -7584,7 +7589,7 @@ export const Chunk = (value: Value): Chunk => { /** * @category api interface - * @since 0.67.23 + * @since 3.10.0 */ export interface NonEmptyChunkFromSelf extends AnnotableClass< @@ -7611,7 +7616,7 @@ const nonEmptyChunkParse = ( /** * @category Chunk - * @since 0.67.23 + * @since 3.10.0 */ export const NonEmptyChunkFromSelf = (value: Value): NonEmptyChunkFromSelf => { return declare( @@ -7631,7 +7636,7 @@ export const NonEmptyChunkFromSelf = (value: Value): N /** * @category api interface - * @since 0.67.23 + * @since 3.10.0 */ export interface NonEmptyChunk extends AnnotableClass< @@ -7644,7 +7649,7 @@ export interface NonEmptyChunk extends /** * @category Chunk transformations - * @since 0.67.23 + * @since 3.10.0 */ export const NonEmptyChunk = (value: Value): NonEmptyChunk => { const value_ = asSchema(value) @@ -7678,7 +7683,7 @@ const dataParse = > | ReadonlyArray = { /** * @category api interface - * @since 0.67.0 + * @since 3.10.0 */ export interface Class extends Schema, R> @@ -7736,7 +7741,7 @@ export interface Class & Omit & Proto - /** @since 0.69.3 */ + /** @since 3.10.0 */ readonly ast: AST.Transformation make, X>(this: { new(...args: Args): X }, ...args: Args): X @@ -7823,7 +7828,7 @@ export interface Class = Struct | { - readonly [refineTypeId]: HasFields + readonly [RefineSchemaId]: HasFields } const isField = (u: unknown) => isSchema(u) || isPropertySignature(u) @@ -7832,7 +7837,7 @@ const isFields = (fields: object): fields is Field util_.ownKeys(fields).every((key) => isField((fields as any)[key])) const getFields = (hasFields: HasFields): Fields => - "fields" in hasFields ? hasFields.fields : getFields(hasFields[refineTypeId]) + "fields" in hasFields ? hasFields.fields : getFields(hasFields[RefineSchemaId]) const getSchemaFromFieldsOr = (fieldsOr: Fields | HasFields): Schema.Any => isFields(fieldsOr) ? Struct(fieldsOr) : isSchema(fieldsOr) ? fieldsOr : Struct(getFields(fieldsOr)) @@ -7842,7 +7847,7 @@ const getFieldsFromFieldsOr = (fieldsOr: Fields | /** * @category classes - * @since 0.67.0 + * @since 3.10.0 */ export const Class = (identifier: string) => ( @@ -7873,7 +7878,7 @@ export const getClassTag = (tag: Tag) => /** * @category api interface - * @since 0.67.0 + * @since 3.10.0 */ export interface TaggedClass extends Class< @@ -7891,7 +7896,7 @@ export interface TaggedClass(identifier?: string) => ( @@ -7919,7 +7924,7 @@ export const TaggedClass = (identifier?: string) => /** * @category api interface - * @since 0.67.0 + * @since 3.10.0 */ export interface TaggedErrorClass extends Class< @@ -7937,7 +7942,7 @@ export interface TaggedErrorClass(identifier?: string) => ( @@ -7976,136 +7981,6 @@ export const TaggedError = (identifier?: string) => } as any } -/** - * @since 0.67.0 - */ -export interface TaggedRequest< - Tag extends string, - A, - I, - R, - SuccessType, - SuccessEncoded, - FailureType, - FailureEncoded, - ResultR -> extends - Request.Request, - Serializable.SerializableWithResult< - A, - I, - R, - SuccessType, - SuccessEncoded, - FailureType, - FailureEncoded, - ResultR - > -{ - readonly _tag: Tag -} - -/** - * @since 0.67.0 - */ -export declare namespace TaggedRequest { - /** - * @since 0.69.0 - */ - export type Any = TaggedRequest - /** - * @since 0.69.0 - */ - export type All = - | Any - | TaggedRequest -} - -/** - * @category api interface - * @since 0.67.0 - */ -export interface TaggedRequestClass< - Self, - Tag extends string, - Payload extends Struct.Fields, - Success extends Schema.All, - Failure extends Schema.All -> extends - Class< - Self, - Payload, - Struct.Encoded, - Struct.Context, - Struct.Constructor>, - TaggedRequest< - Tag, - Self, - Struct.Encoded, - Struct.Context, - Schema.Type, - Schema.Encoded, - Schema.Type, - Schema.Encoded, - Schema.Context | Schema.Context - >, - {} - > -{ - readonly _tag: Tag - /** @since 0.69.1 */ - readonly success: Success - /** @since 0.69.1 */ - readonly failure: Failure -} - -/** - * @category classes - * @since 0.67.0 - */ -export const TaggedRequest = - (identifier?: string) => - ( - tag: Tag, - options: { - failure: Failure - success: Success - payload: Payload - }, - annotations?: Annotations.Schema - ): [Self] extends [never] ? MissingSelfGeneric<"TaggedRequest", `"Tag", SuccessSchema, FailureSchema, `> - : TaggedRequestClass< - Self, - Tag, - { readonly _tag: tag } & Payload, - Success, - Failure - > => - { - const taggedFields = extendFields({ _tag: getClassTag(tag) }, options.payload) - return class TaggedRequestClass extends makeClass({ - kind: "TaggedRequest", - identifier: identifier ?? tag, - schema: Struct(taggedFields), - fields: taggedFields, - Base: Request.Class, - annotations - }) { - static _tag = tag - static success = options.success - static failure = options.failure - get [serializable_.symbol]() { - return this.constructor - } - get [serializable_.symbolResult]() { - return { - failure: options.failure, - success: options.success - } - } - } as any - } - const extendFields = (a: Struct.Fields, b: Struct.Fields): Struct.Fields => { const out = { ...a } for (const key of util_.ownKeys(b)) { @@ -8142,7 +8017,7 @@ const makeClass = ({ Base, annotations, disableToString, fields, identifier, kin annotations?: Annotations.Schema | undefined disableToString?: boolean | undefined }): any => { - const classSymbol = Symbol.for(`@effect/schema/${kind}/${identifier}`) + const classSymbol = Symbol.for(`effect/Schema/${kind}/${identifier}`) const validateSchema = orElseTitleAnnotation(schema, `${identifier} (Constructor)`) const encodedSide: Schema.Any = orElseTitleAnnotation(schema, `${identifier} (Encoded side)`) const typeSide = orElseTitleAnnotation(typeSchema(schema), `${identifier} (Type side)`) @@ -8305,7 +8180,7 @@ const makeClass = ({ Base, annotations, disableToString, fields, identifier, kin /** * @category FiberId - * @since 0.67.0 + * @since 3.10.0 */ export type FiberIdEncoded = | { @@ -8371,7 +8246,7 @@ const fiberIdPretty: pretty_.Pretty = (fiberId) => { /** * @category FiberId constructors - * @since 0.67.0 + * @since 3.10.0 */ export class FiberIdFromSelf extends declare( fiberId_.isFiberId, @@ -8410,7 +8285,7 @@ const fiberIdEncode = (input: fiberId_.FiberId): FiberIdEncoded => { /** * @category FiberId transformations - * @since 0.67.0 + * @since 3.10.0 */ export class FiberId extends transform( FiberIdEncoded, @@ -8420,7 +8295,7 @@ export class FiberId extends transform( /** * @category Cause utils - * @since 0.69.0 + * @since 3.10.0 */ export type CauseEncoded = | { @@ -8552,7 +8427,7 @@ const causeParse = ( /** * @category api interface - * @since 0.69.0 + * @since 3.10.0 */ export interface CauseFromSelf extends AnnotableClass< @@ -8565,7 +8440,7 @@ export interface CauseFromSelf exten /** * @category Cause transformations - * @since 0.69.0 + * @since 3.10.0 */ export const CauseFromSelf = ({ defect, error }: { readonly error: E @@ -8629,7 +8504,7 @@ function causeEncode(cause: cause_.Cause): CauseEncoded { /** * @category api interface - * @since 0.69.0 + * @since 3.10.0 */ export interface Cause extends AnnotableClass< @@ -8642,7 +8517,7 @@ export interface Cause extends /** * @category Cause transformations - * @since 0.69.0 + * @since 3.10.0 */ export const Cause = ({ defect, error }: { readonly error: E @@ -8659,7 +8534,7 @@ export const Cause = ({ defect, erro /** * @category api interface - * @since 0.69.0 + * @since 3.10.0 */ export interface Defect extends transform {} @@ -8674,7 +8549,7 @@ export interface Defect extends transform {} * This is useful for serializing and deserializing errors across network boundaries where error objects do not natively serialize. * * @category defect - * @since 0.69.0 + * @since 3.10.0 */ export const Defect: Defect = transform( Unknown, @@ -8707,7 +8582,7 @@ export const Defect: Defect = transform( /** * @category Exit utils - * @since 0.69.0 + * @since 3.10.0 */ export type ExitEncoded = | { @@ -8788,7 +8663,7 @@ const exitParse = ( /** * @category api interface - * @since 0.69.0 + * @since 3.10.0 */ export interface ExitFromSelf extends AnnotableClass< @@ -8801,7 +8676,7 @@ export interface ExitFromSelf( { defect, failure, success }: { @@ -8833,7 +8708,7 @@ export const ExitFromSelf = extends AnnotableClass< @@ -8846,7 +8721,7 @@ export interface Exit( { defect, failure, success }: { @@ -8873,7 +8748,7 @@ export const Exit = (item: LazyArbitrary, ctx: GenerationContext): LazyArbitrary> => (fc) => { + (item: LazyArbitrary, ctx: ArbitraryGenerationContext): LazyArbitrary> => (fc) => { const items = fc.array(item(fc)) return (ctx.depthIdentifier !== undefined ? fc.oneof(ctx, fc.constant([]), items) : items).map( hashSet_.fromIterable @@ -8900,7 +8775,7 @@ const hashSetParse = ( /** * @category api interface - * @since 0.67.0 + * @since 3.10.0 */ export interface HashSetFromSelf extends AnnotableClass< @@ -8913,7 +8788,7 @@ export interface HashSetFromSelf extends /** * @category HashSet transformations - * @since 0.67.0 + * @since 3.10.0 */ export const HashSetFromSelf = ( value: Value @@ -8935,7 +8810,7 @@ export const HashSetFromSelf = ( /** * @category api interface - * @since 0.67.0 + * @since 3.10.0 */ export interface HashSet extends AnnotableClass< @@ -8948,7 +8823,7 @@ export interface HashSet extends /** * @category HashSet transformations - * @since 0.67.0 + * @since 3.10.0 */ export const HashSet = (value: Value): HashSet => { const value_ = asSchema(value) @@ -8962,7 +8837,7 @@ export const HashSet = (value: Value): HashSet const hashMapArbitrary = ( key: LazyArbitrary, value: LazyArbitrary, - ctx: GenerationContext + ctx: ArbitraryGenerationContext ): LazyArbitrary> => (fc) => { const items = fc.array(fc.tuple(key(fc), value(fc))) @@ -9000,7 +8875,7 @@ const hashMapParse = ( /** * @category api interface - * @since 0.67.0 + * @since 3.10.0 */ export interface HashMapFromSelf extends AnnotableClass< @@ -9013,7 +8888,7 @@ export interface HashMapFromSelf ext /** * @category HashMap transformations - * @since 0.67.0 + * @since 3.10.0 */ export const HashMapFromSelf = ({ key, value }: { readonly key: K @@ -9036,7 +8911,7 @@ export const HashMapFromSelf = ({ ke /** * @category api interface - * @since 0.67.0 + * @since 3.10.0 */ export interface HashMap extends AnnotableClass< @@ -9049,7 +8924,7 @@ export interface HashMap extends /** * @category HashMap transformations - * @since 0.67.0 + * @since 3.10.0 */ export const HashMap = ({ key, value }: { readonly key: K @@ -9064,10 +8939,11 @@ export const HashMap = ({ key, value ) } -const listArbitrary = (item: LazyArbitrary, ctx: GenerationContext): LazyArbitrary> => (fc) => { - const items = fc.array(item(fc)) - return (ctx.depthIdentifier !== undefined ? fc.oneof(ctx, fc.constant([]), items) : items).map(list_.fromIterable) -} +const listArbitrary = + (item: LazyArbitrary, ctx: ArbitraryGenerationContext): LazyArbitrary> => (fc) => { + const items = fc.array(item(fc)) + return (ctx.depthIdentifier !== undefined ? fc.oneof(ctx, fc.constant([]), items) : items).map(list_.fromIterable) + } const listPretty = (item: pretty_.Pretty): pretty_.Pretty> => (set) => `List(${Array.from(set).map((a) => item(a)).join(", ")})` @@ -9089,7 +8965,7 @@ const listParse = ( /** * @category api interface - * @since 0.67.0 + * @since 3.10.0 */ export interface ListFromSelf extends AnnotableClass< @@ -9102,7 +8978,7 @@ export interface ListFromSelf extends /** * @category List transformations - * @since 0.67.0 + * @since 3.10.0 */ export const ListFromSelf = ( value: Value @@ -9124,7 +9000,7 @@ export const ListFromSelf = ( /** * @category api interface - * @since 0.67.0 + * @since 3.10.0 */ export interface List extends AnnotableClass< @@ -9137,7 +9013,7 @@ export interface List extends /** * @category List transformations - * @since 0.67.0 + * @since 3.10.0 */ export const List = (value: Value): List => { const value_ = asSchema(value) @@ -9148,14 +9024,17 @@ export const List = (value: Value): List => { ) } -const sortedSetArbitrary = - (item: LazyArbitrary, ord: Order.Order, ctx: GenerationContext): LazyArbitrary> => - (fc) => { - const items = fc.array(item(fc)) - return (ctx.depthIdentifier !== undefined ? fc.oneof(ctx, fc.constant([]), items) : items).map((as) => - sortedSet_.fromIterable(as, ord) - ) - } +const sortedSetArbitrary = ( + item: LazyArbitrary, + ord: Order.Order, + ctx: ArbitraryGenerationContext +): LazyArbitrary> => +(fc) => { + const items = fc.array(item(fc)) + return (ctx.depthIdentifier !== undefined ? fc.oneof(ctx, fc.constant([]), items) : items).map((as) => + sortedSet_.fromIterable(as, ord) + ) +} const sortedSetPretty = (item: pretty_.Pretty): pretty_.Pretty> => (set) => `new SortedSet([${Array.from(sortedSet_.values(set)).map((a) => item(a)).join(", ")}])` @@ -9176,7 +9055,7 @@ const sortedSetParse = ( /** * @category api interface - * @since 0.67.0 + * @since 3.10.0 */ export interface SortedSetFromSelf extends AnnotableClass< @@ -9189,7 +9068,7 @@ export interface SortedSetFromSelf extends /** * @category SortedSet transformations - * @since 0.67.0 + * @since 3.10.0 */ export const SortedSetFromSelf = ( value: Value, @@ -9213,7 +9092,7 @@ export const SortedSetFromSelf = ( /** * @category api interface - * @since 0.67.0 + * @since 3.10.0 */ export interface SortedSet extends AnnotableClass< @@ -9226,7 +9105,7 @@ export interface SortedSet extends /** * @category SortedSet transformations - * @since 0.67.0 + * @since 3.10.0 */ export const SortedSet = ( value: Value, @@ -9251,7 +9130,7 @@ export const SortedSet = ( * * @see https://developer.mozilla.org/docs/Glossary/Truthy * @category boolean constructors - * @since 0.67.0 + * @since 3.10.0 */ export class BooleanFromUnknown extends transform( Unknown, @@ -9261,15 +9140,705 @@ export class BooleanFromUnknown extends transform( /** * @category Config validations - * @since 0.67.12 + * @since 3.10.0 */ export const Config = (name: string, schema: Schema): config_.Config => { const decodeEither_ = decodeEither(schema) return config_.string(name).pipe( config_.mapOrFail((a) => decodeEither_(a).pipe( - either_.mapLeft((error) => configError_.InvalidData([], TreeFormatter.formatErrorSync(error))) + either_.mapLeft((error) => configError_.InvalidData([], ParseResult.TreeFormatter.formatErrorSync(error))) ) ) ) } + +// --------------------------------------------- +// Serializable +// --------------------------------------------- + +/** + * @since 3.10.0 + * @category symbol + */ +export const symbolSerializable: unique symbol = Symbol.for( + "effect/Schema/Serializable/symbol" +) + +/** + * The `Serializable` trait allows objects to define their own schema for + * serialization. + * + * @since 3.10.0 + * @category model + */ +export interface Serializable { + readonly [symbolSerializable]: Schema +} + +/** + * @since 3.10.0 + * @category model + */ +export declare namespace Serializable { + /** + * @since 3.10.0 + */ + export type Type = T extends Serializable ? A : never + /** + * @since 3.10.0 + */ + export type Encoded = T extends Serializable ? I : never + /** + * @since 3.10.0 + */ + export type Context = T extends Serializable ? R : never + /** + * @since 3.10.0 + */ + export type Any = Serializable + /** + * @since 3.10.0 + */ + export type All = + | Any + | Serializable + | Serializable + | Serializable +} + +/** + * @since 3.10.0 + */ +export const asSerializable = ( + serializable: S +): Serializable, Serializable.Encoded, Serializable.Context> => serializable as any + +/** + * @since 3.10.0 + * @category accessor + */ +export const serializableSchema = (self: Serializable): Schema => self[symbolSerializable] + +/** + * @since 3.10.0 + * @category encoding + */ +export const serialize = (self: Serializable): Effect.Effect => + encodeUnknown(self[symbolSerializable])(self) + +/** + * @since 3.10.0 + * @category decoding + */ +export const deserialize: { + (value: unknown): (self: Serializable) => Effect.Effect + (self: Serializable, value: unknown): Effect.Effect +} = dual( + 2, + (self: Serializable, value: unknown): Effect.Effect => + decodeUnknown(self[symbolSerializable])(value) +) + +/** + * @since 3.10.0 + * @category symbol + */ +export const symbolWithResult: unique symbol = Symbol.for( + "effect/Schema/Serializable/symbolResult" +) + +/** + * The `WithResult` trait is designed to encapsulate the outcome of an + * operation, distinguishing between success and failure cases. Each case is + * associated with a schema that defines the structure and types of the success + * or failure data. + * + * @since 3.10.0 + * @category model + */ +export interface WithResult { + readonly [symbolWithResult]: { + readonly success: Schema + readonly failure: Schema + } +} + +/** + * @since 3.10.0 + * @category model + */ +export declare namespace WithResult { + /** + * @since 3.10.0 + */ + export type Success = T extends WithResult ? _A : never + /** + * @since 3.10.0 + */ + export type SuccessEncoded = T extends WithResult ? _I : never + /** + * @since 3.10.0 + */ + export type Failure = T extends WithResult ? _E : never + /** + * @since 3.10.0 + */ + export type FailureEncoded = T extends WithResult ? _EI : never + + /** + * @since 3.10.0 + */ + export type Context = T extends WithResult ? R : never + /** + * @since 3.10.0 + */ + export type Any = WithResult + /** + * @since 3.10.0 + */ + export type All = + | Any + | WithResult +} + +/** + * @since 3.10.0 + */ +export const asWithResult = ( + withExit: WR +): WithResult< + WithResult.Success, + WithResult.SuccessEncoded, + WithResult.Failure, + WithResult.FailureEncoded, + WithResult.Context +> => withExit as any + +/** + * @since 3.10.0 + * @category accessor + */ +export const failureSchema = (self: WithResult): Schema => + self[symbolWithResult].failure + +/** + * @since 3.10.0 + * @category accessor + */ +export const successSchema = (self: WithResult): Schema => + self[symbolWithResult].success + +const exitSchemaCache = globalValue( + "effect/Schema/Serializable/exitSchemaCache", + () => new WeakMap>() +) + +/** + * @since 3.10.0 + * @category accessor + */ +export const exitSchema = (self: WithResult): Schema< + exit_.Exit, + ExitEncoded, + R +> => { + const proto = Object.getPrototypeOf(self) + if (!(symbolWithResult in proto)) { + return Exit({ + failure: failureSchema(self), + success: successSchema(self), + defect: Defect + }) + } + let schema = exitSchemaCache.get(proto) + if (schema === undefined) { + schema = Exit({ + failure: failureSchema(self), + success: successSchema(self), + defect: Defect + }) + exitSchemaCache.set(proto, schema) + } + return schema +} + +/** + * @since 3.10.0 + * @category encoding + */ +export const serializeFailure: { + (value: FA): ( + self: WithResult + ) => Effect.Effect + (self: WithResult, value: FA): Effect.Effect +} = dual( + 2, + (self: WithResult, value: FA): Effect.Effect => + encode(self[symbolWithResult].failure)(value) +) + +/** + * @since 3.10.0 + * @category decoding + */ +export const deserializeFailure: { + ( + value: unknown + ): (self: WithResult) => Effect.Effect + (self: WithResult, value: unknown): Effect.Effect +} = dual( + 2, + ( + self: WithResult, + value: unknown + ): Effect.Effect => decodeUnknown(self[symbolWithResult].failure)(value) +) + +/** + * @since 3.10.0 + * @category encoding + */ +export const serializeSuccess: { + (value: SA): ( + self: WithResult + ) => Effect.Effect + (self: WithResult, value: SA): Effect.Effect +} = dual( + 2, + (self: WithResult, value: SA): Effect.Effect => + encode(self[symbolWithResult].success)(value) +) + +/** + * @since 3.10.0 + * @category decoding + */ +export const deserializeSuccess: { + (value: unknown): ( + self: WithResult + ) => Effect.Effect + (self: WithResult, value: unknown): Effect.Effect +} = dual( + 2, + ( + self: WithResult, + value: unknown + ): Effect.Effect => decodeUnknown(self[symbolWithResult].success)(value) +) + +/** + * @since 3.10.0 + * @category encoding + */ +export const serializeExit: { + (value: exit_.Exit): ( + self: WithResult + ) => Effect.Effect, ParseResult.ParseError, R> + ( + self: WithResult, + value: exit_.Exit + ): Effect.Effect, ParseResult.ParseError, R> +} = dual(2, ( + self: WithResult, + value: exit_.Exit +): Effect.Effect, ParseResult.ParseError, R> => encode(exitSchema(self))(value)) + +/** + * @since 3.10.0 + * @category decoding + */ +export const deserializeExit: { + (value: unknown): ( + self: WithResult + ) => Effect.Effect, ParseResult.ParseError, R> + ( + self: WithResult, + value: unknown + ): Effect.Effect, ParseResult.ParseError, R> +} = dual(2, ( + self: WithResult, + value: unknown +): Effect.Effect, ParseResult.ParseError, R> => decodeUnknown(exitSchema(self))(value)) + +// --------------------------------------------- +// SerializableWithResult +// --------------------------------------------- + +/** + * The `SerializableWithResult` trait is specifically designed to model remote + * procedures that require serialization of their input and output, managing + * both successful and failed outcomes. + * + * This trait combines functionality from both the `Serializable` and `WithResult` + * traits to handle data serialization and the bifurcation of operation results + * into success or failure categories. + * + * @since 3.10.0 + * @category model + */ +export interface SerializableWithResult< + A, + I, + R, + Success, + SuccessEncoded, + Failure, + FailureEncoded, + ResultR +> extends Serializable, WithResult {} + +/** + * @since 3.10.0 + * @category model + */ +export declare namespace SerializableWithResult { + /** + * @since 3.10.0 + */ + export type Context

= P extends - SerializableWithResult ? SR | RR - : never - /** - * @since 0.69.0 - */ - export type Any = SerializableWithResult - /** - * @since 0.69.0 - */ - export type All = - | Any - | SerializableWithResult -} - -/** - * @since 0.69.0 - */ -export const asSerializableWithResult = ( - procedure: SWR -): SerializableWithResult< - Serializable.Type, - Serializable.Encoded, - Serializable.Context, - WithResult.Success, - WithResult.SuccessEncoded, - WithResult.Failure, - WithResult.FailureEncoded, - WithResult.Context -> => procedure as any diff --git a/packages/schema/src/TreeFormatter.ts b/packages/schema/src/TreeFormatter.ts deleted file mode 100644 index 05eaf3c960..0000000000 --- a/packages/schema/src/TreeFormatter.ts +++ /dev/null @@ -1,215 +0,0 @@ -/** - * @since 0.67.0 - */ - -import type * as Cause from "effect/Cause" -import * as Effect from "effect/Effect" -import * as Option from "effect/Option" -import * as Predicate from "effect/Predicate" -import * as AST from "./AST.js" -import * as util_ from "./internal/util.js" -import type * as ParseResult from "./ParseResult.js" - -interface Forest extends ReadonlyArray> {} - -interface Tree { - readonly value: A - readonly forest: Forest -} - -const make = (value: A, forest: Forest = []): Tree => ({ - value, - forest -}) - -/** - * @category formatting - * @since 0.67.0 - */ -export const formatIssue = (issue: ParseResult.ParseIssue): Effect.Effect => - Effect.map(go(issue), (tree) => drawTree(tree)) - -/** - * @category formatting - * @since 0.67.0 - */ -export const formatIssueSync = (issue: ParseResult.ParseIssue): string => Effect.runSync(formatIssue(issue)) - -/** - * @category formatting - * @since 0.67.0 - */ -export const formatError = (error: ParseResult.ParseError): Effect.Effect => formatIssue(error.issue) - -/** - * @category formatting - * @since 0.67.0 - */ -export const formatErrorSync = (error: ParseResult.ParseError): string => formatIssueSync(error.issue) - -const drawTree = (tree: Tree): string => tree.value + draw("\n", tree.forest) - -const draw = (indentation: string, forest: Forest): string => { - let r = "" - const len = forest.length - let tree: Tree - for (let i = 0; i < len; i++) { - tree = forest[i] - const isLast = i === len - 1 - r += indentation + (isLast ? "└" : "├") + "─ " + tree.value - r += draw(indentation + (len > 1 && !isLast ? "│ " : " "), tree.forest) - } - return r -} - -const formatTransformationKind = (kind: ParseResult.Transformation["kind"]): string => { - switch (kind) { - case "Encoded": - return "Encoded side transformation failure" - case "Transformation": - return "Transformation process failure" - case "Type": - return "Type side transformation failure" - } -} - -const formatRefinementKind = (kind: ParseResult.Refinement["kind"]): string => { - switch (kind) { - case "From": - return "From side refinement failure" - case "Predicate": - return "Predicate refinement failure" - } -} - -const getAnnotated = (issue: ParseResult.ParseIssue): Option.Option => - "ast" in issue ? Option.some(issue.ast) : Option.none() - -interface CurrentMessage { - readonly message: string - readonly override: boolean -} - -const getCurrentMessage = ( - issue: ParseResult.ParseIssue -): Effect.Effect => - getAnnotated(issue).pipe( - Option.flatMap(AST.getMessageAnnotation), - Effect.flatMap((annotation) => { - const out = annotation(issue) - return Predicate.isString(out) - ? Effect.succeed({ message: out, override: false }) - : Effect.isEffect(out) - ? Effect.map(out, (message) => ({ message, override: false })) - : Predicate.isString(out.message) - ? Effect.succeed({ message: out.message, override: out.override }) - : Effect.map(out.message, (message) => ({ message, override: out.override })) - }) - ) - -const createParseIssueGuard = - (tag: T) => - (issue: ParseResult.ParseIssue): issue is Extract => issue._tag === tag - -const isComposite = createParseIssueGuard("Composite") -const isRefinement = createParseIssueGuard("Refinement") -const isTransformation = createParseIssueGuard("Transformation") - -/** @internal */ -export const getMessage: ( - issue: ParseResult.ParseIssue -) => Effect.Effect = (issue: ParseResult.ParseIssue) => - getCurrentMessage(issue).pipe( - Effect.flatMap((currentMessage) => { - const useInnerMessage = !currentMessage.override && ( - isComposite(issue) || - (isRefinement(issue) && issue.kind === "From") || - (isTransformation(issue) && issue.kind !== "Transformation") - ) - return useInnerMessage - ? isTransformation(issue) || isRefinement(issue) ? getMessage(issue.issue) : Option.none() - : Effect.succeed(currentMessage.message) - }) - ) - -const getParseIssueTitleAnnotation = (issue: ParseResult.ParseIssue): Option.Option => - getAnnotated(issue).pipe( - Option.flatMap(AST.getParseIssueTitleAnnotation), - Option.filterMap( - (annotation) => Option.fromNullable(annotation(issue)) - ) - ) - -/** @internal */ -export const formatTypeMessage = (e: ParseResult.Type): Effect.Effect => - getMessage(e).pipe( - Effect.orElse(() => getParseIssueTitleAnnotation(e)), - Effect.catchAll(() => - Effect.succeed(e.message ?? `Expected ${String(e.ast)}, actual ${util_.formatUnknown(e.actual)}`) - ) - ) - -const getParseIssueTitle = ( - issue: ParseResult.Forbidden | ParseResult.Transformation | ParseResult.Refinement | ParseResult.Composite -): string => Option.getOrElse(getParseIssueTitleAnnotation(issue), () => String(issue.ast)) - -/** @internal */ -export const formatForbiddenMessage = (e: ParseResult.Forbidden): string => e.message ?? "is forbidden" - -/** @internal */ -export const formatUnexpectedMessage = (e: ParseResult.Unexpected): string => e.message ?? "is unexpected" - -/** @internal */ -export const formatMissingMessage = (e: ParseResult.Missing): Effect.Effect => - AST.getMissingMessageAnnotation(e.ast).pipe( - Effect.flatMap((annotation) => { - const out = annotation() - return Predicate.isString(out) ? Effect.succeed(out) : out - }), - Effect.catchAll(() => Effect.succeed(e.message ?? "is missing")) - ) - -const getTree = (issue: ParseResult.ParseIssue, onFailure: () => Effect.Effect>) => - Effect.matchEffect(getMessage(issue), { - onFailure, - onSuccess: (message) => Effect.succeed(make(message)) - }) - -const go = ( - e: ParseResult.ParseIssue | ParseResult.Pointer -): Effect.Effect> => { - switch (e._tag) { - case "Type": - return Effect.map(formatTypeMessage(e), make) - case "Forbidden": - return Effect.succeed(make(getParseIssueTitle(e), [make(formatForbiddenMessage(e))])) - case "Unexpected": - return Effect.succeed(make(formatUnexpectedMessage(e))) - case "Missing": - return Effect.map(formatMissingMessage(e), make) - case "Transformation": - return getTree(e, () => - Effect.map( - go(e.issue), - (tree) => make(getParseIssueTitle(e), [make(formatTransformationKind(e.kind), [tree])]) - )) - case "Refinement": - return getTree( - e, - () => - Effect.map(go(e.issue), (tree) => make(getParseIssueTitle(e), [make(formatRefinementKind(e.kind), [tree])])) - ) - case "Pointer": - return Effect.map(go(e.issue), (tree) => make(util_.formatPath(e.path), [tree])) - case "Composite": { - const parseIssueTitle = getParseIssueTitle(e) - return getTree( - e, - () => - util_.isNonEmpty(e.issues) - ? Effect.map(Effect.forEach(e.issues, go), (forest) => make(parseIssueTitle, forest)) - : Effect.map(go(e.issues), (tree) => make(parseIssueTitle, [tree])) - ) - } - } -} diff --git a/packages/schema/src/index.ts b/packages/schema/src/index.ts deleted file mode 100644 index dec2d54df9..0000000000 --- a/packages/schema/src/index.ts +++ /dev/null @@ -1,54 +0,0 @@ -/** - * @since 0.67.0 - */ -export * as AST from "./AST.js" - -/** - * @since 0.67.0 - */ -export * as Arbitrary from "./Arbitrary.js" - -/** - * @since 0.67.0 - */ -export * as ArrayFormatter from "./ArrayFormatter.js" - -/** - * @since 0.67.0 - */ -export * as Equivalence from "./Equivalence.js" - -/** - * @since 0.67.0 - */ -export * as FastCheck from "./FastCheck.js" - -/** - * @since 0.67.0 - */ -export * as JSONSchema from "./JSONSchema.js" - -/** - * @since 0.67.0 - */ -export * as ParseResult from "./ParseResult.js" - -/** - * @since 0.67.0 - */ -export * as Pretty from "./Pretty.js" - -/** - * @since 0.67.0 - */ -export * as Schema from "./Schema.js" - -/** - * @since 0.67.0 - */ -export * as Serializable from "./Serializable.js" - -/** - * @since 0.67.0 - */ -export * as TreeFormatter from "./TreeFormatter.js" diff --git a/packages/schema/src/internal/filters.ts b/packages/schema/src/internal/filters.ts deleted file mode 100644 index c3b1b0ff92..0000000000 --- a/packages/schema/src/internal/filters.ts +++ /dev/null @@ -1,89 +0,0 @@ -import type * as Schema from "../Schema.js" - -/** @internal */ -export const GreaterThanTypeId: Schema.GreaterThanTypeId = Symbol.for( - "@effect/schema/TypeId/GreaterThan" -) as Schema.GreaterThanTypeId - -/** @internal */ -export const GreaterThanOrEqualToTypeId: Schema.GreaterThanOrEqualToTypeId = Symbol.for( - "@effect/schema/TypeId/GreaterThanOrEqualTo" -) as Schema.GreaterThanOrEqualToTypeId - -/** @internal */ -export const LessThanTypeId: Schema.LessThanTypeId = Symbol.for( - "@effect/schema/TypeId/LessThan" -) as Schema.LessThanTypeId - -/** @internal */ -export const LessThanOrEqualToTypeId: Schema.LessThanOrEqualToTypeId = Symbol.for( - "@effect/schema/TypeId/LessThanOrEqualTo" -) as Schema.LessThanOrEqualToTypeId - -/** @internal */ -export const IntTypeId: Schema.IntTypeId = Symbol.for( - "@effect/schema/TypeId/Int" -) as Schema.IntTypeId - -/** @internal */ -export const BetweenTypeId: Schema.BetweenTypeId = Symbol.for( - "@effect/schema/TypeId/Between" -) as Schema.BetweenTypeId - -/** @internal */ -export const GreaterThanBigintTypeId: Schema.GreaterThanBigIntTypeId = Symbol.for( - "@effect/schema/TypeId/GreaterThanBigint" -) as Schema.GreaterThanBigIntTypeId - -/** @internal */ -export const GreaterThanOrEqualToBigIntTypeId: Schema.GreaterThanOrEqualToBigIntTypeId = Symbol.for( - "@effect/schema/TypeId/GreaterThanOrEqualToBigint" -) as Schema.GreaterThanOrEqualToBigIntTypeId - -/** @internal */ -export const LessThanBigIntTypeId: Schema.LessThanBigIntTypeId = Symbol.for( - "@effect/schema/TypeId/LessThanBigint" -) as Schema.LessThanBigIntTypeId - -/** @internal */ -export const LessThanOrEqualToBigIntTypeId: Schema.LessThanOrEqualToBigIntTypeId = Symbol.for( - "@effect/schema/TypeId/LessThanOrEqualToBigint" -) as Schema.LessThanOrEqualToBigIntTypeId - -/** @internal */ -export const BetweenBigintTypeId: Schema.BetweenBigIntTypeId = Symbol.for( - "@effect/schema/TypeId/BetweenBigint" -) as Schema.BetweenBigIntTypeId - -/** @internal */ -export const MinLengthTypeId: Schema.MinLengthTypeId = Symbol.for( - "@effect/schema/TypeId/MinLength" -) as Schema.MinLengthTypeId - -/** @internal */ -export const MaxLengthTypeId: Schema.MaxLengthTypeId = Symbol.for( - "@effect/schema/TypeId/MaxLength" -) as Schema.MaxLengthTypeId - -/** @internal */ -export const LengthTypeId: Schema.LengthTypeId = Symbol.for( - "@effect/schema/TypeId/Length" -) as Schema.LengthTypeId - -/** @internal */ -export const MinItemsTypeId: Schema.MinItemsTypeId = Symbol.for( - "@effect/schema/TypeId/MinItems" -) as Schema.MinItemsTypeId - -/** @internal */ -export const MaxItemsTypeId: Schema.MaxItemsTypeId = Symbol.for( - "@effect/schema/TypeId/MaxItems" -) as Schema.MaxItemsTypeId - -/** @internal */ -export const ItemsCountTypeId: Schema.ItemsCountTypeId = Symbol.for( - "@effect/schema/TypeId/ItemsCount" -) as Schema.ItemsCountTypeId - -/** @internal */ -export const ParseJsonTypeId: unique symbol = Symbol.for("@effect/schema/TypeId/ParseJson") diff --git a/packages/schema/src/internal/serializable.ts b/packages/schema/src/internal/serializable.ts deleted file mode 100644 index eff1d96786..0000000000 --- a/packages/schema/src/internal/serializable.ts +++ /dev/null @@ -1,9 +0,0 @@ -/** @internal */ -export const symbol: unique symbol = Symbol.for( - "@effect/schema/Serializable/symbol" -) - -/** @internal */ -export const symbolResult: unique symbol = Symbol.for( - "@effect/schema/Serializable/symbolResult" -) diff --git a/packages/schema/test/Schema/UniqueSymbol/UniqueSymbolFromSelf.test.ts b/packages/schema/test/Schema/UniqueSymbol/UniqueSymbolFromSelf.test.ts deleted file mode 100644 index b9913dafb2..0000000000 --- a/packages/schema/test/Schema/UniqueSymbol/UniqueSymbolFromSelf.test.ts +++ /dev/null @@ -1,17 +0,0 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" -import { describe, it } from "vitest" - -describe("UniqueSymbolFromSelf", () => { - const a = Symbol.for("@effect/schema/test/a") - const schema = S.UniqueSymbolFromSelf(a) - it("decoding", async () => { - await Util.expectDecodeUnknownSuccess(schema, a) - await Util.expectDecodeUnknownSuccess(schema, Symbol.for("@effect/schema/test/a")) - await Util.expectDecodeUnknownFailure( - schema, - "Symbol(@effect/schema/test/a)", - `Expected Symbol(@effect/schema/test/a), actual "Symbol(@effect/schema/test/a)"` - ) - }) -}) diff --git a/packages/schema/test/Schema/exports.test.ts b/packages/schema/test/Schema/exports.test.ts deleted file mode 100644 index 79788108b0..0000000000 --- a/packages/schema/test/Schema/exports.test.ts +++ /dev/null @@ -1,51 +0,0 @@ -import * as S from "@effect/schema/Schema" -import { expect, it } from "vitest" - -it("exports", () => { - expect(S.decodeUnknown).exist - expect(S.decodeUnknownSync).exist - expect(S.decodeUnknownOption).exist - expect(S.decodeUnknownEither).exist - - expect(S.decode).exist - expect(S.decodeSync).exist - expect(S.decodeOption).exist - expect(S.decodeEither).exist - - expect(S.encode).exist - expect(S.encodeSync).exist - expect(S.encodeOption).exist - expect(S.encodeEither).exist - - expect(S.validate).exist - expect(S.validateSync).exist - expect(S.validateOption).exist - expect(S.validateEither).exist - - expect(S.GreaterThanBigIntTypeId).exist - expect(S.GreaterThanOrEqualToBigIntTypeId).exist - expect(S.LessThanBigIntTypeId).exist - expect(S.LessThanOrEqualToBigIntTypeId).exist - expect(S.BetweenBigIntTypeId).exist - expect(S.BrandTypeId).exist - expect(S.FiniteTypeId).exist - expect(S.GreaterThanTypeId).exist - expect(S.GreaterThanOrEqualToTypeId).exist - expect(S.MultipleOfTypeId).exist - expect(S.IntTypeId).exist - expect(S.LessThanTypeId).exist - expect(S.LessThanOrEqualToTypeId).exist - expect(S.BetweenTypeId).exist - expect(S.NonNaNTypeId).exist - expect(S.InstanceOfTypeId).exist - expect(S.MinItemsTypeId).exist - expect(S.MaxItemsTypeId).exist - expect(S.ItemsCountTypeId).exist - expect(S.TrimmedTypeId).exist - expect(S.PatternTypeId).exist - expect(S.StartsWithTypeId).exist - expect(S.EndsWithTypeId).exist - expect(S.IncludesTypeId).exist - expect(S.UUIDTypeId).exist - expect(S.ULIDTypeId).exist -}) diff --git a/packages/schema/test/formatUnknown.test.ts b/packages/schema/test/formatUnknown.test.ts deleted file mode 100644 index bc42940305..0000000000 --- a/packages/schema/test/formatUnknown.test.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { describe, expect, it } from "vitest" -import { formatUnknown } from "../src/internal/util.js" - -describe("util > formatUnknown", () => { - it("should format symbol property signatures", () => { - expect(formatUnknown({ [Symbol.for("a")]: 1 })).toEqual("{Symbol(a):1}") - }) - - it("should handle unexpected errors", () => { - const circular: any = { a: null } - circular.a = circular - expect(formatUnknown(circular)).toEqual("[object Object]") - }) - - it("should detect data types with a custom `toString` implementation", () => { - const noToString = { a: 1 } - expect(formatUnknown(noToString)).toEqual(`{"a":1}`) - const ToString = Object.create({ - toString() { - return "toString custom implementation" - } - }) - expect(formatUnknown(ToString)).toEqual("toString custom implementation") - // should not detect arrays - expect(formatUnknown([1, 2, 3])).toEqual("[1,2,3]") - }) -}) diff --git a/packages/schema/test/util.test.ts b/packages/schema/test/util.test.ts deleted file mode 100644 index 8ea686e5ba..0000000000 --- a/packages/schema/test/util.test.ts +++ /dev/null @@ -1,14 +0,0 @@ -import * as util from "@effect/schema/internal/util" -import { describe, expect, it } from "vitest" - -describe("util", () => { - it("ownKeys", () => { - expect(util.ownKeys({})).toStrictEqual([]) - expect(util.ownKeys({ a: 1 })).toStrictEqual(["a"]) - expect(util.ownKeys({ a: 1, b: 2 })).toStrictEqual(["a", "b"]) - const a = Symbol.for("@effect/schema/test/a") - const b = Symbol.for("@effect/schema/test/b") - expect(util.ownKeys({ [a]: 3, [b]: 4 })).toStrictEqual([a, b]) - expect(util.ownKeys({ a: 1, [a]: 3, b: 2, [b]: 4 })).toStrictEqual(["a", "b", a, b]) - }) -}) diff --git a/packages/schema/tsconfig.build.json b/packages/schema/tsconfig.build.json deleted file mode 100644 index 76ee3883a1..0000000000 --- a/packages/schema/tsconfig.build.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "extends": "./tsconfig.src.json", - "references": [ - { "path": "../effect/tsconfig.build.json" } - ], - "compilerOptions": { - "tsBuildInfoFile": ".tsbuildinfo/build.tsbuildinfo", - "outDir": "build/esm", - "declarationDir": "build/dts", - "stripInternal": true - } -} diff --git a/packages/schema/tsconfig.json b/packages/schema/tsconfig.json deleted file mode 100644 index 2c291d2192..0000000000 --- a/packages/schema/tsconfig.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "include": [], - "references": [ - { "path": "tsconfig.src.json" }, - { "path": "tsconfig.test.json" } - ] -} diff --git a/packages/schema/tsconfig.src.json b/packages/schema/tsconfig.src.json deleted file mode 100644 index 272866fcc3..0000000000 --- a/packages/schema/tsconfig.src.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "include": ["src"], - "references": [ - { "path": "../effect" } - ], - "compilerOptions": { - "outDir": "build/src", - "tsBuildInfoFile": ".tsbuildinfo/src.tsbuildinfo", - "rootDir": "src" - } -} diff --git a/packages/schema/tsconfig.test.json b/packages/schema/tsconfig.test.json deleted file mode 100644 index d1c3c57a18..0000000000 --- a/packages/schema/tsconfig.test.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "include": ["test"], - "references": [ - { "path": "tsconfig.src.json" }, - { "path": "../effect" } - ], - "compilerOptions": { - "tsBuildInfoFile": ".tsbuildinfo/test.tsbuildinfo", - "rootDir": "test", - "noEmit": true - } -} diff --git a/packages/schema/vitest.config.ts b/packages/schema/vitest.config.ts deleted file mode 100644 index 0411095f25..0000000000 --- a/packages/schema/vitest.config.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { mergeConfig, type UserConfigExport } from "vitest/config" -import shared from "../../vitest.shared.js" - -const config: UserConfigExport = {} - -export default mergeConfig(shared, config) diff --git a/packages/sql-d1/test/Resolver.test.ts b/packages/sql-d1/test/Resolver.test.ts index 96e0a73473..b94ecfc3a0 100644 --- a/packages/sql-d1/test/Resolver.test.ts +++ b/packages/sql-d1/test/Resolver.test.ts @@ -1,8 +1,8 @@ -import * as Schema from "@effect/schema/Schema" import { SqlError, SqlResolver } from "@effect/sql" import { D1Client } from "@effect/sql-d1" import { assert, describe, it } from "@effect/vitest" import { Array, Effect, Option } from "effect" +import * as Schema from "effect/Schema" import { D1Miniflare } from "./utils.js" const seededClient = Effect.gen(function*(_) { diff --git a/packages/sql-kysely/test/Sqlite.test.ts b/packages/sql-kysely/test/Sqlite.test.ts index 59eb3a311f..cad5d1ee75 100644 --- a/packages/sql-kysely/test/Sqlite.test.ts +++ b/packages/sql-kysely/test/Sqlite.test.ts @@ -1,9 +1,8 @@ -import { Schema } from "@effect/schema" import { SqlResolver } from "@effect/sql" import * as SqliteKysely from "@effect/sql-kysely/Sqlite" import * as Sqlite from "@effect/sql-sqlite-node" import { assert, describe, it } from "@effect/vitest" -import { Config, Context, Effect, Exit, Layer, Option } from "effect" +import { Config, Context, Effect, Exit, Layer, Option, Schema } from "effect" import type { Generated } from "kysely" export interface User { diff --git a/packages/sql-libsql/test/Resolver.test.ts b/packages/sql-libsql/test/Resolver.test.ts index 72d9a7a7c9..2c38a46442 100644 --- a/packages/sql-libsql/test/Resolver.test.ts +++ b/packages/sql-libsql/test/Resolver.test.ts @@ -1,8 +1,8 @@ -import * as Schema from "@effect/schema/Schema" import { SqlError, SqlResolver } from "@effect/sql" import { LibsqlClient } from "@effect/sql-libsql" import { assert, describe, layer } from "@effect/vitest" import { Array, Effect, Option } from "effect" +import * as Schema from "effect/Schema" import { LibsqlContainer } from "./util.js" const seededClient = Effect.gen(function*(_) { diff --git a/packages/sql-mysql2/test/Model.test.ts b/packages/sql-mysql2/test/Model.test.ts index 7328bfa9f1..82fe19bd8e 100644 --- a/packages/sql-mysql2/test/Model.test.ts +++ b/packages/sql-mysql2/test/Model.test.ts @@ -1,7 +1,6 @@ -import { Schema } from "@effect/schema" import { Model, SqlClient } from "@effect/sql" import { assert, describe, it } from "@effect/vitest" -import { Effect, Option } from "effect" +import { Effect, Option, Schema } from "effect" import { MysqlContainer } from "./utils.js" class User extends Model.Class("User")({ diff --git a/packages/sql-pg/examples/resolver.ts b/packages/sql-pg/examples/resolver.ts index 9bfe741777..a20ae9817b 100644 --- a/packages/sql-pg/examples/resolver.ts +++ b/packages/sql-pg/examples/resolver.ts @@ -1,8 +1,8 @@ import * as DevTools from "@effect/experimental/DevTools" -import * as Schema from "@effect/schema/Schema" import { SqlClient, SqlResolver } from "@effect/sql" import { PgClient } from "@effect/sql-pg" import { Config, Effect, Layer, String } from "effect" +import * as Schema from "effect/Schema" class Person extends Schema.Class("Person")({ id: Schema.Number, diff --git a/packages/sql-sqlite-node/test/Resolver.test.ts b/packages/sql-sqlite-node/test/Resolver.test.ts index a945b0f43e..2a6d0d97a5 100644 --- a/packages/sql-sqlite-node/test/Resolver.test.ts +++ b/packages/sql-sqlite-node/test/Resolver.test.ts @@ -1,10 +1,10 @@ import { FileSystem } from "@effect/platform" import { NodeFileSystem } from "@effect/platform-node" -import * as Schema from "@effect/schema/Schema" import { SqlError, SqlResolver } from "@effect/sql" import { SqliteClient } from "@effect/sql-sqlite-node" import { assert, describe, it } from "@effect/vitest" import { Array, Effect, Option } from "effect" +import * as Schema from "effect/Schema" const makeClient = Effect.gen(function*(_) { const fs = yield* _(FileSystem.FileSystem) diff --git a/packages/sql/README.md b/packages/sql/README.md index 124590be52..45dcf4ff3f 100644 --- a/packages/sql/README.md +++ b/packages/sql/README.md @@ -95,8 +95,7 @@ In `sqlfx` you could pass an array to the `sql(array)` function to pass an list ## INSERT resolver ```ts -import { Effect, pipe } from "effect" -import { Schema } from "@effect/schema" +import { Effect, Schema, pipe } from "effect" import { SqlClient } from "@effect/sql" class Person extends Schema.Class("Person")({ @@ -114,15 +113,15 @@ export const makePersonService = Effect.gen(function* () { const sql = yield* SqlClient.SqlClient const InsertPerson = yield* SqlResolver.ordered("InsertPerson", { - Request: InsertPersonSchema, - Result: Person, - execute: (requests) => - sql` + Request: InsertPersonSchema, + Result: Person, + execute: (requests) => + sql` INSERT INTO people ${sql.insert(requests)} RETURNING people.* ` - }) + }) const insert = InsertPerson.execute @@ -133,8 +132,7 @@ export const makePersonService = Effect.gen(function* () { ## SELECT resolver ```ts -import { Effect, pipe } from "effect" -import { Schema } from "@effect/schema" +import { Effect, Schema, pipe } from "effect" import { SqlResolver, SqlClient } from "@effect/sql" class Person extends Schema.Class("Person")({ diff --git a/packages/sql/package.json b/packages/sql/package.json index edf407a671..4dce439c3f 100644 --- a/packages/sql/package.json +++ b/packages/sql/package.json @@ -46,13 +46,11 @@ "devDependencies": { "@effect/experimental": "workspace:^", "@effect/platform": "workspace:^", - "@effect/schema": "workspace:^", "effect": "workspace:^" }, "peerDependencies": { "@effect/experimental": "workspace:^", "@effect/platform": "workspace:^", - "@effect/schema": "workspace:^", "effect": "workspace:^" }, "effect": { diff --git a/packages/sql/src/Model.ts b/packages/sql/src/Model.ts index 52b1b9ed89..5b4280a2c3 100644 --- a/packages/sql/src/Model.ts +++ b/packages/sql/src/Model.ts @@ -3,13 +3,13 @@ */ import * as RRX from "@effect/experimental/RequestResolver" import * as VariantSchema from "@effect/experimental/VariantSchema" -import * as ParseResult from "@effect/schema/ParseResult" -import * as Schema from "@effect/schema/Schema" import type { Brand } from "effect/Brand" import * as DateTime from "effect/DateTime" import type { DurationInput } from "effect/Duration" import * as Effect from "effect/Effect" import * as Option from "effect/Option" +import * as ParseResult from "effect/ParseResult" +import * as Schema from "effect/Schema" import type { Scope } from "effect/Scope" import { SqlClient } from "./SqlClient.js" import * as SqlResolver from "./SqlResolver.js" @@ -77,7 +77,7 @@ export { * @since 1.0.0 * @category constructors * @example - * import { Schema } from "@effect/schema" + * import { Schema } from "effect" * import { Model } from "@effect/sql" * * export const GroupId = Schema.Number.pipe(Schema.brand("GroupId")) diff --git a/packages/sql/src/SqlResolver.ts b/packages/sql/src/SqlResolver.ts index 9c5d1aa2ae..eeb7ca2f50 100644 --- a/packages/sql/src/SqlResolver.ts +++ b/packages/sql/src/SqlResolver.ts @@ -1,8 +1,6 @@ /** * @since 1.0.0 */ -import type { ParseError } from "@effect/schema/ParseResult" -import * as Schema from "@effect/schema/Schema" import type { NonEmptyArray } from "effect/Array" import * as Context from "effect/Context" import * as Effect from "effect/Effect" @@ -12,8 +10,10 @@ import * as FiberRef from "effect/FiberRef" import * as Hash from "effect/Hash" import * as MutableHashMap from "effect/MutableHashMap" import * as Option from "effect/Option" +import type { ParseError } from "effect/ParseResult" import * as Request from "effect/Request" import * as RequestResolver from "effect/RequestResolver" +import * as Schema from "effect/Schema" import * as Tracer from "effect/Tracer" import type * as Types from "effect/Types" import * as internalClient from "./internal/client.js" diff --git a/packages/sql/src/SqlSchema.ts b/packages/sql/src/SqlSchema.ts index b3f6b0c8f5..934d6ea7d4 100644 --- a/packages/sql/src/SqlSchema.ts +++ b/packages/sql/src/SqlSchema.ts @@ -1,11 +1,11 @@ /** * @since 1.0.0 */ -import type { ParseError } from "@effect/schema/ParseResult" -import * as Schema from "@effect/schema/Schema" import * as Cause from "effect/Cause" import * as Effect from "effect/Effect" import type * as Option from "effect/Option" +import type { ParseError } from "effect/ParseResult" +import * as Schema from "effect/Schema" /** * Run a sql query with a request schema and a result schema. diff --git a/packages/sql/tsconfig.build.json b/packages/sql/tsconfig.build.json index b0c5d088bf..6b9244b50c 100644 --- a/packages/sql/tsconfig.build.json +++ b/packages/sql/tsconfig.build.json @@ -3,8 +3,7 @@ "references": [ { "path": "../effect/tsconfig.build.json" }, { "path": "../experimental/tsconfig.build.json" }, - { "path": "../platform/tsconfig.build.json" }, - { "path": "../schema/tsconfig.build.json" } + { "path": "../platform/tsconfig.build.json" } ], "compilerOptions": { "tsBuildInfoFile": ".tsbuildinfo/build.tsbuildinfo", diff --git a/packages/sql/tsconfig.examples.json b/packages/sql/tsconfig.examples.json index 718637d3f2..b52b121594 100644 --- a/packages/sql/tsconfig.examples.json +++ b/packages/sql/tsconfig.examples.json @@ -4,8 +4,7 @@ "references": [ { "path": "tsconfig.src.json" }, { "path": "../effect" }, - { "path": "../platform" }, - { "path": "../schema" } + { "path": "../platform" } ], "compilerOptions": { "tsBuildInfoFile": ".tsbuildinfo/examples.tsbuildinfo", diff --git a/packages/sql/tsconfig.src.json b/packages/sql/tsconfig.src.json index 8ed66efe1b..098b4d92f3 100644 --- a/packages/sql/tsconfig.src.json +++ b/packages/sql/tsconfig.src.json @@ -4,8 +4,7 @@ "references": [ { "path": "../effect" }, { "path": "../experimental" }, - { "path": "../platform" }, - { "path": "../schema" } + { "path": "../platform" } ], "compilerOptions": { "tsBuildInfoFile": ".tsbuildinfo/src.tsbuildinfo", diff --git a/packages/sql/tsconfig.test.json b/packages/sql/tsconfig.test.json index 380524224f..8939416ac7 100644 --- a/packages/sql/tsconfig.test.json +++ b/packages/sql/tsconfig.test.json @@ -4,8 +4,7 @@ "references": [ { "path": "tsconfig.src.json" }, { "path": "../effect" }, - { "path": "../platform" }, - { "path": "../schema" } + { "path": "../platform" } ], "compilerOptions": { "tsBuildInfoFile": ".tsbuildinfo/test.tsbuildinfo", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 04d8560b88..c0aacf7cb2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -168,9 +168,6 @@ importers: '@effect/platform': specifier: workspace:^ version: link:../../platform/dist - '@effect/schema': - specifier: workspace:^ - version: link:../../schema/dist effect: specifier: workspace:^ version: link:../../effect/dist @@ -194,9 +191,6 @@ importers: '@effect/platform-node': specifier: workspace:^ version: link:../../platform-node/dist - '@effect/schema': - specifier: workspace:^ - version: link:../../schema/dist '@tim-smart/openapi-gen': specifier: ^0.2.0 version: 0.2.0 @@ -229,9 +223,6 @@ importers: '@effect/printer-ansi': specifier: workspace:^ version: link:../printer-ansi/dist - '@effect/schema': - specifier: workspace:^ - version: link:../schema/dist '@types/ini': specifier: ^4.1.1 version: 4.1.1 @@ -251,9 +242,6 @@ importers: '@effect/platform-node': specifier: workspace:^ version: link:../platform-node/dist - '@effect/schema': - specifier: workspace:^ - version: link:../schema/dist '@effect/sql': specifier: workspace:^ version: link:../sql/dist @@ -270,9 +258,6 @@ importers: '@effect/rpc': specifier: workspace:^ version: link:../rpc/dist - '@effect/schema': - specifier: workspace:^ - version: link:../schema/dist effect: specifier: workspace:^ version: link:../effect/dist @@ -296,9 +281,6 @@ importers: '@effect/rpc-http': specifier: workspace:^ version: link:../rpc-http/dist - '@effect/schema': - specifier: workspace:^ - version: link:../schema/dist '@types/node': specifier: ^22.5.4 version: 22.5.4 @@ -318,9 +300,6 @@ importers: '@effect/platform-node': specifier: workspace:^ version: link:../platform-node/dist - '@effect/schema': - specifier: workspace:^ - version: link:../schema/dist '@effect/sql': specifier: workspace:^ version: link:../sql/dist @@ -333,6 +312,10 @@ importers: publishDirectory: dist packages/effect: + dependencies: + fast-check: + specifier: ^3.21.0 + version: 3.21.0 devDependencies: '@types/jscodeshift': specifier: ^0.11.11 @@ -340,12 +323,21 @@ importers: '@types/node': specifier: ^22.5.4 version: 22.5.4 + ajv: + specifier: ^8.17.1 + version: 8.17.1 ast-types: specifier: ^0.14.2 version: 0.14.2 jscodeshift: specifier: ^0.16.1 version: 0.16.1(@babel/preset-env@7.25.4(@babel/core@7.25.2)) + tinybench: + specifier: ^2.9.0 + version: 2.9.0 + zod: + specifier: ^3.23.5 + version: 3.23.8 publishDirectory: dist packages/experimental: @@ -356,9 +348,6 @@ importers: '@effect/platform-node': specifier: workspace:^ version: link:../platform-node/dist - '@effect/schema': - specifier: workspace:^ - version: link:../schema/dist effect: specifier: workspace:^ version: link:../effect/dist @@ -436,9 +425,6 @@ importers: specifier: ^0.2.5 version: 0.2.5 devDependencies: - '@effect/schema': - specifier: workspace:^ - version: link:../schema/dist ajv: specifier: ^8.17.1 version: 8.17.1 @@ -456,9 +442,6 @@ importers: '@effect/platform': specifier: workspace:^ version: link:../platform/dist - '@effect/schema': - specifier: workspace:^ - version: link:../schema/dist effect: specifier: workspace:^ version: link:../effect/dist @@ -479,9 +462,6 @@ importers: '@effect/platform': specifier: workspace:^ version: link:../platform/dist - '@effect/schema': - specifier: workspace:^ - version: link:../schema/dist bun-types: specifier: 1.1.22 version: 1.1.22 @@ -508,9 +488,6 @@ importers: '@effect/platform': specifier: workspace:^ version: link:../platform/dist - '@effect/schema': - specifier: workspace:^ - version: link:../schema/dist '@types/mime': specifier: ^3.0.4 version: 3.0.4 @@ -537,9 +514,6 @@ importers: '@effect/platform': specifier: workspace:^ version: link:../platform/dist - '@effect/schema': - specifier: workspace:^ - version: link:../schema/dist '@types/node': specifier: ^22.5.4 version: 22.5.4 @@ -583,9 +557,6 @@ importers: '@effect/platform': specifier: workspace:^ version: link:../platform/dist - '@effect/schema': - specifier: workspace:^ - version: link:../schema/dist effect: specifier: workspace:^ version: link:../effect/dist @@ -603,32 +574,9 @@ importers: '@effect/platform-node': specifier: workspace:^ version: link:../platform-node/dist - '@effect/schema': - specifier: workspace:^ - version: link:../schema/dist - effect: - specifier: workspace:^ - version: link:../effect/dist - publishDirectory: dist - - packages/schema: - dependencies: - fast-check: - specifier: ^3.21.0 - version: 3.21.0 - devDependencies: - ajv: - specifier: ^8.17.1 - version: 8.17.1 effect: specifier: workspace:^ version: link:../effect/dist - tinybench: - specifier: ^2.9.0 - version: 2.9.0 - zod: - specifier: ^3.23.5 - version: 3.23.8 publishDirectory: dist packages/sql: @@ -643,9 +591,6 @@ importers: '@effect/platform': specifier: workspace:^ version: link:../platform/dist - '@effect/schema': - specifier: workspace:^ - version: link:../schema/dist effect: specifier: workspace:^ version: link:../effect/dist diff --git a/packages/schema/CHANGELOG.md b/schema/CHANGELOG.md similarity index 100% rename from packages/schema/CHANGELOG.md rename to schema/CHANGELOG.md diff --git a/packages/schema/comparisons.md b/schema/comparisons.md similarity index 97% rename from packages/schema/comparisons.md rename to schema/comparisons.md index 60dec44be3..9f09afe32e 100644 --- a/packages/schema/comparisons.md +++ b/schema/comparisons.md @@ -33,7 +33,7 @@ mySchema.safeParse(12) // => { success: false; error: ZodError } Schema ```ts -import { Schema as S } from "@effect/schema" +import { Schema as S } from "effect" // creating a schema for strings const mySchema = S.String @@ -68,7 +68,7 @@ type User = z.infer Schema ```ts -import { Schema as S } from "@effect/schema" +import { Schema as S } from "effect" const User = S.Struct({ username: S.String @@ -114,7 +114,7 @@ z.never() Schema ```ts -import { Schema as S } from "@effect/schema" +import { Schema as S } from "effect" // primitive values S.String @@ -163,7 +163,7 @@ tuna.value // "tuna" Schema ```ts -import { Schema as S } from "@effect/schema" +import { Schema as S } from "effect" const tuna = S.Literal("tuna") const twelve = S.Literal(12) @@ -214,7 +214,7 @@ z.string().toUpperCase() // toUpperCase Schema ```ts -import { Schema as S } from "@effect/schema" +import { Schema as S } from "effect" // validations S.String.pipe(S.maxLength(5)) @@ -298,7 +298,7 @@ date.parse("2020-01-32") // fail Schema ```ts -import { Schema as S } from "@effect/schema" +import { Schema as S } from "effect" S.decodeUnknownSync(S.Date)("2020-01-01") // pass S.decodeUnknownSync(S.Date)("2020-1-1") // pass @@ -339,7 +339,7 @@ z.number().safe() // value must be between Number.MIN_SAFE_INTEGER and Number.MA Schema ```ts -import { Schema as S } from "@effect/schema" +import { Schema as S } from "effect" S.Number.pipe(S.greaterThan(5)) S.Number.pipe(S.greaterThanOrEqualTo(5)) @@ -394,7 +394,7 @@ z.bigint().multipleOf(5n) // Evenly divisible by 5n. Schema ```ts -import { Schema as S } from "@effect/schema" +import { Schema as S } from "effect" S.BigInt.pipe(S.greaterThanBigInt(5n)) S.BigInt.pipe(S.greaterThanOrEqualToBigInt(5n)) @@ -782,7 +782,7 @@ console.log(schema.parse("tuna")) // => 42 Schema ```ts -import { Schema } from "@effect/schema" +import { Schema } from "effect" import { Either } from "effect" const schema = Schema.Number.annotations({ @@ -1176,7 +1176,7 @@ documentedString.description // A useful bit of text… Schema ```ts -import { AST, Schema as S } from "@effect/schema" +import { AST, Schema as S } from "effect" const documentedString = S.String.annotations({ description: "A useful bit of text, if you know what to do with it." diff --git a/tsconfig.base.json b/tsconfig.base.json index 3233e348a7..707972acfe 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -106,9 +106,6 @@ "@effect/rpc-http": ["./packages/rpc-http/src/index.js"], "@effect/rpc-http/*": ["./packages/rpc-http/src/*.js"], "@effect/rpc-http/test/*": ["./packages/rpc-http/test/*.js"], - "@effect/schema": ["./packages/schema/src/index.js"], - "@effect/schema/*": ["./packages/schema/src/*.js"], - "@effect/schema/test/*": ["./packages/schema/test/*.js"], "@effect/sql": ["./packages/sql/src/index.js"], "@effect/sql/*": ["./packages/sql/src/*.js"], "@effect/sql/test/*": ["./packages/sql/test/*.js"], diff --git a/tsconfig.build.json b/tsconfig.build.json index a30a4c497f..2608695615 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -21,7 +21,6 @@ { "path": "packages/printer-ansi/tsconfig.build.json" }, { "path": "packages/rpc/tsconfig.build.json" }, { "path": "packages/rpc-http/tsconfig.build.json" }, - { "path": "packages/schema/tsconfig.build.json" }, { "path": "packages/sql/tsconfig.build.json" }, { "path": "packages/sql-clickhouse/tsconfig.build.json" }, { "path": "packages/sql-d1/tsconfig.build.json" }, diff --git a/tsconfig.json b/tsconfig.json index 9ebf6e89f4..c05e27bbf7 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -21,8 +21,6 @@ { "path": "packages/printer-ansi" }, { "path": "packages/rpc" }, { "path": "packages/rpc-http" }, - { "path": "packages/schema" }, - { "path": "packages/schema" }, { "path": "packages/sql" }, { "path": "packages/sql-clickhouse" }, { "path": "packages/sql-d1" }, diff --git a/vitest.shared.ts b/vitest.shared.ts index d661813be8..cddc05e450 100644 --- a/vitest.shared.ts +++ b/vitest.shared.ts @@ -47,7 +47,6 @@ const config: UserConfig = { ...alias("printer-ansi"), ...alias("rpc"), ...alias("rpc-http"), - ...alias("schema"), ...alias("sql"), ...alias("sql-clickhouse"), ...alias("sql-d1"), From db7e5647737af4797ea89f1047c9c24336098026 Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Wed, 16 Oct 2024 10:16:53 +0200 Subject: [PATCH 4/8] Schema.equivalence: fix discriminated tuples (#3789) --- packages/effect/src/ParseResult.ts | 5 +---- packages/effect/src/Predicate.ts | 4 +++- packages/effect/src/Schema.ts | 2 +- packages/effect/test/Schema/Schema/Union/Union.test.ts | 8 ++++---- packages/effect/test/Schema/Schema/equivalence.test.ts | 8 ++++---- 5 files changed, 13 insertions(+), 14 deletions(-) diff --git a/packages/effect/src/ParseResult.ts b/packages/effect/src/ParseResult.ts index 1339939f65..a9147d75d6 100644 --- a/packages/effect/src/ParseResult.ts +++ b/packages/effect/src/ParseResult.ts @@ -1383,8 +1383,7 @@ const go = (ast: AST.AST, isDecoding: boolean): Parser => { let stepKey = 0 let candidates: Array = [] if (len > 0) { - // if there is at least one key then input must be an object - if (isObject(input)) { + if (Predicate.isRecordOrArray(input)) { for (let i = 0; i < len; i++) { const name = ownKeys[i] const buckets = searchTree.keys[name].buckets @@ -1512,8 +1511,6 @@ const go = (ast: AST.AST, isDecoding: boolean): Parser => { } } -const isObject = (input: unknown): input is { [x: PropertyKey]: unknown } => typeof input === "object" && input !== null - const fromRefinement = (ast: AST.AST, refinement: (u: unknown) => u is A): Parser => (u) => refinement(u) ? Either.right(u) : Either.left(new Type(ast, u)) diff --git a/packages/effect/src/Predicate.ts b/packages/effect/src/Predicate.ts index 0fbc6f3bf8..523f095f2e 100644 --- a/packages/effect/src/Predicate.ts +++ b/packages/effect/src/Predicate.ts @@ -415,7 +415,9 @@ export const isNever: (input: unknown) => input is never = (_: unknown): _ is ne */ export const isUnknown: (input: unknown) => input is unknown = (_): _ is unknown => true -const isRecordOrArray = (input: unknown) => typeof input === "object" && input !== null +/** @internal */ +export const isRecordOrArray = (input: unknown): input is { [x: PropertyKey]: unknown } => + typeof input === "object" && input !== null /** * Tests if a value is an `object`. diff --git a/packages/effect/src/Schema.ts b/packages/effect/src/Schema.ts index 512cd08b52..4227c5fbf6 100644 --- a/packages/effect/src/Schema.ts +++ b/packages/effect/src/Schema.ts @@ -9813,7 +9813,7 @@ const go = (ast: AST.AST, path: ReadonlyArray): Equivalence.Equival const len = ownKeys.length return Equivalence.make((a, b) => { let candidates: Array = [] - if (len > 0 && Predicate.isRecord(a)) { + if (len > 0 && Predicate.isRecordOrArray(a)) { for (let i = 0; i < len; i++) { const name = ownKeys[i] const buckets = searchTree.keys[name].buckets diff --git a/packages/effect/test/Schema/Schema/Union/Union.test.ts b/packages/effect/test/Schema/Schema/Union/Union.test.ts index dd77590ee4..0af7d856a1 100644 --- a/packages/effect/test/Schema/Schema/Union/Union.test.ts +++ b/packages/effect/test/Schema/Schema/Union/Union.test.ts @@ -37,7 +37,7 @@ describe("Union", () => { await Util.expectDecodeUnknownFailure(schema, 1, "Expected never, actual 1") }) - it("struct members", async () => { + it("discriminated structs", async () => { const schema = S.Union( S.Struct({ a: S.Literal(1), c: S.String }), S.Struct({ b: S.Literal(2), d: S.Number }) @@ -82,7 +82,7 @@ describe("Union", () => { ) }) - it("struct members with multiple tags", async () => { + it("discriminated structs with multiple tags", async () => { const schema = S.Union( S.Struct({ category: S.Literal("catA"), tag: S.Literal("a") }), S.Struct({ category: S.Literal("catA"), tag: S.Literal("b") }), @@ -158,7 +158,7 @@ describe("Union", () => { ) }) - it("tuple members", async () => { + it("discriminated tuples", async () => { const schema = S.Union( S.Tuple(S.Literal("a"), S.String), S.Tuple(S.Literal("b"), S.Number) @@ -194,7 +194,7 @@ describe("Union", () => { ) }) - it("tuple members with multiple tags", async () => { + it("discriminated tuples with multiple tags", async () => { const schema = S.Union( S.Tuple(S.Literal("a"), S.Literal("b"), S.String), S.Tuple(S.Literal("a"), S.Literal("c"), S.Number), diff --git a/packages/effect/test/Schema/Schema/equivalence.test.ts b/packages/effect/test/Schema/Schema/equivalence.test.ts index af314bae85..50f7c28a6a 100644 --- a/packages/effect/test/Schema/Schema/equivalence.test.ts +++ b/packages/effect/test/Schema/Schema/equivalence.test.ts @@ -70,8 +70,8 @@ const MySymbol = S.SymbolFromSelf.annotations({ } }) -describe("SchemaEquivalence", () => { - it("the errors should disply a path", () => { +describe("equivalence", () => { + it("the errors should display a path", () => { expect(() => S.equivalence(S.Tuple(S.Never as any))).toThrow( new Error(`Unsupported schema at path: [0] @@ -301,7 +301,7 @@ schema (NeverKeyword): never`) // propertyType(schema) }) - it("discriminated", () => { + it("discriminated structs", () => { const schema = S.Union( S.Struct({ tag: S.Literal("a"), a: MyString }), S.Struct({ tag: S.Literal("b"), b: S.Number }) @@ -321,7 +321,7 @@ schema (NeverKeyword): never`) S.Tuple(S.Literal("a"), S.String), S.Tuple(S.Literal("b"), S.Number) ) - const equivalence = E.make(schema) + const equivalence = S.equivalence(schema) expect(equivalence(["a", "x"], ["a", "x"])).toBe(true) expect(equivalence(["a", "x"], ["a", "y"])).toBe(false) From dac760ead84534f43e52467de47e6632d5cb7106 Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Wed, 16 Oct 2024 14:38:01 +0200 Subject: [PATCH 5/8] porting of #3792 (#3793) --- packages/effect/src/SchemaAST.ts | 13 +++++-------- packages/effect/test/Schema/Schema/pick.test.ts | 14 +++++++------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/packages/effect/src/SchemaAST.ts b/packages/effect/src/SchemaAST.ts index 4befd23444..1d27f129b3 100644 --- a/packages/effect/src/SchemaAST.ts +++ b/packages/effect/src/SchemaAST.ts @@ -2183,18 +2183,15 @@ export const getPropertyKeyIndexedAccess = (ast: AST, name: PropertyKey): Proper case "Refinement": return getPropertyKeyIndexedAccess(ast.from, name) } - return new PropertySignature(name, neverKeyword, false, true) + throw new Error(errors_.getASTUnsupportedSchema(ast)) } const getPropertyKeys = (ast: AST): Array => { + const annotation = getSurrogateAnnotation(ast) + if (Option.isSome(annotation)) { + return getPropertyKeys(annotation.value) + } switch (ast._tag) { - case "Declaration": { - const annotation = getSurrogateAnnotation(ast) - if (Option.isSome(annotation)) { - return getPropertyKeys(annotation.value) - } - break - } case "TypeLiteral": return ast.propertySignatures.map((ps) => ps.name) case "Suspend": diff --git a/packages/effect/test/Schema/Schema/pick.test.ts b/packages/effect/test/Schema/Schema/pick.test.ts index 03563b7d09..f7801a9a2f 100644 --- a/packages/effect/test/Schema/Schema/pick.test.ts +++ b/packages/effect/test/Schema/Schema/pick.test.ts @@ -4,7 +4,7 @@ import { describe, expect, it } from "vitest" describe("pick", () => { it("Struct", async () => { - const a = Symbol.for("effect/Schema/test/a") + const a = Symbol.for("@effect/schema/test/a") const schema = S.Struct({ [a]: S.String, b: S.NumberFromString, c: S.Boolean }).pipe( S.pick(a, "b") ) @@ -113,22 +113,22 @@ describe("pick", () => { }) it("Record(symbol, number)", async () => { - const a = Symbol.for("effect/Schema/test/a") - const b = Symbol.for("effect/Schema/test/b") + const a = Symbol.for("@effect/schema/test/a") + const b = Symbol.for("@effect/schema/test/b") const schema = S.Record({ key: S.SymbolFromSelf, value: S.Number }).pipe(S.pick(a, b)) await Util.expectDecodeUnknownSuccess(schema, { [a]: 1, [b]: 2 }) await Util.expectDecodeUnknownFailure( schema, { [a]: "a", [b]: 2 }, - `{ readonly Symbol(effect/Schema/test/a): number; readonly Symbol(effect/Schema/test/b): number } -└─ [Symbol(effect/Schema/test/a)] + `{ readonly Symbol(@effect/schema/test/a): number; readonly Symbol(@effect/schema/test/b): number } +└─ [Symbol(@effect/schema/test/a)] └─ Expected number, actual "a"` ) await Util.expectDecodeUnknownFailure( schema, { [a]: 1, [b]: "b" }, - `{ readonly Symbol(effect/Schema/test/a): number; readonly Symbol(effect/Schema/test/b): number } -└─ [Symbol(effect/Schema/test/b)] + `{ readonly Symbol(@effect/schema/test/a): number; readonly Symbol(@effect/schema/test/b): number } +└─ [Symbol(@effect/schema/test/b)] └─ Expected number, actual "b"` ) }) From 87f4d9520e0604b6d5bb5db2f8da0199354904f8 Mon Sep 17 00:00:00 2001 From: Tim Date: Mon, 21 Oct 2024 13:12:25 +1300 Subject: [PATCH 6/8] HttpApi second revision (#3794) --- .changeset/fair-cheetahs-learn.md | 16 + .changeset/four-monkeys-arrive.md | 5 + packages/experimental/src/VariantSchema.ts | 5 +- packages/platform-node/examples/api.ts | 218 ++-- packages/platform-node/test/HttpApi.test.ts | 282 ++--- .../platform-node/test/fixtures/openapi.json | 887 ++++++---------- packages/platform/README.md | 515 +++++---- packages/platform/src/HttpApi.ts | 379 ++++--- packages/platform/src/HttpApiBuilder.ts | 978 ++++++++++-------- packages/platform/src/HttpApiClient.ts | 271 +++-- packages/platform/src/HttpApiEndpoint.ts | 893 ++++++++-------- packages/platform/src/HttpApiGroup.ts | 505 +++++---- packages/platform/src/HttpApiMiddleware.ts | 318 ++++++ packages/platform/src/HttpApiSchema.ts | 37 + packages/platform/src/HttpApiSecurity.ts | 2 +- packages/platform/src/HttpApiSwagger.ts | 6 +- packages/platform/src/HttpServer.ts | 21 + packages/platform/src/OpenApi.ts | 200 ++-- packages/platform/src/OpenApiJsonSchema.ts | 100 +- packages/platform/src/index.ts | 5 + packages/platform/src/internal/httpServer.ts | 13 + .../platform/test/OpenApiJsonSchema.test.ts | 150 +-- 22 files changed, 3139 insertions(+), 2667 deletions(-) create mode 100644 .changeset/fair-cheetahs-learn.md create mode 100644 .changeset/four-monkeys-arrive.md create mode 100644 packages/platform/src/HttpApiMiddleware.ts diff --git a/.changeset/fair-cheetahs-learn.md b/.changeset/fair-cheetahs-learn.md new file mode 100644 index 0000000000..86fd418e2a --- /dev/null +++ b/.changeset/fair-cheetahs-learn.md @@ -0,0 +1,16 @@ +--- +"@effect/platform": minor +--- + +HttpApi second revision + +- `HttpApi`, `HttpApiGroup` & `HttpApiEndpoint` now use a chainable api instead + of a pipeable api. +- `HttpApiMiddleware` module has been added, with a updated way of defining + security middleware. +- You can now add multiple success schemas +- A url search parameter schema has been added +- Error schemas now support `HttpApiSchema` encoding apis +- `toWebHandler` has been simplified + +For more information, see the [README](https://github.com/Effect-TS/effect/blob/main/packages/platform/README.md#http-api). diff --git a/.changeset/four-monkeys-arrive.md b/.changeset/four-monkeys-arrive.md new file mode 100644 index 0000000000..a86ad6839c --- /dev/null +++ b/.changeset/four-monkeys-arrive.md @@ -0,0 +1,5 @@ +--- +"@effect/experimental": patch +--- + +add identifiers to VariantSchema variants diff --git a/packages/experimental/src/VariantSchema.ts b/packages/experimental/src/VariantSchema.ts index c3bfa43e86..4e334bce81 100644 --- a/packages/experimental/src/VariantSchema.ts +++ b/packages/experimental/src/VariantSchema.ts @@ -506,7 +506,10 @@ export const make = < } for (const variant of options.variants) { Object.defineProperty(Base, variant, { - value: extract(variantStruct, variant) + value: extract(variantStruct, variant).annotations({ + identifier: `${identifier}.${variant}`, + title: `${identifier}.${variant}` + }) }) } return Base diff --git a/packages/platform-node/examples/api.ts b/packages/platform-node/examples/api.ts index a985c091e1..7be14189e5 100644 --- a/packages/platform-node/examples/api.ts +++ b/packages/platform-node/examples/api.ts @@ -5,9 +5,12 @@ import { HttpApiClient, HttpApiEndpoint, HttpApiGroup, + HttpApiMiddleware, HttpApiSchema, HttpApiSecurity, HttpApiSwagger, + HttpClient, + HttpClientRequest, HttpMiddleware, HttpServer, OpenApi @@ -27,59 +30,63 @@ class Unauthorized extends Schema.TaggedError()("Unauthorized", { message: Schema.String }, HttpApiSchema.annotations({ status: 401 })) {} -const security = HttpApiSecurity.bearer - -const securityMiddleware = HttpApiBuilder.middlewareSecurity( - security, - CurrentUser, - (token) => Effect.succeed(new User({ id: 1000, name: `Authenticated with ${Redacted.value(token)}` })) -) +export class Authentication extends HttpApiMiddleware.Tag()("Authentication", { + failure: Unauthorized, + provides: CurrentUser, + security: { + bearer: HttpApiSecurity.bearer + } +}) {} -class UsersApi extends HttpApiGroup.make("users").pipe( - HttpApiGroup.add( - HttpApiEndpoint.get("findById", "/:id").pipe( - HttpApiEndpoint.setPath(Schema.Struct({ +class UsersApi extends HttpApiGroup.make("users") + .add( + HttpApiEndpoint.get("findById", "/:id") + .setPath(Schema.Struct({ id: Schema.NumberFromString - })), - HttpApiEndpoint.setSuccess(User), - HttpApiEndpoint.setHeaders(Schema.Struct({ + })) + .addSuccess(User) + .setHeaders(Schema.Struct({ page: Schema.NumberFromString.pipe( Schema.optionalWith({ default: () => 1 }) ) - })), - HttpApiEndpoint.addError(Schema.String.pipe( + })) + .addError(Schema.String.pipe( HttpApiSchema.asEmpty({ status: 413, decode: () => "boom" }) )) - ) - ), - HttpApiGroup.add( - HttpApiEndpoint.post("create", "/").pipe( - HttpApiEndpoint.setPayload(HttpApiSchema.Multipart(Schema.Struct({ + ) + .add( + HttpApiEndpoint.post("create", "/") + .setPayload(HttpApiSchema.Multipart(Schema.Struct({ name: Schema.String - }))), - HttpApiEndpoint.setSuccess(User) - ) - ), - HttpApiGroup.add( - HttpApiEndpoint.get("me", "/me").pipe( - HttpApiEndpoint.setSuccess(User) - ) - ), - HttpApiGroup.add( - HttpApiEndpoint.get("csv", "/csv").pipe( - HttpApiEndpoint.setSuccess(HttpApiSchema.Text({ + }))) + .addSuccess(User) + ) + .add( + HttpApiEndpoint.get("me", "/me") + .addSuccess(User) + ) + .middleware(Authentication) + .prefix("/users") + .annotateContext(OpenApi.annotations({ + title: "Users API", + description: "API for managing users" + })) +{} + +class TopLevelApi extends HttpApiGroup.make("topLevel", { topLevel: true }) + .add( + HttpApiEndpoint.get("csv", "/csv") + .addSuccess(HttpApiSchema.Text({ contentType: "text/csv" })) - ) - ), - HttpApiGroup.add( - HttpApiEndpoint.get("binary", "/binary").pipe( - HttpApiEndpoint.setSuccess(HttpApiSchema.Uint8Array()) - ) - ), - HttpApiGroup.add( - HttpApiEndpoint.get("urlParams", "/url-params").pipe( - HttpApiEndpoint.setSuccess( + ) + .add( + HttpApiEndpoint.get("binary", "/binary") + .addSuccess(HttpApiSchema.Uint8Array()) + ) + .add( + HttpApiEndpoint.get("urlParams", "/url-params") + .addSuccess( Schema.Struct({ id: Schema.NumberFromString, name: Schema.String @@ -89,53 +96,82 @@ class UsersApi extends HttpApiGroup.make("users").pipe( }) ) ) - ) - ), - HttpApiGroup.addError(Unauthorized), - HttpApiGroup.prefix("/users"), - OpenApi.annotate({ security }) -) {} - -class MyApi extends HttpApi.empty.pipe( - HttpApi.addGroup(UsersApi), - OpenApi.annotate({ - title: "Users API", - description: "API for managing users" - }) -) {} - -const UsersLive = HttpApiBuilder.group(MyApi, "users", (handlers) => - handlers.pipe( - HttpApiBuilder.handle("create", (_) => Effect.succeed(new User({ ..._.payload, id: 123 }))), - HttpApiBuilder.handle("findById", (_) => - Effect.as( - HttpApiBuilder.securitySetCookie( - HttpApiSecurity.apiKey({ - in: "cookie", - key: "token" - }), - "secret123" - ), + ) + .annotateContext(OpenApi.annotations({ + title: "Top Level API", + description: "API for top level endpoints" + })) +{} + +class MyApi extends HttpApi.empty + .add(UsersApi) + .add(TopLevelApi) +{} + +// ------------------------------------------------ +// implementation +// ------------------------------------------------ + +const AuthenticationLive = Layer.succeed( + Authentication, + Authentication.of({ + bearer: (token) => + Effect.succeed( new User({ - id: _.path.id, - name: `John Doe (${_.headers.page})` + id: 1000, + name: `Authenticated with ${Redacted.value(token)}` }) - )), - HttpApiBuilder.handle("me", (_) => CurrentUser), - HttpApiBuilder.handle("csv", (_) => Effect.succeed("id,name\n1,John")), - HttpApiBuilder.handle("urlParams", (_) => - Effect.succeed({ - id: 123, - name: "John" - })), - HttpApiBuilder.handle("binary", (_) => Effect.succeed(new Uint8Array([1, 2, 3, 4, 5]))), - securityMiddleware - )) + ) + }) +) + +const UsersLive = HttpApiBuilder.group( + MyApi, + "users", + (handlers) => + handlers + .handle("create", (_) => Effect.succeed(new User({ ..._.payload, id: 123 }))) + .handle("findById", (_) => + Effect.as( + HttpApiBuilder.securitySetCookie( + HttpApiSecurity.apiKey({ + in: "cookie", + key: "token" + }), + "secret123" + ), + new User({ + id: _.path.id, + name: `John Doe (${_.headers.page})` + }) + )) + .handle("me", (_) => CurrentUser) +).pipe( + Layer.provide(AuthenticationLive) +) + +const TopLevelLive = HttpApiBuilder.group( + MyApi, + "topLevel", + (handlers) => + handlers + .handle("csv", (_) => Effect.succeed("id,name\n1,John")) + .handle("urlParams", (_) => + Effect.succeed({ + id: 123, + name: "John" + })) + .handle("binary", (_) => Effect.succeed(new Uint8Array([1, 2, 3, 4, 5]))) +) const ApiLive = HttpApiBuilder.api(MyApi).pipe( - Layer.provide(UsersLive) + Layer.provide([UsersLive, TopLevelLive]) ) +// ------------------------------------------------ +// server +// ------------------------------------------------ + HttpApiBuilder.serve(HttpMiddleware.logger).pipe( Layer.provide(HttpApiSwagger.layer()), Layer.provide(HttpApiBuilder.middlewareOpenApi()), @@ -150,26 +186,30 @@ HttpApiBuilder.serve(HttpMiddleware.logger).pipe( Effect.gen(function*() { yield* Effect.sleep(2000) const client = yield* HttpApiClient.make(MyApi, { - baseUrl: "http://localhost:3000" + baseUrl: "http://localhost:3000", + transformClient: HttpClient.mapRequest(HttpClientRequest.bearerToken("token")) }) const data = new FormData() data.append("name", "John") console.log("Multipart", yield* client.users.create({ payload: data })) - const user = yield* client.users.findById({ + let user = yield* client.users.findById({ path: { id: 123 }, headers: { page: 10 } }) console.log("json", user) - const csv = yield* client.users.csv() + user = yield* client.users.me() + console.log("json me", user) + + const csv = yield* client.csv() console.log("csv", csv) - const urlParams = yield* client.users.urlParams() + const urlParams = yield* client.urlParams() console.log("urlParams", urlParams) - const binary = yield* client.users.binary() + const binary = yield* client.binary() console.log("binary", binary) }).pipe( Effect.provide(FetchHttpClient.layer), diff --git a/packages/platform-node/test/HttpApi.test.ts b/packages/platform-node/test/HttpApi.test.ts index 8b3b6aaca4..958073221c 100644 --- a/packages/platform-node/test/HttpApi.test.ts +++ b/packages/platform-node/test/HttpApi.test.ts @@ -6,6 +6,7 @@ import { HttpApiClient, HttpApiEndpoint, HttpApiGroup, + HttpApiMiddleware, HttpApiSchema, HttpApiSecurity, HttpClient, @@ -25,12 +26,13 @@ describe("HttpApi", () => { Effect.gen(function*() { const client = yield* HttpApiClient.make(Api) const user = yield* client.users.create({ + urlParams: { id: 123 }, payload: { name: "Joe" } }) assert.deepStrictEqual( user, new User({ - id: 1, + id: 123, name: "Joe", createdAt: DateTime.unsafeMake(0) }) @@ -103,6 +105,7 @@ describe("HttpApi", () => { it.scoped("class level annotations", () => Effect.gen(function*() { const response = yield* HttpClientRequest.post("/users").pipe( + HttpClientRequest.setUrlParams({ id: "0" }), HttpClientRequest.bodyUnsafeJson({ name: "boom" }), HttpClient.execute ) @@ -163,7 +166,7 @@ describe("HttpApi", () => { it.effect("apiKey query security", () => Effect.gen(function*() { - const decode = HttpApiBuilder.securityDecode(securityQuery).pipe( + const redacted = yield* HttpApiBuilder.securityDecode(securityQuery).pipe( Effect.provideService( HttpServerRequest.HttpServerRequest, HttpServerRequest.fromWeb(new Request("http://localhost:3000/")) @@ -172,7 +175,6 @@ describe("HttpApi", () => { api_key: "foo" }) ) - const redacted = yield* decode assert.strictEqual(Redacted.value(redacted), "foo") }).pipe(Effect.provide(HttpLive))) }) @@ -199,11 +201,6 @@ class Group extends Schema.Class("Group")({ name: Schema.String }) {} -const securityCookie = HttpApiSecurity.apiKey({ - in: "cookie", - key: "token" -}) - const securityHeader = HttpApiSecurity.apiKey({ in: "header", key: "x-api-key" @@ -214,80 +211,89 @@ const securityQuery = HttpApiSecurity.apiKey({ key: "api_key" }) -class GroupsApi extends HttpApiGroup.make("groups").pipe( - HttpApiGroup.add( - HttpApiEndpoint.get("findById", "/:id").pipe( - HttpApiEndpoint.setPath(Schema.Struct({ +class CurrentUser extends Context.Tag("CurrentUser")() {} + +class Authorization extends HttpApiMiddleware.Tag()("Authorization", { + security: { + cookie: HttpApiSecurity.apiKey({ + in: "cookie", + key: "token" + }) + }, + provides: CurrentUser +}) {} + +class GroupsApi extends HttpApiGroup.make("groups") + .add( + HttpApiEndpoint.get("findById", "/:id") + .setPath(Schema.Struct({ id: Schema.NumberFromString - })), - HttpApiEndpoint.setSuccess(Group) - ) - ), - HttpApiGroup.add( - HttpApiEndpoint.post("create", "/").pipe( - HttpApiEndpoint.setPayload(Schema.Struct(Struct.pick(Group.fields, "name"))), - HttpApiEndpoint.setSuccess(Group) - ) - ), - HttpApiGroup.addError(GroupError.pipe( + })) + .addSuccess(Group) + ) + .add( + HttpApiEndpoint.post("create", "/") + .setPayload(Schema.Struct(Struct.pick(Group.fields, "name"))) + .addSuccess(Group) + ) + .addError(GroupError.pipe( HttpApiSchema.asEmpty({ status: 418, decode: () => new GroupError() }) - )), - HttpApiGroup.prefix("/groups"), - OpenApi.annotate({ security: securityCookie }) -) {} + )) + .prefix("/groups") +{} -class UsersApi extends HttpApiGroup.make("users").pipe( - HttpApiGroup.add( - HttpApiEndpoint.get("findById", "/:id").pipe( - HttpApiEndpoint.setPath(Schema.Struct({ +class UsersApi extends HttpApiGroup.make("users") + .add( + HttpApiEndpoint.get("findById", "/:id") + .setPath(Schema.Struct({ id: Schema.NumberFromString - })), - HttpApiEndpoint.setSuccess(User) - ) - ), - HttpApiGroup.add( - HttpApiEndpoint.post("create", "/").pipe( - HttpApiEndpoint.setPayload(Schema.Struct(Struct.omit( + })) + .addSuccess(User) + ) + .add( + HttpApiEndpoint.post("create", "/") + .setPayload(Schema.Struct(Struct.omit( User.fields, "id", "createdAt" - ))), - HttpApiEndpoint.setSuccess(User), - HttpApiEndpoint.addError(UserError) - ) - ), - HttpApiGroup.add( - HttpApiEndpoint.get("list", "/").pipe( - HttpApiEndpoint.setHeaders(Schema.Struct({ + ))) + .setUrlParams(Schema.Struct({ + id: Schema.NumberFromString + })) + .addSuccess(User) + .addError(UserError) + ) + .add( + HttpApiEndpoint.get("list", "/") + .setHeaders(Schema.Struct({ page: Schema.NumberFromString.pipe( Schema.optionalWith({ default: () => 1 }) ) - })), - HttpApiEndpoint.setSuccess(Schema.Array(User)), - HttpApiEndpoint.addError(NoStatusError), - OpenApi.annotate({ identifier: "listUsers" }) - ) - ), - HttpApiGroup.add( - HttpApiEndpoint.post("upload", "/upload").pipe( - HttpApiEndpoint.setPayload(HttpApiSchema.Multipart(Schema.Struct({ + })) + .addSuccess(Schema.Array(User)) + .addError(NoStatusError) + .annotateContext(OpenApi.annotations({ identifier: "listUsers" })) + ) + .add( + HttpApiEndpoint.post("upload", "/upload") + .setPayload(HttpApiSchema.Multipart(Schema.Struct({ file: Multipart.SingleFileSchema - }))), - HttpApiEndpoint.setSuccess(Schema.Struct({ + }))) + .addSuccess(Schema.Struct({ contentType: Schema.String, length: Schema.Int })) - ) - ), - OpenApi.annotate({ title: "Users API" }) -) {} + ) + .middleware(Authorization) + .annotateContext(OpenApi.annotations({ title: "Users API" })) +{} -class Api extends HttpApi.empty.pipe( - HttpApi.addGroup(GroupsApi), - HttpApi.addGroup("/users", UsersApi), - HttpApi.addError(GlobalError, { status: 413 }), - OpenApi.annotate({ title: "API" }) -) {} +class Api extends HttpApi.empty + .add(GroupsApi) + .add(UsersApi.prefix("/users")) + .addError(GlobalError, { status: 413 }) + .annotateContext(OpenApi.annotations({ title: "API" })) +{} // impl @@ -299,80 +305,84 @@ class UserRepo extends Context.Tag("UserRepo")() {} - -const securityMiddleware = HttpApiBuilder.middlewareSecurity( - securityCookie, - CurrentUser, - (token) => - Effect.succeed( - new User({ - id: 1, - name: Redacted.value(token), - createdAt: DateTime.unsafeNow() - }) - ) +const AuthorizationLive = Layer.succeed( + Authorization, + Authorization.of({ + cookie: (token) => + Effect.succeed( + new User({ + id: 1, + name: Redacted.value(token), + createdAt: DateTime.unsafeNow() + }) + ) + }) ) -const HttpUsersLive = HttpApiBuilder.group(Api, "users", (handlers) => - Effect.gen(function*() { - const fs = yield* FileSystem.FileSystem - const repo = yield* UserRepo - return handlers.pipe( - HttpApiBuilder.handle("findById", (_) => - _.path.id === -1 - ? CurrentUser : - repo.findById(_.path.id)), - HttpApiBuilder.handle("create", (_) => - _.payload.name === "boom" - ? Effect.fail(new UserError()) - : Effect.map(DateTime.now, (now) => - new User({ - id: 1, - name: _.payload.name, - createdAt: now - }))), - HttpApiBuilder.handle("list", (_) => - _.headers.page === 0 - ? Effect.fail(new NoStatusError()) - // test handler level context - : Effect.map(DateTime.nowInCurrentZone, (now) => [ - new User({ - id: 1, - name: `page ${_.headers.page}`, - createdAt: DateTime.unsafeMake(now.epochMillis) - }) - ])), - HttpApiBuilder.handle("upload", (_) => - Effect.gen(function*() { - const stat = yield* fs.stat(_.payload.file.path).pipe(Effect.orDie) - return { - contentType: _.payload.file.contentType, - length: Number(stat.size) - } - })), - securityMiddleware - ) - })).pipe( - Layer.provide(DateTime.layerCurrentZoneOffset(0)), - Layer.provide(UserRepo.Live) - ) - -const HttpGroupsLive = HttpApiBuilder.group(Api, "groups", (handlers) => - handlers.pipe( - HttpApiBuilder.handle("findById", (_) => - _.path.id === 0 - ? Effect.fail(new GroupError()) - : Effect.succeed(new Group({ id: 1, name: "foo" }))), - HttpApiBuilder.handle("create", (_) => Effect.succeed(new Group({ id: 1, name: _.payload.name }))), - securityMiddleware - )) +const HttpUsersLive = HttpApiBuilder.group( + Api, + "users", + (handlers) => + Effect.gen(function*() { + const fs = yield* FileSystem.FileSystem + const repo = yield* UserRepo + return handlers + .handle("findById", (_) => + _.path.id === -1 + ? CurrentUser : + repo.findById(_.path.id)) + .handle("create", (_) => + _.payload.name === "boom" + ? Effect.fail(new UserError()) + : Effect.map(DateTime.now, (now) => + new User({ + id: _.urlParams.id, + name: _.payload.name, + createdAt: now + }))) + .handle("list", (_) => + _.headers.page === 0 + ? Effect.fail(new NoStatusError()) + // test handler level context + : Effect.map(DateTime.nowInCurrentZone, (now) => [ + new User({ + id: 1, + name: `page ${_.headers.page}`, + createdAt: DateTime.unsafeMake(now.epochMillis) + }) + ])) + .handle("upload", (_) => + Effect.gen(function*() { + const stat = yield* fs.stat(_.payload.file.path).pipe(Effect.orDie) + return { + contentType: _.payload.file.contentType, + length: Number(stat.size) + } + })) + }) +).pipe(Layer.provide([ + DateTime.layerCurrentZoneOffset(0), + UserRepo.Live, + AuthorizationLive +])) -const HttpApiLive = HttpApiBuilder.api(Api).pipe( - Layer.provide(HttpUsersLive), - Layer.provide(HttpGroupsLive) +const HttpGroupsLive = HttpApiBuilder.group( + Api, + "groups", + (handlers) => + handlers + .handle("findById", ({ path }) => + path.id === 0 + ? Effect.fail(new GroupError()) + : Effect.succeed(new Group({ id: 1, name: "foo" }))) + .handle("create", ({ payload }) => Effect.succeed(new Group({ id: 1, name: payload.name }))) ) +const HttpApiLive = Layer.provide(HttpApiBuilder.api(Api), [ + HttpGroupsLive, + HttpUsersLive +]) + const HttpLive = HttpApiBuilder.serve().pipe( Layer.provide(HttpApiBuilder.middlewareCors()), Layer.provide(HttpApiLive), diff --git a/packages/platform-node/test/fixtures/openapi.json b/packages/platform-node/test/fixtures/openapi.json index 3b71befafe..fa6fd5560c 100644 --- a/packages/platform-node/test/fixtures/openapi.json +++ b/packages/platform-node/test/fixtures/openapi.json @@ -5,47 +5,110 @@ "version": "0.0.1" }, "paths": { - "/groups/{id}": { - "get": { - "tags": ["groups"], - "operationId": "groups.findById", + "/users": { + "post": { + "tags": ["Users API"], + "operationId": "users.create", "parameters": [ { "name": "id", - "in": "path", + "in": "query", "schema": { - "description": "a string that will be parsed into a number", - "type": "string" + "$ref": "#/components/schemas/NumberFromString" }, "required": true } ], "security": [ { - "ApiKey": [] + "Authorization/cookie": [] } ], "responses": { "200": { - "description": "an instance of Group", + "description": "an instance of User", "content": { "application/json": { "schema": { - "description": "an instance of Group", - "title": "Group", - "type": "object", - "required": ["id", "name"], - "properties": { - "id": { - "type": "integer", - "description": "an integer", - "title": "Int" + "$ref": "#/components/schemas/User" + } + } + } + }, + "400": { + "description": "Error", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/HttpApiDecodeError" }, - "name": { - "type": "string" + { + "$ref": "#/components/schemas/UserError" } - }, - "additionalProperties": false + ] + } + } + } + }, + "413": { + "description": "an instance of GlobalError", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GlobalError" + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "required": ["name"], + "properties": { + "name": { + "type": "string" + } + }, + "additionalProperties": false + } + } + }, + "required": true + } + }, + "get": { + "tags": ["Users API"], + "operationId": "listUsers", + "parameters": [ + { + "name": "page", + "in": "header", + "schema": { + "$ref": "#/components/schemas/NumberFromString" + }, + "required": false + } + ], + "security": [ + { + "Authorization/cookie": [] + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/User" + } } } } @@ -55,57 +118,7 @@ "content": { "application/json": { "schema": { - "description": "HttpApiDecodeError: The request did not match the expected schema", - "title": "HttpApiDecodeError", - "type": "object", - "required": ["issues", "message", "_tag"], - "properties": { - "issues": { - "type": "array", - "items": { - "type": "object", - "required": ["_tag", "path", "message"], - "properties": { - "_tag": { - "enum": [ - "Pointer", - "Unexpected", - "Missing", - "Composite", - "Refinement", - "Transformation", - "Type", - "Forbidden" - ] - }, - "path": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - } - ] - } - }, - "message": { - "type": "string" - } - }, - "additionalProperties": false - } - }, - "message": { - "type": "string" - }, - "_tag": { - "enum": ["HttpApiDecodeError"] - } - }, - "additionalProperties": false + "$ref": "#/components/schemas/HttpApiDecodeError" } } } @@ -115,54 +128,50 @@ "content": { "application/json": { "schema": { - "description": "an instance of GlobalError", - "title": "GlobalError", - "type": "object", - "required": ["_tag"], - "properties": { - "_tag": { - "enum": ["GlobalError"] - } - }, - "additionalProperties": false + "$ref": "#/components/schemas/GlobalError" } } } }, - "418": { - "description": "an instance of GroupError" + "500": { + "description": "an instance of NoStatusError", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NoStatusError" + } + } + } } } } }, - "/groups": { + "/users/upload": { "post": { - "tags": ["groups"], - "operationId": "groups.create", + "tags": ["Users API"], + "operationId": "users.upload", "parameters": [], "security": [ { - "ApiKey": [] + "Authorization/cookie": [] } ], "responses": { "200": { - "description": "an instance of Group", + "description": "Success", "content": { "application/json": { "schema": { - "description": "an instance of Group", - "title": "Group", "type": "object", - "required": ["id", "name"], + "required": ["contentType", "length"], "properties": { - "id": { + "contentType": { + "type": "string" + }, + "length": { "type": "integer", "description": "an integer", "title": "Int" - }, - "name": { - "type": "string" } }, "additionalProperties": false @@ -175,57 +184,7 @@ "content": { "application/json": { "schema": { - "description": "HttpApiDecodeError: The request did not match the expected schema", - "title": "HttpApiDecodeError", - "type": "object", - "required": ["issues", "message", "_tag"], - "properties": { - "issues": { - "type": "array", - "items": { - "type": "object", - "required": ["_tag", "path", "message"], - "properties": { - "_tag": { - "enum": [ - "Pointer", - "Unexpected", - "Missing", - "Composite", - "Refinement", - "Transformation", - "Type", - "Forbidden" - ] - }, - "path": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - } - ] - } - }, - "message": { - "type": "string" - } - }, - "additionalProperties": false - } - }, - "message": { - "type": "string" - }, - "_tag": { - "enum": ["HttpApiDecodeError"] - } - }, - "additionalProperties": false + "$ref": "#/components/schemas/HttpApiDecodeError" } } } @@ -235,33 +194,28 @@ "content": { "application/json": { "schema": { - "description": "an instance of GlobalError", - "title": "GlobalError", - "type": "object", - "required": ["_tag"], - "properties": { - "_tag": { - "enum": ["GlobalError"] - } - }, - "additionalProperties": false + "$ref": "#/components/schemas/GlobalError" } } } - }, - "418": { - "description": "an instance of GroupError" } }, "requestBody": { "content": { - "application/json": { + "multipart/form-data": { "schema": { "type": "object", - "required": ["name"], + "required": ["file"], "properties": { - "name": { - "type": "string" + "file": { + "type": "array", + "items": { + "type": "string", + "format": "binary" + }, + "description": "an array of exactly 1 item(s)", + "minItems": 1, + "maxItems": 1 } }, "additionalProperties": false @@ -281,38 +235,23 @@ "name": "id", "in": "path", "schema": { - "description": "a string that will be parsed into a number", - "type": "string" + "$ref": "#/components/schemas/NumberFromString" }, "required": true } ], - "security": [], + "security": [ + { + "Authorization/cookie": [] + } + ], "responses": { "200": { "description": "an instance of User", "content": { "application/json": { "schema": { - "description": "an instance of User", - "title": "User", - "type": "object", - "required": ["id", "name", "createdAt"], - "properties": { - "id": { - "type": "integer", - "description": "an integer", - "title": "Int" - }, - "name": { - "type": "string" - }, - "createdAt": { - "description": "a string that will be parsed into a DateTime.Utc", - "type": "string" - } - }, - "additionalProperties": false + "$ref": "#/components/schemas/User" } } } @@ -322,57 +261,7 @@ "content": { "application/json": { "schema": { - "description": "HttpApiDecodeError: The request did not match the expected schema", - "title": "HttpApiDecodeError", - "type": "object", - "required": ["issues", "message", "_tag"], - "properties": { - "issues": { - "type": "array", - "items": { - "type": "object", - "required": ["_tag", "path", "message"], - "properties": { - "_tag": { - "enum": [ - "Pointer", - "Unexpected", - "Missing", - "Composite", - "Refinement", - "Transformation", - "Type", - "Forbidden" - ] - }, - "path": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - } - ] - } - }, - "message": { - "type": "string" - } - }, - "additionalProperties": false - } - }, - "message": { - "type": "string" - }, - "_tag": { - "enum": ["HttpApiDecodeError"] - } - }, - "additionalProperties": false + "$ref": "#/components/schemas/HttpApiDecodeError" } } } @@ -382,16 +271,7 @@ "content": { "application/json": { "schema": { - "description": "an instance of GlobalError", - "title": "GlobalError", - "type": "object", - "required": ["_tag"], - "properties": { - "_tag": { - "enum": ["GlobalError"] - } - }, - "additionalProperties": false + "$ref": "#/components/schemas/GlobalError" } } } @@ -399,113 +279,29 @@ } } }, - "/users": { + "/groups": { "post": { - "tags": ["Users API"], - "operationId": "users.create", + "tags": ["groups"], + "operationId": "groups.create", "parameters": [], "security": [], "responses": { "200": { - "description": "an instance of User", + "description": "an instance of Group", "content": { "application/json": { "schema": { - "description": "an instance of User", - "title": "User", - "type": "object", - "required": ["id", "name", "createdAt"], - "properties": { - "id": { - "type": "integer", - "description": "an integer", - "title": "Int" - }, - "name": { - "type": "string" - }, - "createdAt": { - "description": "a string that will be parsed into a DateTime.Utc", - "type": "string" - } - }, - "additionalProperties": false + "$ref": "#/components/schemas/Group" } } } }, "400": { - "description": "Error", + "description": "HttpApiDecodeError: The request did not match the expected schema", "content": { "application/json": { "schema": { - "anyOf": [ - { - "description": "HttpApiDecodeError: The request did not match the expected schema", - "title": "HttpApiDecodeError", - "type": "object", - "required": ["issues", "message", "_tag"], - "properties": { - "issues": { - "type": "array", - "items": { - "type": "object", - "required": ["_tag", "path", "message"], - "properties": { - "_tag": { - "enum": [ - "Pointer", - "Unexpected", - "Missing", - "Composite", - "Refinement", - "Transformation", - "Type", - "Forbidden" - ] - }, - "path": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - } - ] - } - }, - "message": { - "type": "string" - } - }, - "additionalProperties": false - } - }, - "message": { - "type": "string" - }, - "_tag": { - "enum": ["HttpApiDecodeError"] - } - }, - "additionalProperties": false - }, - { - "description": "an instance of UserError", - "title": "UserError", - "type": "object", - "required": ["_tag"], - "properties": { - "_tag": { - "enum": ["UserError"] - } - }, - "additionalProperties": false - } - ] + "$ref": "#/components/schemas/HttpApiDecodeError" } } } @@ -515,19 +311,13 @@ "content": { "application/json": { "schema": { - "description": "an instance of GlobalError", - "title": "GlobalError", - "type": "object", - "required": ["_tag"], - "properties": { - "_tag": { - "enum": ["GlobalError"] - } - }, - "additionalProperties": false + "$ref": "#/components/schemas/GlobalError" } } } + }, + "418": { + "description": "an instance of GroupError" } }, "requestBody": { @@ -547,50 +337,30 @@ }, "required": true } - }, + } + }, + "/groups/{id}": { "get": { - "tags": ["Users API"], - "operationId": "listUsers", + "tags": ["groups"], + "operationId": "groups.findById", "parameters": [ { - "name": "page", - "in": "header", + "name": "id", + "in": "path", "schema": { - "description": "a string that will be parsed into a number", - "type": "string" + "$ref": "#/components/schemas/NumberFromString" }, - "required": false + "required": true } ], "security": [], "responses": { "200": { - "description": "Success", + "description": "an instance of Group", "content": { "application/json": { "schema": { - "type": "array", - "items": { - "description": "an instance of User", - "title": "User", - "type": "object", - "required": ["id", "name", "createdAt"], - "properties": { - "id": { - "type": "integer", - "description": "an integer", - "title": "Int" - }, - "name": { - "type": "string" - }, - "createdAt": { - "description": "a string that will be parsed into a DateTime.Utc", - "type": "string" - } - }, - "additionalProperties": false - } + "$ref": "#/components/schemas/Group" } } } @@ -600,57 +370,7 @@ "content": { "application/json": { "schema": { - "description": "HttpApiDecodeError: The request did not match the expected schema", - "title": "HttpApiDecodeError", - "type": "object", - "required": ["issues", "message", "_tag"], - "properties": { - "issues": { - "type": "array", - "items": { - "type": "object", - "required": ["_tag", "path", "message"], - "properties": { - "_tag": { - "enum": [ - "Pointer", - "Unexpected", - "Missing", - "Composite", - "Refinement", - "Transformation", - "Type", - "Forbidden" - ] - }, - "path": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - } - ] - } - }, - "message": { - "type": "string" - } - }, - "additionalProperties": false - } - }, - "message": { - "type": "string" - }, - "_tag": { - "enum": ["HttpApiDecodeError"] - } - }, - "additionalProperties": false + "$ref": "#/components/schemas/HttpApiDecodeError" } } } @@ -660,190 +380,165 @@ "content": { "application/json": { "schema": { - "description": "an instance of GlobalError", - "title": "GlobalError", - "type": "object", - "required": ["_tag"], - "properties": { - "_tag": { - "enum": ["GlobalError"] - } - }, - "additionalProperties": false + "$ref": "#/components/schemas/GlobalError" } } } }, - "500": { - "description": "an instance of NoStatusError", - "content": { - "application/json": { - "schema": { - "description": "an instance of NoStatusError", - "title": "NoStatusError", - "type": "object", - "required": ["_tag"], - "properties": { - "_tag": { - "enum": ["NoStatusError"] - } - }, - "additionalProperties": false - } - } - } + "418": { + "description": "an instance of GroupError" } } } + } + }, + "tags": [ + { + "name": "Users API" }, - "/users/upload": { - "post": { - "tags": ["Users API"], - "operationId": "users.upload", - "parameters": [], - "security": [], - "responses": { - "200": { - "description": "Success", - "content": { - "application/json": { - "schema": { - "type": "object", - "required": ["contentType", "length"], - "properties": { - "contentType": { - "type": "string" - }, - "length": { - "type": "integer", - "description": "an integer", - "title": "Int" - } - }, - "additionalProperties": false - } - } - } + { + "name": "groups" + } + ], + "components": { + "schemas": { + "User": { + "description": "an instance of User", + "title": "User", + "type": "object", + "required": ["id", "name", "createdAt"], + "properties": { + "id": { + "type": "integer", + "description": "an integer", + "title": "Int" }, - "400": { - "description": "HttpApiDecodeError: The request did not match the expected schema", - "content": { - "application/json": { - "schema": { - "description": "HttpApiDecodeError: The request did not match the expected schema", - "title": "HttpApiDecodeError", - "type": "object", - "required": ["issues", "message", "_tag"], - "properties": { - "issues": { - "type": "array", - "items": { - "type": "object", - "required": ["_tag", "path", "message"], - "properties": { - "_tag": { - "enum": [ - "Pointer", - "Unexpected", - "Missing", - "Composite", - "Refinement", - "Transformation", - "Type", - "Forbidden" - ] - }, - "path": { - "type": "array", - "items": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "number" - } - ] - } - }, - "message": { - "type": "string" - } - }, - "additionalProperties": false - } - }, - "message": { - "type": "string" - }, - "_tag": { - "enum": ["HttpApiDecodeError"] - } - }, - "additionalProperties": false - } - } - } + "name": { + "type": "string" }, - "413": { - "description": "an instance of GlobalError", - "content": { - "application/json": { - "schema": { - "description": "an instance of GlobalError", - "title": "GlobalError", - "type": "object", - "required": ["_tag"], - "properties": { - "_tag": { - "enum": ["GlobalError"] - } - }, - "additionalProperties": false - } - } - } + "createdAt": { + "$ref": "#/components/schemas/DateTimeUtc" } }, - "requestBody": { - "content": { - "multipart/form-data": { - "schema": { - "type": "object", - "required": ["file"], - "properties": { - "file": { - "type": "array", - "items": { - "type": "string", - "format": "binary" - }, - "description": "an array of exactly 1 item(s)", - "minItems": 1, - "maxItems": 1 + "additionalProperties": false + }, + "DateTimeUtc": { + "description": "a string that will be parsed into a DateTime.Utc", + "type": "string" + }, + "NumberFromString": { + "type": "string", + "description": "a string that will be parsed into a number" + }, + "HttpApiDecodeError": { + "description": "HttpApiDecodeError: The request did not match the expected schema", + "title": "HttpApiDecodeError", + "type": "object", + "required": ["issues", "message", "_tag"], + "properties": { + "issues": { + "type": "array", + "items": { + "type": "object", + "required": ["_tag", "path", "message"], + "properties": { + "_tag": { + "enum": [ + "Pointer", + "Unexpected", + "Missing", + "Composite", + "Refinement", + "Transformation", + "Type", + "Forbidden" + ] + }, + "path": { + "type": "array", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + } + ] } }, - "additionalProperties": false - } + "message": { + "type": "string" + } + }, + "additionalProperties": false } }, - "required": true - } + "message": { + "type": "string" + }, + "_tag": { + "enum": ["HttpApiDecodeError"] + } + }, + "additionalProperties": false + }, + "UserError": { + "description": "an instance of UserError", + "title": "UserError", + "type": "object", + "required": ["_tag"], + "properties": { + "_tag": { + "enum": ["UserError"] + } + }, + "additionalProperties": false + }, + "GlobalError": { + "description": "an instance of GlobalError", + "title": "GlobalError", + "type": "object", + "required": ["_tag"], + "properties": { + "_tag": { + "enum": ["GlobalError"] + } + }, + "additionalProperties": false + }, + "NoStatusError": { + "description": "an instance of NoStatusError", + "title": "NoStatusError", + "type": "object", + "required": ["_tag"], + "properties": { + "_tag": { + "enum": ["NoStatusError"] + } + }, + "additionalProperties": false + }, + "Group": { + "description": "an instance of Group", + "title": "Group", + "type": "object", + "required": ["id", "name"], + "properties": { + "id": { + "type": "integer", + "description": "an integer", + "title": "Int" + }, + "name": { + "type": "string" + } + }, + "additionalProperties": false } - } - }, - "tags": [ - { - "name": "groups" }, - { - "name": "Users API" - } - ], - "components": { - "schemas": {}, "securitySchemes": { - "ApiKey": { + "Authorization/cookie": { "type": "apiKey", "name": "token", "in": "cookie" diff --git a/packages/platform/README.md b/packages/platform/README.md index c03df934ce..bb64c333ad 100644 --- a/packages/platform/README.md +++ b/packages/platform/README.md @@ -41,58 +41,52 @@ class User extends Schema.Class("User")({ createdAt: Schema.DateTimeUtc }) {} -const usersApi = HttpApiGroup.make("users").pipe( - HttpApiGroup.add( +const usersApi = HttpApiGroup.make("users") + .add( // each endpoint has a name and a path - HttpApiEndpoint.get("findById", "/users/:id").pipe( + HttpApiEndpoint.get("findById", "/users/:id") // the endpoint can have a Schema for a successful response - HttpApiEndpoint.setSuccess(User), + .addSuccess(User) // and here is a Schema for the path parameters - HttpApiEndpoint.setPath( + .setPath( Schema.Struct({ id: Schema.NumberFromString }) ) - ) - ), - HttpApiGroup.add( - HttpApiEndpoint.post("create", "/users").pipe( - HttpApiEndpoint.setSuccess(User), + ) + .add( + HttpApiEndpoint.post("create", "/users") + .addSuccess(User) // and here is a Schema for the request payload / body // // this is a POST request, so the payload is in the body // but for a GET request, the payload would be in the URL search params - HttpApiEndpoint.setPayload( + .setPayload( Schema.Struct({ name: Schema.String }) ) - ) - ), + ) // by default, the endpoint will respond with a 204 No Content - HttpApiGroup.add(HttpApiEndpoint.del("delete", "/users/:id")), - HttpApiGroup.add( - HttpApiEndpoint.patch("update", "/users/:id").pipe( - HttpApiEndpoint.setSuccess(User), - HttpApiEndpoint.setPayload( + .add(HttpApiEndpoint.del("delete", "/users/:id")) + .add( + HttpApiEndpoint.patch("update", "/users/:id") + .addSuccess(User) + .setPayload( Schema.Struct({ name: Schema.String }) ) - ) ) -) ``` You can also extend the `HttpApiGroup` with a class to gain an opaque type. We will use this API style in the following examples: ```ts -class UsersApi extends HttpApiGroup.make("users").pipe( - HttpApiGroup.add( - HttpApiEndpoint.get("findById", "/users/:id") - // ... same as above - ) +class UsersApi extends HttpApiGroup.make("users").add( + HttpApiEndpoint.get("findById", "/users/:id") + // ... same as above ) {} ``` @@ -103,13 +97,13 @@ Once you have defined your groups, you can combine them into a single `HttpApi`. ```ts import { HttpApi } from "@effect/platform" -class MyApi extends HttpApi.empty.pipe(HttpApi.addGroup(UsersApi)) {} +class MyApi extends HttpApi.empty.add(UsersApi) {} ``` Or with the non-opaque style: ```ts -const api = HttpApi.empty.pipe(HttpApi.addGroup(usersApi)) +const api = HttpApi.empty.add(usersApi) ``` ### Adding OpenApi annotations @@ -121,17 +115,21 @@ Let's add a title to our `UsersApi` group: ```ts import { OpenApi } from "@effect/platform" -class UsersApi extends HttpApiGroup.make("users").pipe( - HttpApiGroup.add( +class UsersApi extends HttpApiGroup.make("users") + .add( HttpApiEndpoint.get("findById", "/users/:id") // ... same as above - ), + ) // add an OpenApi title & description - OpenApi.annotate({ - title: "Users API", - description: "API for managing users" - }) -) {} + // You can set one attribute at a time + .annotate(OpenApi.Title, "Users API") + // or multiple at once + .annotateContext( + OpenApi.annotations({ + title: "Users API", + description: "API for managing users" + }) + ) {} ``` Now when you generate OpenApi documentation, the title and description will be @@ -140,13 +138,9 @@ included. You can also add OpenApi annotations to the top-level `HttpApi`: ```ts -class MyApi extends HttpApi.empty.pipe( - HttpApi.addGroup(UsersApi), - OpenApi.annotate({ - title: "My API", - description: "My awesome API" - }) -) {} +class MyApi extends HttpApi.empty + .add(UsersApi) + .annotate(OpenApi.Title, "My API") {} ``` ### Adding errors @@ -174,18 +168,16 @@ class Unauthorized extends Schema.TaggedError()( {} ) {} -class UsersApi extends HttpApiGroup.make("users").pipe( - HttpApiGroup.add( - HttpApiEndpoint.get("findById", "/users/:id").pipe( +class UsersApi extends HttpApiGroup.make("users") + .add( + HttpApiEndpoint.get("findById", "/users/:id") // here we are adding our error response - HttpApiEndpoint.addError(UserNotFound, { status: 404 }), - HttpApiEndpoint.setSuccess(User), - HttpApiEndpoint.setPath(Schema.Struct({ id: Schema.NumberFromString })) - ) - ), + .addError(UserNotFound, { status: 404 }) + .addSuccess(User) + .setPath(Schema.Struct({ id: Schema.NumberFromString })) + ) // or we could add an error to the group - HttpApiGroup.addError(Unauthorized, { status: 401 }) -) {} + .addError(Unauthorized, { status: 401 }) {} ``` It is worth noting that you can add multiple error responses to an endpoint, @@ -202,62 +194,18 @@ shape of the multipart request. ```ts import { HttpApiSchema, Multipart } from "@effect/platform" -class UsersApi extends HttpApiGroup.make("users").pipe( - HttpApiGroup.add( - HttpApiEndpoint.post("upload", "/users/upload").pipe( - HttpApiEndpoint.setPayload( - HttpApiSchema.Multipart( - Schema.Struct({ - // add a "files" field to the schema - files: Multipart.FilesSchema - }) - ) - ) +class UsersApi extends HttpApiGroup.make("users").add( + HttpApiEndpoint.post("upload", "/users/upload").setPayload( + HttpApiSchema.Multipart( + Schema.Struct({ + // add a "files" field to the schema + files: Multipart.FilesSchema + }) ) ) ) {} ``` -### Adding security annotations - -The `HttpApiSecurity` module provides a way to add security annotations to your -API. - -It offers the following authorization types: - -- `HttpApiSecurity.apiKey` - API key authorization through headers, query - parameters, or cookies. -- `HttpApiSecurity.basicAuth` - HTTP Basic authentication. -- `HttpApiSecurity.bearerAuth` - Bearer token authentication. - -You can annotate your API with these security types using the -`OpenApi.annotate` api as before. - -```ts -import { HttpApiSecurity } from "@effect/platform" - -const security = HttpApiSecurity.apiKey({ - in: "cookie", - key: "token" -}) - -class UsersApi extends HttpApiGroup.make("users").pipe( - HttpApiGroup.add( - HttpApiEndpoint.get("findById", "/users/:id").pipe( - // add the security annotation to the endpoint - OpenApi.annotate({ security }) - ) - ), - // or at the group level - OpenApi.annotate({ security }), - - // or just for the endpoints above this line - HttpApiGroup.annotateEndpoints(OpenApi.Security, security), - // this endpoint will not have the security annotation - HttpApiGroup.add(HttpApiEndpoint.get("list", "/users")) -) {} -``` - ### Changing the response encoding By default, the response is encoded as JSON. You can change the encoding using @@ -266,17 +214,13 @@ the `HttpApiSchema.withEncoding` api. Here is an example of changing the encoding to text/csv: ```ts -class UsersApi extends HttpApiGroup.make("users").pipe( - HttpApiGroup.add( - HttpApiEndpoint.get("csv", "/users/csv").pipe( - HttpApiEndpoint.setSuccess( - Schema.String.pipe( - HttpApiSchema.withEncoding({ - kind: "Text", - contentType: "text/csv" - }) - ) - ) +class UsersApi extends HttpApiGroup.make("users").add( + HttpApiEndpoint.get("csv", "/users/csv").addSuccess( + Schema.String.pipe( + HttpApiSchema.withEncoding({ + kind: "Text", + contentType: "text/csv" + }) ) ) ) {} @@ -306,7 +250,7 @@ import { HttpApiEndpoint, HttpApiGroup } from "@effect/platform" -import { DateTime, Effect, Schema } from "effect" +import { DateTime, Effect, Layer, Schema } from "effect" // here is our api definition class User extends Schema.Class("User")({ @@ -315,31 +259,28 @@ class User extends Schema.Class("User")({ createdAt: Schema.DateTimeUtc }) {} -class UsersApi extends HttpApiGroup.make("users").pipe( - HttpApiGroup.add( - HttpApiEndpoint.get("findById", "/users/:id").pipe( - HttpApiEndpoint.setSuccess(User), - HttpApiEndpoint.setPath( - Schema.Struct({ - id: Schema.NumberFromString - }) - ) +class UsersApi extends HttpApiGroup.make("users").add( + HttpApiEndpoint.get("findById", "/users/:id") + .addSuccess(User) + .setPath( + Schema.Struct({ + id: Schema.NumberFromString + }) ) - ) ) {} -class MyApi extends HttpApi.empty.pipe(HttpApi.addGroup(UsersApi)) {} +class MyApi extends HttpApi.empty.add(UsersApi) {} // -------------------------------------------- // Implementation // -------------------------------------------- // the `HttpApiBuilder.group` api returns a `Layer` -const UsersApiLive: Layer.Layer> = +const UsersApiLive: Layer.Layer> = HttpApiBuilder.group(MyApi, "users", (handlers) => - handlers.pipe( + handlers // the parameters & payload are passed to the handler function. - HttpApiBuilder.handle("findById", ({ path: { id } }) => + .handle("findById", ({ path: { id } }) => Effect.succeed( new User({ id, @@ -348,7 +289,6 @@ const UsersApiLive: Layer.Layer> = }) ) ) - ) ) ``` @@ -367,17 +307,15 @@ class UsersRepository extends Context.Tag("UsersRepository")< // the dependencies will show up in the resulting `Layer` const UsersApiLive: Layer.Layer< - HttpApiGroup.HttpApiGroup.Service<"users">, + HttpApiGroup.Group<"users">, never, UsersRepository > = HttpApiBuilder.group(MyApi, "users", (handlers) => // we can return an Effect that creates our handlers Effect.gen(function* () { const repository = yield* UsersRepository - return handlers.pipe( - HttpApiBuilder.handle("findById", ({ path: { id } }) => - repository.findById(id) - ) + return handlers.handle("findById", ({ path: { id } }) => + repository.findById(id) ) }) ) @@ -391,9 +329,9 @@ This is done using the `HttpApiBuilder.api` api, and then using `Layer.provide` to add all the group implementations. ```ts -const MyApiLive: Layer.Layer = HttpApiBuilder.api( - MyApi -).pipe(Layer.provide(UsersApiLive)) +const MyApiLive: Layer.Layer = HttpApiBuilder.api(MyApi).pipe( + Layer.provide(UsersApiLive) +) ``` ### Serving the API @@ -425,71 +363,241 @@ const HttpLive = HttpApiBuilder.serve(HttpMiddleware.logger).pipe( Layer.launch(HttpLive).pipe(NodeRuntime.runMain) ``` -## Implementing `HttpApiSecurity` +### Serving Swagger documentation -If you are using `HttpApiSecurity` in your API, you can use the security -definition to implement a middleware that will protect your endpoints. +You can add Swagger documentation to your API using the `HttpApiSwagger` module. -The `HttpApiBuilder.middlewareSecurity` api will assist you in creating this -middleware. +You just need to provide the `HttpApiSwagger.layer` to your server +implementation: -Here is an example: +```ts +import { HttpApiSwagger } from "@effect/platform" + +const HttpLive = HttpApiBuilder.serve(HttpMiddleware.logger).pipe( + // add the swagger documentation layer + Layer.provide( + HttpApiSwagger.layer({ + // "/docs" is the default path for the swagger documentation + path: "/docs" + }) + ), + Layer.provide(HttpApiBuilder.middlewareCors()), + Layer.provide(MyApiLive), + Layer.provide(NodeHttpServer.layer(createServer, { port: 3000 })) +) +``` + +## Adding middleware + +### Defining middleware + +The `HttpApiMiddleware` module provides a way to add middleware to your API. + +You can create a `HttpApiMiddleware.Tag` that represents your middleware, which +allows you to set: + +- `failure` - a Schema for any errors that the middleware can return +- `provides` - a `Context.Tag` that the middleware will provide +- `security` - `HttpApiSecurity` definitions that the middleware will + implement +- `optional` - a boolean that indicates that if the middleware fails with an + expected error, the request should continue. When using optional middleware, + `provides` & `failure` options will not affect the handlers or final error type. + +Here is an example of defining a simple logger middleware: ```ts -// our cookie security definition -const security = HttpApiSecurity.apiKey({ - in: "cookie", - key: "token" -}) +import { + HttpApiEndpoint, + HttpApiGroup, + HttpApiMiddleware +} from "@effect/platform" +import { Schema } from "effect" -// the user repository service -class UsersRepository extends Context.Tag("UsersRepository")< - UsersRepository, - { - readonly findByToken: (token: Redacted.Redacted) => Effect.Effect - } ->() {} +class LoggerError extends Schema.TaggedError()( + "LoggerError", + {} +) {} + +// first extend the HttpApiMiddleware.Tag class +class Logger extends HttpApiMiddleware.Tag()("Http/Logger", { + // optionally define any errors that the middleware can return + failure: LoggerError +}) {} + +// apply the middleware to an `HttpApiGroup` +class UsersApi extends HttpApiGroup.make("users") + .add( + HttpApiEndpoint.get("findById", "/:id") + // apply the middleware to a single endpoint + .middleware(Logger) + ) + // or apply the middleware to the group + .middleware(Logger) {} +``` + +### Defining security middleware + +The `HttpApiSecurity` module provides a way to add security annotations to your +API. + +It offers the following authorization types: + +- `HttpApiSecurity.apiKey` - API key authorization through headers, query + parameters, or cookies. +- `HttpApiSecurity.basicAuth` - HTTP Basic authentication. +- `HttpApiSecurity.bearerAuth` - Bearer token authentication. + +You can then use these security annotations in combination with `HttpApiMiddleware` +to define middleware that will protect your endpoints. + +```ts +import { + HttpApiGroup, + HttpApiEndpoint, + HttpApiMiddleware, + HttpApiSchema, + HttpApiSecurity +} from "@effect/platform" +import { Context, Schema } from "effect" + +class User extends Schema.Class("User")({ id: Schema.Number }) {} + +class Unauthorized extends Schema.TaggedError()( + "Unauthorized", + {}, + HttpApiSchema.annotations({ status: 401 }) +) {} -// the security middleware will supply the current user to the handlers class CurrentUser extends Context.Tag("CurrentUser")() {} -// implement the middleware -const makeSecurityMiddleware: Effect.Effect< - HttpApiBuilder.SecurityMiddleware, - never, - UsersRepository -> = Effect.gen(function* () { - const repository = yield* UsersRepository - return HttpApiBuilder.middlewareSecurity( - // the security definition - security, - // the Context.Tag this middleware will provide - CurrentUser, - // the function to get the user from the token - (token) => repository.findByToken(token) +// first extend the HttpApiMiddleware.Tag class +class Authorization extends HttpApiMiddleware.Tag()( + "Authorization", + { + // add your error schema + failure: Unauthorized, + // add the Context.Tag that the middleware will provide + provides: CurrentUser, + // add the security definitions + security: { + // the object key is a custom name for the security definition + myBearer: HttpApiSecurity.bearer + // You can add more security definitions here. + // They will attempt to be resolved in the order they are defined + } + } +) {} + +// apply the middleware to an `HttpApiGroup` +class UsersApi extends HttpApiGroup.make("users") + .add( + HttpApiEndpoint.get("findById", "/:id") + // apply the middleware to a single endpoint + .middleware(Authorization) ) -}) + // or apply the middleware to the group + .middleware(Authorization) {} +``` -// use the middleware -const UsersApiLive = HttpApiBuilder.group(MyApi, "users", (handlers) => - Effect.gen(function* () { - // construct the security middleware - const securityMiddleware = yield* makeSecurityMiddleware +### Implementing `HttpApiMiddleware` - return handlers.pipe( - HttpApiBuilder.handle("findById", ({ path: { id } }) => - Effect.succeed( - new User({ id, name: "John Doe", createdAt: DateTime.unsafeNow() }) - ) - ), - // apply the middleware to the findById endpoint - securityMiddleware - // any endpoint after this will not be protected +Once your `HttpApiMiddleware` is defined, you can use the +`HttpApiMiddleware.Tag` definition to implement your middleware. + +By using the `Layer` apis, you can create a Layer that implements your +middleware. + +Here is an example: + +```ts +import { HttpApiMiddleware, HttpServerRequest } from "@effect/platform" +import { Effect, Layer } from "effect" + +class Logger extends HttpApiMiddleware.Tag()("Http/Logger") {} + +const LoggerLive = Layer.effect( + Logger, + Effect.gen(function* () { + yield* Effect.log("creating Logger middleware") + + // standard middleware is just an Effect, that can access the `HttpRouter` + // context. + return Logger.of( + Effect.gen(function* () { + const request = yield* HttpServerRequest.HttpServerRequest + yield* Effect.log(`Request: ${request.method} ${request.url}`) + }) ) }) ) ``` +When the `Layer` is created, you can then provide it to your group layers: + +```ts +const UsersApiLive = HttpApiBuilder.group(...).pipe( + Layer.provide(LoggerLive) +) +``` + +### Implementing `HttpApiSecurity` middleware + +If you are using `HttpApiSecurity` in your middleware, implementing the `Layer` +looks a bit different. + +Here is an example of implementing a `HttpApiSecurity.bearer` middleware: + +```ts +import { + HttpApiMiddleware, + HttpApiSchema, + HttpApiSecurity +} from "@effect/platform" +import { Context, Effect, Layer, Redacted, Schema } from "effect" + +class User extends Schema.Class("User")({ id: Schema.Number }) {} + +class Unauthorized extends Schema.TaggedError()( + "Unauthorized", + {}, + HttpApiSchema.annotations({ status: 401 }) +) {} + +class CurrentUser extends Context.Tag("CurrentUser")() {} + +class Authorization extends HttpApiMiddleware.Tag()( + "Authorization", + { + failure: Unauthorized, + provides: CurrentUser, + security: { myBearer: HttpApiSecurity.bearer } + } +) {} + +const AuthorizationLive = Layer.effect( + Authorization, + Effect.gen(function* () { + yield* Effect.log("creating Authorization middleware") + + // return the security handlers + return Authorization.of({ + myBearer: (bearerToken) => + Effect.gen(function* () { + yield* Effect.log( + "checking bearer token", + Redacted.value(bearerToken) + ) + // return the `User` that will be provided as the `CurrentUser` + return new User({ id: 1 }) + }) + }) + }) +) +``` + +### Setting `HttpApiSecurity` cookies + If you need to set the security cookie from within a handler, you can use the `HttpApiBuilder.securitySetCookie` api. @@ -502,42 +610,13 @@ const security = HttpApiSecurity.apiKey({ }) const UsersApiLive = HttpApiBuilder.group(MyApi, "users", (handlers) => - handlers.pipe( - HttpApiBuilder.handle("login", () => - // set the security cookie - HttpApiBuilder.securitySetCookie( - security, - Redacted.make("keep me secret") - ) - ) + handlers.handle("login", () => + // set the security cookie + HttpApiBuilder.securitySetCookie(security, Redacted.make("keep me secret")) ) ) ``` -### Serving Swagger documentation - -You can add Swagger documentation to your API using the `HttpApiSwagger` module. - -You just need to provide the `HttpApiSwagger.layer` to your server -implementation: - -```ts -import { HttpApiSwagger } from "@effect/platform" - -const HttpLive = HttpApiBuilder.serve(HttpMiddleware.logger).pipe( - // add the swagger documentation layer - Layer.provide( - HttpApiSwagger.layer({ - // "/docs" is the default path for the swagger documentation - path: "/docs" - }) - ), - Layer.provide(HttpApiBuilder.middlewareCors()), - Layer.provide(MyApiLive), - Layer.provide(NodeHttpServer.layer(createServer, { port: 3000 })) -) -``` - ## Deriving a client Once you have defined your API, you can derive a client that can interact with diff --git a/packages/platform/src/HttpApi.ts b/packages/platform/src/HttpApi.ts index 2a941edf7f..3be80544d9 100644 --- a/packages/platform/src/HttpApi.ts +++ b/packages/platform/src/HttpApi.ts @@ -1,21 +1,21 @@ /** * @since 1.0.0 */ -import * as Chunk from "effect/Chunk" import * as Context from "effect/Context" -import { dual } from "effect/Function" +import * as HashMap from "effect/HashMap" +import * as HashSet from "effect/HashSet" import * as Option from "effect/Option" -import type { Pipeable } from "effect/Pipeable" -import { pipeArguments } from "effect/Pipeable" +import { type Pipeable, pipeArguments } from "effect/Pipeable" import * as Predicate from "effect/Predicate" import type * as Schema from "effect/Schema" import * as AST from "effect/SchemaAST" -import * as HttpApiEndpoint from "./HttpApiEndpoint.js" +import type * as HttpApiEndpoint from "./HttpApiEndpoint.js" import { HttpApiDecodeError } from "./HttpApiError.js" -import * as HttpApiGroup from "./HttpApiGroup.js" +import type * as HttpApiGroup from "./HttpApiGroup.js" +import type * as HttpApiMiddleware from "./HttpApiMiddleware.js" import * as HttpApiSchema from "./HttpApiSchema.js" import type { HttpMethod } from "./HttpMethod.js" -import type * as HttpRouter from "./HttpRouter.js" +import type { PathInput } from "./HttpRouter.js" /** * @since 1.0.0 @@ -33,34 +33,78 @@ export type TypeId = typeof TypeId * @since 1.0.0 * @category guards */ -export const isHttpApi = (u: unknown): u is HttpApi => Predicate.hasProperty(u, TypeId) +export const isHttpApi = (u: unknown): u is HttpApi.Any => Predicate.hasProperty(u, TypeId) /** - * An `HttpApi` represents a collection of `HttpApiGroup`s. You can use an `HttpApi` to - * represent your entire domain. + * An `HttpApi` is a collection of `HttpApiEndpoint`s. You can use an `HttpApi` to + * represent a portion of your domain. + * + * The endpoints can be implemented later using the `HttpApiBuilder.make` api. * * @since 1.0.0 * @category models */ export interface HttpApi< out Groups extends HttpApiGroup.HttpApiGroup.Any = never, - in out Error = never, - out ErrorR = never + in out E = never, + out R = never > extends Pipeable { new(_: never): {} readonly [TypeId]: TypeId - readonly groups: Chunk.Chunk - readonly errorSchema: Schema.Schema + readonly groups: HashMap.HashMap readonly annotations: Context.Context + readonly errorSchema: Schema.Schema + readonly middlewares: HashSet.HashSet + + /** + * Add an endpoint to the `HttpApi`. + */ + add(group: A): HttpApi + /** + * Add an global error to the `HttpApi`. + */ + addError( + schema: Schema.Schema, + annotations?: { + readonly status?: number | undefined + } + ): HttpApi + /** + * Prefix all endpoints in the `HttpApi`. + */ + prefix(prefix: PathInput): HttpApi + /** + * Add a middleware to a `HttpApi`. It will be applied to all endpoints in the + * `HttpApi`. + */ + middleware( + middleware: Context.Tag + ): HttpApi< + Groups, + E | HttpApiMiddleware.HttpApiMiddleware.Error, + R | I | HttpApiMiddleware.HttpApiMiddleware.ErrorContext + > + /** + * Annotate the `HttpApi`. + */ + annotate(tag: Context.Tag, value: S): HttpApi + /** + * Annotate the `HttpApi` with a Context. + */ + annotateContext(context: Context.Context): HttpApi } /** * @since 1.0.0 * @category tags */ -export const HttpApi: Context.Tag = Context.GenericTag( - "@effect/platform/HttpApi" -) +export class Api extends Context.Tag("@effect/platform/HttpApi/Api")< + Api, + { + readonly api: HttpApi + readonly context: Context.Context + } +>() {} /** * @since 1.0.0 @@ -71,183 +115,122 @@ export declare namespace HttpApi { * @since 1.0.0 * @category models */ - export interface Service { - readonly _: unique symbol - } - - /** - * @since 1.0.0 - * @category models - */ - export interface Any extends Pipeable { - new(_: never): {} + export interface Any { readonly [TypeId]: TypeId - readonly groups: Chunk.Chunk - readonly errorSchema: Schema.Schema.All - readonly annotations: Context.Context } /** * @since 1.0.0 * @category models */ - export type Context = A extends HttpApi - ? _ApiErrorR | HttpApiGroup.HttpApiGroup.Context<_Groups> - : never + export type AnyWithProps = HttpApi } const Proto = { [TypeId]: TypeId, pipe() { return pipeArguments(this, arguments) + }, + add( + this: HttpApi.AnyWithProps, + group: HttpApiGroup.HttpApiGroup.AnyWithProps + ) { + return makeProto({ + groups: HashMap.set(this.groups, group.identifier, group), + errorSchema: this.errorSchema, + annotations: this.annotations, + middlewares: this.middlewares + }) + }, + addError( + this: HttpApi.AnyWithProps, + schema: Schema.Schema.Any, + annotations?: { readonly status?: number } + ) { + return makeProto({ + groups: this.groups, + errorSchema: HttpApiSchema.UnionUnify( + this.errorSchema, + schema.annotations(HttpApiSchema.annotations({ + status: annotations?.status ?? HttpApiSchema.getStatusError(schema) + })) + ), + annotations: this.annotations, + middlewares: this.middlewares + }) + }, + prefix(this: HttpApi.AnyWithProps, prefix: PathInput) { + return makeProto({ + groups: HashMap.map(this.groups, (group) => group.prefix(prefix)), + errorSchema: this.errorSchema, + annotations: this.annotations, + middlewares: this.middlewares + }) + }, + middleware(this: HttpApi.AnyWithProps, tag: HttpApiMiddleware.TagClassAny) { + return makeProto({ + groups: this.groups, + errorSchema: HttpApiSchema.UnionUnify( + this.errorSchema, + tag.failure.annotations(HttpApiSchema.annotations({ + status: HttpApiSchema.getStatusError(tag.failure) + }) as any) + ), + annotations: this.annotations, + middlewares: HashSet.add(this.middlewares, tag) + }) + }, + annotate(this: HttpApi.AnyWithProps, tag: Context.Tag, value: any) { + return makeProto({ + groups: this.groups, + errorSchema: this.errorSchema, + annotations: Context.add(this.annotations, tag, value), + middlewares: this.middlewares + }) + }, + annotateContext(this: HttpApi.AnyWithProps, context: Context.Context) { + return makeProto({ + groups: this.groups, + errorSchema: this.errorSchema, + annotations: Context.merge(this.annotations, context), + middlewares: this.middlewares + }) } } -const makeProto = (options: { - readonly groups: Chunk.Chunk - readonly errorSchema: Schema.Schema - readonly annotations: Context.Context -}): HttpApi => { +const makeProto = ( + options: { + readonly groups: HashMap.HashMap + readonly errorSchema: Schema.Schema + readonly annotations: Context.Context + readonly middlewares: HashSet.HashSet + } +): HttpApi => { function HttpApi() {} Object.setPrototypeOf(HttpApi, Proto) - return Object.assign(HttpApi, options) as any + HttpApi.groups = options.groups + HttpApi.errorSchema = options.errorSchema + HttpApi.annotations = options.annotations + HttpApi.middlewares = options.middlewares + return HttpApi as any } /** - * An empty `HttpApi`. You can use this to start building your `HttpApi`. + * An `HttpApi` is a collection of `HttpApiEndpoint`s. You can use an `HttpApi` to + * represent a portion of your domain. * - * You can add groups to this `HttpApi` using the `addGroup` function. + * The endpoints can be implemented later using the `HttpApiBuilder.make` api. * * @since 1.0.0 * @category constructors */ -export const empty: HttpApi = makeProto({ - groups: Chunk.empty(), - errorSchema: HttpApiDecodeError as any, - annotations: Context.empty() +export const empty: HttpApi = makeProto({ + groups: HashMap.empty(), + errorSchema: HttpApiDecodeError, + annotations: Context.empty(), + middlewares: HashSet.empty() }) -/** - * Add a `HttpApiGroup` to an `HttpApi`. - * - * @since 1.0.0 - * @category constructors - */ -export const addGroup: { - ( - group: Group - ): ( - self: HttpApi - ) => HttpApi - ( - path: HttpRouter.PathInput, - group: Group - ): ( - self: HttpApi - ) => HttpApi - ( - self: HttpApi, - group: Group - ): HttpApi - ( - self: HttpApi, - path: HttpRouter.PathInput, - group: Group - ): HttpApi -} = dual( - (args) => isHttpApi(args[0]), - ( - self: HttpApi.Any, - ...args: [group: HttpApiGroup.HttpApiGroup.Any] | [path: HttpRouter.PathInput, group: HttpApiGroup.HttpApiGroup.Any] - ): HttpApi.Any => { - const group = args.length === 1 ? args[0] : HttpApiGroup.prefix(args[1] as any, args[0]) - return makeProto({ - errorSchema: self.errorSchema as any, - annotations: self.annotations, - groups: Chunk.append(self.groups, group) - }) - } -) -/** - * Add an error schema to an `HttpApi`, which is shared by all endpoints in the - * `HttpApi`. - * - * Useful for adding error types from middleware or other shared error types. - * - * @since 1.0.0 - * @category errors - */ -export const addError: { - ( - schema: Schema.Schema, - annotations?: { - readonly status?: number | undefined - } - ): ( - self: HttpApi - ) => HttpApi - ( - self: HttpApi, - schema: Schema.Schema, - annotations?: { - readonly status?: number | undefined - } - ): HttpApi -} = dual( - (args) => isHttpApi(args[0]), - ( - self: HttpApi, - schema: Schema.Schema, - annotations?: { - readonly status?: number | undefined - } - ): HttpApi => - makeProto({ - groups: self.groups, - annotations: self.annotations, - errorSchema: HttpApiSchema.UnionUnify( - self.errorSchema, - schema.annotations(HttpApiSchema.annotations({ - status: annotations?.status ?? HttpApiSchema.getStatusError(schema) - })) - ) - }) -) - -/** - * @since 1.0.0 - * @category annotations - */ -export const annotateMerge: { - (context: Context.Context): (self: A) => A - (self: A, context: Context.Context): A -} = dual( - 2, - (self: A, context: Context.Context): A => - makeProto({ - groups: self.groups, - errorSchema: self.errorSchema as any, - annotations: Context.merge(self.annotations, context) - }) as A -) - -/** - * @since 1.0.0 - * @category annotations - */ -export const annotate: { - (tag: Context.Tag, value: S): (self: A) => A - (self: A, tag: Context.Tag, value: S): A -} = dual( - 3, - (self: A, tag: Context.Tag, value: S): A => - makeProto({ - groups: self.groups, - errorSchema: self.errorSchema as any, - annotations: Context.add(self.annotations, tag, value) - }) as A -) - /** * Extract metadata from an `HttpApi`, which can be used to generate documentation * or other tooling. @@ -257,46 +240,42 @@ export const annotate: { * @since 1.0.0 * @category reflection */ -export const reflect = ( - self: HttpApi, +export const reflect = ( + self: HttpApi, options: { readonly onGroup: (options: { - readonly group: HttpApiGroup.HttpApiGroup + readonly group: HttpApiGroup.HttpApiGroup.AnyWithProps readonly mergedAnnotations: Context.Context }) => void readonly onEndpoint: (options: { - readonly group: HttpApiGroup.HttpApiGroup + readonly group: HttpApiGroup.HttpApiGroup.AnyWithProps readonly endpoint: HttpApiEndpoint.HttpApiEndpoint readonly mergedAnnotations: Context.Context - readonly successAST: Option.Option - readonly successStatus: number - readonly successEncoding: HttpApiSchema.Encoding + readonly middleware: HashSet.HashSet + readonly successes: ReadonlyMap> readonly errors: ReadonlyMap> }) => void } ) => { - const apiErrors = extractErrors(self.errorSchema.ast, new Map()) - - const groups = self.groups as Iterable> - for (const group of groups) { - const groupErrors = extractErrors(group.errorSchema.ast, apiErrors) + const apiErrors = extractMembers(self.errorSchema.ast, new Map(), HttpApiSchema.getStatusErrorAST) + const groups = self.groups as Iterable<[string, HttpApiGroup.HttpApiGroup.AnyWithProps]> + for (const [, group] of groups) { + const groupErrors = extractMembers(group.errorSchema.ast, apiErrors, HttpApiSchema.getStatusErrorAST) const groupAnnotations = Context.merge(self.annotations, group.annotations) options.onGroup({ group, mergedAnnotations: groupAnnotations }) - const endpoints = group.endpoints as Iterable> - for (const endpoint of endpoints) { + const endpoints = group.endpoints as Iterable<[string, HttpApiEndpoint.HttpApiEndpoint]> + for (const [, endpoint] of endpoints) { + const errors = extractMembers(endpoint.errorSchema.ast, groupErrors, HttpApiSchema.getStatusErrorAST) options.onEndpoint({ group, endpoint, + middleware: HashSet.union(group.middlewares, endpoint.middlewares), mergedAnnotations: Context.merge(groupAnnotations, endpoint.annotations), - successAST: HttpApiEndpoint.schemaSuccess(endpoint).pipe( - Option.map((schema) => schema.ast) - ), - successStatus: HttpApiSchema.getStatusSuccess(endpoint.successSchema), - successEncoding: HttpApiSchema.getEncoding(endpoint.successSchema.ast), - errors: extractErrors(endpoint.errorSchema.ast, groupErrors) + successes: extractMembers(endpoint.successSchema.ast, new Map(), HttpApiSchema.getStatusSuccessAST), + errors }) } } @@ -304,20 +283,24 @@ export const reflect = > +const extractMembers = ( + topAst: AST.AST, + inherited: ReadonlyMap>, + getStatus: (ast: AST.AST) => number ): ReadonlyMap> => { - const topStatus = HttpApiSchema.getStatusErrorAST(ast) - const errors = new Map(inherited) + const members = new Map(inherited) function process(ast: AST.AST) { if (ast._tag === "NeverKeyword") { return } - const status = HttpApiSchema.getStatus(ast, topStatus) + ast = AST.annotations(ast, { + ...topAst.annotations, + ...ast.annotations + }) + const status = getStatus(ast) const emptyDecodeable = HttpApiSchema.getEmptyDecodeable(ast) - const current = errors.get(status) ?? Option.none() - errors.set( + const current = members.get(status) ?? Option.none() + members.set( status, current.pipe( Option.map((current) => @@ -331,12 +314,12 @@ const extractErrors = ( ) ) } - if (ast._tag === "Union") { - for (const type of ast.types) { + if (topAst._tag === "Union") { + for (const type of topAst.types) { process(type) } } else { - process(ast) + process(topAst) } - return errors + return members } diff --git a/packages/platform/src/HttpApiBuilder.ts b/packages/platform/src/HttpApiBuilder.ts index 79c45b0ac2..f8d6d798fd 100644 --- a/packages/platform/src/HttpApiBuilder.ts +++ b/packages/platform/src/HttpApiBuilder.ts @@ -8,24 +8,27 @@ import * as Encoding from "effect/Encoding" import * as FiberRef from "effect/FiberRef" import { identity } from "effect/Function" import { globalValue } from "effect/GlobalValue" +import * as HashMap from "effect/HashMap" +import * as HashSet from "effect/HashSet" import * as Layer from "effect/Layer" -import type { ManagedRuntime } from "effect/ManagedRuntime" +import * as ManagedRuntime from "effect/ManagedRuntime" import * as Option from "effect/Option" import * as ParseResult from "effect/ParseResult" import { type Pipeable, pipeArguments } from "effect/Pipeable" import type { ReadonlyRecord } from "effect/Record" import * as Redacted from "effect/Redacted" import * as Schema from "effect/Schema" -import * as AST from "effect/SchemaAST" +import type * as AST from "effect/SchemaAST" import type { Scope } from "effect/Scope" -import type { Covariant, Mutable, NoInfer } from "effect/Types" +import type { Covariant, NoInfer } from "effect/Types" import { unify } from "effect/Unify" import type { Cookie } from "./Cookies.js" import type { FileSystem } from "./FileSystem.js" import * as HttpApi from "./HttpApi.js" -import * as HttpApiEndpoint from "./HttpApiEndpoint.js" +import type * as HttpApiEndpoint from "./HttpApiEndpoint.js" import { HttpApiDecodeError } from "./HttpApiError.js" import type * as HttpApiGroup from "./HttpApiGroup.js" +import * as HttpApiMiddleware from "./HttpApiMiddleware.js" import * as HttpApiSchema from "./HttpApiSchema.js" import type * as HttpApiSecurity from "./HttpApiSecurity.js" import * as HttpApp from "./HttpApp.js" @@ -46,6 +49,24 @@ import type { Path } from "./Path.js" */ export class Router extends HttpRouter.Tag("@effect/platform/HttpApiBuilder/Router")() {} +/** + * Create a top-level `HttpApi` layer. + * + * @since 1.0.0 + * @category constructors + */ +export const api = ( + api: HttpApi.HttpApi +): Layer.Layer< + HttpApi.Api, + never, + HttpApiGroup.HttpApiGroup.ToService | R | HttpApiGroup.HttpApiGroup.ErrorContext +> => + Layer.effect( + HttpApi.Api, + Effect.map(Effect.context(), (context) => ({ api: api as any, context })) + ) + /** * Build an `HttpApp` from an `HttpApi` instance, and serve it using an * `HttpServer`. @@ -56,25 +77,18 @@ export class Router extends HttpRouter.Tag("@effect/platform/HttpApiBuilder/Rout * @since 1.0.0 * @category constructors */ -export const serve: { - (): Layer.Layer - ( - middleware: (httpApp: HttpApp.Default) => HttpApp.Default - ): Layer.Layer< - never, - never, - | HttpServer.HttpServer - | HttpRouter.HttpRouter.DefaultServices - | Exclude - | HttpApi.HttpApi.Service - > -} = (middleware?: HttpMiddleware.HttpMiddleware.Applied): Layer.Layer< +export const serve = ( + middleware?: (httpApp: HttpApp.Default) => HttpApp.Default +): Layer.Layer< never, never, - any + | HttpServer.HttpServer + | HttpRouter.HttpRouter.DefaultServices + | Exclude + | HttpApi.Api > => httpApp.pipe( - Effect.map(HttpServer.serve(middleware!)), + Effect.map((app) => HttpServer.serve(app as any, middleware!)), Layer.unwrapEffect, Layer.provide(Router.Live) ) @@ -88,17 +102,18 @@ export const serve: { export const httpApp: Effect.Effect< HttpApp.Default, never, - Router | HttpApi.HttpApi.Service + Router | HttpApi.Api > = Effect.gen(function*() { - const api = yield* HttpApi.HttpApi - const router = yield* Router.router + const { api, context } = yield* HttpApi.Api + const middleware = makeMiddlewareMap(api.middlewares, context) + const router = applyMiddleware(middleware, yield* Router.router) const apiMiddleware = yield* Effect.serviceOption(Middleware) const errorSchema = makeErrorSchema(api as any) const encodeError = Schema.encodeUnknown(errorSchema) return router.pipe( apiMiddleware._tag === "Some" ? apiMiddleware.value : identity, Effect.catchAll((error) => - Effect.matchEffect(encodeError(error), { + Effect.matchEffect(Effect.provide(encodeError(error), context), { onFailure: () => Effect.die(error), onSuccess: Effect.succeed }) @@ -112,59 +127,60 @@ export const httpApp: Effect.Effect< * @since 1.0.0 * @category constructors * @example - * import { HttpApi } from "@effect/platform" - * import { Etag, HttpApiBuilder, HttpMiddleware, HttpPlatform } from "@effect/platform" - * import { NodeContext } from "@effect/platform-node" - * import { Layer, ManagedRuntime } from "effect" + * import { HttpApi, HttpApiBuilder, HttpServer } from "@effect/platform" + * import { Layer } from "effect" + * + * class MyApi extends HttpApi.empty {} * - * const ApiLive = HttpApiBuilder.api(HttpApi.empty) + * const MyApiLive = HttpApiBuilder.api(MyApi) * - * const runtime = ManagedRuntime.make( + * const { dispose, handler } = HttpApiBuilder.toWebHandler( * Layer.mergeAll( - * ApiLive, - * HttpApiBuilder.Router.Live, - * HttpPlatform.layer, - * Etag.layerWeak - * ).pipe( - * Layer.provideMerge(NodeContext.layer) + * MyApiLive, + * HttpServer.layerContext * ) * ) - * - * const handler = HttpApiBuilder.toWebHandler(runtime, HttpMiddleware.logger) */ -export const toWebHandler = ( - runtime: ManagedRuntime, - middleware?: ( - httpApp: HttpApp.Default - ) => HttpApp.Default -): (request: Request) => Promise => { +export const toWebHandler = ( + layer: Layer.Layer, + options?: { + readonly middleware?: ( + httpApp: HttpApp.Default + ) => HttpApp.Default< + never, + HttpApi.Api | Router | HttpRouter.HttpRouter.DefaultServices + > + readonly memoMap?: Layer.MemoMap + } +): { + readonly handler: (request: Request) => Promise + readonly dispose: () => Promise +} => { + const runtime = ManagedRuntime.make( + Layer.merge(layer, Router.Live), + options?.memoMap + ) + let handlerCached: ((request: Request) => Promise) | undefined const handlerPromise = httpApp.pipe( Effect.bindTo("httpApp"), Effect.bind("runtime", () => runtime.runtimeEffect), Effect.map(({ httpApp, runtime }) => - HttpApp.toWebHandlerRuntime(runtime)(middleware ? middleware(httpApp as any) : httpApp) + HttpApp.toWebHandlerRuntime(runtime)(options?.middleware ? options.middleware(httpApp as any) as any : httpApp) ), + Effect.tap((handler) => { + handlerCached = handler + }), runtime.runPromise ) - return (request) => handlerPromise.then((handler) => handler(request)) + function handler(request: Request): Promise { + if (handlerCached !== undefined) { + return handlerCached(request) + } + return handlerPromise.then((handler) => handler(request)) + } + return { handler, dispose: runtime.dispose } as const } -/** - * Build a root level `Layer` from an `HttpApi` instance. - * - * The `Layer` will provide the `HttpApi` service, and will require the - * implementation for all the `HttpApiGroup`'s contained in the `HttpApi`. - * - * The resulting `Layer` can be provided to the `HttpApiBuilder.serve` layer. - * - * @since 1.0.0 - * @category constructors - */ -export const api = ( - self: HttpApi.HttpApi -): Layer.Layer | ErrorR> => - Layer.succeed(HttpApi.HttpApi, self) as any - /** * @since 1.0.0 * @category handlers @@ -178,21 +194,49 @@ export const HandlersTypeId: unique symbol = Symbol.for("@effect/platform/HttpAp export type HandlersTypeId = typeof HandlersTypeId /** - * Represents a handled, or partially handled, `HttpApiGroup`. + * Represents a handled `HttpApi`. * * @since 1.0.0 * @category handlers */ export interface Handlers< E, + Provides, R, - Endpoints extends HttpApiEndpoint.HttpApiEndpoint.All = never + Endpoints extends HttpApiEndpoint.HttpApiEndpoint.Any = never > extends Pipeable { readonly [HandlersTypeId]: { _Endpoints: Covariant } - readonly group: HttpApiGroup.HttpApiGroup + readonly group: HttpApiGroup.HttpApiGroup.AnyWithProps readonly handlers: Chunk.Chunk> + + /** + * Add the implementation for an `HttpApiEndpoint` to a `Handlers` group. + */ + handle, R1>( + name: Name, + handler: HttpApiEndpoint.HttpApiEndpoint.HandlerWithName + ): Handlers< + E, + Provides, + R | Exclude, Provides>, + HttpApiEndpoint.HttpApiEndpoint.ExcludeName + > + + /** + * Add the implementation for an `HttpApiEndpoint` to a `Handlers` group. + * This version of the api allows you to return the full response object. + */ + handleRaw, R1>( + name: Name, + handler: HttpApiEndpoint.HttpApiEndpoint.HandlerResponseWithName + ): Handlers< + E, + Provides, + R | Exclude, Provides>, + HttpApiEndpoint.HttpApiEndpoint.ExcludeName + > } /** @@ -200,6 +244,14 @@ export interface Handlers< * @category handlers */ export declare namespace Handlers { + /** + * @since 1.0.0 + * @category handlers + */ + export interface Any { + readonly [HandlersTypeId]: any + } + /** * @since 1.0.0 * @category handlers @@ -211,14 +263,90 @@ export declare namespace Handlers { * @category handlers */ export type Item = { - readonly _tag: "Handler" readonly endpoint: HttpApiEndpoint.HttpApiEndpoint.Any readonly handler: HttpApiEndpoint.HttpApiEndpoint.Handler readonly withFullResponse: boolean - } | { - readonly _tag: "Middleware" - readonly middleware: Middleware } + + /** + * @since 1.0.0 + * @category handlers + */ + export type FromGroup< + ApiError, + ApiR, + Group extends HttpApiGroup.HttpApiGroup.Any + > = Handlers< + | ApiError + | HttpApiGroup.HttpApiGroup.Error, + | HttpApiMiddleware.HttpApiMiddleware.ExtractProvides + | HttpApiGroup.HttpApiGroup.Provides, + never, + HttpApiGroup.HttpApiGroup.Endpoints + > + + /** + * @since 1.0.0 + * @category handlers + */ + export type ValidateReturn = A extends ( + | Handlers< + infer _E, + infer _Provides, + infer _R, + infer _Endpoints + > + | Effect.Effect< + Handlers< + infer _E, + infer _Provides, + infer _R, + infer _Endpoints + >, + infer _EX, + infer _RX + > + ) ? [_Endpoints] extends [never] ? A + : `Endpoint not handled: ${HttpApiEndpoint.HttpApiEndpoint.Name<_Endpoints>}` : + `Must return the implemented handlers` + + /** + * @since 1.0.0 + * @category handlers + */ + export type Error = A extends Effect.Effect< + Handlers< + infer _E, + infer _Provides, + infer _R, + infer _Endpoints + >, + infer _EX, + infer _RX + > ? _EX : + never + + /** + * @since 1.0.0 + * @category handlers + */ + export type Context = A extends Handlers< + infer _E, + infer _Provides, + infer _R, + infer _Endpoints + > ? _R : + A extends Effect.Effect< + Handlers< + infer _E, + infer _Provides, + infer _R, + infer _Endpoints + >, + infer _EX, + infer _RX + > ? _R | _RX : + never } const HandlersProto = { @@ -227,15 +355,45 @@ const HandlersProto = { }, pipe() { return pipeArguments(this, arguments) + }, + handle( + this: Handlers, + name: string, + handler: HttpApiEndpoint.HttpApiEndpoint.Handler + ) { + const endpoint = HashMap.unsafeGet(this.group.endpoints, name) + return makeHandlers({ + group: this.group, + handlers: Chunk.append(this.handlers, { + endpoint, + handler, + withFullResponse: false + }) as any + }) + }, + handleRaw( + this: Handlers, + name: string, + handler: HttpApiEndpoint.HttpApiEndpoint.Handler + ) { + const endpoint = HashMap.unsafeGet(this.group.endpoints, name) + return makeHandlers({ + group: this.group, + handlers: Chunk.append(this.handlers, { + endpoint, + handler, + withFullResponse: true + }) as any + }) } } -const makeHandlers = ( +const makeHandlers = ( options: { - readonly group: HttpApiGroup.HttpApiGroup + readonly group: HttpApiGroup.HttpApiGroup.Any readonly handlers: Chunk.Chunk> } -): Handlers => { +): Handlers => { const self = Object.create(HandlersProto) self.group = options.group self.handlers = options.handlers @@ -243,12 +401,12 @@ const makeHandlers = , + Return >( - api: HttpApi.HttpApi, + api: HttpApi.HttpApi, groupName: Name, build: ( - handlers: Handlers> - ) => - | Handlers | HttpApiGroup.HttpApiGroup.ErrorWithName, RH> - | Effect.Effect | HttpApiGroup.HttpApiGroup.ErrorWithName, RH>, EX, RX> + handlers: Handlers.FromGroup> + ) => Handlers.ValidateReturn ): Layer.Layer< - HttpApiGroup.HttpApiGroup.Service, - EX, - RX | RH | HttpApiGroup.HttpApiGroup.ContextWithName | ApiErrorR + HttpApiGroup.Group, + Handlers.Error, + | Handlers.Context + | HttpApiGroup.HttpApiGroup.ContextWithName > => Router.use((router) => Effect.gen(function*() { const context = yield* Effect.context() - const group = Chunk.findFirst(api.groups, (group) => group.identifier === groupName) - if (group._tag === "None") { - throw new Error(`Group "${groupName}" not found in API`) - } - const result = build(makeHandlers({ group: group.value as any, handlers: Chunk.empty() })) - const handlers = Effect.isEffect(result) ? (yield* result) : result + const group = HashMap.unsafeGet(api.groups, groupName) + const result = build(makeHandlers({ group, handlers: Chunk.empty() })) + const handlers: Handlers = Effect.isEffect(result) + ? (yield* result as Effect.Effect) + : result + const groupMiddleware = makeMiddlewareMap((group as any).middlewares, context) const routes: Array> = [] for (const item of handlers.handlers) { - if (item._tag === "Middleware") { - for (const route of routes) { - ;(route as Mutable>).handler = item.middleware(route.handler as any) - } - } else { - routes.push(handlerToRoute( - item.endpoint, - function(request) { - return Effect.mapInputContext( - item.handler(request), - (input) => Context.merge(context, input) - ) - }, - item.withFullResponse - )) - } + const middleware = makeMiddlewareMap((item as any).endpoint.middlewares, context, groupMiddleware) + routes.push(handlerToRoute( + item.endpoint, + middleware, + function(request) { + return Effect.mapInputContext( + item.handler(request), + (input) => Context.merge(context, input) + ) + }, + item.withFullResponse + )) } yield* router.concat(HttpRouter.fromIterable(routes)) }) ) as any -/** - * Add the implementation for an `HttpApiEndpoint` to a `Handlers` group. - * - * @since 1.0.0 - * @category handlers - */ -export const handle: { - ( - name: Name, - handler: HttpApiEndpoint.HttpApiEndpoint.HandlerWithName - ): (self: Handlers) => Handlers< - EG | Exclude> | HttpApiDecodeError, - RG | HttpApiEndpoint.HttpApiEndpoint.ExcludeProvided, - HttpApiEndpoint.HttpApiEndpoint.ExcludeName - > - ( - name: Name, - handler: HttpApiEndpoint.HttpApiEndpoint.HandlerResponseWithName, - options: { - readonly withFullResponse: true +// internal + +const requestPayload = ( + request: HttpServerRequest.HttpServerRequest, + urlParams: ReadonlyRecord>, + isMultipart: boolean +): Effect.Effect< + unknown, + never, + | FileSystem + | Path + | Scope +> => + HttpMethod.hasBody(request.method) + ? isMultipart + ? Effect.orDie(request.multipart) + : Effect.orDie(request.json) + : Effect.succeed(urlParams) + +type MiddlewareMap = Map +}> + +const makeMiddlewareMap = ( + middleware: HashSet.HashSet, + context: Context.Context, + initial?: MiddlewareMap +): MiddlewareMap => { + const map = new Map + }>(initial) + HashSet.forEach(middleware, (tag) => { + map.set(tag.key, { + tag, + effect: Context.unsafeGet(context, tag as any) + }) + }) + return map +} + +const handlerToRoute = ( + endpoint_: HttpApiEndpoint.HttpApiEndpoint.Any, + middleware: MiddlewareMap, + handler: HttpApiEndpoint.HttpApiEndpoint.Handler, + isFullResponse: boolean +): HttpRouter.Route => { + const endpoint = endpoint_ as HttpApiEndpoint.HttpApiEndpoint.AnyWithProps + const decodePath = Option.map(endpoint.pathSchema, Schema.decodeUnknown) + const isMultipart = endpoint.payloadSchema.pipe( + Option.map((schema) => HttpApiSchema.getMultipart(schema.ast)), + Option.getOrElse(() => false) + ) + const decodePayload = Option.map(endpoint.payloadSchema, Schema.decodeUnknown) + const decodeHeaders = Option.map(endpoint.headersSchema, Schema.decodeUnknown) + const decodeUrlParams = Option.map(endpoint.urlParamsSchema, Schema.decodeUnknown) + const encodeSuccess = Schema.encode(makeSuccessSchema(endpoint.successSchema)) + return HttpRouter.makeRoute( + endpoint.method, + endpoint.path, + applyMiddleware( + middleware, + Effect.withFiberRuntime((fiber) => { + const context = fiber.getFiberRef(FiberRef.currentContext) + const request = Context.unsafeGet(context, HttpServerRequest.HttpServerRequest) + const routeContext = Context.unsafeGet(context, HttpRouter.RouteContext) + const urlParams = Context.unsafeGet(context, HttpServerRequest.ParsedSearchParams) + return ( + decodePath._tag === "Some" + ? decodePath.value(routeContext.params) + : Effect.succeed(routeContext.params) + ).pipe( + Effect.bindTo("pathParams"), + decodePayload._tag === "Some" + ? Effect.bind( + "payload", + (_) => + Effect.flatMap( + requestPayload(request, urlParams, isMultipart), + decodePayload.value + ) + ) as typeof identity + : identity, + decodeHeaders._tag === "Some" + ? Effect.bind("headers", (_) => decodeHeaders.value(request.headers)) as typeof identity + : identity, + decodeUrlParams._tag === "Some" + ? Effect.bind("urlParams", (_) => decodeUrlParams.value(urlParams)) as typeof identity + : identity, + Effect.flatMap((input) => { + const request: any = { path: input.pathParams } + if ("payload" in input) { + request.payload = input.payload + } + if ("headers" in input) { + request.headers = input.headers + } + if ("urlParams" in input) { + request.urlParams = input.urlParams + } + return handler(request) + }), + isFullResponse ? + identity as (_: any) => Effect.Effect : + Effect.flatMap(encodeSuccess), + Effect.catchIf(ParseResult.isParseError, HttpApiDecodeError.refailParseError) + ) + }) + ) + ) +} + +const applyMiddleware = >( + middleware: MiddlewareMap, + handler: A +) => { + for (const entry of middleware.values()) { + const effect = HttpApiMiddleware.SecurityTypeId in entry.tag ? makeSecurityMiddleware(entry as any) : entry.effect + if (entry.tag.optional) { + const previous = handler + handler = Effect.matchEffect(effect, { + onFailure: () => previous, + onSuccess: entry.tag.provides !== undefined + ? (value) => Effect.provideService(previous, entry.tag.provides as any, value) + : (_) => previous + }) as any + } else { + handler = entry.tag.provides !== undefined + ? Effect.provideServiceEffect(handler, entry.tag.provides as any, effect) as any + : Effect.zipRight(effect, handler) as any } - ): (self: Handlers) => Handlers< - EG | Exclude> | HttpApiDecodeError, - RG | HttpApiEndpoint.HttpApiEndpoint.ExcludeProvided, - HttpApiEndpoint.HttpApiEndpoint.ExcludeName - > -} = ( - name: Name, - handler: HttpApiEndpoint.HttpApiEndpoint.HandlerWithName, - options?: { - readonly withFullResponse: true } -) => -( - self: Handlers -): Handlers< - EG | Exclude> | HttpApiDecodeError, - RG | HttpApiEndpoint.HttpApiEndpoint.ExcludeProvided, - HttpApiEndpoint.HttpApiEndpoint.ExcludeName -> => { - const o = Chunk.findFirst(self.group.endpoints, (endpoint) => endpoint.name === name) - if (o._tag === "None") { - throw new Error(`Endpoint "${name}" not found in group "${self.group.identifier}"`) + return handler +} + +const securityMiddlewareCache = globalValue>>( + "securityMiddlewareCache", + () => new WeakMap() +) + +const makeSecurityMiddleware = ( + entry: { + readonly tag: HttpApiMiddleware.TagClassSecurityAny + readonly effect: Record Effect.Effect> } - const endpoint = o.value - return makeHandlers({ - group: self.group, - handlers: Chunk.append(self.handlers, { - _tag: "Handler", - endpoint, - handler, - withFullResponse: options?.withFullResponse === true - }) as any +): Effect.Effect => { + if (securityMiddlewareCache.has(entry.tag)) { + return securityMiddlewareCache.get(entry.tag)! + } + + let effect: Effect.Effect | undefined + for (const [key, security] of Object.entries(entry.tag.security)) { + const decode = securityDecode(security) + const handler = entry.effect[key] + const middleware = Effect.flatMap(decode, handler) + effect = effect === undefined ? middleware : Effect.catchAll(effect, () => middleware) + } + if (effect === undefined) { + effect = Effect.void + } + securityMiddlewareCache.set(entry.tag, effect) + return effect +} + +const responseSchema = Schema.declare(HttpServerResponse.isServerResponse) + +const makeSuccessSchema = ( + schema: Schema.Schema.Any +): Schema.Schema => { + const schemas = new Set() + HttpApiSchema.deunionize(schemas, schema) + return Schema.Union(...Array.from(schemas, toResponseSuccess)) as any +} + +const makeErrorSchema = ( + api: HttpApi.HttpApi.AnyWithProps +): Schema.Schema => { + const schemas = new Set() + HttpApiSchema.deunionize(schemas, api.errorSchema) + HashMap.forEach(api.groups, (group) => { + HashMap.forEach(group.endpoints, (endpoint) => { + HttpApiSchema.deunionize(schemas, endpoint.errorSchema) + }) + HttpApiSchema.deunionize(schemas, group.errorSchema) }) + return Schema.Union(...Array.from(schemas, toResponseError)) as any } -/** - * Add `HttpMiddleware` to a `Handlers` group. - * - * Any errors are required to have a corresponding schema in the API. - * You can add middleware errors to an `HttpApiGroup` using the `HttpApiGroup.addError` - * api. - * - * @since 1.0.0 - * @category middleware - */ -export const middleware = - (middleware: Handlers.Middleware) => - ( - self: Handlers - ): Handlers, Endpoints> => - makeHandlers, Endpoints>({ - ...self as any, - handlers: Chunk.append(self.handlers, { - _tag: "Middleware", - middleware - }) +const decodeForbidden = (_: A, __: AST.ParseOptions, ast: AST.Transformation) => + ParseResult.fail(new ParseResult.Forbidden(ast, _, "Encode only schema")) + +const toResponseSchema = (getStatus: (ast: AST.AST) => number) => { + const cache = new WeakMap() + const schemaToResponse = ( + data: any, + _: AST.ParseOptions, + ast: AST.Transformation + ): Effect.Effect => { + const isEmpty = HttpApiSchema.isVoid(ast.to) + const status = getStatus(ast.to) + if (isEmpty) { + return HttpServerResponse.empty({ status }) + } + const encoding = HttpApiSchema.getEncoding(ast.to) + switch (encoding.kind) { + case "Json": { + return Effect.mapError( + HttpServerResponse.json(data, { + status, + contentType: encoding.contentType + }), + (error) => new ParseResult.Type(ast, error, "Could not encode to JSON") + ) + } + case "Text": { + return ParseResult.succeed(HttpServerResponse.text(data as any, { + status, + contentType: encoding.contentType + })) + } + case "Uint8Array": { + return ParseResult.succeed(HttpServerResponse.uint8Array(data as any, { + status, + contentType: encoding.contentType + })) + } + case "UrlParams": { + return ParseResult.succeed(HttpServerResponse.urlParams(data as any, { + status, + contentType: encoding.contentType + })) + } + } + } + return (schema: Schema.Schema): Schema.Schema => { + if (cache.has(schema.ast)) { + return cache.get(schema.ast)! as any + } + const transform = Schema.transformOrFail(responseSchema, schema, { + decode: decodeForbidden, + encode: schemaToResponse }) + cache.set(transform.ast, transform) + return transform + } +} + +const toResponseSuccess = toResponseSchema(HttpApiSchema.getStatusSuccessAST) +const toResponseError = toResponseSchema(HttpApiSchema.getStatusErrorAST) + +// ---------------------------------------------------------------------------- +// Global middleware +// ---------------------------------------------------------------------------- /** * @since 1.0.0 @@ -396,17 +723,11 @@ export class Middleware extends Context.Tag("@effect/platform/HttpApiBuilder/Mid /** * @since 1.0.0 - * @category middleware + * @category global */ -export declare namespace ApiMiddleware { - /** - * @since 1.0.0 - * @category middleware - */ - export type Fn = ( - httpApp: HttpApp.Default - ) => HttpApp.Default -} +export type MiddlewareFn = ( + httpApp: HttpApp.Default +) => HttpApp.Default const middlewareAdd = (middleware: HttpMiddleware.HttpMiddleware): Effect.Effect => Effect.map( @@ -435,42 +756,42 @@ const middlewareAddNoContext = ( * @since 1.0.0 * @category middleware */ -export const middlewareLayer: { +export const middleware: { ( - middleware: ApiMiddleware.Fn | Effect.Effect, EX, RX>, + middleware: MiddlewareFn | Effect.Effect, EX, RX>, options?: { readonly withContext?: false | undefined } ): Layer.Layer ( - middleware: ApiMiddleware.Fn | Effect.Effect, EX, RX>, + middleware: MiddlewareFn | Effect.Effect, EX, RX>, options: { readonly withContext: true } ): Layer.Layer | RX> ( api: HttpApi.HttpApi, - middleware: ApiMiddleware.Fn> | Effect.Effect>, EX, RX>, + middleware: MiddlewareFn> | Effect.Effect>, EX, RX>, options?: { readonly withContext?: false | undefined } ): Layer.Layer ( api: HttpApi.HttpApi, - middleware: ApiMiddleware.Fn, R> | Effect.Effect, R>, EX, RX>, + middleware: MiddlewareFn, R> | Effect.Effect, R>, EX, RX>, options: { readonly withContext: true } ): Layer.Layer | RX> } = ( ...args: [ - middleware: ApiMiddleware.Fn | Effect.Effect, any, any>, + middleware: MiddlewareFn | Effect.Effect, any, any>, options?: { readonly withContext?: boolean | undefined } | undefined ] | [ api: HttpApi.HttpApi.Any, - middleware: ApiMiddleware.Fn | Effect.Effect, any, any>, + middleware: MiddlewareFn | Effect.Effect, any, any>, options?: { readonly withContext?: boolean | undefined } | undefined @@ -492,42 +813,42 @@ export const middlewareLayer: { * @since 1.0.0 * @category middleware */ -export const middlewareLayerScoped: { +export const middlewareScoped: { ( - middleware: Effect.Effect, EX, RX>, + middleware: Effect.Effect, EX, RX>, options?: { readonly withContext?: false | undefined } ): Layer.Layer> ( - middleware: Effect.Effect, EX, RX>, + middleware: Effect.Effect, EX, RX>, options: { readonly withContext: true } ): Layer.Layer | Exclude> ( api: HttpApi.HttpApi, - middleware: Effect.Effect>, EX, RX>, + middleware: Effect.Effect>, EX, RX>, options?: { readonly withContext?: false | undefined } ): Layer.Layer> ( api: HttpApi.HttpApi, - middleware: Effect.Effect, R>, EX, RX>, + middleware: Effect.Effect, R>, EX, RX>, options: { readonly withContext: true } ): Layer.Layer | Exclude> } = ( ...args: [ - middleware: ApiMiddleware.Fn | Effect.Effect, any, any>, + middleware: MiddlewareFn | Effect.Effect, any, any>, options?: { readonly withContext?: boolean | undefined } | undefined ] | [ api: HttpApi.HttpApi.Any, - middleware: ApiMiddleware.Fn | Effect.Effect, any, any>, + middleware: MiddlewareFn | Effect.Effect, any, any>, options?: { readonly withContext?: boolean | undefined } | undefined @@ -555,7 +876,7 @@ export const middlewareCors = ( readonly maxAge?: number | undefined readonly credentials?: boolean | undefined } | undefined -): Layer.Layer => middlewareLayer(HttpMiddleware.cors(options)) +): Layer.Layer => middleware(HttpMiddleware.cors(options)) /** * A middleware that adds an openapi.json endpoint to the API. @@ -567,10 +888,10 @@ export const middlewareOpenApi = ( options?: { readonly path?: HttpRouter.PathInput | undefined } | undefined -): Layer.Layer => +): Layer.Layer => Router.use((router) => Effect.gen(function*() { - const api = yield* HttpApi.HttpApi + const { api } = yield* HttpApi.Api const spec = OpenApi.fromApi(api) const response = yield* HttpServerResponse.json(spec).pipe( Effect.orDie @@ -579,21 +900,11 @@ export const middlewareOpenApi = ( }) ) -/** - * @since 1.0.0 - * @category middleware - */ -export interface SecurityMiddleware { - ( - self: Handlers - ): Handlers | HttpApiEndpoint.HttpApiEndpoint.ExcludeProvided, Endpoints> -} - const bearerLen = `Bearer `.length /** * @since 1.0.0 - * @category middleware + * @category security */ export const securityDecode = ( self: Security @@ -656,9 +967,9 @@ export const securityDecode = * You can use this api before returning a response from an endpoint handler. * * ```ts - * ApiBuilder.handle( + * handlers.handle( * "authenticate", - * (_) => ApiBuilder.securitySetCookie(security, "secret123") + * (_) => HttpApiBuilder.securitySetCookie(security, "secret123") * ) * ``` * @@ -681,232 +992,3 @@ export const securitySetCookie = ( ) ) } - -/** - * Make a middleware from an `HttpApiSecurity` instance, that can be used when - * constructing a `Handlers` group. - * - * @since 1.0.0 - * @category middleware - * @example - * import { HttpApiBuilder, HttpApiSecurity } from "@effect/platform" - * import { Context, Effect, Redacted, Schema } from "effect" - * - * class User extends Schema.Class("User")({ - * id: Schema.Number - * }) {} - * - * class CurrentUser extends Context.Tag("CurrentUser")() {} - * - * class Accounts extends Context.Tag("Accounts") Effect.Effect - * }>() {} - * - * const securityMiddleware = Effect.gen(function*() { - * const accounts = yield* Accounts - * return HttpApiBuilder.middlewareSecurity( - * HttpApiSecurity.bearer, - * CurrentUser, - * (token) => accounts.findUserByAccessToken(Redacted.value(token)) - * ) - * }) - */ -export const middlewareSecurity = ( - self: Security, - tag: Context.Tag, - f: ( - credentials: HttpApiSecurity.HttpApiSecurity.Type - ) => Effect.Effect -): SecurityMiddleware => - middleware(Effect.provideServiceEffect( - tag, - Effect.flatMap(securityDecode(self), f) - )) as SecurityMiddleware - -/** - * Make a middleware from an `HttpApiSecurity` instance, that can be used when - * constructing a `Handlers` group. - * - * This version does not supply any context to the handlers. - * - * @since 1.0.0 - * @category middleware - */ -export const middlewareSecurityVoid = ( - self: Security, - f: ( - credentials: HttpApiSecurity.HttpApiSecurity.Type - ) => Effect.Effect -): SecurityMiddleware => - middleware((httpApp) => - securityDecode(self).pipe( - Effect.flatMap(f), - Effect.zipRight(httpApp) - ) - ) as SecurityMiddleware - -// internal - -const requestPayload = ( - request: HttpServerRequest.HttpServerRequest, - urlParams: ReadonlyRecord>, - isMultipart: boolean -): Effect.Effect< - unknown, - never, - | FileSystem - | Path - | Scope -> => - HttpMethod.hasBody(request.method) - ? isMultipart - ? Effect.orDie(request.multipart) - : Effect.orDie(request.json) - : Effect.succeed(urlParams) - -const handlerToRoute = ( - endpoint: HttpApiEndpoint.HttpApiEndpoint.Any, - handler: HttpApiEndpoint.HttpApiEndpoint.Handler, - isFullResponse: boolean -): HttpRouter.Route => { - const decodePath = Option.map(endpoint.pathSchema, Schema.decodeUnknown) - const isMultipart = endpoint.payloadSchema.pipe( - Option.map((schema) => HttpApiSchema.getMultipart(schema.ast)), - Option.getOrElse(() => false) - ) - const decodePayload = Option.map(endpoint.payloadSchema, Schema.decodeUnknown) - const decodeHeaders = Option.map(endpoint.headersSchema, Schema.decodeUnknown) - const encoding = HttpApiSchema.getEncoding(endpoint.successSchema.ast) - const successStatus = HttpApiSchema.getStatusSuccess(endpoint.successSchema) - const encodeSuccess = Option.map(HttpApiEndpoint.schemaSuccess(endpoint), (schema) => { - const encode = Schema.encodeUnknown(schema) - switch (encoding.kind) { - case "Json": { - return (body: unknown) => - Effect.orDie( - Effect.flatMap(encode(body), (json) => - HttpServerResponse.json(json, { - status: successStatus, - contentType: encoding.contentType - })) - ) - } - case "Text": { - return (body: unknown) => - Effect.map(Effect.orDie(encode(body)), (text) => - HttpServerResponse.text(text as any, { - status: successStatus, - contentType: encoding.contentType - })) - } - case "Uint8Array": { - return (body: unknown) => - Effect.map(Effect.orDie(encode(body)), (data) => - HttpServerResponse.uint8Array(data as any, { - status: successStatus, - contentType: encoding.contentType - })) - } - case "UrlParams": { - return (body: unknown) => - Effect.map(Effect.orDie(encode(body)), (params) => - HttpServerResponse.urlParams(params as any, { - status: successStatus, - contentType: encoding.contentType - })) - } - } - }) - return HttpRouter.makeRoute( - endpoint.method, - endpoint.path, - Effect.withFiberRuntime((fiber) => { - const context = fiber.getFiberRef(FiberRef.currentContext) - const request = Context.unsafeGet(context, HttpServerRequest.HttpServerRequest) - const routeContext = Context.unsafeGet(context, HttpRouter.RouteContext) - const urlParams = Context.unsafeGet(context, HttpServerRequest.ParsedSearchParams) - return (decodePath._tag === "Some" - ? Effect.catchAll(decodePath.value(routeContext.params), HttpApiDecodeError.refailParseError) - : Effect.succeed(routeContext.params)).pipe( - Effect.bindTo("pathParams"), - decodePayload._tag === "Some" - ? Effect.bind("payload", (_) => - requestPayload(request, urlParams, isMultipart).pipe( - Effect.orDie, - Effect.flatMap((raw) => Effect.catchAll(decodePayload.value(raw), HttpApiDecodeError.refailParseError)) - )) - : identity, - decodeHeaders._tag === "Some" - ? Effect.bind("headers", (_) => Effect.orDie(decodeHeaders.value(request.headers))) - : identity, - Effect.flatMap((input) => { - const request: any = { path: input.pathParams } - if ("payload" in input) { - request.payload = input.payload - } - if ("headers" in input) { - request.headers = input.headers - } - return handler(request) - }), - isFullResponse ? - identity as (_: any) => Effect.Effect : - encodeSuccess._tag === "Some" - ? Effect.flatMap(encodeSuccess.value) - : Effect.as(HttpServerResponse.empty({ status: successStatus })) - ) - }) - ) -} - -const astCache = globalValue( - "@effect/platform/HttpApiBuilder/astCache", - () => new WeakMap() -) - -const makeErrorSchema = ( - api: HttpApi.HttpApi, any, any> -): Schema.Schema => { - const schemas = new Set() - function processSchema(schema: Schema.Schema.Any): void { - if (astCache.has(schema.ast)) { - schemas.add(astCache.get(schema.ast)!) - return - } - const ast = schema.ast - if (ast._tag === "Union") { - for (const astType of ast.types) { - const errorSchema = Schema.make(astType).annotations({ - ...ast.annotations, - ...astType.annotations - }) - astCache.set(astType, errorSchema) - schemas.add(errorSchema) - } - } else { - astCache.set(ast, schema) - schemas.add(schema) - } - } - processSchema(api.errorSchema) - for (const group of api.groups) { - for (const endpoint of group.endpoints) { - processSchema(endpoint.errorSchema) - } - processSchema(group.errorSchema) - } - return Schema.Union(...[...schemas].map((schema) => { - const status = HttpApiSchema.getStatusError(schema) - const encoded = AST.encodedAST(schema.ast) - const isEmpty = encoded._tag === "VoidKeyword" - return Schema.transformOrFail(Schema.Any, schema, { - decode: (_, __, ast) => ParseResult.fail(new ParseResult.Forbidden(ast, _, "Encode only schema")), - encode: (error, _, ast) => - isEmpty ? - HttpServerResponse.empty({ status }) : - HttpServerResponse.json(error, { status }).pipe( - Effect.mapError((error) => new ParseResult.Type(ast, error, "Could not encode to JSON")) - ) - }) - })) as any -} diff --git a/packages/platform/src/HttpApiClient.ts b/packages/platform/src/HttpApiClient.ts index 48d7cbf241..152c3d8075 100644 --- a/packages/platform/src/HttpApiClient.ts +++ b/packages/platform/src/HttpApiClient.ts @@ -7,6 +7,8 @@ import { identity } from "effect/Function" import * as Option from "effect/Option" import * as ParseResult from "effect/ParseResult" import * as Schema from "effect/Schema" +import type * as AST from "effect/SchemaAST" +import type { Scope } from "effect/Scope" import type { Simplify } from "effect/Types" import * as HttpApi from "./HttpApi.js" import type { HttpApiEndpoint } from "./HttpApiEndpoint.js" @@ -17,49 +19,89 @@ import * as HttpClientError from "./HttpClientError.js" import * as HttpClientRequest from "./HttpClientRequest.js" import * as HttpClientResponse from "./HttpClientResponse.js" import * as HttpMethod from "./HttpMethod.js" +import type { HttpApiMiddleware } from "./index.js" /** * @since 1.0.0 * @category models */ -export type Client = [A] extends - [HttpApi.HttpApi] ? { - readonly [GroupName in _Groups["identifier"]]: [HttpApiGroup.WithName<_Groups, GroupName>] extends - [HttpApiGroup] ? { - readonly [Name in _Endpoints["name"]]: [HttpApiEndpoint.WithName<_Endpoints, Name>] extends [ - HttpApiEndpoint< - Name, - infer _Method, - infer _Path, - infer _Payload, - infer _Headers, - infer _Success, - infer _Error, - infer _R - > - ] ? ( - request: Simplify> - ) => Effect.Effect< - _Success, - _Error | _GroupError | _ApiError | HttpClientError.HttpClientError - > : - never +export type Client = Simplify< + & { + readonly [Group in Extract as HttpApiGroup.Name]: [Group] extends + [HttpApiGroup] ? { + readonly [Endpoint in _Endpoints as HttpApiEndpoint.Name]: Client.Method< + Endpoint, + ApiError, + _GroupError + > } : never - } : - never + } + & { + readonly [Method in Client.TopLevelMethods as Method[0]]: Method[1] + } +> + +/** + * @since 1.0.0 + * @category models + */ +export declare namespace Client { + /** + * @since 1.0.0 + * @category models + */ + export type Method = [Endpoint] extends [ + HttpApiEndpoint< + infer _Name, + infer _Method, + infer _Path, + infer _UrlParams, + infer _Payload, + infer _Headers, + infer _Success, + infer _Error, + infer _R, + infer _RE + > + ] ? ( + request: Simplify> + ) => Effect.Effect< + _Success, + _Error | GroupError | ApiError | HttpClientError.HttpClientError + > : + never + + /** + * @since 1.0.0 + * @category models + */ + export type TopLevelMethods = + Extract extends + HttpApiGroup ? + _Endpoints extends infer Endpoint ? [HttpApiEndpoint.Name, Client.Method] + : never : + never +} /** * @since 1.0.0 * @category constructors */ -export const make = ( - api: A, +export const make = ( + api: HttpApi.HttpApi, options?: { readonly transformClient?: ((client: HttpClient.HttpClient) => HttpClient.HttpClient) | undefined + readonly transformResponse?: + | ((effect: Effect.Effect) => Effect.Effect) + | undefined readonly baseUrl?: string | undefined } -): Effect.Effect>, never, HttpApi.HttpApi.Context | HttpClient.HttpClient> => +): Effect.Effect< + Simplify>, + never, + HttpApiMiddleware.HttpApiMiddleware.Without> | HttpClient.HttpClient +> => Effect.gen(function*() { const context = yield* Effect.context() const httpClient = (yield* HttpClient.HttpClient).pipe( @@ -69,82 +111,26 @@ export const make = ( const client: Record> = {} HttpApi.reflect(api as any, { onGroup({ group }) { + if (group.topLevel) return client[group.identifier] = {} }, - onEndpoint({ endpoint, errors, group, successAST, successEncoding, successStatus }) { + onEndpoint({ endpoint, errors, group, successes }) { const makeUrl = compilePath(endpoint.path) - const successDecode = successAST.pipe( - Option.map((ast) => { - const schema = Schema.make(ast) - switch (successEncoding.kind) { - case "Json": { - return HttpClientResponse.schemaBodyJson(schema) - } - case "UrlParams": { - return HttpClientResponse.schemaBodyUrlParams(schema as any) - } - case "Uint8Array": { - return (response: HttpClientResponse.HttpClientResponse) => - response.arrayBuffer.pipe( - Effect.map((buffer) => new Uint8Array(buffer)), - Effect.flatMap(Schema.decodeUnknown(schema)) - ) - } - case "Text": { - return (response: HttpClientResponse.HttpClientResponse) => - Effect.flatMap(response.text, Schema.decodeUnknown(schema)) - } - } - }) - ) - const handleError = ( - request: HttpClientRequest.HttpClientRequest, - response: HttpClientResponse.HttpClientResponse - ) => { - const error = errors.get(response.status) - if (error === undefined) { - return Effect.die( - new HttpClientError.ResponseError({ - reason: "Decode", - request, - response - }) - ) - } else if (Option.isNone(error)) { - return Effect.fail( - new HttpClientError.ResponseError({ - reason: "StatusCode", - request, - response - }) - ) + const decodeMap: Record< + number | "orElse", + (response: HttpClientResponse.HttpClientResponse) => Effect.Effect + > = { orElse: statusOrElse } + errors.forEach((ast, status) => { + if (ast._tag === "None") { + decodeMap[status] = statusCodeError + return } - const decode = Schema.decodeUnknown(Schema.make(error.value)) - return response.text.pipe( - Effect.flatMap((text) => - text === "" ? Effect.void : Effect.try({ - try: () => JSON.parse(text), - catch: (cause) => - new HttpClientError.ResponseError({ - reason: "Decode", - request, - response, - cause - }) - }) - ), - Effect.flatMap((json) => - Effect.mapError(decode(json), (cause) => - new HttpClientError.ResponseError({ - reason: "Decode", - request, - response, - cause - })) - ), - Effect.flatMap(Effect.fail) - ) - } + const decode = schemaToResponse(ast.value) + decodeMap[status] = (response) => Effect.flatMap(decode(response), Effect.fail) + }) + successes.forEach((ast, status) => { + decodeMap[status] = ast._tag === "None" ? responseAsVoid : schemaToResponse(ast.value) + }) const isMultipart = endpoint.payloadSchema.pipe( Option.map((schema) => HttpApiSchema.getMultipart(schema.ast)), Option.getOrElse(() => false) @@ -156,12 +142,16 @@ export const make = ( const encodeHeaders = endpoint.headersSchema.pipe( Option.map(Schema.encodeUnknown) ) - client[group.identifier][endpoint.name] = (request: { + const encodeUrlParams = endpoint.urlParamsSchema.pipe( + Option.map(Schema.encodeUnknown) + ) + ;(group.topLevel ? client : client[group.identifier])[endpoint.name] = (request: { readonly path: any + readonly urlParams: any readonly payload: any readonly headers: any }) => { - const url = request && request.path ? makeUrl(request && request.path) : endpoint.path + const url = request && request.path ? makeUrl(request.path) : endpoint.path const baseRequest = HttpClientRequest.make(endpoint.method)(url) return (isMultipart ? Effect.succeed(baseRequest.pipe( @@ -185,15 +175,17 @@ export const make = ( ) ) : identity, - Effect.flatMap((request) => - Effect.flatMap(httpClient.execute(request), (response) => - response.status !== successStatus - ? handleError(request, response) - : Effect.succeed(response)) - ), - successDecode._tag === "Some" - ? Effect.flatMap(successDecode.value) - : Effect.asVoid, + encodeUrlParams._tag === "Some" + ? Effect.flatMap((httpRequest) => + encodeUrlParams.value(request.urlParams).pipe( + Effect.orDie, + Effect.map((params) => HttpClientRequest.appendUrlParams(httpRequest, params as any)) + ) + ) + : identity, + Effect.flatMap(httpClient.execute), + Effect.flatMap(HttpClientResponse.matchStatus(decodeMap)), + options?.transformResponse === undefined ? identity : options.transformResponse, Effect.scoped, Effect.catchIf(ParseResult.isParseError, Effect.die), Effect.mapInputContext((input) => Context.merge(context, input)) @@ -226,3 +218,62 @@ const compilePath = (path: string) => { return url } } + +const schemaToResponse = ( + ast: AST.AST +): (response: HttpClientResponse.HttpClientResponse) => Effect.Effect => { + const schema = Schema.make(ast) + const encoding = HttpApiSchema.getEncoding(ast) + const decode = Schema.decodeUnknown(schema) + switch (encoding.kind) { + case "Json": { + return (response) => Effect.flatMap(responseJson(response), decode) + } + case "UrlParams": { + return HttpClientResponse.schemaBodyUrlParams(schema as any) + } + case "Uint8Array": { + return (response: HttpClientResponse.HttpClientResponse) => + response.arrayBuffer.pipe( + Effect.map((buffer) => new Uint8Array(buffer)), + Effect.flatMap(decode) + ) + } + case "Text": { + return (response) => Effect.flatMap(response.text, decode) + } + } +} + +const responseJson = (response: HttpClientResponse.HttpClientResponse) => + Effect.flatMap(response.text, (text) => + text === "" ? Effect.void : Effect.try({ + try: () => JSON.parse(text), + catch: (cause) => + new HttpClientError.ResponseError({ + reason: "Decode", + request: response.request, + response, + cause + }) + })) + +const statusOrElse = (response: HttpClientResponse.HttpClientResponse) => + Effect.fail( + new HttpClientError.ResponseError({ + reason: "Decode", + request: response.request, + response + }) + ) + +const statusCodeError = (response: HttpClientResponse.HttpClientResponse) => + Effect.fail( + new HttpClientError.ResponseError({ + reason: "StatusCode", + request: response.request, + response + }) + ) + +const responseAsVoid = (_response: HttpClientResponse.HttpClientResponse) => Effect.void diff --git a/packages/platform/src/HttpApiEndpoint.ts b/packages/platform/src/HttpApiEndpoint.ts index 0135dbaf6f..5ef772e395 100644 --- a/packages/platform/src/HttpApiEndpoint.ts +++ b/packages/platform/src/HttpApiEndpoint.ts @@ -4,13 +4,13 @@ import type { Brand } from "effect/Brand" import * as Context from "effect/Context" import type { Effect } from "effect/Effect" -import { dual } from "effect/Function" +import * as HashSet from "effect/HashSet" import * as Option from "effect/Option" import { type Pipeable, pipeArguments } from "effect/Pipeable" import * as Predicate from "effect/Predicate" -import type { Redacted } from "effect/Redacted" import * as Schema from "effect/Schema" import type * as Types from "effect/Types" +import type * as HttpApiMiddleware from "./HttpApiMiddleware.js" import * as HttpApiSchema from "./HttpApiSchema.js" import type { HttpMethod } from "./HttpMethod.js" import * as HttpRouter from "./HttpRouter.js" @@ -45,22 +45,189 @@ export interface HttpApiEndpoint< out Name extends string, out Method extends HttpMethod, in out Path = never, + in out UrlParams = never, in out Payload = never, in out Headers = never, in out Success = void, in out Error = never, - out R = never + out R = never, + out RE = never > extends Pipeable { readonly [TypeId]: TypeId readonly name: Name readonly path: HttpRouter.PathInput readonly method: Method readonly pathSchema: Option.Option> + readonly urlParamsSchema: Option.Option> readonly payloadSchema: Option.Option> readonly headersSchema: Option.Option> readonly successSchema: Schema.Schema - readonly errorSchema: Schema.Schema + readonly errorSchema: Schema.Schema readonly annotations: Context.Context + readonly middlewares: HashSet.HashSet + + /** + * Add a schema for the success response of the endpoint. The status code + * will be inferred from the schema, otherwise it will default to 200. + */ + addSuccess( + schema: S, + annotations?: { + readonly status?: number | undefined + } + ): HttpApiEndpoint< + Name, + Method, + Path, + UrlParams, + Payload, + Headers, + Exclude | Schema.Schema.Type, + Error, + R | Schema.Schema.Context, + RE + > + + /** + * Add an error response schema to the endpoint. The status code + * will be inferred from the schema, otherwise it will default to 500. + */ + addError( + schema: E, + annotations?: { + readonly status?: number | undefined + } + ): HttpApiEndpoint< + Name, + Method, + Path, + UrlParams, + Payload, + Headers, + Success, + Error | Schema.Schema.Type, + R, + RE | Schema.Schema.Context + > + + /** + * Set the schema for the request body of the endpoint. The schema will be + * used to validate the request body before the handler is called. + * + * For endpoints with no request body, the payload will use the url search + * parameters. + * + * You can set a multipart schema to handle file uploads by using the + * `HttpApiSchema.Multipart` combinator. + */ + setPayload

( + schema: P & HttpApiEndpoint.ValidatePayload + ): HttpApiEndpoint< + Name, + Method, + Path, + UrlParams, + Schema.Schema.Type

, + Headers, + Success, + Error, + R | Schema.Schema.Context

, + RE + > + + /** + * Set the schema for the path parameters of the endpoint. The schema will be + * used to validate the path parameters before the handler is called. + */ + setPath( + schema: Path & HttpApiEndpoint.ValidatePath + ): HttpApiEndpoint< + Name, + Method, + Schema.Schema.Type, + UrlParams, + Payload, + Headers, + Success, + Error, + R | Schema.Schema.Context, + RE + > + + /** + * Set the schema for the url search parameters of the endpoint. + */ + setUrlParams( + schema: UrlParams & HttpApiEndpoint.ValidateUrlParams + ): HttpApiEndpoint< + Name, + Method, + Path, + Schema.Schema.Type, + Payload, + Headers, + Success, + Error, + R | Schema.Schema.Context, + RE + > + + /** + * Set the schema for the headers of the endpoint. The schema will be + * used to validate the headers before the handler is called. + */ + setHeaders( + schema: H & HttpApiEndpoint.ValidateHeaders + ): HttpApiEndpoint< + Name, + Method, + Path, + UrlParams, + Payload, + Schema.Schema.Type, + Success, + Error, + R | Schema.Schema.Context, + RE + > + + /** + * Add a prefix to the path of the endpoint. + */ + prefix( + prefix: HttpRouter.PathInput + ): HttpApiEndpoint + + /** + * Add an `HttpApiMiddleware` to the endpoint. + */ + middleware(middleware: Context.Tag): HttpApiEndpoint< + Name, + Method, + Path, + UrlParams, + Payload, + Headers, + Success, + Error | HttpApiMiddleware.HttpApiMiddleware.Error, + R | I, + RE | HttpApiMiddleware.HttpApiMiddleware.ErrorContext + > + + /** + * Add an annotation on the endpoint. + */ + annotate( + tag: Context.Tag, + value: S + ): HttpApiEndpoint + + /** + * Merge the annotations of the endpoint with the provided context. + */ + annotateContext( + context: Context.Context + ): HttpApiEndpoint } /** @@ -74,47 +241,47 @@ export declare namespace HttpApiEndpoint { */ export interface Any extends Pipeable { readonly [TypeId]: TypeId - readonly name: string - readonly path: HttpRouter.PathInput - readonly method: HttpMethod - readonly pathSchema: Option.Option - readonly payloadSchema: Option.Option - readonly headersSchema: Option.Option - readonly successSchema: Schema.Schema.Any - readonly errorSchema: Schema.Schema.Any - readonly annotations: Context.Context } /** * @since 1.0.0 * @category models */ - export interface All extends Pipeable { - readonly [TypeId]: TypeId - readonly name: string - readonly path: HttpRouter.PathInput - readonly method: HttpMethod - readonly pathSchema: Option.Option - readonly payloadSchema: Option.Option - readonly headersSchema: Option.Option - readonly successSchema: Schema.Schema.Any - readonly errorSchema: Schema.Schema.All - readonly annotations: Context.Context - } + export interface AnyWithProps extends HttpApiEndpoint {} + + /** + * @since 1.0.0 + * @category models + */ + export type Name = Endpoint extends HttpApiEndpoint< + infer _Name, + infer _Method, + infer _Path, + infer _UrlParams, + infer _Payload, + infer _Headers, + infer _Success, + infer _Error, + infer _R, + infer _RE + > ? _Name + : never /** * @since 1.0.0 * @category models */ - export type Success = Endpoint extends HttpApiEndpoint< + export type Success = Endpoint extends HttpApiEndpoint< infer _Name, infer _Method, infer _Path, + infer _UrlParams, infer _Payload, infer _Headers, infer _Success, infer _Error, - infer _R + infer _R, + infer _RE > ? _Success : never @@ -122,15 +289,17 @@ export declare namespace HttpApiEndpoint { * @since 1.0.0 * @category models */ - export type Error = Endpoint extends HttpApiEndpoint< + export type Error = Endpoint extends HttpApiEndpoint< infer _Name, infer _Method, infer _Path, + infer _UrlParams, infer _Payload, infer _Headers, infer _Success, infer _Error, - infer _R + infer _R, + infer _RE > ? _Error : never @@ -138,15 +307,17 @@ export declare namespace HttpApiEndpoint { * @since 1.0.0 * @category models */ - export type PathParsed = Endpoint extends HttpApiEndpoint< + export type PathParsed = Endpoint extends HttpApiEndpoint< infer _Name, infer _Method, infer _Path, + infer _UrlParams, infer _Payload, infer _Headers, infer _Success, infer _Error, - infer _R + infer _R, + infer _RE > ? _Path : never @@ -154,15 +325,35 @@ export declare namespace HttpApiEndpoint { * @since 1.0.0 * @category models */ - export type Payload = Endpoint extends HttpApiEndpoint< + export type UrlParams = Endpoint extends HttpApiEndpoint< infer _Name, infer _Method, infer _Path, + infer _UrlParams, infer _Payload, infer _Headers, infer _Success, infer _Error, - infer _R + infer _R, + infer _RE + > ? _UrlParams + : never + + /** + * @since 1.0.0 + * @category models + */ + export type Payload = Endpoint extends HttpApiEndpoint< + infer _Name, + infer _Method, + infer _Path, + infer _UrlParams, + infer _Payload, + infer _Headers, + infer _Success, + infer _Error, + infer _R, + infer _RE > ? _Payload : never @@ -170,15 +361,17 @@ export declare namespace HttpApiEndpoint { * @since 1.0.0 * @category models */ - export type Headers = Endpoint extends HttpApiEndpoint< + export type Headers = Endpoint extends HttpApiEndpoint< infer _Name, infer _Method, infer _Path, + infer _UrlParams, infer _Payload, infer _Headers, infer _Success, infer _Error, - infer _R + infer _R, + infer _RE > ? _Headers : never @@ -186,19 +379,31 @@ export declare namespace HttpApiEndpoint { * @since 1.0.0 * @category models */ - export type Request = - & { - readonly path: PathParsed - } - & ([Payload] extends [infer P] ? [P] extends [never] ? {} : { readonly payload: P } : {}) - & ([Headers] extends [infer H] ? [H] extends [never] ? {} : { readonly headers: H } : {}) + export type Request = Endpoint extends HttpApiEndpoint< + infer _Name, + infer _Method, + infer _Path, + infer _UrlParams, + infer _Payload, + infer _Headers, + infer _Success, + infer _Error, + infer _R, + infer _RE + > ? + & ([_Path] extends [never] ? {} : { readonly path: _Path }) + & ([_UrlParams] extends [never] ? {} : { readonly urlParams: _UrlParams }) + & ([_Payload] extends [never] ? {} : { readonly payload: _Payload }) + & ([_Headers] extends [never] ? {} : { readonly headers: _Headers }) + : {} /** * @since 1.0.0 * @category models */ - export type ClientRequest = ( + export type ClientRequest = ( & ([Path] extends [void] ? {} : { readonly path: Path }) + & ([UrlParams] extends [never] ? {} : { readonly urlParams: UrlParams }) & ([Headers] extends [never] ? {} : { readonly headers: Headers }) & ([Payload] extends [never] ? {} : [Payload] extends [Brand] ? { readonly payload: FormData } @@ -213,11 +418,13 @@ export declare namespace HttpApiEndpoint { infer _Name, infer _Method, infer _Path, + infer _UrlParams, infer _Payload, infer _Headers, infer _Success, infer _Error, - infer _R + infer _R, + infer _RE > ? _R : never @@ -225,45 +432,53 @@ export declare namespace HttpApiEndpoint { * @since 1.0.0 * @category models */ - export type Handler = ( - request: Types.Simplify> - ) => Effect, E, R> + export type ErrorContext = Endpoint extends HttpApiEndpoint< + infer _Name, + infer _Method, + infer _Path, + infer _UrlParams, + infer _Payload, + infer _Headers, + infer _Success, + infer _Error, + infer _R, + infer _RE + > ? _RE + : never /** * @since 1.0.0 * @category models */ - export type HandlerRedacted = ( + export type Handler = ( request: Types.Simplify> - ) => Effect, Redacted], E, R> + ) => Effect, Error | E, R> /** * @since 1.0.0 * @category models */ - export type HandlerResponse = ( + export type HandlerResponse = ( request: Types.Simplify> - ) => Effect + ) => Effect | E, R> /** * @since 1.0.0 * @category models */ - export type WithName = Endpoints extends infer Endpoint - ? Endpoint extends { readonly name: Name } ? Endpoint : never - : never + export type WithName = Extract /** * @since 1.0.0 * @category models */ - export type ExcludeName = Exclude + export type ExcludeName = Exclude /** * @since 1.0.0 * @category models */ - export type HandlerWithName = Handler< + export type HandlerWithName = Handler< WithName, E, R @@ -273,7 +488,7 @@ export declare namespace HttpApiEndpoint { * @since 1.0.0 * @category models */ - export type HandlerResponseWithName = HandlerResponse< + export type HandlerResponseWithName = HandlerResponse< WithName, E, R @@ -283,31 +498,29 @@ export declare namespace HttpApiEndpoint { * @since 1.0.0 * @category models */ - export type HandlerRedactedWithName = HandlerRedacted< - WithName, - E, - R - > + export type SuccessWithName = Success> /** * @since 1.0.0 * @category models */ - export type SuccessWithName = Success> + export type ErrorWithName = Error> /** * @since 1.0.0 * @category models */ - export type ErrorWithName = Error> + export type ContextWithName = Context> /** * @since 1.0.0 * @category models */ - export type ExcludeProvided = Exclude< + export type ExcludeProvided = Exclude< R, - HttpRouter.HttpRouter.DefaultServices | HttpRouter.HttpRouter.Provided + | HttpRouter.HttpRouter.DefaultServices + | HttpRouter.HttpRouter.Provided + | HttpApiMiddleware.HttpApiMiddleware.ExtractProvides> > /** @@ -319,6 +532,15 @@ export declare namespace HttpApiEndpoint { : `Path schema must be encodeable to strings` : {} + /** + * @since 1.0.0 + * @category models + */ + export type ValidateUrlParams = S extends Schema.Schema + ? [_I] extends [Readonly>] ? {} + : `UrlParams schema must be encodeable to strings` + : {} + /** * @since 1.0.0 * @category models @@ -332,19 +554,163 @@ export declare namespace HttpApiEndpoint { * @since 1.0.0 * @category models */ - export type ValidatePayload = Method extends + export type ValidatePayload = Method extends HttpMethod.NoBody ? P extends Schema.Schema ? [_I] extends [Readonly | undefined>>] ? {} : `'${Method}' payload must be encodeable to strings` : {} : {} + + /** + * @since 1.0.0 + * @category models + */ + export type AddError = Endpoint extends HttpApiEndpoint< + infer _Name, + infer _Method, + infer _Path, + infer _UrlParams, + infer _Payload, + infer _Headers, + infer _Success, + infer _Error, + infer _R, + infer _RE + > ? HttpApiEndpoint< + _Name, + _Method, + _Path, + _UrlParams, + _Payload, + _Headers, + _Success, + _Error | E, + _R, + _RE | R + > : + never + + /** + * @since 1.0.0 + * @category models + */ + export type AddContext = Endpoint extends HttpApiEndpoint< + infer _Name, + infer _Method, + infer _Path, + infer _UrlParams, + infer _Payload, + infer _Headers, + infer _Success, + infer _Error, + infer _R, + infer _RE + > ? HttpApiEndpoint< + _Name, + _Method, + _Path, + _UrlParams, + _Payload, + _Headers, + _Success, + _Error | HttpApiMiddleware.HttpApiMiddleware.Error, + _R | R, + _RE | HttpApiMiddleware.HttpApiMiddleware.ErrorContext + > : + never } const Proto = { [TypeId]: TypeId, pipe() { return pipeArguments(this, arguments) + }, + addSuccess( + this: HttpApiEndpoint.AnyWithProps, + schema: Schema.Schema.Any, + annotations?: { readonly status?: number } + ) { + schema = schema.pipe( + Schema.annotations(HttpApiSchema.annotations({ + status: annotations?.status ?? HttpApiSchema.getStatusSuccess(schema) + })) + ) + return makeProto({ + ...this, + successSchema: this.successSchema === HttpApiSchema.NoContent ? + schema : + HttpApiSchema.UnionUnify(this.successSchema, schema) + }) + }, + addError(this: HttpApiEndpoint.AnyWithProps, schema: Schema.Schema.Any, annotations?: { readonly status?: number }) { + return makeProto({ + ...this, + errorSchema: HttpApiSchema.UnionUnify( + this.errorSchema, + schema.pipe( + Schema.annotations(HttpApiSchema.annotations({ + status: annotations?.status ?? HttpApiSchema.getStatusError(schema) + })) + ) + ) + }) + }, + setPayload(this: HttpApiEndpoint.AnyWithProps, schema: Schema.Schema.Any) { + return makeProto({ + ...this, + payloadSchema: Option.some(schema) + }) + }, + setPath(this: HttpApiEndpoint.AnyWithProps, schema: Schema.Schema.Any) { + return makeProto({ + ...this, + pathSchema: Option.some(schema) + }) + }, + setUrlParams(this: HttpApiEndpoint.AnyWithProps, schema: Schema.Schema.Any) { + return makeProto({ + ...this, + urlParamsSchema: Option.some(schema) + }) + }, + setHeaders(this: HttpApiEndpoint.AnyWithProps, schema: Schema.Schema.Any) { + return makeProto({ + ...this, + headersSchema: Option.some(schema) + }) + }, + prefix(this: HttpApiEndpoint.AnyWithProps, prefix: HttpRouter.PathInput) { + return makeProto({ + ...this, + path: HttpRouter.prefixPath(this.path, prefix) as HttpRouter.PathInput + }) + }, + middleware(this: HttpApiEndpoint.AnyWithProps, middleware: HttpApiMiddleware.TagClassAny) { + return makeProto({ + ...this, + errorSchema: HttpApiSchema.UnionUnify( + this.errorSchema, + middleware.failure.pipe( + Schema.annotations(HttpApiSchema.annotations({ + status: HttpApiSchema.getStatusError(middleware.failure) + })) + ) + ), + middlewares: HashSet.add(this.middlewares, middleware) + }) + }, + annotate(this: HttpApiEndpoint.AnyWithProps, tag: Context.Tag, value: any) { + return makeProto({ + ...this, + annotations: Context.add(this.annotations, tag, value) + }) + }, + annotateContext(this: HttpApiEndpoint.AnyWithProps, context: Context.Context) { + return makeProto({ + ...this, + annotations: Context.merge(this.annotations, context) + }) } } @@ -352,22 +718,26 @@ const makeProto = < Name extends string, Method extends HttpMethod, Path, + UrlParams, Payload, Headers, Success, Error, - R + R, + RE >(options: { readonly name: Name readonly path: HttpRouter.PathInput readonly method: Method readonly pathSchema: Option.Option> + readonly urlParamsSchema: Option.Option> readonly payloadSchema: Option.Option> readonly headersSchema: Option.Option> readonly successSchema: Schema.Schema - readonly errorSchema: Schema.Schema + readonly errorSchema: Schema.Schema readonly annotations: Context.Context -}): HttpApiEndpoint => + readonly middlewares: HashSet.HashSet +}): HttpApiEndpoint => Object.assign(Object.create(Proto), options) /** @@ -384,11 +754,13 @@ export const make = (method: Method) => path, method, pathSchema: Option.none(), + urlParamsSchema: Option.none(), payloadSchema: Option.none(), headersSchema: Option.none(), successSchema: HttpApiSchema.NoContent as any, errorSchema: Schema.Never as any, - annotations: Context.empty() + annotations: Context.empty(), + middlewares: HashSet.empty() }) /** @@ -435,384 +807,3 @@ export const del: ( name: Name, path: HttpRouter.PathInput ) => HttpApiEndpoint = make("DELETE") - -/** - * Set the schema for the success response of the endpoint. The status code - * will be inferred from the schema, otherwise it will default to 200. - * - * @since 1.0.0 - * @category result - */ -export const setSuccess: { - ( - schema: S, - annotations?: { - readonly status?: number | undefined - } - ): < - Name extends string, - Method extends HttpMethod, - _Path, - _P, - _H, - _S, - _E, - _R - >( - self: HttpApiEndpoint - ) => HttpApiEndpoint, _E, _R | Schema.Schema.Context> - < - Name extends string, - Method extends HttpMethod, - _Path, - _P, - _H, - _S, - _E, - _R, - S extends Schema.Schema.Any - >( - self: HttpApiEndpoint, - schema: S, - annotations?: { - readonly status?: number | undefined - } - ): HttpApiEndpoint, _E, _R | Schema.Schema.Context> -} = dual( - (args) => isHttpApiEndpoint(args[0]), - < - Name extends string, - Method extends HttpMethod, - _Path, - _P, - _H, - _S, - _E, - _R, - S extends Schema.Schema.Any - >( - self: HttpApiEndpoint, - schema: S, - annotations?: { - readonly status?: number | undefined - } - ): HttpApiEndpoint, _E, _R | Schema.Schema.Context> => - makeProto({ - ...self as any, - successSchema: schema.annotations(HttpApiSchema.annotations({ - status: annotations?.status ?? HttpApiSchema.getStatusSuccess(schema) - })) - }) -) - -/** - * Add an error response schema to the endpoint. The status code - * will be inferred from the schema, otherwise it will default to 500. - * - * @since 1.0.0 - * @category result - */ -export const addError: { - ( - schema: E, - annotations?: { - readonly status?: number | undefined - } - ): < - Name extends string, - Method extends HttpMethod, - _Path, - _P, - _H, - _S, - _E, - _R - >( - self: HttpApiEndpoint - ) => HttpApiEndpoint, _R | Schema.Schema.Context> - < - Name extends string, - Method extends HttpMethod, - _Path, - _P, - _H, - _S, - _E, - _R, - E extends Schema.Schema.All - >( - self: HttpApiEndpoint, - schema: E, - annotations?: { - readonly status?: number | undefined - } - ): HttpApiEndpoint, _R | Schema.Schema.Context> -} = dual( - (args) => isHttpApiEndpoint(args[0]), - < - Name extends string, - Method extends HttpMethod, - _Path, - _P, - _H, - _S, - _E, - _R, - E extends Schema.Schema.All - >( - self: HttpApiEndpoint, - schema: E, - annotations?: { - readonly status?: number | undefined - } - ): HttpApiEndpoint, _R | Schema.Schema.Context> => - makeProto({ - ...self as any, - errorSchema: HttpApiSchema.UnionUnify( - self.errorSchema, - schema.pipe( - Schema.annotations(HttpApiSchema.annotations({ - status: annotations?.status ?? HttpApiSchema.getStatusError(schema) - })) - ) - ) - }) -) - -/** - * Set the schema for the request body of the endpoint. The schema will be - * used to validate the request body before the handler is called. - * - * For endpoints with no request body, the payload will use the url search - * parameters. - * - * You can set a multipart schema to handle file uploads by using the - * `HttpApiSchema.Multipart` combinator. - * - * @since 1.0.0 - * @category request - */ -export const setPayload: { - ( - schema: P & HttpApiEndpoint.ValidatePayload - ): < - Name extends string, - _Path, - _P, - _H, - _S, - _E, - _R - >( - self: HttpApiEndpoint - ) => HttpApiEndpoint, _H, _S, _E, _R | Schema.Schema.Context

> - < - Name extends string, - Method extends HttpMethod, - _Path, - _P, - _H, - _S, - _E, - _R, - P extends Schema.Schema.All - >( - self: HttpApiEndpoint, - schema: P & HttpApiEndpoint.ValidatePayload - ): HttpApiEndpoint, _H, _S, _E, _R | Schema.Schema.Context

> -} = dual( - 2, - < - Name extends string, - Method extends HttpMethod, - _Path, - _P, - _H, - _S, - _E, - _R, - P extends Schema.Schema.All - >( - self: HttpApiEndpoint, - schema: P & HttpApiEndpoint.ValidatePayload - ): HttpApiEndpoint, _H, _S, _E, _R | Schema.Schema.Context

> => - makeProto({ - ...self as any, - payloadSchema: Option.some(schema) - }) -) - -/** - * Set the schema for the path parameters of the endpoint. The schema will be - * used to validate the path parameters before the handler is called. - * - * @since 1.0.0 - * @category request - */ -export const setPath: { - ( - schema: Path & HttpApiEndpoint.ValidatePath - ): < - Name extends string, - Method extends HttpMethod, - _Path, - _P, - _H, - _S, - _E, - _R - >( - self: HttpApiEndpoint - ) => HttpApiEndpoint, _P, _H, _S, _E, _R | Schema.Schema.Context> - < - Name extends string, - Method extends HttpMethod, - _Path, - _P, - _H, - _S, - _E, - _R, - Path extends Schema.Schema.Any - >( - self: HttpApiEndpoint, - schema: Path & HttpApiEndpoint.ValidatePath - ): HttpApiEndpoint, _P, _H, _S, _E, _R | Schema.Schema.Context> -} = dual( - 2, - < - Name extends string, - Method extends HttpMethod, - _Path, - _P, - _H, - _S, - _E, - _R, - Path extends Schema.Schema.Any - >( - self: HttpApiEndpoint, - schema: Path & HttpApiEndpoint.ValidatePath - ): HttpApiEndpoint, _P, _H, _S, _E, _R | Schema.Schema.Context> => - makeProto({ - ...self as any, - pathSchema: Option.some(schema) - }) -) - -/** - * Set the schema for the headers of the endpoint. The schema will be - * used to validate the headers before the handler is called. - * - * @since 1.0.0 - * @category request - */ -export const setHeaders: { - ( - schema: H & HttpApiEndpoint.ValidateHeaders - ): < - Name extends string, - _Path, - _P, - _H, - _S, - _E, - _R - >( - self: HttpApiEndpoint - ) => HttpApiEndpoint, _S, _E, _R | Schema.Schema.Context> - < - Name extends string, - Method extends HttpMethod, - _Path, - _P, - _H, - _S, - _E, - _R, - H extends Schema.Schema.Any - >( - self: HttpApiEndpoint, - schema: H & HttpApiEndpoint.ValidateHeaders - ): HttpApiEndpoint, _S, _E, _R | Schema.Schema.Context> -} = dual( - 2, - < - Name extends string, - Method extends HttpMethod, - _Path, - _P, - _H, - _S, - _E, - _R, - H extends Schema.Schema.Any - >( - self: HttpApiEndpoint, - schema: H & HttpApiEndpoint.ValidateHeaders - ): HttpApiEndpoint, _S, _E, _R | Schema.Schema.Context> => - makeProto({ - ...self as any, - headersSchema: Option.some(schema) - }) -) - -/** - * Add a prefix to the path of the endpoint. - * - * @since 1.0.0 - * @category request - */ -export const prefix: { - (prefix: HttpRouter.PathInput): (self: A) => A - (self: A, prefix: HttpRouter.PathInput): A -} = dual(2, (self: A, prefix: HttpRouter.PathInput): A => - makeProto({ - ...self as any, - path: HttpRouter.prefixPath(self.path, prefix) - }) as A) - -/** - * @since 1.0.0 - * @category reflection - */ -export const schemaSuccess = ( - self: A -): Option.Option, unknown, HttpApiEndpoint.Context>> => - HttpApiSchema.isVoid(self.successSchema.ast) ? Option.none() : Option.some(self.successSchema as any) - -/** - * Merge the annotations of the endpoint with the provided context. - * - * @since 1.0.0 - * @category annotations - */ -export const annotateMerge: { - (context: Context.Context): (self: A) => A - (self: A, context: Context.Context): A -} = dual( - 2, - (self: A, context: Context.Context): A => - makeProto({ - ...self as any, - annotations: Context.merge(self.annotations, context) - }) as A -) - -/** - * Add an annotation to the endpoint. - * - * @since 1.0.0 - * @category annotations - */ -export const annotate: { - (tag: Context.Tag, value: S): (self: A) => A - (self: A, tag: Context.Tag, value: S): A -} = dual( - 3, - (self: A, tag: Context.Tag, value: S): A => - makeProto({ - ...self as any, - annotations: Context.add(self.annotations, tag, value) - }) as A -) diff --git a/packages/platform/src/HttpApiGroup.ts b/packages/platform/src/HttpApiGroup.ts index 0275037cac..a6e5e5515a 100644 --- a/packages/platform/src/HttpApiGroup.ts +++ b/packages/platform/src/HttpApiGroup.ts @@ -1,14 +1,15 @@ /** * @since 1.0.0 */ -import * as Chunk from "effect/Chunk" import * as Context from "effect/Context" -import { dual } from "effect/Function" +import * as HashMap from "effect/HashMap" +import * as HashSet from "effect/HashSet" import { type Pipeable, pipeArguments } from "effect/Pipeable" import * as Predicate from "effect/Predicate" import * as Schema from "effect/Schema" -import * as HttpApiEndpoint from "./HttpApiEndpoint.js" +import type * as HttpApiEndpoint from "./HttpApiEndpoint.js" import type { HttpApiDecodeError } from "./HttpApiError.js" +import type * as HttpApiMiddleware from "./HttpApiMiddleware.js" import * as HttpApiSchema from "./HttpApiSchema.js" import type { PathInput } from "./HttpRouter.js" @@ -40,17 +41,108 @@ export const isHttpApiGroup = (u: unknown): u is HttpApiGroup.Any => Predicate.h * @category models */ export interface HttpApiGroup< - out Name extends string, - out Endpoints extends HttpApiEndpoint.HttpApiEndpoint.All = never, + out Id extends string, + out Endpoints extends HttpApiEndpoint.HttpApiEndpoint.Any = never, in out Error = HttpApiDecodeError, - out ErrorR = never + out R = never, + out TopLevel extends (true | false) = false > extends Pipeable { new(_: never): {} readonly [TypeId]: TypeId - readonly identifier: Name - readonly endpoints: Chunk.Chunk - readonly errorSchema: Schema.Schema + readonly identifier: Id + readonly topLevel: TopLevel + readonly endpoints: HashMap.HashMap + readonly errorSchema: Schema.Schema readonly annotations: Context.Context + readonly middlewares: HashSet.HashSet + + /** + * Add an `HttpApiEndpoint` to an `HttpApiGroup`. + */ + add( + endpoint: A + ): HttpApiGroup + + /** + * Add an error schema to an `HttpApiGroup`, which is shared by all endpoints in the + * group. + */ + addError( + schema: Schema.Schema, + annotations?: { + readonly status?: number | undefined + } + ): HttpApiGroup + + /** + * Add a path prefix to all endpoints in an `HttpApiGroup`. Note that this will only + * add the prefix to the endpoints before this api is called. + */ + prefix(prefix: PathInput): HttpApiGroup + + /** + * Add an `HttpApiMiddleware` to the `HttpApiGroup`. + * + * It will be applied to all endpoints in the group. + */ + middleware(middleware: Context.Tag): HttpApiGroup< + Id, + Endpoints, + Error | HttpApiMiddleware.HttpApiMiddleware.Error, + R | I | HttpApiMiddleware.HttpApiMiddleware.ErrorContext, + TopLevel + > + + /** + * Add an `HttpApiMiddleware` to each endpoint in the `HttpApiGroup`. + * + * Endpoints added after this api is called will not have the middleware + * applied. + */ + middlewareEndpoints( + middleware: Context.Tag + ): HttpApiGroup< + Id, + HttpApiEndpoint.HttpApiEndpoint.AddContext, + Error, + R, + TopLevel + > + + /** + * Merge the annotations of an `HttpApiGroup` with a new context. + */ + annotateContext(context: Context.Context): HttpApiGroup + + /** + * Add an annotation to an `HttpApiGroup`. + */ + annotate(tag: Context.Tag, value: S): HttpApiGroup + + /** + * For each endpoint in an `HttpApiGroup`, update the annotations with a new + * context. + * + * Note that this will only update the annotations before this api is called. + */ + annotateEndpointsContext(context: Context.Context): HttpApiGroup + + /** + * For each endpoint in an `HttpApiGroup`, add an annotation. + * + * Note that this will only add the annotation to the endpoints before this api + * is called. + */ + annotateEndpoints(tag: Context.Tag, value: S): HttpApiGroup +} + +/** + * @since 1.0.0 + * @category models + */ +export interface Group { + readonly _: unique symbol + readonly name: Name } /** @@ -62,26 +154,22 @@ export declare namespace HttpApiGroup { * @since 1.0.0 * @category models */ - export type Any = - | HttpApiGroup - | HttpApiGroup - | HttpApiGroup + export interface Any { + readonly [TypeId]: TypeId + } /** * @since 1.0.0 * @category models */ - export interface Service { - readonly _: unique symbol - readonly name: Name - } + export type AnyWithProps = HttpApiGroup /** * @since 1.0.0 * @category models */ - export type ToService = Group extends HttpApiGroup - ? Service + export type ToService = A extends + HttpApiGroup ? Group : never /** @@ -94,8 +182,16 @@ export declare namespace HttpApiGroup { * @since 1.0.0 * @category models */ - export type Endpoints = Group extends HttpApiGroup - ? _Endpoints + export type Name = Group extends + HttpApiGroup ? _Name + : never + + /** + * @since 1.0.0 + * @category models + */ + export type Endpoints = Group extends + HttpApiGroup ? _Endpoints : never /** @@ -108,10 +204,16 @@ export declare namespace HttpApiGroup { * @since 1.0.0 * @category models */ - export type Error = Group extends HttpApiGroup ? - _Error + export type Error = Group extends + HttpApiGroup ? _Error : never + /** + * @since 1.0.0 + * @category models + */ + export type Provides = HttpApiMiddleware.HttpApiMiddleware.ExtractProvides> + /** * @since 1.0.0 * @category models @@ -122,8 +224,33 @@ export declare namespace HttpApiGroup { * @since 1.0.0 * @category models */ - export type Context = Group extends HttpApiGroup - ? _ErrorR | HttpApiEndpoint.HttpApiEndpoint.Context<_Endpoints> + export type Context = Group extends + HttpApiGroup ? + | HttpApiMiddleware.HttpApiMiddleware.Only<_R> + | Exclude< + HttpApiEndpoint.HttpApiEndpoint.Context<_Endpoints>, + HttpApiMiddleware.HttpApiMiddleware.ExtractProvides | _R> + > + : never + + /** + * @since 1.0.0 + * @category models + */ + export type ClientContext = Group extends + HttpApiGroup ? + | _R + | HttpApiEndpoint.HttpApiEndpoint.Context<_Endpoints> + | HttpApiEndpoint.HttpApiEndpoint.ErrorContext<_Endpoints> + : never + + /** + * @since 1.0.0 + * @category models + */ + export type ErrorContext = Group extends + HttpApiGroup + ? HttpApiMiddleware.HttpApiMiddleware.Without<_R> | HttpApiEndpoint.HttpApiEndpoint.ErrorContext<_Endpoints> : never /** @@ -135,17 +262,129 @@ export declare namespace HttpApiGroup { const Proto = { [TypeId]: TypeId, + add(this: HttpApiGroup.AnyWithProps, endpoint: A) { + return makeProto({ + identifier: this.identifier, + topLevel: this.topLevel, + endpoints: HashMap.set(this.endpoints, endpoint.name, endpoint), + errorSchema: this.errorSchema, + annotations: this.annotations, + middlewares: this.middlewares + }) + }, + addError( + this: HttpApiGroup.AnyWithProps, + schema: Schema.Schema, + annotations?: { readonly status?: number } + ) { + return makeProto({ + identifier: this.identifier, + topLevel: this.topLevel, + endpoints: this.endpoints, + errorSchema: HttpApiSchema.UnionUnify( + this.errorSchema, + schema.annotations(HttpApiSchema.annotations({ + status: annotations?.status ?? HttpApiSchema.getStatusError(schema) + })) + ), + annotations: this.annotations, + middlewares: this.middlewares + }) + }, + prefix(this: HttpApiGroup.AnyWithProps, prefix: PathInput) { + return makeProto({ + identifier: this.identifier, + topLevel: this.topLevel, + endpoints: HashMap.map(this.endpoints, (endpoint) => endpoint.prefix(prefix)), + errorSchema: this.errorSchema, + annotations: this.annotations, + middlewares: this.middlewares + }) + }, + middleware(this: HttpApiGroup.AnyWithProps, middleware: HttpApiMiddleware.TagClassAny) { + return makeProto({ + identifier: this.identifier, + topLevel: this.topLevel, + endpoints: this.endpoints, + errorSchema: HttpApiSchema.UnionUnify( + this.errorSchema, + middleware.failure.annotations(HttpApiSchema.annotations({ + status: HttpApiSchema.getStatusError(middleware.failure) + }) as any) + ), + annotations: this.annotations, + middlewares: HashSet.add(this.middlewares, middleware) + }) + }, + middlewareEndpoints(this: HttpApiGroup.AnyWithProps, middleware: HttpApiMiddleware.TagClassAny) { + return makeProto({ + identifier: this.identifier, + topLevel: this.topLevel, + endpoints: HashMap.map(this.endpoints, (endpoint) => endpoint.middleware(middleware)), + errorSchema: this.errorSchema, + annotations: this.annotations, + middlewares: this.middlewares + }) + }, + annotateContext(this: HttpApiGroup.AnyWithProps, context: Context.Context) { + return makeProto({ + identifier: this.identifier, + topLevel: this.topLevel, + endpoints: this.endpoints, + errorSchema: this.errorSchema, + annotations: Context.merge(this.annotations, context), + middlewares: this.middlewares + }) + }, + annotate(this: HttpApiGroup.AnyWithProps, tag: Context.Tag, value: S) { + return makeProto({ + identifier: this.identifier, + topLevel: this.topLevel, + endpoints: this.endpoints, + errorSchema: this.errorSchema, + annotations: Context.add(this.annotations, tag, value), + middlewares: this.middlewares + }) + }, + annotateEndpointsContext(this: HttpApiGroup.AnyWithProps, context: Context.Context) { + return makeProto({ + identifier: this.identifier, + topLevel: this.topLevel, + endpoints: HashMap.map(this.endpoints, (endpoint) => endpoint.annotateContext(context)), + errorSchema: this.errorSchema, + annotations: this.annotations, + middlewares: this.middlewares + }) + }, + annotateEndpoints(this: HttpApiGroup.AnyWithProps, tag: Context.Tag, value: S) { + return makeProto({ + identifier: this.identifier, + topLevel: this.topLevel, + endpoints: HashMap.map(this.endpoints, (endpoint) => endpoint.annotate(tag, value)), + errorSchema: this.errorSchema, + annotations: this.annotations, + middlewares: this.middlewares + }) + }, pipe() { return pipeArguments(this, arguments) } } -const makeProto = (options: { - readonly identifier: Name - readonly endpoints: Chunk.Chunk - readonly errorSchema: Schema.Schema +const makeProto = < + Id extends string, + Endpoints extends HttpApiEndpoint.HttpApiEndpoint.Any, + Error, + R, + TopLevel extends (true | false) +>(options: { + readonly identifier: Id + readonly topLevel: TopLevel + readonly endpoints: HashMap.HashMap + readonly errorSchema: Schema.Schema readonly annotations: Context.Context -}): HttpApiGroup => { + readonly middlewares: HashSet.HashSet +}): HttpApiGroup => { function HttpApiGroup() {} Object.setPrototypeOf(HttpApiGroup, Proto) return Object.assign(HttpApiGroup, options) as any @@ -160,206 +399,14 @@ const makeProto = (identifier: Name): HttpApiGroup => +export const make = (identifier: Id, options?: { + readonly topLevel?: TopLevel | undefined +}): HttpApiGroup => makeProto({ identifier, - endpoints: Chunk.empty(), + topLevel: options?.topLevel ?? false as any, + endpoints: HashMap.empty(), errorSchema: Schema.Never as any, - annotations: Context.empty() + annotations: Context.empty(), + middlewares: HashSet.empty() }) - -/** - * Add an `HttpApiEndpoint` to an `HttpApiGroup`. - * - * @since 1.0.0 - * @category endpoints - */ -export const add: { - ( - endpoint: A - ): ( - self: HttpApiGroup - ) => HttpApiGroup - < - Name extends string, - Endpoints extends HttpApiEndpoint.HttpApiEndpoint.All, - Error, - ErrorR, - A extends HttpApiEndpoint.HttpApiEndpoint.All - >( - self: HttpApiGroup, - endpoint: A - ): HttpApiGroup -} = dual(2, < - Name extends string, - Endpoints extends HttpApiEndpoint.HttpApiEndpoint.All, - Error, - ErrorR, - A extends HttpApiEndpoint.HttpApiEndpoint.All ->( - self: HttpApiGroup, - endpoint: A -): HttpApiGroup => - makeProto({ - identifier: self.identifier, - errorSchema: self.errorSchema, - annotations: self.annotations, - endpoints: Chunk.append(self.endpoints, endpoint) - })) - -/** - * Add an error schema to an `HttpApiGroup`, which is shared by all endpoints in the - * group. - * - * @since 1.0.0 - * @category errors - */ -export const addError: { - ( - schema: Schema.Schema, - annotations?: { - readonly status?: number | undefined - } - ): ( - self: HttpApiGroup - ) => HttpApiGroup - ( - self: HttpApiGroup, - schema: Schema.Schema, - annotations?: { - readonly status?: number | undefined - } - ): HttpApiGroup -} = dual( - (args) => isHttpApiGroup(args[0]), - ( - self: HttpApiGroup, - schema: Schema.Schema, - annotations?: { - readonly status?: number | undefined - } - ): HttpApiGroup => - makeProto({ - identifier: self.identifier, - annotations: self.annotations, - endpoints: self.endpoints, - errorSchema: HttpApiSchema.UnionUnify( - self.errorSchema, - schema.annotations(HttpApiSchema.annotations({ - status: annotations?.status ?? HttpApiSchema.getStatusError(schema) - })) - ) - }) -) - -/** - * Add a path prefix to all endpoints in an `HttpApiGroup`. Note that this will only - * add the prefix to the endpoints before this api is called. - * - * @since 1.0.0 - * @category endpoints - */ -export const prefix: { - ( - prefix: PathInput - ): ( - self: HttpApiGroup - ) => HttpApiGroup - ( - self: HttpApiGroup, - prefix: PathInput - ): HttpApiGroup -} = dual(2, ( - self: HttpApiGroup, - prefix: PathInput -): HttpApiGroup => - makeProto({ - identifier: self.identifier, - errorSchema: self.errorSchema, - annotations: self.annotations, - endpoints: Chunk.map(self.endpoints, HttpApiEndpoint.prefix(prefix)) - })) - -/** - * Merge the annotations of an `HttpApiGroup` with a new context. - * - * @since 1.0.0 - * @category annotations - */ -export const annotateMerge: { - (context: Context.Context): (self: A) => A - (self: A, context: Context.Context): A -} = dual( - 2, - (self: A, context: Context.Context): A => - makeProto({ - ...self as any, - annotations: Context.merge(self.annotations, context) - }) as A -) - -/** - * Add an annotation to an `HttpApiGroup`. - * - * @since 1.0.0 - * @category annotations - */ -export const annotate: { - (tag: Context.Tag, value: S): (self: A) => A - (self: A, tag: Context.Tag, value: S): A -} = dual( - 3, - (self: A, tag: Context.Tag, value: S): A => - makeProto({ - identifier: self.identifier, - errorSchema: self.errorSchema as any, - endpoints: self.endpoints, - annotations: Context.add(self.annotations, tag, value) - }) as A -) - -/** - * For each endpoint in an `HttpApiGroup`, update the annotations with a new - * context. - * - * Note that this will only update the annotations before this api is called. - * - * @since 1.0.0 - * @category annotations - */ -export const annotateEndpointsMerge: { - (context: Context.Context): (self: A) => A - (self: A, context: Context.Context): A -} = dual( - 2, - (self: A, context: Context.Context): A => - makeProto({ - identifier: self.identifier, - errorSchema: self.errorSchema as any, - annotations: self.annotations, - endpoints: Chunk.map(self.endpoints, HttpApiEndpoint.annotateMerge(context)) - }) as A -) - -/** - * For each endpoint in an `HttpApiGroup`, add an annotation. - * - * Note that this will only add the annotation to the endpoints before this api - * is called. - * - * @since 1.0.0 - * @category annotations - */ -export const annotateEndpoints: { - (tag: Context.Tag, value: S): (self: A) => A - (self: A, tag: Context.Tag, value: S): A -} = dual( - 3, - (self: A, tag: Context.Tag, value: S): A => - makeProto({ - identifier: self.identifier, - errorSchema: self.errorSchema as any, - annotations: self.annotations, - endpoints: Chunk.map(self.endpoints, HttpApiEndpoint.annotate(tag, value)) - }) as A -) diff --git a/packages/platform/src/HttpApiMiddleware.ts b/packages/platform/src/HttpApiMiddleware.ts new file mode 100644 index 0000000000..36cbf3bd38 --- /dev/null +++ b/packages/platform/src/HttpApiMiddleware.ts @@ -0,0 +1,318 @@ +/** + * @since 1.0.0 + */ +import * as Context from "effect/Context" +import type * as Effect from "effect/Effect" +import { hasProperty } from "effect/Predicate" +import * as Schema from "effect/Schema" +import type { Mutable, Simplify } from "effect/Types" +import type * as HttpApiSecurity from "./HttpApiSecurity.js" +import type * as HttpRouter from "./HttpRouter.js" + +/** + * @since 1.0.0 + * @category type ids + */ +export const TypeId: unique symbol = Symbol.for("@effect/platform/HttpApiMiddleware") + +/** + * @since 1.0.0 + * @category type ids + */ +export type TypeId = typeof TypeId + +/** + * @since 1.0.0 + * @category type ids + */ +export const SecurityTypeId: unique symbol = Symbol.for("@effect/platform/HttpApiMiddleware/Security") + +/** + * @since 1.0.0 + * @category type ids + */ +export type SecurityTypeId = typeof SecurityTypeId + +/** + * @since 1.0.0 + * @category guards + */ +export const isSecurity = (u: TagClassAny): u is TagClassSecurityAny => hasProperty(u, SecurityTypeId) + +/** + * @since 1.0.0 + * @category models + */ +export interface HttpApiMiddleware extends Effect.Effect {} + +/** + * @since 1.0.0 + * @category models + */ +export type HttpApiMiddlewareSecurity, Provides, E> = { + readonly [K in keyof Security]: ( + _: HttpApiSecurity.HttpApiSecurity.Type + ) => Effect.Effect +} + +/** + * @since 1.0.0 + * @category models + */ +export declare namespace HttpApiMiddleware { + /** + * @since 1.0.0 + * @category models + */ + export interface Any { + readonly [TypeId]: TypeId + } + + /** + * @since 1.0.0 + * @category models + */ + export interface AnyId { + readonly [TypeId]: { + readonly provides: any + } + } + + /** + * @since 1.0.0 + * @category models + */ + export type Provides = A extends { readonly [TypeId]: { readonly provides: infer P } } ? P : never + + /** + * @since 1.0.0 + * @category models + */ + export type ExtractProvides = Provides> + + /** + * @since 1.0.0 + * @category models + */ + export type Error = A extends { readonly [TypeId]: { readonly failure: infer E } } ? E : never + + /** + * @since 1.0.0 + * @category models + */ + export type ErrorContext = A extends { readonly [TypeId]: { readonly failureContext: infer R } } ? R : never + + /** + * @since 1.0.0 + * @category models + */ + export type Only = Extract + + /** + * @since 1.0.0 + * @category models + */ + export type Without = Exclude +} + +/** + * @since 1.0.0 + * @category models + */ +export type TagClass< + Self, + Name extends string, + Options +> = Options extends { readonly security: Record } ? + & TagClass.Base< + Self, + Name, + Options, + Simplify< + HttpApiMiddlewareSecurity< + Options["security"], + TagClass.Service, + TagClass.FailureService + > + > + > + & TagClass.SecurityFields + : TagClass.Base< + Self, + Name, + Options, + HttpApiMiddleware< + TagClass.Service, + TagClass.FailureService + > + > + +/** + * @since 1.0.0 + * @category models + */ +export declare namespace TagClass { + /** + * @since 1.0.0 + * @category models + */ + export type Provides = Options extends { + readonly provides: Context.Tag + readonly optional?: false + } ? Context.Tag.Identifier + : never + + /** + * @since 1.0.0 + * @category models + */ + export type Service = Options extends { readonly provides: Context.Tag } + ? Context.Tag.Service + : void + + /** + * @since 1.0.0 + * @category models + */ + export type FailureSchema = Options extends + { readonly failure: Schema.Schema.All; readonly optional?: false } ? Options["failure"] + : typeof Schema.Never + + /** + * @since 1.0.0 + * @category models + */ + export type Failure = Schema.Schema.Type> + + /** + * @since 1.0.0 + * @category models + */ + export type FailureContext = Schema.Schema.Context> + + /** + * @since 1.0.0 + * @category models + */ + export type FailureService = Optional extends true ? unknown : Failure + + /** + * @since 1.0.0 + * @category models + */ + export type Optional = Options extends { readonly optional: true } ? true : false + + /** + * @since 1.0.0 + * @category models + */ + export type Base = + & BaseConstructor + & (Optional extends true ? {} + : Options extends { readonly provides: Context.Tag } ? { readonly provides: Options["provides"] } + : {}) + + /** + * @since 1.0.0 + * @category models + */ + export interface BaseConstructor extends Context.Tag { + new(_: never): + & Context.TagClassShape + & { + readonly [TypeId]: { + readonly provides: Provides + readonly failure: Failure + readonly failureContext: FailureContext + } + } + readonly [TypeId]: TypeId + readonly optional: Optional + readonly failure: FailureSchema + } + + /** + * @since 1.0.0 + * @category models + */ + export interface SecurityFields> { + readonly [SecurityTypeId]: SecurityTypeId + readonly security: Security + } +} + +/** + * @since 1.0.0 + * @category models + */ +export interface TagClassAny extends Context.Tag { + readonly [TypeId]: TypeId + readonly optional: boolean + readonly provides?: Context.Tag + readonly failure: Schema.Schema.All +} + +/** + * @since 1.0.0 + * @category models + */ +export interface TagClassSecurityAny extends TagClassAny { + readonly [SecurityTypeId]: SecurityTypeId + readonly security: Record +} + +/** + * @since 1.0.0 + * @category tags + */ +export const Tag = (): < + const Name extends string, + const Options extends { + readonly optional?: boolean + readonly failure?: Schema.Schema.All + readonly provides?: Context.Tag + readonly security?: Record + } +>( + id: Name, + options?: Options | undefined +) => TagClass => +( + id: string, + options?: { + readonly optional?: boolean + readonly security?: Record + readonly failure?: Schema.Schema.All + readonly provides?: Context.Tag + } +) => { + const Err = globalThis.Error as any + const limit = Err.stackTraceLimit + Err.stackTraceLimit = 2 + const creationError = new Err() + Err.stackTraceLimit = limit + + function TagClass() {} + const TagClass_ = TagClass as any as Mutable + Object.setPrototypeOf(TagClass, Object.getPrototypeOf(Context.GenericTag(id))) + TagClass.key = id + Object.defineProperty(TagClass, "stack", { + get() { + return creationError.stack + } + }) + TagClass_[TypeId] = TypeId + TagClass_.failure = options?.optional === true || options?.failure === undefined ? Schema.Never : options.failure + if (options?.provides) { + TagClass_.provides = options.provides + } + TagClass_.optional = options?.optional ?? false + if (options?.security) { + if (Object.keys(options.security).length === 0) { + throw new Error("HttpApiMiddleware.Tag: security object must not be empty") + } + TagClass_[SecurityTypeId] = SecurityTypeId + TagClass_.security = options.security + } + return TagClass as any +} diff --git a/packages/platform/src/HttpApiSchema.ts b/packages/platform/src/HttpApiSchema.ts index b471b86ff7..aa698413dc 100644 --- a/packages/platform/src/HttpApiSchema.ts +++ b/packages/platform/src/HttpApiSchema.ts @@ -4,6 +4,7 @@ import type { Brand } from "effect/Brand" import type { LazyArg } from "effect/Function" import { constVoid, dual } from "effect/Function" +import { globalValue } from "effect/GlobalValue" import * as Schema from "effect/Schema" import * as AST from "effect/SchemaAST" import * as Struct from "effect/Struct" @@ -382,3 +383,39 @@ export const Text = (options?: { export const Uint8Array = (options?: { readonly contentType?: string }): typeof Schema.Uint8ArrayFromSelf => withEncoding(Schema.Uint8ArrayFromSelf, { kind: "Uint8Array", ...options }) + +const astCache = globalValue( + "@effect/platform/HttpApiSchema/astCache", + () => new WeakMap() +) + +/** + * @since 1.0.0 + */ +export const deunionize = ( + schemas: Set, + schema: Schema.Schema.Any +): void => { + if (astCache.has(schema.ast)) { + schemas.add(astCache.get(schema.ast)!) + return + } + const ast = schema.ast + if (ast._tag === "Union") { + for (const astType of ast.types) { + if (astCache.has(astType)) { + schemas.add(astCache.get(astType)!) + continue + } + const memberSchema = Schema.make(AST.annotations(astType, { + ...ast.annotations, + ...astType.annotations + })) + astCache.set(astType, memberSchema) + schemas.add(memberSchema) + } + } else { + astCache.set(ast, schema) + schemas.add(schema) + } +} diff --git a/packages/platform/src/HttpApiSecurity.ts b/packages/platform/src/HttpApiSecurity.ts index 31578289b7..ad265e669d 100644 --- a/packages/platform/src/HttpApiSecurity.ts +++ b/packages/platform/src/HttpApiSecurity.ts @@ -140,7 +140,7 @@ export const basic: Basic = Object.assign(Object.create(Proto), { * @since 1.0.0 * @category annotations */ -export const annotateMerge: { +export const annotateContext: { (context: Context.Context): (self: A) => A (self: A, context: Context.Context): A } = dual( diff --git a/packages/platform/src/HttpApiSwagger.ts b/packages/platform/src/HttpApiSwagger.ts index 67f4eeb80a..ff1175faa4 100644 --- a/packages/platform/src/HttpApiSwagger.ts +++ b/packages/platform/src/HttpApiSwagger.ts @@ -3,7 +3,7 @@ */ import * as Effect from "effect/Effect" import type { Layer } from "effect/Layer" -import { HttpApi } from "./HttpApi.js" +import { Api } from "./HttpApi.js" import { Router } from "./HttpApiBuilder.js" import * as HttpServerResponse from "./HttpServerResponse.js" import * as internal from "./internal/apiSwagger.js" @@ -15,10 +15,10 @@ import * as OpenApi from "./OpenApi.js" */ export const layer = (options?: { readonly path?: `/${string}` | undefined -}): Layer => +}): Layer => Router.use((router) => Effect.gen(function*() { - const api = yield* HttpApi + const { api } = yield* Api const spec = OpenApi.fromApi(api) const response = HttpServerResponse.html(` diff --git a/packages/platform/src/HttpServer.ts b/packages/platform/src/HttpServer.ts index 695ce3e98b..120590be0e 100644 --- a/packages/platform/src/HttpServer.ts +++ b/packages/platform/src/HttpServer.ts @@ -5,11 +5,15 @@ import type * as Context from "effect/Context" import type * as Effect from "effect/Effect" import type * as Layer from "effect/Layer" import type * as Scope from "effect/Scope" +import type { Generator } from "./Etag.js" +import type { FileSystem } from "./FileSystem.js" import type * as App from "./HttpApp.js" import type * as Client from "./HttpClient.js" import type * as Middleware from "./HttpMiddleware.js" +import type { HttpPlatform } from "./HttpPlatform.js" import type * as ServerRequest from "./HttpServerRequest.js" import * as internal from "./internal/httpServer.js" +import type { Path } from "./Path.js" /** * @since 1.0.0 @@ -203,3 +207,20 @@ export const withLogAddress: (layer: Layer.Layer) => Layer.Lay */ export const layerTestClient: Layer.Layer = internal.layerTestClient + +/** + * A Layer providing the `HttpPlatform`, `FileSystem`, `Etag.Generator`, and `Path` + * services. + * + * The `FileSystem` service is a no-op implementation, so this layer is only + * useful for platforms that have no file system. + * + * @since 1.0.0 + * @category layers + */ +export const layerContext: Layer.Layer< + | HttpPlatform + | FileSystem + | Generator + | Path +> = internal.layerContext diff --git a/packages/platform/src/OpenApi.ts b/packages/platform/src/OpenApi.ts index f447d2a282..5c2b16ea20 100644 --- a/packages/platform/src/OpenApi.ts +++ b/packages/platform/src/OpenApi.ts @@ -2,13 +2,14 @@ * @since 1.0.0 */ import * as Context from "effect/Context" -import { dual } from "effect/Function" +import * as HashSet from "effect/HashSet" import * as Option from "effect/Option" import type { ReadonlyRecord } from "effect/Record" import * as Schema from "effect/Schema" import * as AST from "effect/SchemaAST" import type { DeepMutable, Mutable } from "effect/Types" import * as HttpApi from "./HttpApi.js" +import * as HttpApiMiddleware from "./HttpApiMiddleware.js" import * as HttpApiSchema from "./HttpApiSchema.js" import type { HttpApiSecurity } from "./HttpApiSecurity.js" import * as HttpMethod from "./HttpMethod.js" @@ -48,16 +49,24 @@ export class License extends Context.Tag("@effect/platform/OpenApi/License")() {} +export class ExternalDocs + extends Context.Tag("@effect/platform/OpenApi/ExternalDocs")() +{} /** * @since 1.0.0 * @category annotations */ -export class ExternalDocs - extends Context.Tag("@effect/platform/OpenApi/ExternalDocs")() +export class Servers + extends Context.Tag("@effect/platform/OpenApi/Servers")>() {} +/** + * @since 1.0.0 + * @category annotations + */ +export class Override extends Context.Tag("@effect/platform/OpenApi/Override")>() {} + /** * @since 1.0.0 * @category annotations @@ -68,8 +77,9 @@ export const annotations = (annotations: { readonly description?: string | undefined readonly version?: string | undefined readonly license?: OpenAPISpecLicense | undefined - readonly security?: HttpApiSecurity | undefined readonly externalDocs?: OpenAPISpecExternalDocs | undefined + readonly servers?: ReadonlyArray | undefined + readonly override?: Record | undefined }): Context.Context => { let context = Context.empty() if (annotations.identifier !== undefined) { @@ -87,12 +97,15 @@ export const annotations = (annotations: { if (annotations.license !== undefined) { context = Context.add(context, License, annotations.license) } - if (annotations.security !== undefined) { - context = Context.add(context, Security, annotations.security) - } if (annotations.externalDocs !== undefined) { context = Context.add(context, ExternalDocs, annotations.externalDocs) } + if (annotations.servers !== undefined) { + context = Context.add(context, Servers, annotations.servers) + } + if (annotations.override !== undefined) { + context = Context.add(context, Override, annotations.override) + } return context } @@ -104,54 +117,13 @@ export interface Annotatable { readonly annotations: Context.Context } -/** - * @since 1.0.0 - * @category annotations - */ -export const annotate: { - (annotations: { - readonly identifier?: string | undefined - readonly title?: string | undefined - readonly description?: string | undefined - readonly version?: string | undefined - readonly license?: OpenAPISpecLicense | undefined - readonly security?: HttpApiSecurity | undefined - readonly externalDocs?: OpenAPISpecExternalDocs | undefined - }): (self: A) => A - (self: A, annotations: { - readonly identifier?: string | undefined - readonly title?: string | undefined - readonly description?: string | undefined - readonly version?: string | undefined - readonly license?: OpenAPISpecLicense | undefined - readonly security?: HttpApiSecurity | undefined - readonly externalDocs?: OpenAPISpecExternalDocs | undefined - }): A -} = dual(2, (self: A, annotations_: { - readonly identifier?: string | undefined - readonly title?: string | undefined - readonly description?: string | undefined - readonly version?: string | undefined - readonly license?: OpenAPISpecLicense | undefined - readonly security?: HttpApiSecurity | undefined - readonly externalDocs?: OpenAPISpecExternalDocs | undefined -}): A => { - const base = typeof self === "function" ? function() {} : self - Object.setPrototypeOf(base, Object.getPrototypeOf(self)) - const context = Context.merge( - self.annotations, - annotations(annotations_) - ) - return Object.assign(base, self, { - annotations: context - }) -}) - /** * @category constructors * @since 1.0.0 */ -export const fromApi = (api: A): OpenAPISpec => { +export const fromApi = (self: A): OpenAPISpec => { + const api = self as unknown as HttpApi.HttpApi.AnyWithProps + const jsonSchemaDefs: Record = {} const spec: DeepMutable = { openapi: "3.0.3", info: { @@ -161,22 +133,28 @@ export const fromApi = (api: A): OpenAPISpec => { paths: {}, tags: [], components: { - schemas: {}, + schemas: jsonSchemaDefs, securitySchemes: {} }, security: [] } - const securityMap = new Map() - let securityCount = 0 - function registerSecurity(security: HttpApiSecurity): string { - if (securityMap.has(security)) { - return securityMap.get(security)! + function makeJsonSchemaOrRef(schema: Schema.Schema.All): JsonSchema.JsonSchema { + return JsonSchema.makeWithDefs(schema as any, { + defs: jsonSchemaDefs, + defsPath: "#/components/schemas/" + }) + } + function registerSecurity( + tag: HttpApiMiddleware.TagClassSecurityAny, + name: string, + security: HttpApiSecurity + ): string { + const id = `${tag.key}/${name}` + if (spec.components!.securitySchemes![id]) { + return id } - const count = securityCount++ - const id = `${security._tag}${count === 0 ? "" : count}` const scheme = makeSecurityScheme(security) spec.components!.securitySchemes![id] = scheme - securityMap.set(security, id) return id } Option.map(Context.getOption(api.annotations, Description), (description) => { @@ -185,10 +163,22 @@ export const fromApi = (api: A): OpenAPISpec => { Option.map(Context.getOption(api.annotations, License), (license) => { spec.info.license = license }) - Option.map(Context.getOption(api.annotations, Security), (apiSecurity) => { - spec.security!.push({ - [registerSecurity(apiSecurity)]: [] - }) + Option.map(Context.getOption(api.annotations, Servers), (servers) => { + spec.servers = servers as any + }) + Option.map(Context.getOption(api.annotations, Override), (override) => { + Object.assign(spec, override) + }) + HashSet.forEach(api.middlewares, (middleware) => { + if (!HttpApiMiddleware.isSecurity(middleware)) { + return + } + for (const [name, security] of Object.entries(middleware.security)) { + const id = registerSecurity(middleware, name, security) + spec.security!.push({ + [id]: [] + }) + } }) HttpApi.reflect(api as any, { onGroup({ group }) { @@ -201,21 +191,24 @@ export const fromApi = (api: A): OpenAPISpec => { Option.map(Context.getOption(group.annotations, ExternalDocs), (externalDocs) => { tag.externalDocs = externalDocs }) + Option.map(Context.getOption(group.annotations, Override), (override) => { + Object.assign(tag, override) + }) spec.tags!.push(tag) }, - onEndpoint({ endpoint, errors, group, mergedAnnotations, successAST, successEncoding, successStatus }) { + onEndpoint({ endpoint, errors, group, middleware, successes }) { const path = endpoint.path.replace(/:(\w+)[^/]*/g, "{$1}") const method = endpoint.method.toLowerCase() as OpenAPISpecMethodName const op: DeepMutable = { tags: [Context.getOrElse(group.annotations, Title, () => group.identifier)], - operationId: Context.getOrElse(endpoint.annotations, Identifier, () => `${group.identifier}.${endpoint.name}`), + operationId: Context.getOrElse( + endpoint.annotations, + Identifier, + () => group.topLevel ? endpoint.name : `${group.identifier}.${endpoint.name}` + ), parameters: [], security: [], - responses: { - [successStatus]: { - description: Option.getOrElse(getDescriptionOrIdentifier(successAST), () => "Success") - } - } + responses: {} } Option.map(Context.getOption(endpoint.annotations, Description), (description) => { op.description = description @@ -223,10 +216,16 @@ export const fromApi = (api: A): OpenAPISpec => { Option.map(Context.getOption(endpoint.annotations, ExternalDocs), (externalDocs) => { op.externalDocs = externalDocs }) - Option.map(Context.getOption(mergedAnnotations, Security), (apiSecurity) => { - op.security!.push({ - [registerSecurity(apiSecurity)]: [] - }) + HashSet.forEach(middleware, (middleware) => { + if (!HttpApiMiddleware.isSecurity(middleware)) { + return + } + for (const [name, security] of Object.entries(middleware.security)) { + const id = registerSecurity(middleware, name, security) + op.security!.push({ + [id]: [] + }) + } }) endpoint.payloadSchema.pipe( Option.filter(() => HttpMethod.hasBody(endpoint.method)), @@ -234,24 +233,31 @@ export const fromApi = (api: A): OpenAPISpec => { op.requestBody = { content: { [HttpApiSchema.getMultipart(schema.ast) ? "multipart/form-data" : "application/json"]: { - schema: JsonSchema.make(schema) + schema: makeJsonSchemaOrRef(schema) } }, required: true } }) ) - successAST.pipe( - Option.map((ast) => { - op.responses![successStatus].content = { - [successEncoding.contentType]: { - schema: JsonSchema.make(Schema.make(ast)) + for (const [status, ast] of successes) { + if (op.responses![status]) continue + op.responses![status] = { + description: Option.getOrElse(getDescriptionOrIdentifier(ast), () => "Success") + } + ast.pipe( + Option.filter((ast) => !HttpApiSchema.getEmptyDecodeable(ast)), + Option.map((ast) => { + op.responses![status].content = { + "application/json": { + schema: makeJsonSchemaOrRef(Schema.make(ast)) + } } - } - }) - ) + }) + ) + } if (Option.isSome(endpoint.pathSchema)) { - const schema = JsonSchema.make(endpoint.pathSchema.value) as JsonSchema.Object + const schema = makeJsonSchemaOrRef(endpoint.pathSchema.value) as JsonSchema.Object if ("properties" in schema) { Object.entries(schema.properties).forEach(([name, jsonSchema]) => { op.parameters!.push({ @@ -264,7 +270,7 @@ export const fromApi = (api: A): OpenAPISpec => { } } if (!HttpMethod.hasBody(endpoint.method) && Option.isSome(endpoint.payloadSchema)) { - const schema = JsonSchema.make(endpoint.payloadSchema.value) as JsonSchema.Object + const schema = makeJsonSchemaOrRef(endpoint.payloadSchema.value) as JsonSchema.Object if ("properties" in schema) { Object.entries(schema.properties).forEach(([name, jsonSchema]) => { op.parameters!.push({ @@ -277,7 +283,7 @@ export const fromApi = (api: A): OpenAPISpec => { } } if (Option.isSome(endpoint.headersSchema)) { - const schema = JsonSchema.make(endpoint.headersSchema.value) as JsonSchema.Object + const schema = makeJsonSchemaOrRef(endpoint.headersSchema.value) as JsonSchema.Object if ("properties" in schema) { Object.entries(schema.properties).forEach(([name, jsonSchema]) => { op.parameters!.push({ @@ -289,6 +295,19 @@ export const fromApi = (api: A): OpenAPISpec => { }) } } + if (Option.isSome(endpoint.urlParamsSchema)) { + const schema = makeJsonSchemaOrRef(endpoint.urlParamsSchema.value) as JsonSchema.Object + if ("properties" in schema) { + Object.entries(schema.properties).forEach(([name, jsonSchema]) => { + op.parameters!.push({ + name, + in: "query", + schema: jsonSchema, + required: schema.required.includes(name) + }) + }) + } + } for (const [status, ast] of errors) { if (op.responses![status]) continue op.responses![status] = { @@ -299,7 +318,7 @@ export const fromApi = (api: A): OpenAPISpec => { Option.map((ast) => { op.responses![status].content = { "application/json": { - schema: JsonSchema.make(Schema.make(ast)) + schema: makeJsonSchemaOrRef(Schema.make(ast)) } } }) @@ -308,6 +327,9 @@ export const fromApi = (api: A): OpenAPISpec => { if (!spec.paths[path]) { spec.paths[path] = {} } + Option.map(Context.getOption(endpoint.annotations, Override), (override) => { + Object.assign(op, override) + }) spec.paths[path][method] = op } }) diff --git a/packages/platform/src/OpenApiJsonSchema.ts b/packages/platform/src/OpenApiJsonSchema.ts index 8a7e2487a5..8aa1fa165f 100644 --- a/packages/platform/src/OpenApiJsonSchema.ts +++ b/packages/platform/src/OpenApiJsonSchema.ts @@ -213,19 +213,32 @@ export type Root = JsonSchema & { */ export const make = (schema: Schema.Schema): Root => { const $defs: Record = {} - const out = go(schema.ast, $defs, true, []) as Root - // clean up self-referencing entries - for (const id in $defs) { - if ($defs[id]["$ref"] === get$ref(id)) { - delete $defs[id] - } - } + const out = makeWithDefs(schema, { defs: $defs }) if (!Record.isEmptyRecord($defs)) { out.$defs = $defs } return out } +/** + * @category encoding + * @since 1.0.0 + */ +export const makeWithDefs = (schema: Schema.Schema, options: { + readonly defs: Record + readonly defsPath?: string +}): Root => { + const defsPath = options.defsPath ?? "#/$defs/" + const getRef = (id: string) => `${defsPath}${id}` + const out = go(schema.ast, options.defs, true, [], { getRef }) as Root + for (const id in options.defs) { + if (options.defs[id]["$ref"] === getRef(id)) { + delete options.defs[id] + } + } + return out +} + const constAny: JsonSchema = { $id: "/schemas/any" } const constUnknown: JsonSchema = { $id: "/schemas/unknown" } @@ -293,10 +306,6 @@ const pruneUndefinedKeyword = (ps: AST.PropertySignature): AST.AST | undefined = } } -const DEFINITION_PREFIX = "#/$defs/" - -const get$ref = (id: string): string => `${DEFINITION_PREFIX}${id}` - const getRefinementInnerTransformation = (ast: AST.Refinement): AST.AST | undefined => { switch (ast.from._tag) { case "Transformation": @@ -313,7 +322,8 @@ const getRefinementInnerTransformation = (ast: AST.Refinement): AST.AST | undefi } const isParseJsonTransformation = (ast: AST.AST): boolean => - ast.annotations[AST.SchemaIdAnnotationId] === AST.ParseJsonSchemaId + ast._tag === "Transformation" && + ast.from.annotations[AST.SchemaIdAnnotationId] === AST.ParseJsonSchemaId const isOverrideAnnotation = (jsonSchema: JsonSchema): boolean => { return ("type" in jsonSchema) || ("oneOf" in jsonSchema) || ("anyOf" in jsonSchema) || ("const" in jsonSchema) || @@ -324,7 +334,10 @@ const go = ( ast: AST.AST, $defs: Record, handleIdentifier: boolean, - path: ReadonlyArray + path: ReadonlyArray, + options: { + readonly getRef: (id: string) => string + } ): JsonSchema => { const hook = AST.getJSONSchemaAnnotation(ast) if (Option.isSome(hook)) { @@ -334,7 +347,7 @@ const go = ( if (t === undefined) { try { return { - ...go(ast.from, $defs, true, path), + ...go(ast.from, $defs, true, path, options), ...getJsonSchemaAnnotations(ast), ...handler } @@ -346,7 +359,7 @@ const go = ( } } else if (!isOverrideAnnotation(handler)) { return { - ...go(t, $defs, true, path), + ...go(t, $defs, true, path, options), ...getJsonSchemaAnnotations(ast) } } @@ -354,25 +367,34 @@ const go = ( return handler } const surrogate = AST.getSurrogateAnnotation(ast) - if (Option.isSome(surrogate)) { - return { - ...(ast._tag === "Transformation" ? getJsonSchemaAnnotations(ast.to) : {}), - ...go(surrogate.value, $defs, handleIdentifier, path), - ...getJsonSchemaAnnotations(ast) - } - } - if (handleIdentifier && !AST.isTransformation(ast) && !AST.isRefinement(ast)) { - const identifier = AST.getJSONIdentifier(ast) + if (handleIdentifier && !AST.isRefinement(ast)) { + const identifier = AST.getJSONIdentifier( + Option.isSome(surrogate) ? + { + annotations: { + ...(ast._tag === "Transformation" ? ast.to.annotations : {}), + ...ast.annotations + } + } : + ast + ) if (Option.isSome(identifier)) { const id = identifier.value - const out = { $ref: get$ref(id) } + const out = { $ref: options.getRef(id) } if (!Record.has($defs, id)) { $defs[id] = out - $defs[id] = go(ast, $defs, false, path) + $defs[id] = go(ast, $defs, false, path, options) } return out } } + if (Option.isSome(surrogate)) { + return { + ...(ast._tag === "Transformation" ? getJsonSchemaAnnotations(ast.to) : {}), + ...go(surrogate.value, $defs, handleIdentifier, path, options), + ...getJsonSchemaAnnotations(ast) + } + } switch (ast._tag) { case "Declaration": throw new Error(getJSONSchemaMissingAnnotationErrorMessage(path, ast)) @@ -430,11 +452,11 @@ const go = ( throw new Error(getJSONSchemaMissingAnnotationErrorMessage(path, ast)) case "TupleType": { const elements = ast.elements.map((e, i) => ({ - ...go(e.type, $defs, true, path.concat(i)), + ...go(e.type, $defs, true, path.concat(i), options), ...getJsonSchemaAnnotations(e) })) const rest = ast.rest.map((annotatedAST) => ({ - ...go(annotatedAST.type, $defs, true, path), + ...go(annotatedAST.type, $defs, true, path, options), ...getJsonSchemaAnnotations(annotatedAST) })) const output: Array = { type: "array" } @@ -491,11 +513,11 @@ const go = ( const parameter = is.parameter switch (parameter._tag) { case "StringKeyword": { - patternProperties = go(is.type, $defs, true, path) + patternProperties = go(is.type, $defs, true, path, options) break } case "TemplateLiteral": { - patternProperties = go(is.type, $defs, true, path) + patternProperties = go(is.type, $defs, true, path, options) propertyNames = { type: "string", pattern: AST.getTemplateLiteralRegExp(parameter).source @@ -503,8 +525,8 @@ const go = ( break } case "Refinement": { - patternProperties = go(is.type, $defs, true, path) - propertyNames = go(parameter, $defs, true, path) + patternProperties = go(is.type, $defs, true, path, options) + propertyNames = go(parameter, $defs, true, path, options) break } case "SymbolKeyword": @@ -526,7 +548,7 @@ const go = ( if (Predicate.isString(name)) { const pruned = pruneUndefinedKeyword(ps) output.properties[name] = { - ...go(pruned ? pruned : ps.type, $defs, true, path.concat(ps.name)), + ...go(pruned ? pruned : ps.type, $defs, true, path.concat(ps.name), options), ...getJsonSchemaAnnotations(ps) } // --------------------------------------------- @@ -559,7 +581,7 @@ const go = ( const enums: globalThis.Array = [] const anyOf: globalThis.Array = [] for (const type of ast.types) { - const schema = go(type, $defs, true, path) + const schema = go(type, $defs, true, path, options) if ("enum" in schema) { if (Object.keys(schema).length > 1) { anyOf.push(schema) @@ -592,7 +614,7 @@ const go = ( if (AST.encodedBoundAST(ast) === ast) { throw new Error(getJSONSchemaMissingAnnotationErrorMessage(path, ast)) } - return go(ast.from, $defs, true, path) + return go(ast.from, $defs, true, path, options) } case "TemplateLiteral": { const regex = AST.getTemplateLiteralRegExp(ast) @@ -609,7 +631,7 @@ const go = ( throw new Error(getJSONSchemaMissingIdentifierAnnotationErrorMessage(path, ast)) } return { - ...go(ast.f(), $defs, true, path), + ...go(ast.f(), $defs, true, path, options), ...getJsonSchemaAnnotations(ast) } } @@ -618,17 +640,17 @@ const go = ( // the 'to' side of the AST. This approach prevents the generation of useless schemas // derived from the 'from' side (type: string), ensuring the output matches the intended // complex schema type. - if (isParseJsonTransformation(ast.from)) { + if (isParseJsonTransformation(ast)) { return { type: "string", contentMediaType: "application/json", - contentSchema: go(ast.to, $defs, true, path), + contentSchema: go(ast.to, $defs, true, path, options), ...getJsonSchemaAnnotations(ast) } } return { ...getASTJsonSchemaAnnotations(ast.to), - ...go(ast.from, $defs, true, path), + ...go(ast.from, $defs, true, path, options), ...getJsonSchemaAnnotations(ast) } } diff --git a/packages/platform/src/index.ts b/packages/platform/src/index.ts index 51d7599777..926cb2b624 100644 --- a/packages/platform/src/index.ts +++ b/packages/platform/src/index.ts @@ -73,6 +73,11 @@ export * as HttpApiError from "./HttpApiError.js" */ export * as HttpApiGroup from "./HttpApiGroup.js" +/** + * @since 1.0.0 + */ +export * as HttpApiMiddleware from "./HttpApiMiddleware.js" + /** * @since 1.0.0 */ diff --git a/packages/platform/src/internal/httpServer.ts b/packages/platform/src/internal/httpServer.ts index 402faa13a6..9d73ed1e90 100644 --- a/packages/platform/src/internal/httpServer.ts +++ b/packages/platform/src/internal/httpServer.ts @@ -9,6 +9,10 @@ import * as ClientRequest from "../HttpClientRequest.js" import type * as Middleware from "../HttpMiddleware.js" import type * as Server from "../HttpServer.js" import type * as ServerRequest from "../HttpServerRequest.js" +import * as internalEtag from "./etag.js" +import * as internalFileSystem from "./fileSystem.js" +import * as internalPlatform from "./httpPlatform.js" +import * as internalPath from "./path.js" /** @internal */ export const TypeId: Server.TypeId = Symbol.for("@effect/platform/HttpServer") as Server.TypeId @@ -181,3 +185,12 @@ export const makeTestClient = addressWith((address) => /** @internal */ export const layerTestClient = Layer.effect(Client.HttpClient, makeTestClient) + +/** @internal */ +export const layerContext = Layer.mergeAll( + internalPlatform.layer, + internalPath.layer, + internalEtag.layerWeak +).pipe( + Layer.provideMerge(internalFileSystem.layerNoop({})) +) diff --git a/packages/platform/test/OpenApiJsonSchema.test.ts b/packages/platform/test/OpenApiJsonSchema.test.ts index be83d847a9..35da971ba9 100644 --- a/packages/platform/test/OpenApiJsonSchema.test.ts +++ b/packages/platform/test/OpenApiJsonSchema.test.ts @@ -1426,36 +1426,46 @@ schema (Suspend): ` it("should support make(Class)", () => { class A extends Schema.Class("A")({ a: Schema.String }) {} expectJSONSchema(A, { - "type": "object", - "required": [ - "a" - ], - "properties": { - "a": { - "type": "string" + $defs: { + "A": { + "type": "object", + "required": [ + "a" + ], + "properties": { + "a": { + "type": "string" + } + }, + "additionalProperties": false, + "description": "an instance of A", + "title": "A" } }, - "additionalProperties": false, - "description": "an instance of A", - "title": "A" + $ref: "#/$defs/A" }) }) it("should support make(S.typeSchema(Class))", () => { class A extends Schema.Class("A")({ a: Schema.String }) {} expectJSONSchema(Schema.typeSchema(A), { - "type": "object", - "required": [ - "a" - ], - "properties": { - "a": { - "type": "string" + $defs: { + "A": { + "type": "object", + "required": [ + "a" + ], + "properties": { + "a": { + "type": "string" + } + }, + "additionalProperties": false, + "description": "an instance of A", + "title": "A" } }, - "additionalProperties": false, - "description": "an instance of A", - "title": "A" + $ref: "#/$defs/A" }) }) @@ -1819,21 +1829,39 @@ schema (Suspend): ` it("refinement of a transformation without an override annotation", () => { expectJSONSchema(Schema.Trim.pipe(Schema.nonEmptyString()), { - "type": "string", - "title": "Trimmed", + $defs: { + "Trim": { + "type": "string", + "title": "Trimmed", + "description": "a string that will be trimmed" + } + }, + $ref: "#/$defs/Trim", "description": "a non empty string" }, false) expectJSONSchema(Schema.Trim.pipe(Schema.nonEmptyString({ jsonSchema: { title: "Description" } })), { - "description": "a non empty string", - "type": "string", - "title": "Trimmed" + $defs: { + "Trim": { + "type": "string", + "title": "Trimmed", + "description": "a string that will be trimmed" + } + }, + $ref: "#/$defs/Trim", + "description": "a non empty string" }, false) expectJSONSchema( Schema.Trim.pipe(Schema.nonEmptyString()).annotations({ jsonSchema: { title: "Description" } }), { - "description": "a non empty string", - "type": "string", - "title": "Trimmed" + $defs: { + "Trim": { + "type": "string", + "title": "Trimmed", + "description": "a string that will be trimmed" + } + }, + $ref: "#/$defs/Trim", + "description": "a non empty string" }, false ) @@ -1841,27 +1869,6 @@ schema (Suspend): ` }) describe("transformations", () => { - it("should not handle identifiers", () => { - expectJSONSchema( - Schema.Struct({ - a: Schema.NumberFromString - }), - { - "type": "object", - "required": [ - "a" - ], - "properties": { - "a": { - description: "a string that will be parsed into a number", - "type": "string" - } - }, - "additionalProperties": false - } - ) - }) - it("compose", () => { expectJSONSchema( Schema.Struct({ @@ -2043,6 +2050,12 @@ schema (Suspend): ` a: Schema.parseJson(Schema.NumberFromString) // Nested parsing from JSON string to number })), { + $defs: { + "NumberFromString": { + "type": "string", + "description": "a string that will be parsed into a number" + } + }, type: "string", contentMediaType: "application/json", contentSchema: { @@ -2052,8 +2065,7 @@ schema (Suspend): ` a: { contentMediaType: "application/json", contentSchema: { - description: "a string that will be parsed into a number", - type: "string" + $ref: "#/$defs/NumberFromString" }, type: "string" } @@ -2095,14 +2107,19 @@ schema (Suspend): ` value: Schema.NumberFromString }), { + $defs: { + "NumberFromString": { + "type": "string", + "description": "a string that will be parsed into a number" + } + }, "description": "a record that will be parsed into a ReadonlyMap", "type": "object", "required": [], "properties": {}, "patternProperties": { "": { - "description": "a string that will be parsed into a number", - "type": "string" + $ref: "#/$defs/NumberFromString" } }, "propertyNames": { @@ -2121,14 +2138,19 @@ schema (Suspend): ` value: Schema.NumberFromString }), { + $defs: { + "NumberFromString": { + "type": "string", + "description": "a string that will be parsed into a number" + } + }, "type": "object", "description": "a record that will be parsed into a Map", "required": [], "properties": {}, "patternProperties": { "": { - "description": "a string that will be parsed into a number", - "type": "string" + $ref: "#/$defs/NumberFromString" } }, "propertyNames": { @@ -2155,8 +2177,13 @@ schema (Suspend): ` expectJSONSchema( Schema.DateFromString, { - "type": "string", - "description": "a string that will be parsed into a Date" + $defs: { + "DateFromString": { + "type": "string", + "description": "a string that will be parsed into a Date" + } + }, + $ref: "#/$defs/DateFromString" } ) }) @@ -2165,8 +2192,13 @@ schema (Suspend): ` expectJSONSchema( Schema.Date, { - "type": "string", - "description": "a string that will be parsed into a Date" + $defs: { + "DateFromString": { + "type": "string", + "description": "a string that will be parsed into a Date" + } + }, + $ref: "#/$defs/DateFromString" } ) }) From c2575c420c95265a35776d441f5af49861f8e3e3 Mon Sep 17 00:00:00 2001 From: Jesse Kelly Date: Mon, 21 Oct 2024 03:12:36 +0200 Subject: [PATCH 7/8] Vitest prop testing (#3703) --- .changeset/young-boxes-reflect.md | 31 +++++++++++++++ packages/vitest/src/index.ts | 53 ++++++++++++++++++++++++- packages/vitest/src/internal.ts | 64 ++++++++++++++++++++++++++++-- packages/vitest/test/index.test.ts | 31 ++++++++++++++- 4 files changed, 173 insertions(+), 6 deletions(-) create mode 100644 .changeset/young-boxes-reflect.md diff --git a/.changeset/young-boxes-reflect.md b/.changeset/young-boxes-reflect.md new file mode 100644 index 0000000000..2c86f04656 --- /dev/null +++ b/.changeset/young-boxes-reflect.md @@ -0,0 +1,31 @@ +--- +"@effect/vitest": patch +--- + +Adds property testing to @effect/vitest + +```ts +import { Schema } from "effect" +import { it } from "@effect/vitest" + +const realNumber = Schema.Finite.pipe(Schema.nonNaN()) + +it.prop("symmetry", [realNumber, realNumber], ([a, b]) => a + b === b + a) + +it.effect.prop("symmetry", [realNumber, realNumber], ([a, b]) => + Effect.gen(function* () { + yield* Effect.void + return a + b === b + a + }) +) + +it.scoped.prop( + "should detect the substring", + { a: Schema.String, b: Schema.String, c: Schema.String }, + ({ a, b, c }) => + Effect.gen(function* () { + yield* Effect.scope + return (a + b + c).includes(b) + }) +) +``` diff --git a/packages/vitest/src/index.ts b/packages/vitest/src/index.ts index fb3df71a59..dbed927fdd 100644 --- a/packages/vitest/src/index.ts +++ b/packages/vitest/src/index.ts @@ -4,6 +4,7 @@ import type * as Duration from "effect/Duration" import type * as Effect from "effect/Effect" import type * as Layer from "effect/Layer" +import type * as Schema from "effect/Schema" import type * as Scope from "effect/Scope" import type * as TestServices from "effect/TestServices" import * as V from "vitest" @@ -36,6 +37,11 @@ export namespace Vitest { ): void } + /** + * @since 1.0.0 + */ + export type SchemaObj = Array | { [K in string]: Schema.Schema.Any } + /** * @since 1.0.0 */ @@ -47,6 +53,21 @@ export namespace Vitest { each: ( cases: ReadonlyArray ) => (name: string, self: TestFunction>, timeout?: number | V.TestOptions) => void + + /** + * @since 1.0.0 + */ + prop: ( + name: string, + schemas: S, + self: TestFunction< + A, + E, + R, + [{ [K in keyof S]: Schema.Schema.Type }, V.TaskContext> & V.TestContext] + >, + timeout?: number | V.TestOptions + ) => void } /** @@ -67,6 +88,19 @@ export namespace Vitest { (f: (it: Vitest.Methods) => void): void (name: string, f: (it: Vitest.Methods) => void): void } + + /** + * @since 1.0.0 + */ + readonly prop: ( + name: string, + schemas: S, + self: ( + schemas: { [K in keyof S]: Schema.Schema.Type }, + ctx: V.TaskContext> & V.TestContext + ) => void, + timeout?: number | V.TestOptions + ) => void } } @@ -151,8 +185,25 @@ export const flakyTest: ( timeout?: Duration.DurationInput ) => Effect.Effect = internal.flakyTest +/** + * @since 1.0.0 + */ +export const prop: ( + name: string, + schemas: S, + self: ( + schemas: { [K in keyof S]: Schema.Schema.Type }, + ctx: V.TaskContext> & V.TestContext + ) => void, + timeout?: number | V.TestOptions +) => void = internal.prop + +/** + * @since 1.0.0 + */ + /** @ignored */ -const methods = { effect, live, flakyTest, scoped, scopedLive, layer } as const +const methods = { effect, live, flakyTest, scoped, scopedLive, layer, prop } as const /** * @since 1.0.0 diff --git a/packages/vitest/src/internal.ts b/packages/vitest/src/internal.ts index 6285ac9150..c12b4b657b 100644 --- a/packages/vitest/src/internal.ts +++ b/packages/vitest/src/internal.ts @@ -2,6 +2,7 @@ * @since 1.0.0 */ import type { Tester, TesterContext } from "@vitest/expect" +import * as Arbitrary from "effect/Arbitrary" import * as Cause from "effect/Cause" import * as Duration from "effect/Duration" import * as Effect from "effect/Effect" @@ -16,6 +17,7 @@ import * as Scope from "effect/Scope" import * as TestEnvironment from "effect/TestContext" import type * as TestServices from "effect/TestServices" import * as Utils from "effect/Utils" +import fc from "fast-check" import * as V from "vitest" import type * as Vitest from "./index.js" @@ -45,8 +47,7 @@ const runPromise = (ctx?: Vitest.TaskContext) => (effect: Effect.Effect f()) /** @internal */ -const runTest = (ctx?: Vitest.TaskContext) => (effect: Effect.Effect) => - runPromise(ctx)(Effect.asVoid(effect)) +const runTest = (ctx?: Vitest.TaskContext) => (effect: Effect.Effect) => runPromise(ctx)(effect) /** @internal */ const TestEnv = TestEnvironment.TestContext.pipe( @@ -93,10 +94,62 @@ const makeTester = ( V.it.for(cases)( name, typeof timeout === "number" ? { timeout } : timeout ?? {}, - (args, ctx) => run(ctx, [args], self) + (args, ctx) => run(ctx, [args], self) as any ) - return Object.assign(f, { skip, skipIf, runIf, only, each }) + const prop: Vitest.Vitest.Tester["prop"] = (name, schemaObj, self, timeout) => { + if (Array.isArray(schemaObj)) { + const arbs = schemaObj.map((schema) => Arbitrary.make(schema)) + return V.it( + name, + // @ts-ignore + (ctx) => fc.assert(fc.asyncProperty(...arbs, (...as) => run(ctx, [as as any, ctx], self))), + timeout + ) + } + + const arbs = fc.record( + Object.keys(schemaObj).reduce(function(result, key) { + result[key] = Arbitrary.make(schemaObj[key]) + return result + }, {} as Record>) + ) + + return V.it( + name, + // @ts-ignore + (ctx) => fc.assert(fc.asyncProperty(arbs, (...as) => run(ctx, [as[0] as any, ctx], self))), + timeout + ) + } + + return Object.assign(f, { skip, skipIf, runIf, only, each, prop }) +} + +export const prop: Vitest.Vitest.Methods["prop"] = (name, schemaObj, self, timeout) => { + if (Array.isArray(schemaObj)) { + const arbs = schemaObj.map((schema) => Arbitrary.make(schema)) + return V.it( + name, + // @ts-ignore + (ctx) => fc.assert(fc.property(...arbs, (...as) => self(as, ctx))), + timeout + ) + } + + const arbs = fc.record( + Object.keys(schemaObj).reduce(function(result, key) { + result[key] = Arbitrary.make(schemaObj[key]) + return result + }, {} as Record>) + ) + + return V.it( + name, + // @ts-ignore + (ctx) => fc.assert(fc.property(arbs, (...as) => self(as[0], ctx))), + timeout + ) } /** @internal */ @@ -127,6 +180,9 @@ export const layer = (layer_: Layer.Layer, options?: { Effect.provide(TestEnv) )) ), + + prop, + scoped: makeTester((effect) => Effect.flatMap(runtimeEffect, (runtime) => effect.pipe( diff --git a/packages/vitest/test/index.test.ts b/packages/vitest/test/index.test.ts index 4670862365..15efbbde13 100644 --- a/packages/vitest/test/index.test.ts +++ b/packages/vitest/test/index.test.ts @@ -1,5 +1,5 @@ import { afterAll, describe, expect, it, layer } from "@effect/vitest" -import { Context, Effect, Layer } from "effect" +import { Context, Effect, Layer, Schema } from "effect" it.live( "live %s", @@ -146,5 +146,34 @@ layer(Foo.Live)("layer", (it) => { expect(scoped).toEqual("scoped") })) }) + + it.effect.prop("adds context", [Schema.Number], ([num]) => + Effect.gen(function*() { + const foo = yield* Foo + expect(foo).toEqual("foo") + return num === num + })) }) }) + +// property testing + +const realNumber = Schema.Finite.pipe(Schema.nonNaN()) + +it.prop("symmetry", [realNumber, realNumber], ([a, b]) => a + b === b + a) + +it.effect.prop("symmetry", [realNumber, realNumber], ([a, b]) => + Effect.gen(function*() { + yield* Effect.void + return a + b === b + a + })) + +it.scoped.prop( + "should detect the substring", + { a: Schema.String, b: Schema.String, c: Schema.String }, + ({ a, b, c }) => + Effect.gen(function*() { + yield* Effect.scope + return (a + b + c).includes(b) + }) +) From 8e898acaca2c6f95894052648899d5dd0d9b696e Mon Sep 17 00:00:00 2001 From: Patrick Roza Date: Mon, 21 Oct 2024 03:48:01 +0200 Subject: [PATCH 8/8] add Redactable to Inspectable module (#3777) Co-authored-by: Tim --- .changeset/unlucky-apples-warn.md | 6 ++ packages/effect/src/Inspectable.ts | 58 +++++++++++- packages/effect/src/internal/cause.ts | 6 +- packages/effect/src/internal/fiberRuntime.ts | 26 +++--- packages/effect/src/internal/logger.ts | 13 +-- packages/effect/src/internal/redacted.ts | 4 + packages/platform/src/Headers.ts | 14 ++- packages/platform/test/Headers.test.ts | 98 +++++++++++++++++++- 8 files changed, 198 insertions(+), 27 deletions(-) create mode 100644 .changeset/unlucky-apples-warn.md diff --git a/.changeset/unlucky-apples-warn.md b/.changeset/unlucky-apples-warn.md new file mode 100644 index 0000000000..5ba81815b7 --- /dev/null +++ b/.changeset/unlucky-apples-warn.md @@ -0,0 +1,6 @@ +--- +"@effect/platform": minor +"effect": minor +--- + +feat: implement Redactable. Used by Headers to not log sensitive information diff --git a/packages/effect/src/Inspectable.ts b/packages/effect/src/Inspectable.ts index 9573277190..c187e8abe9 100644 --- a/packages/effect/src/Inspectable.ts +++ b/packages/effect/src/Inspectable.ts @@ -2,6 +2,8 @@ * @since 2.0.0 */ +import type * as FiberRefs from "./FiberRefs.js" +import { globalValue } from "./GlobalValue.js" import { hasProperty, isFunction } from "./Predicate.js" /** @@ -38,7 +40,7 @@ export const toJSON = (x: unknown): unknown => { } else if (Array.isArray(x)) { return x.map(toJSON) } - return x + return redact(x) } /** @@ -108,10 +110,62 @@ export const stringifyCircular = (obj: unknown, whitespace?: number | string | u typeof value === "object" && value !== null ? cache.includes(value) ? undefined // circular reference - : cache.push(value) && value + : cache.push(value) && (redactableState.fiberRefs !== undefined && isRedactable(value) + ? value[symbolRedactable](redactableState.fiberRefs) + : value) : value, whitespace ) ;(cache as any) = undefined return retVal } + +/** + * @since 3.10.0 + * @category redactable + */ +export interface Redactable { + readonly [symbolRedactable]: (fiberRefs: FiberRefs.FiberRefs) => unknown +} + +/** + * @since 3.10.0 + * @category redactable + */ +export const symbolRedactable: unique symbol = Symbol.for("effect/Inspectable/Redactable") + +/** + * @since 3.10.0 + * @category redactable + */ +export const isRedactable = (u: unknown): u is Redactable => + typeof u === "object" && u !== null && symbolRedactable in u + +const redactableState = globalValue("effect/Inspectable/redactableState", () => ({ + fiberRefs: undefined as FiberRefs.FiberRefs | undefined +})) + +/** + * @since 3.10.0 + * @category redactable + */ +export const withRedactableContext = (context: FiberRefs.FiberRefs, f: () => A): A => { + const prev = redactableState.fiberRefs + redactableState.fiberRefs = context + try { + return f() + } finally { + redactableState.fiberRefs = prev + } +} + +/** + * @since 3.10.0 + * @category redactable + */ +export const redact = (u: unknown): unknown => { + if (isRedactable(u) && redactableState.fiberRefs !== undefined) { + return u[symbolRedactable](redactableState.fiberRefs) + } + return u +} diff --git a/packages/effect/src/internal/cause.ts b/packages/effect/src/internal/cause.ts index bb705011d4..38bcbb4ddd 100644 --- a/packages/effect/src/internal/cause.ts +++ b/packages/effect/src/internal/cause.ts @@ -8,7 +8,7 @@ import { constFalse, constTrue, dual, identity, pipe } from "../Function.js" import { globalValue } from "../GlobalValue.js" import * as Hash from "../Hash.js" import * as HashSet from "../HashSet.js" -import { NodeInspectSymbol, toJSON } from "../Inspectable.js" +import { NodeInspectSymbol, stringifyCircular, toJSON } from "../Inspectable.js" import * as Option from "../Option.js" import { pipeArguments } from "../Pipeable.js" import type { Predicate, Refinement } from "../Predicate.js" @@ -1042,7 +1042,7 @@ class PrettyError extends globalThis.Error implements Cause.PrettyError { * 1) If the input `u` is already a string, it's considered a message. * 2) If `u` is an Error instance with a message defined, it uses the message. * 3) If `u` has a user-defined `toString()` method, it uses that method. - * 4) Otherwise, it uses `JSON.stringify` to produce a string representation and uses it as the error message, + * 4) Otherwise, it uses `Inspectable.stringifyCircular` to produce a string representation and uses it as the error message, * with "Error" added as a prefix. * * @internal @@ -1070,7 +1070,7 @@ export const prettyErrorMessage = (u: unknown): string => { // something's off, rollback to json } // 4) - return JSON.stringify(u) + return stringifyCircular(u) } const locationRegex = /\((.*)\)/ diff --git a/packages/effect/src/internal/fiberRuntime.ts b/packages/effect/src/internal/fiberRuntime.ts index 428e9cdf08..984f78d09b 100644 --- a/packages/effect/src/internal/fiberRuntime.ts +++ b/packages/effect/src/internal/fiberRuntime.ts @@ -827,18 +827,20 @@ export class FiberRuntime extends Effectable.Class 0) { const clockService = Context.get(this.getFiberRef(defaultServices.currentServices), clock.clockTag) const date = new Date(clockService.unsafeCurrentTimeMillis()) - for (const logger of loggers) { - logger.log({ - fiberId: this.id(), - logLevel, - message, - cause, - context: contextMap, - spans, - annotations, - date - }) - } + Inspectable.withRedactableContext(contextMap, () => { + for (const logger of loggers) { + logger.log({ + fiberId: this.id(), + logLevel, + message, + cause, + context: contextMap, + spans, + annotations, + date + }) + } + }) } } diff --git a/packages/effect/src/internal/logger.ts b/packages/effect/src/internal/logger.ts index 5bb919236a..f3cfdfeaa4 100644 --- a/packages/effect/src/internal/logger.ts +++ b/packages/effect/src/internal/logger.ts @@ -341,7 +341,7 @@ export const structuredMessage = (u: unknown): unknown => { return String(u) } default: { - return u + return Inspectable.toJSON(u) } } } @@ -488,13 +488,13 @@ const prettyLoggerTty = (options: { if (messageIndex < message.length) { for (; messageIndex < message.length; messageIndex++) { - log(message[messageIndex]) + log(Inspectable.redact(message[messageIndex])) } } if (HashMap.size(annotations) > 0) { for (const [key, value] of annotations) { - log(color(`${key}:`, colors.bold, colors.white), value) + log(color(`${key}:`, colors.bold, colors.white), Inspectable.redact(value)) } } @@ -553,16 +553,17 @@ const prettyLoggerBrowser = (options: { if (messageIndex < message.length) { for (; messageIndex < message.length; messageIndex++) { - console.log(message[messageIndex]) + console.log(Inspectable.redact(message[messageIndex])) } } if (HashMap.size(annotations) > 0) { for (const [key, value] of annotations) { + const redacted = Inspectable.redact(value) if (options.colors) { - console.log(`%c${key}:`, "color:gray", value) + console.log(`%c${key}:`, "color:gray", redacted) } else { - console.log(`${key}:`, value) + console.log(`${key}:`, redacted) } } } diff --git a/packages/effect/src/internal/redacted.ts b/packages/effect/src/internal/redacted.ts index bf4365c183..0dedecd231 100644 --- a/packages/effect/src/internal/redacted.ts +++ b/packages/effect/src/internal/redacted.ts @@ -1,3 +1,4 @@ +import { NodeInspectSymbol } from "effect/Inspectable" import * as Equal from "../Equal.js" import { pipe } from "../Function.js" import { globalValue } from "../GlobalValue.js" @@ -34,6 +35,9 @@ export const proto = { toJSON() { return "" }, + [NodeInspectSymbol]() { + return "" + }, [Hash.symbol](this: Redacted.Redacted): number { return pipe( Hash.hash(RedactedSymbolKey), diff --git a/packages/platform/src/Headers.ts b/packages/platform/src/Headers.ts index ec2508e5fd..830e713665 100644 --- a/packages/platform/src/Headers.ts +++ b/packages/platform/src/Headers.ts @@ -1,9 +1,11 @@ /** * @since 1.0.0 */ +import { FiberRefs } from "effect" import * as FiberRef from "effect/FiberRef" import { dual, identity } from "effect/Function" import { globalValue } from "effect/GlobalValue" +import { type Redactable, symbolRedactable } from "effect/Inspectable" import type * as Option from "effect/Option" import * as Predicate from "effect/Predicate" import * as Record from "effect/Record" @@ -34,13 +36,19 @@ export const isHeaders = (u: unknown): u is Headers => Predicate.hasProperty(u, * @since 1.0.0 * @category models */ -export interface Headers { +export interface Headers extends Redactable { readonly [HeadersTypeId]: HeadersTypeId readonly [key: string]: string } const Proto = Object.assign(Object.create(null), { - [HeadersTypeId]: HeadersTypeId + [HeadersTypeId]: HeadersTypeId, + [symbolRedactable]( + this: Headers, + fiberRefs: FiberRefs.FiberRefs + ): Record> { + return redact(this, FiberRefs.getOrDefault(fiberRefs, currentRedactedNames)) + } }) const make = (input: Record.ReadonlyRecord): Mutable => @@ -248,7 +256,7 @@ export const redact: { * @since 1.0.0 * @category fiber refs */ -export const currentRedactedNames = globalValue( +export const currentRedactedNames: FiberRef.FiberRef> = globalValue( "@effect/platform/Headers/currentRedactedNames", () => FiberRef.unsafeMake>([ diff --git a/packages/platform/test/Headers.test.ts b/packages/platform/test/Headers.test.ts index 46d0e7e329..95abe753c6 100644 --- a/packages/platform/test/Headers.test.ts +++ b/packages/platform/test/Headers.test.ts @@ -1,8 +1,104 @@ import * as Headers from "@effect/platform/Headers" +import { assert, describe, it } from "@effect/vitest" +import { Effect, FiberId, FiberRef, FiberRefs, HashSet, Inspectable, Logger } from "effect" import * as Redacted from "effect/Redacted" -import { assert, describe, it } from "vitest" describe("Headers", () => { + describe("Redactable", () => { + it("one key", () => { + const headers = Headers.fromInput({ + "Content-Type": "application/json", + "Authorization": "Bearer some-token", + "X-Api-Key": "some-key" + }) + + const fiberRefs = FiberRefs.unsafeMake( + new Map([ + [ + Headers.currentRedactedNames, + [[FiberId.none, ["Authorization"]] as const] + ] as const + ]) + ) + const r = Inspectable.withRedactableContext(fiberRefs, () => Inspectable.toStringUnknown(headers)) + const redacted = JSON.parse(r) + + assert.deepEqual(redacted, { + "content-type": "application/json", + "authorization": "", + "x-api-key": "some-key" + }) + }) + + it("one key nested", () => { + const headers = Headers.fromInput({ + "Content-Type": "application/json", + "Authorization": "Bearer some-token", + "X-Api-Key": "some-key" + }) + + const fiberRefs = FiberRefs.unsafeMake( + new Map([ + [ + Headers.currentRedactedNames, + [[FiberId.none, ["Authorization"]] as const] + ] as const + ]) + ) + const r = Inspectable.withRedactableContext(fiberRefs, () => Inspectable.toStringUnknown({ headers })) + const redacted = JSON.parse(r) as { headers: unknown } + + assert.deepEqual(redacted.headers, { + "content-type": "application/json", + "authorization": "", + "x-api-key": "some-key" + }) + }) + + it.effect("logs redacted", () => + Effect.gen(function*() { + const messages: Array = [] + const logger = Logger.stringLogger.pipe( + Logger.map((msg) => { + messages.push(msg) + }) + ) + yield* FiberRef.update(FiberRef.currentLoggers, HashSet.add(logger)) + const headers = Headers.fromInput({ + "Content-Type": "application/json", + "Authorization": "Bearer some-token", + "X-Api-Key": "some-key" + }) + yield* Effect.log(headers).pipe( + Effect.annotateLogs({ headers }) + ) + assert.include(messages[0], "application/json") + assert.notInclude(messages[0], "some-token") + assert.notInclude(messages[0], "some-key") + })) + + it.effect("logs redacted structured", () => + Effect.gen(function*() { + const messages: Array = [] + const logger = Logger.structuredLogger.pipe( + Logger.map((msg) => { + messages.push(msg) + }) + ) + yield* FiberRef.update(FiberRef.currentLoggers, HashSet.add(logger)) + const headers = Headers.fromInput({ + "Content-Type": "application/json", + "Authorization": "Bearer some-token", + "X-Api-Key": "some-key" + }) + yield* Effect.log(headers).pipe( + Effect.annotateLogs({ headers }) + ) + assert.strictEqual(Redacted.isRedacted(messages[0].message.authorization), true) + assert.strictEqual(Redacted.isRedacted(messages[0].annotations.headers.authorization), true) + })) + }) + describe("redact", () => { it("one key", () => { const headers = Headers.fromInput({

= P extends + SerializableWithResult ? SR | RR + : never + /** + * @since 3.10.0 + */ + export type Any = SerializableWithResult + /** + * @since 3.10.0 + */ + export type All = + | Any + | SerializableWithResult +} + +/** + * @since 3.10.0 + */ +export const asSerializableWithResult = ( + procedure: SWR +): SerializableWithResult< + Serializable.Type, + Serializable.Encoded, + Serializable.Context, + WithResult.Success, + WithResult.SuccessEncoded, + WithResult.Failure, + WithResult.FailureEncoded, + WithResult.Context +> => procedure as any + +/** + * @since 3.10.0 + */ +export interface TaggedRequest< + Tag extends string, + A, + I, + R, + SuccessType, + SuccessEncoded, + FailureType, + FailureEncoded, + ResultR +> extends + Request.Request, + SerializableWithResult< + A, + I, + R, + SuccessType, + SuccessEncoded, + FailureType, + FailureEncoded, + ResultR + > +{ + readonly _tag: Tag +} + +/** + * @since 3.10.0 + */ +export declare namespace TaggedRequest { + /** + * @since 3.10.0 + */ + export type Any = TaggedRequest + /** + * @since 3.10.0 + */ + export type All = + | Any + | TaggedRequest +} + +/** + * @category api interface + * @since 3.10.0 + */ +export interface TaggedRequestClass< + Self, + Tag extends string, + Payload extends Struct.Fields, + Success extends Schema.All, + Failure extends Schema.All +> extends + Class< + Self, + Payload, + Struct.Encoded, + Struct.Context, + Struct.Constructor>, + TaggedRequest< + Tag, + Self, + Struct.Encoded, + Struct.Context, + Schema.Type, + Schema.Encoded, + Schema.Type, + Schema.Encoded, + Schema.Context | Schema.Context + >, + {} + > +{ + readonly _tag: Tag + readonly success: Success + readonly failure: Failure +} + +/** + * @category classes + * @since 3.10.0 + */ +export const TaggedRequest = + (identifier?: string) => + ( + tag: Tag, + options: { + failure: Failure + success: Success + payload: Payload + }, + annotations?: Annotations.Schema + ): [Self] extends [never] ? MissingSelfGeneric<"TaggedRequest", `"Tag", SuccessSchema, FailureSchema, `> + : TaggedRequestClass< + Self, + Tag, + { readonly _tag: tag } & Payload, + Success, + Failure + > => + { + const taggedFields = extendFields({ _tag: getClassTag(tag) }, options.payload) + return class TaggedRequestClass extends makeClass({ + kind: "TaggedRequest", + identifier: identifier ?? tag, + schema: Struct(taggedFields), + fields: taggedFields, + Base: Request.Class, + annotations + }) { + static _tag = tag + static success = options.success + static failure = options.failure + get [symbolSerializable]() { + return this.constructor + } + get [symbolWithResult]() { + return { + failure: options.failure, + success: options.success + } + } + } as any + } + +// ------------------------------------------------------------------------------------------------- +// Equivalence compiler +// ------------------------------------------------------------------------------------------------- + +/** + * Given a schema `Schema`, returns an `Equivalence` instance for `A`. + * + * @category Equivalence + * @since 3.10.0 + */ +export const equivalence = (schema: Schema): Equivalence.Equivalence => go(schema.ast, []) + +const getEquivalenceAnnotation = AST.getAnnotation>(AST.EquivalenceAnnotationId) + +const go = (ast: AST.AST, path: ReadonlyArray): Equivalence.Equivalence => { + const hook = getEquivalenceAnnotation(ast) + if (option_.isSome(hook)) { + switch (ast._tag) { + case "Declaration": + return hook.value(...ast.typeParameters.map((tp) => go(tp, path))) + case "Refinement": + return hook.value(go(ast.from, path)) + default: + return hook.value() + } + } + switch (ast._tag) { + case "NeverKeyword": + throw new Error(errors_.getEquivalenceUnsupportedErrorMessage(ast, path)) + case "Transformation": + return go(ast.to, path) + case "Declaration": + case "Literal": + case "StringKeyword": + case "TemplateLiteral": + case "UniqueSymbol": + case "SymbolKeyword": + case "UnknownKeyword": + case "AnyKeyword": + case "NumberKeyword": + case "BooleanKeyword": + case "BigIntKeyword": + case "UndefinedKeyword": + case "VoidKeyword": + case "Enums": + case "ObjectKeyword": + return Equal.equals + case "Refinement": + return go(ast.from, path) + case "Suspend": { + const get = util_.memoizeThunk(() => go(ast.f(), path)) + return (a, b) => get()(a, b) + } + case "TupleType": { + const elements = ast.elements.map((element, i) => go(element.type, path.concat(i))) + const rest = ast.rest.map((annotatedAST) => go(annotatedAST.type, path)) + return Equivalence.make((a, b) => { + const len = a.length + if (len !== b.length) { + return false + } + // --------------------------------------------- + // handle elements + // --------------------------------------------- + let i = 0 + for (; i < Math.min(len, ast.elements.length); i++) { + if (!elements[i](a[i], b[i])) { + return false + } + } + // --------------------------------------------- + // handle rest element + // --------------------------------------------- + if (array_.isNonEmptyReadonlyArray(rest)) { + const [head, ...tail] = rest + for (; i < len - tail.length; i++) { + if (!head(a[i], b[i])) { + return false + } + } + // --------------------------------------------- + // handle post rest elements + // --------------------------------------------- + for (let j = 0; j < tail.length; j++) { + i += j + if (!tail[j](a[i], b[i])) { + return false + } + } + } + return true + }) + } + case "TypeLiteral": { + if (ast.propertySignatures.length === 0 && ast.indexSignatures.length === 0) { + return Equal.equals + } + const propertySignatures = ast.propertySignatures.map((ps) => go(ps.type, path.concat(ps.name))) + const indexSignatures = ast.indexSignatures.map((is) => go(is.type, path)) + return Equivalence.make((a, b) => { + const aStringKeys = Object.keys(a) + const aSymbolKeys = Object.getOwnPropertySymbols(a) + // --------------------------------------------- + // handle property signatures + // --------------------------------------------- + for (let i = 0; i < propertySignatures.length; i++) { + const ps = ast.propertySignatures[i] + const name = ps.name + const aHas = Object.prototype.hasOwnProperty.call(a, name) + const bHas = Object.prototype.hasOwnProperty.call(b, name) + if (ps.isOptional) { + if (aHas !== bHas) { + return false + } + } + if (aHas && bHas && !propertySignatures[i](a[name], b[name])) { + return false + } + } + // --------------------------------------------- + // handle index signatures + // --------------------------------------------- + let bSymbolKeys: Array | undefined + let bStringKeys: Array | undefined + for (let i = 0; i < indexSignatures.length; i++) { + const is = ast.indexSignatures[i] + const base = AST.getParameterBase(is.parameter) + const isSymbol = AST.isSymbolKeyword(base) + if (isSymbol) { + bSymbolKeys = bSymbolKeys || Object.getOwnPropertySymbols(b) + if (aSymbolKeys.length !== bSymbolKeys.length) { + return false + } + } else { + bStringKeys = bStringKeys || Object.keys(b) + if (aStringKeys.length !== bStringKeys.length) { + return false + } + } + const aKeys = isSymbol ? aSymbolKeys : aStringKeys + for (let j = 0; j < aKeys.length; j++) { + const key = aKeys[j] + if ( + !Object.prototype.hasOwnProperty.call(b, key) || !indexSignatures[i](a[key], b[key]) + ) { + return false + } + } + } + return true + }) + } + case "Union": { + const searchTree = ParseResult.getSearchTree(ast.types, true) + const ownKeys = util_.ownKeys(searchTree.keys) + const len = ownKeys.length + return Equivalence.make((a, b) => { + let candidates: Array = [] + if (len > 0 && Predicate.isRecord(a)) { + for (let i = 0; i < len; i++) { + const name = ownKeys[i] + const buckets = searchTree.keys[name].buckets + if (Object.prototype.hasOwnProperty.call(a, name)) { + const literal = String(a[name]) + if (Object.prototype.hasOwnProperty.call(buckets, literal)) { + candidates = candidates.concat(buckets[literal]) + } + } + } + } + if (searchTree.otherwise.length > 0) { + candidates = candidates.concat(searchTree.otherwise) + } + const tuples = candidates.map((ast) => [go(ast, path), ParseResult.is({ ast } as any)] as const) + for (let i = 0; i < tuples.length; i++) { + const [equivalence, is] = tuples[i] + if (is(a) && is(b)) { + if (equivalence(a, b)) { + return true + } + } + } + return false + }) + } + } +} diff --git a/packages/schema/src/AST.ts b/packages/effect/src/SchemaAST.ts similarity index 89% rename from packages/schema/src/AST.ts rename to packages/effect/src/SchemaAST.ts index 535daaf24c..4befd23444 100644 --- a/packages/schema/src/AST.ts +++ b/packages/effect/src/SchemaAST.ts @@ -1,24 +1,25 @@ /** - * @since 0.67.0 - */ - -import * as Arr from "effect/Array" -import type { Effect } from "effect/Effect" -import { dual, identity } from "effect/Function" -import { globalValue } from "effect/GlobalValue" -import * as Number from "effect/Number" -import * as Option from "effect/Option" -import * as Order from "effect/Order" -import * as Predicate from "effect/Predicate" -import * as regexp from "effect/RegExp" -import type { Concurrency } from "effect/Types" -import * as errors_ from "./internal/errors.js" -import * as util_ from "./internal/util.js" + * @since 3.10.0 + */ + +import * as Arr from "./Array.js" +import type { Effect } from "./Effect.js" +import type { Equivalence } from "./Equivalence.js" +import { dual, identity } from "./Function.js" +import { globalValue } from "./GlobalValue.js" +import * as errors_ from "./internal/schema/errors.js" +import * as util_ from "./internal/schema/util.js" +import * as Number from "./Number.js" +import * as Option from "./Option.js" +import * as Order from "./Order.js" import type { ParseIssue } from "./ParseResult.js" +import * as Predicate from "./Predicate.js" +import * as regexp from "./RegExp.js" +import type { Concurrency } from "./Types.js" /** * @category model - * @since 0.67.0 + * @since 3.10.0 */ export type AST = | Declaration @@ -52,31 +53,31 @@ export type AST = /** * @category annotations - * @since 0.67.0 + * @since 3.10.0 */ export type BrandAnnotation = Arr.NonEmptyReadonlyArray /** * @category annotations - * @since 0.67.0 + * @since 3.10.0 */ -export const BrandAnnotationId = Symbol.for("@effect/schema/annotation/Brand") +export const BrandAnnotationId: unique symbol = Symbol.for("effect/annotation/Brand") /** * @category annotations - * @since 0.67.0 + * @since 3.10.0 */ -export type TypeAnnotation = symbol +export type SchemaIdAnnotation = string | symbol /** * @category annotations - * @since 0.67.0 + * @since 3.10.0 */ -export const TypeAnnotationId = Symbol.for("@effect/schema/annotation/Type") +export const SchemaIdAnnotationId: unique symbol = Symbol.for("effect/annotation/SchemaId") /** * @category annotations - * @since 0.67.0 + * @since 3.10.0 */ export type MessageAnnotation = (issue: ParseIssue) => string | Effect | { readonly message: string | Effect @@ -85,179 +86,200 @@ export type MessageAnnotation = (issue: ParseIssue) => string | Effect | /** * @category annotations - * @since 0.67.0 + * @since 3.10.0 */ -export const MessageAnnotationId = Symbol.for("@effect/schema/annotation/Message") +export const MessageAnnotationId: unique symbol = Symbol.for("effect/annotation/Message") /** * @category annotations - * @since 0.67.0 + * @since 3.10.0 */ export type MissingMessageAnnotation = () => string | Effect /** * @category annotations - * @since 0.67.0 + * @since 3.10.0 */ -export const MissingMessageAnnotationId = Symbol.for("@effect/schema/annotation/MissingMessage") +export const MissingMessageAnnotationId: unique symbol = Symbol.for("effect/annotation/MissingMessage") /** * @category annotations - * @since 0.67.0 + * @since 3.10.0 */ export type IdentifierAnnotation = string /** * @category annotations - * @since 0.67.0 + * @since 3.10.0 */ -export const IdentifierAnnotationId = Symbol.for("@effect/schema/annotation/Identifier") +export const IdentifierAnnotationId: unique symbol = Symbol.for("effect/annotation/Identifier") /** * @category annotations - * @since 0.67.0 + * @since 3.10.0 */ export type TitleAnnotation = string /** * @category annotations - * @since 0.67.0 + * @since 3.10.0 */ -export const TitleAnnotationId = Symbol.for("@effect/schema/annotation/Title") +export const TitleAnnotationId: unique symbol = Symbol.for("effect/annotation/Title") /** * @category annotations - * @since 0.67.0 + * @since 3.10.0 */ export type DescriptionAnnotation = string /** * @category annotations - * @since 0.67.0 + * @since 3.10.0 */ -export const DescriptionAnnotationId = Symbol.for("@effect/schema/annotation/Description") +export const DescriptionAnnotationId: unique symbol = Symbol.for("effect/annotation/Description") /** * @category annotations - * @since 0.67.0 + * @since 3.10.0 */ export type ExamplesAnnotation = Arr.NonEmptyReadonlyArray /** * @category annotations - * @since 0.67.0 + * @since 3.10.0 */ -export const ExamplesAnnotationId = Symbol.for("@effect/schema/annotation/Examples") +export const ExamplesAnnotationId: unique symbol = Symbol.for("effect/annotation/Examples") /** * @category annotations - * @since 0.67.0 + * @since 3.10.0 */ export type DefaultAnnotation = A /** * @category annotations - * @since 0.67.0 + * @since 3.10.0 */ -export const DefaultAnnotationId = Symbol.for("@effect/schema/annotation/Default") +export const DefaultAnnotationId: unique symbol = Symbol.for("effect/annotation/Default") /** * @category annotations - * @since 0.67.0 + * @since 3.10.0 */ export type JSONSchemaAnnotation = object /** * @category annotations - * @since 0.67.0 + * @since 3.10.0 */ -export const JSONSchemaAnnotationId = Symbol.for("@effect/schema/annotation/JSONSchema") +export const JSONSchemaAnnotationId: unique symbol = Symbol.for("effect/annotation/JSONSchema") /** * @category annotations - * @since 0.67.0 + * @since 3.10.0 + */ +export const ArbitraryAnnotationId: unique symbol = Symbol.for("effect/annotation/Arbitrary") + +/** + * @category annotations + * @since 3.10.0 + */ +export const PrettyAnnotationId: unique symbol = Symbol.for("effect/annotation/Pretty") + +/** + * @category annotations + * @since 3.10.0 + */ +export type EquivalenceAnnotation = readonly []> = ( + ...equivalences: { readonly [K in keyof TypeParameters]: Equivalence } +) => Equivalence + +/** + * @category annotations + * @since 3.10.0 + */ +export const EquivalenceAnnotationId: unique symbol = Symbol.for("effect/annotation/Equivalence") + +/** + * @category annotations + * @since 3.10.0 */ export type DocumentationAnnotation = string /** * @category annotations - * @since 0.67.0 + * @since 3.10.0 */ -export const DocumentationAnnotationId = Symbol.for("@effect/schema/annotation/Documentation") +export const DocumentationAnnotationId: unique symbol = Symbol.for("effect/annotation/Documentation") /** * @category annotations - * @since 0.67.0 + * @since 3.10.0 */ export type ConcurrencyAnnotation = Concurrency | undefined /** * @category annotations - * @since 0.67.0 + * @since 3.10.0 */ -export const ConcurrencyAnnotationId = Symbol.for("@effect/schema/annotation/Concurrency") +export const ConcurrencyAnnotationId: unique symbol = Symbol.for("effect/annotation/Concurrency") /** * @category annotations - * @since 0.67.0 + * @since 3.10.0 */ export type BatchingAnnotation = boolean | "inherit" | undefined /** * @category annotations - * @since 0.67.0 + * @since 3.10.0 */ -export const BatchingAnnotationId = Symbol.for("@effect/schema/annotation/Batching") +export const BatchingAnnotationId: unique symbol = Symbol.for("effect/annotation/Batching") /** * @category annotations - * @since 0.67.0 + * @since 3.10.0 */ export type ParseIssueTitleAnnotation = (issue: ParseIssue) => string | undefined /** * @category annotations - * @since 0.67.0 + * @since 3.10.0 */ -export const ParseIssueTitleAnnotationId = Symbol.for("@effect/schema/annotation/ParseIssueTitle") +export const ParseIssueTitleAnnotationId: unique symbol = Symbol.for("effect/annotation/ParseIssueTitle") /** * @category annotations - * @since 0.68.3 + * @since 3.10.0 */ -export const ParseOptionsAnnotationId = Symbol.for("@effect/schema/annotation/ParseOptions") +export const ParseOptionsAnnotationId: unique symbol = Symbol.for("effect/annotation/ParseOptions") /** * @category annotations - * @since 0.70.1 + * @since 3.10.0 */ export type DecodingFallbackAnnotation = (issue: ParseIssue) => Effect /** * @category annotations - * @since 0.70.1 + * @since 3.10.0 */ -export const DecodingFallbackAnnotationId = Symbol.for("@effect/schema/annotation/DecodingFallback") +export const DecodingFallbackAnnotationId: unique symbol = Symbol.for("effect/annotation/DecodingFallback") -/** @internal */ -export const SurrogateAnnotationId = Symbol.for("@effect/schema/annotation/Surrogate") +/** + * @category annotations + * @since 3.10.0 + */ +export const SurrogateAnnotationId: unique symbol = Symbol.for("effect/annotation/Surrogate") /** - * Used by: - * - * - AST.keyof - * - AST.getPropertyKeyIndexedAccess - * - AST.getPropertyKeys - * - AST.getPropertySignatures - * - AST.getWeight - * - Parser.getLiterals - * - * @internal + * @category annotations + * @since 3.10.0 */ export type SurrogateAnnotation = AST /** @internal */ -export const StableFilterAnnotationId = Symbol.for("@effect/schema/annotation/StableFilter") +export const StableFilterAnnotationId: unique symbol = Symbol.for("effect/annotation/StableFilter") /** * A stable filter consistently applies fixed validation rules, such as @@ -270,15 +292,16 @@ export type StableFilterAnnotation = boolean /** * @category annotations - * @since 0.67.0 + * @since 3.10.0 */ export interface Annotations { + readonly [_: string]: unknown readonly [_: symbol]: unknown } /** * @category annotations - * @since 0.67.0 + * @since 3.10.0 */ export interface Annotated { readonly annotations: Annotations @@ -286,7 +309,7 @@ export interface Annotated { /** * @category annotations - * @since 0.67.0 + * @since 3.10.0 */ export const getAnnotation: { (key: symbol): (annotated: Annotated) => Option.Option @@ -301,97 +324,100 @@ export const getAnnotation: { /** * @category annotations - * @since 0.67.0 + * @since 3.10.0 */ export const getBrandAnnotation = getAnnotation(BrandAnnotationId) /** * @category annotations - * @since 0.67.0 + * @since 3.10.0 */ export const getMessageAnnotation = getAnnotation(MessageAnnotationId) /** * @category annotations - * @since 0.67.0 + * @since 3.10.0 */ export const getMissingMessageAnnotation = getAnnotation(MissingMessageAnnotationId) /** * @category annotations - * @since 0.67.0 + * @since 3.10.0 */ export const getTitleAnnotation = getAnnotation(TitleAnnotationId) /** * @category annotations - * @since 0.67.0 + * @since 3.10.0 */ export const getIdentifierAnnotation = getAnnotation(IdentifierAnnotationId) /** * @category annotations - * @since 0.67.0 + * @since 3.10.0 */ export const getDescriptionAnnotation = getAnnotation(DescriptionAnnotationId) /** * @category annotations - * @since 0.67.0 + * @since 3.10.0 */ export const getExamplesAnnotation = getAnnotation>(ExamplesAnnotationId) /** * @category annotations - * @since 0.67.0 + * @since 3.10.0 */ export const getDefaultAnnotation = getAnnotation>(DefaultAnnotationId) /** * @category annotations - * @since 0.67.0 + * @since 3.10.0 */ export const getJSONSchemaAnnotation = getAnnotation(JSONSchemaAnnotationId) /** * @category annotations - * @since 0.67.0 + * @since 3.10.0 */ export const getDocumentationAnnotation = getAnnotation(DocumentationAnnotationId) /** * @category annotations - * @since 0.67.0 + * @since 3.10.0 */ export const getConcurrencyAnnotation = getAnnotation(ConcurrencyAnnotationId) /** * @category annotations - * @since 0.67.0 + * @since 3.10.0 */ export const getBatchingAnnotation = getAnnotation(BatchingAnnotationId) /** * @category annotations - * @since 0.67.0 + * @since 3.10.0 */ export const getParseIssueTitleAnnotation = getAnnotation(ParseIssueTitleAnnotationId) /** * @category annotations - * @since 0.68.3 + * @since 3.10.0 */ export const getParseOptionsAnnotation = getAnnotation(ParseOptionsAnnotationId) /** * @category annotations - * @since 0.70.1 + * @since 3.10.0 */ export const getDecodingFallbackAnnotation = getAnnotation>( DecodingFallbackAnnotationId ) -/** @internal */ +/** + * @category annotations + * @since 3.10.0 + */ export const getSurrogateAnnotation = getAnnotation(SurrogateAnnotationId) const getStableFilterAnnotation = getAnnotation(StableFilterAnnotationId) @@ -400,18 +426,42 @@ const getStableFilterAnnotation = getAnnotation(StableFi export const hasStableFilter = (annotated: Annotated) => Option.exists(getStableFilterAnnotation(annotated), (b) => b === true) -const JSONIdentifierAnnotationId = Symbol.for("@effect/schema/annotation/JSONIdentifier") +/** + * @category annotations + * @since 3.10.0 + */ +export const JSONIdentifierAnnotationId: unique symbol = Symbol.for("effect/annotation/JSONIdentifier") -/** @internal */ +/** + * @category annotations + * @since 3.10.0 + */ export const getJSONIdentifierAnnotation = getAnnotation(JSONIdentifierAnnotationId) +/** + * @category annotations + * @since 3.10.0 + */ +export const getJSONIdentifier = (annotated: Annotated) => + Option.orElse(getJSONIdentifierAnnotation(annotated), () => getIdentifierAnnotation(annotated)) + +// ------------------------------------------------------------------------------------- +// schema ids +// ------------------------------------------------------------------------------------- + +/** + * @category schema id + * @since 3.10.0 + */ +export const ParseJsonSchemaId: unique symbol = Symbol.for("effect/schema/ParseJson") + /** * @category model - * @since 0.67.0 + * @since 3.10.0 */ export class Declaration implements Annotated { /** - * @since 0.67.0 + * @since 3.10.0 */ readonly _tag = "Declaration" constructor( @@ -425,13 +475,13 @@ export class Declaration implements Annotated { readonly annotations: Annotations = {} ) {} /** - * @since 0.67.0 + * @since 3.10.0 */ toString() { return Option.getOrElse(getExpected(this), () => "") } /** - * @since 0.67.0 + * @since 3.10.0 */ toJSON(): object { return { @@ -447,34 +497,34 @@ const createASTGuard = (tag: T) => (ast: AST): ast is Ext /** * @category guards - * @since 0.67.0 + * @since 3.10.0 */ export const isDeclaration: (ast: AST) => ast is Declaration = createASTGuard("Declaration") /** * @category model - * @since 0.67.0 + * @since 3.10.0 */ export type LiteralValue = string | number | boolean | null | bigint /** * @category model - * @since 0.67.0 + * @since 3.10.0 */ export class Literal implements Annotated { /** - * @since 0.67.0 + * @since 3.10.0 */ readonly _tag = "Literal" constructor(readonly literal: LiteralValue, readonly annotations: Annotations = {}) {} /** - * @since 0.67.0 + * @since 3.10.0 */ toString() { return Option.getOrElse(getExpected(this), () => util_.formatUnknown(this.literal)) } /** - * @since 0.67.0 + * @since 3.10.0 */ toJSON(): object { return { @@ -487,7 +537,7 @@ export class Literal implements Annotated { /** * @category guards - * @since 0.67.0 + * @since 3.10.0 */ export const isLiteral: (ast: AST) => ast is Literal = createASTGuard("Literal") @@ -496,29 +546,29 @@ const $null = new Literal(null) export { /** * @category constructors - * @since 0.67.0 + * @since 3.10.0 */ $null as null } /** * @category model - * @since 0.67.0 + * @since 3.10.0 */ export class UniqueSymbol implements Annotated { /** - * @since 0.67.0 + * @since 3.10.0 */ readonly _tag = "UniqueSymbol" constructor(readonly symbol: symbol, readonly annotations: Annotations = {}) {} /** - * @since 0.67.0 + * @since 3.10.0 */ toString() { return Option.getOrElse(getExpected(this), () => util_.formatUnknown(this.symbol)) } /** - * @since 0.67.0 + * @since 3.10.0 */ toJSON(): object { return { @@ -531,28 +581,28 @@ export class UniqueSymbol implements Annotated { /** * @category guards - * @since 0.67.0 + * @since 3.10.0 */ export const isUniqueSymbol: (ast: AST) => ast is UniqueSymbol = createASTGuard("UniqueSymbol") /** * @category model - * @since 0.67.0 + * @since 3.10.0 */ export class UndefinedKeyword implements Annotated { /** - * @since 0.67.0 + * @since 3.10.0 */ readonly _tag = "UndefinedKeyword" constructor(readonly annotations: Annotations = {}) {} /** - * @since 0.67.0 + * @since 3.10.0 */ toString() { return formatKeyword(this) } /** - * @since 0.67.0 + * @since 3.10.0 */ toJSON(): object { return { @@ -564,7 +614,7 @@ export class UndefinedKeyword implements Annotated { /** * @category constructors - * @since 0.67.0 + * @since 3.10.0 */ export const undefinedKeyword: UndefinedKeyword = new UndefinedKeyword({ [TitleAnnotationId]: "undefined" @@ -572,28 +622,28 @@ export const undefinedKeyword: UndefinedKeyword = new UndefinedKeyword({ /** * @category guards - * @since 0.67.0 + * @since 3.10.0 */ export const isUndefinedKeyword: (ast: AST) => ast is UndefinedKeyword = createASTGuard("UndefinedKeyword") /** * @category model - * @since 0.67.0 + * @since 3.10.0 */ export class VoidKeyword implements Annotated { /** - * @since 0.67.0 + * @since 3.10.0 */ readonly _tag = "VoidKeyword" constructor(readonly annotations: Annotations = {}) {} /** - * @since 0.67.0 + * @since 3.10.0 */ toString() { return formatKeyword(this) } /** - * @since 0.67.0 + * @since 3.10.0 */ toJSON(): object { return { @@ -605,7 +655,7 @@ export class VoidKeyword implements Annotated { /** * @category constructors - * @since 0.67.0 + * @since 3.10.0 */ export const voidKeyword: VoidKeyword = new VoidKeyword({ [TitleAnnotationId]: "void" @@ -613,28 +663,28 @@ export const voidKeyword: VoidKeyword = new VoidKeyword({ /** * @category guards - * @since 0.67.0 + * @since 3.10.0 */ export const isVoidKeyword: (ast: AST) => ast is VoidKeyword = createASTGuard("VoidKeyword") /** * @category model - * @since 0.67.0 + * @since 3.10.0 */ export class NeverKeyword implements Annotated { /** - * @since 0.67.0 + * @since 3.10.0 */ readonly _tag = "NeverKeyword" constructor(readonly annotations: Annotations = {}) {} /** - * @since 0.67.0 + * @since 3.10.0 */ toString() { return formatKeyword(this) } /** - * @since 0.67.0 + * @since 3.10.0 */ toJSON(): object { return { @@ -646,7 +696,7 @@ export class NeverKeyword implements Annotated { /** * @category constructors - * @since 0.67.0 + * @since 3.10.0 */ export const neverKeyword: NeverKeyword = new NeverKeyword({ [TitleAnnotationId]: "never" @@ -654,28 +704,28 @@ export const neverKeyword: NeverKeyword = new NeverKeyword({ /** * @category guards - * @since 0.67.0 + * @since 3.10.0 */ export const isNeverKeyword: (ast: AST) => ast is NeverKeyword = createASTGuard("NeverKeyword") /** * @category model - * @since 0.67.0 + * @since 3.10.0 */ export class UnknownKeyword implements Annotated { /** - * @since 0.67.0 + * @since 3.10.0 */ readonly _tag = "UnknownKeyword" constructor(readonly annotations: Annotations = {}) {} /** - * @since 0.67.0 + * @since 3.10.0 */ toString() { return formatKeyword(this) } /** - * @since 0.67.0 + * @since 3.10.0 */ toJSON(): object { return { @@ -687,7 +737,7 @@ export class UnknownKeyword implements Annotated { /** * @category constructors - * @since 0.67.0 + * @since 3.10.0 */ export const unknownKeyword: UnknownKeyword = new UnknownKeyword({ [TitleAnnotationId]: "unknown" @@ -695,28 +745,28 @@ export const unknownKeyword: UnknownKeyword = new UnknownKeyword({ /** * @category guards - * @since 0.67.0 + * @since 3.10.0 */ export const isUnknownKeyword: (ast: AST) => ast is UnknownKeyword = createASTGuard("UnknownKeyword") /** * @category model - * @since 0.67.0 + * @since 3.10.0 */ export class AnyKeyword implements Annotated { /** - * @since 0.67.0 + * @since 3.10.0 */ readonly _tag = "AnyKeyword" constructor(readonly annotations: Annotations = {}) {} /** - * @since 0.67.0 + * @since 3.10.0 */ toString() { return formatKeyword(this) } /** - * @since 0.67.0 + * @since 3.10.0 */ toJSON(): object { return { @@ -728,7 +778,7 @@ export class AnyKeyword implements Annotated { /** * @category constructors - * @since 0.67.0 + * @since 3.10.0 */ export const anyKeyword: AnyKeyword = new AnyKeyword({ [TitleAnnotationId]: "any" @@ -736,28 +786,28 @@ export const anyKeyword: AnyKeyword = new AnyKeyword({ /** * @category guards - * @since 0.67.0 + * @since 3.10.0 */ export const isAnyKeyword: (ast: AST) => ast is AnyKeyword = createASTGuard("AnyKeyword") /** * @category model - * @since 0.67.0 + * @since 3.10.0 */ export class StringKeyword implements Annotated { /** - * @since 0.67.0 + * @since 3.10.0 */ readonly _tag = "StringKeyword" constructor(readonly annotations: Annotations = {}) {} /** - * @since 0.67.0 + * @since 3.10.0 */ toString() { return formatKeyword(this) } /** - * @since 0.67.0 + * @since 3.10.0 */ toJSON(): object { return { @@ -769,7 +819,7 @@ export class StringKeyword implements Annotated { /** * @category constructors - * @since 0.67.0 + * @since 3.10.0 */ export const stringKeyword: StringKeyword = new StringKeyword({ [TitleAnnotationId]: "string", @@ -778,28 +828,28 @@ export const stringKeyword: StringKeyword = new StringKeyword({ /** * @category guards - * @since 0.67.0 + * @since 3.10.0 */ export const isStringKeyword: (ast: AST) => ast is StringKeyword = createASTGuard("StringKeyword") /** * @category model - * @since 0.67.0 + * @since 3.10.0 */ export class NumberKeyword implements Annotated { /** - * @since 0.67.0 + * @since 3.10.0 */ readonly _tag = "NumberKeyword" constructor(readonly annotations: Annotations = {}) {} /** - * @since 0.67.0 + * @since 3.10.0 */ toString() { return formatKeyword(this) } /** - * @since 0.67.0 + * @since 3.10.0 */ toJSON(): object { return { @@ -811,7 +861,7 @@ export class NumberKeyword implements Annotated { /** * @category constructors - * @since 0.67.0 + * @since 3.10.0 */ export const numberKeyword: NumberKeyword = new NumberKeyword({ [TitleAnnotationId]: "number", @@ -820,28 +870,28 @@ export const numberKeyword: NumberKeyword = new NumberKeyword({ /** * @category guards - * @since 0.67.0 + * @since 3.10.0 */ export const isNumberKeyword: (ast: AST) => ast is NumberKeyword = createASTGuard("NumberKeyword") /** * @category model - * @since 0.67.0 + * @since 3.10.0 */ export class BooleanKeyword implements Annotated { /** - * @since 0.67.0 + * @since 3.10.0 */ readonly _tag = "BooleanKeyword" constructor(readonly annotations: Annotations = {}) {} /** - * @since 0.67.0 + * @since 3.10.0 */ toString() { return formatKeyword(this) } /** - * @since 0.67.0 + * @since 3.10.0 */ toJSON(): object { return { @@ -853,7 +903,7 @@ export class BooleanKeyword implements Annotated { /** * @category constructors - * @since 0.67.0 + * @since 3.10.0 */ export const booleanKeyword: BooleanKeyword = new BooleanKeyword({ [TitleAnnotationId]: "boolean", @@ -862,28 +912,28 @@ export const booleanKeyword: BooleanKeyword = new BooleanKeyword({ /** * @category guards - * @since 0.67.0 + * @since 3.10.0 */ export const isBooleanKeyword: (ast: AST) => ast is BooleanKeyword = createASTGuard("BooleanKeyword") /** * @category model - * @since 0.67.0 + * @since 3.10.0 */ export class BigIntKeyword implements Annotated { /** - * @since 0.67.0 + * @since 3.10.0 */ readonly _tag = "BigIntKeyword" constructor(readonly annotations: Annotations = {}) {} /** - * @since 0.67.0 + * @since 3.10.0 */ toString() { return formatKeyword(this) } /** - * @since 0.67.0 + * @since 3.10.0 */ toJSON(): object { return { @@ -895,7 +945,7 @@ export class BigIntKeyword implements Annotated { /** * @category constructors - * @since 0.67.0 + * @since 3.10.0 */ export const bigIntKeyword: BigIntKeyword = new BigIntKeyword({ [TitleAnnotationId]: "bigint", @@ -904,28 +954,28 @@ export const bigIntKeyword: BigIntKeyword = new BigIntKeyword({ /** * @category guards - * @since 0.67.0 + * @since 3.10.0 */ export const isBigIntKeyword: (ast: AST) => ast is BigIntKeyword = createASTGuard("BigIntKeyword") /** * @category model - * @since 0.67.0 + * @since 3.10.0 */ export class SymbolKeyword implements Annotated { /** - * @since 0.67.0 + * @since 3.10.0 */ readonly _tag = "SymbolKeyword" constructor(readonly annotations: Annotations = {}) {} /** - * @since 0.67.0 + * @since 3.10.0 */ toString() { return formatKeyword(this) } /** - * @since 0.67.0 + * @since 3.10.0 */ toJSON(): object { return { @@ -937,7 +987,7 @@ export class SymbolKeyword implements Annotated { /** * @category constructors - * @since 0.67.0 + * @since 3.10.0 */ export const symbolKeyword: SymbolKeyword = new SymbolKeyword({ [TitleAnnotationId]: "symbol", @@ -946,28 +996,28 @@ export const symbolKeyword: SymbolKeyword = new SymbolKeyword({ /** * @category guards - * @since 0.67.0 + * @since 3.10.0 */ export const isSymbolKeyword: (ast: AST) => ast is SymbolKeyword = createASTGuard("SymbolKeyword") /** * @category model - * @since 0.67.0 + * @since 3.10.0 */ export class ObjectKeyword implements Annotated { /** - * @since 0.67.0 + * @since 3.10.0 */ readonly _tag = "ObjectKeyword" constructor(readonly annotations: Annotations = {}) {} /** - * @since 0.67.0 + * @since 3.10.0 */ toString() { return formatKeyword(this) } /** - * @since 0.67.0 + * @since 3.10.0 */ toJSON(): object { return { @@ -979,7 +1029,7 @@ export class ObjectKeyword implements Annotated { /** * @category constructors - * @since 0.67.0 + * @since 3.10.0 */ export const objectKeyword: ObjectKeyword = new ObjectKeyword({ [TitleAnnotationId]: "object", @@ -988,17 +1038,17 @@ export const objectKeyword: ObjectKeyword = new ObjectKeyword({ /** * @category guards - * @since 0.67.0 + * @since 3.10.0 */ export const isObjectKeyword: (ast: AST) => ast is ObjectKeyword = createASTGuard("ObjectKeyword") /** * @category model - * @since 0.67.0 + * @since 3.10.0 */ export class Enums implements Annotated { /** - * @since 0.67.0 + * @since 3.10.0 */ readonly _tag = "Enums" constructor( @@ -1006,7 +1056,7 @@ export class Enums implements Annotated { readonly annotations: Annotations = {} ) {} /** - * @since 0.67.0 + * @since 3.10.0 */ toString() { return Option.getOrElse( @@ -1015,7 +1065,7 @@ export class Enums implements Annotated { ) } /** - * @since 0.67.0 + * @since 3.10.0 */ toJSON(): object { return { @@ -1028,25 +1078,25 @@ export class Enums implements Annotated { /** * @category guards - * @since 0.67.0 + * @since 3.10.0 */ export const isEnums: (ast: AST) => ast is Enums = createASTGuard("Enums") /** * @category model - * @since 0.67.0 + * @since 3.10.0 */ export class TemplateLiteralSpan { constructor(readonly type: StringKeyword | NumberKeyword, readonly literal: string) {} /** - * @since 0.67.0 + * @since 3.10.0 */ toString() { const type = "${" + String(this.type) + "}" return type + this.literal } /** - * @since 0.67.0 + * @since 3.10.0 */ toJSON(): object { return { @@ -1058,11 +1108,11 @@ export class TemplateLiteralSpan { /** * @category model - * @since 0.67.0 + * @since 3.10.0 */ export class TemplateLiteral implements Annotated { /** - * @since 0.67.0 + * @since 3.10.0 */ readonly _tag = "TemplateLiteral" constructor( @@ -1071,13 +1121,13 @@ export class TemplateLiteral implements Annotated { readonly annotations: Annotations = {} ) {} /** - * @since 0.67.0 + * @since 3.10.0 */ toString() { return Option.getOrElse(getExpected(this), () => formatTemplateLiteral(this)) } /** - * @since 0.67.0 + * @since 3.10.0 */ toJSON(): object { return { @@ -1095,13 +1145,13 @@ const formatTemplateLiteral = (ast: TemplateLiteral): string => /** * @category guards - * @since 0.67.0 + * @since 3.10.0 */ export const isTemplateLiteral: (ast: AST) => ast is TemplateLiteral = createASTGuard("TemplateLiteral") /** * @category model - * @since 0.68.0 + * @since 3.10.0 */ export class Type implements Annotated { constructor( @@ -1109,7 +1159,7 @@ export class Type implements Annotated { readonly annotations: Annotations = {} ) {} /** - * @since 0.68.0 + * @since 3.10.0 */ toJSON(): object { return { @@ -1118,7 +1168,7 @@ export class Type implements Annotated { } } /** - * @since 0.68.0 + * @since 3.10.0 */ toString() { return String(this.type) @@ -1127,7 +1177,7 @@ export class Type implements Annotated { /** * @category model - * @since 0.68.0 + * @since 3.10.0 */ export class OptionalType extends Type { constructor( @@ -1138,7 +1188,7 @@ export class OptionalType extends Type { super(type, annotations) } /** - * @since 0.68.0 + * @since 3.10.0 */ toJSON(): object { return { @@ -1148,7 +1198,7 @@ export class OptionalType extends Type { } } /** - * @since 0.68.0 + * @since 3.10.0 */ toString() { return String(this.type) + (this.isOptional ? "?" : "") @@ -1159,11 +1209,11 @@ const getRestASTs = (rest: ReadonlyArray): ReadonlyArray => rest.map( /** * @category model - * @since 0.67.0 + * @since 3.10.0 */ export class TupleType implements Annotated { /** - * @since 0.67.0 + * @since 3.10.0 */ readonly _tag = "TupleType" constructor( @@ -1187,13 +1237,13 @@ export class TupleType implements Annotated { } } /** - * @since 0.67.0 + * @since 3.10.0 */ toString() { return Option.getOrElse(getExpected(this), () => formatTuple(this)) } /** - * @since 0.67.0 + * @since 3.10.0 */ toJSON(): object { return { @@ -1235,13 +1285,13 @@ const formatTuple = (ast: TupleType): string => { /** * @category guards - * @since 0.67.0 + * @since 3.10.0 */ export const isTupleType: (ast: AST) => ast is TupleType = createASTGuard("TupleType") /** * @category model - * @since 0.67.0 + * @since 3.10.0 */ export class PropertySignature extends OptionalType { constructor( @@ -1254,14 +1304,14 @@ export class PropertySignature extends OptionalType { super(type, isOptional, annotations) } /** - * @since 0.68.18 + * @since 3.10.0 */ toString(): string { return (this.isReadonly ? "readonly " : "") + String(this.name) + (this.isOptional ? "?" : "") + ": " + this.type } /** - * @since 0.67.0 + * @since 3.10.0 */ toJSON(): object { return { @@ -1275,12 +1325,12 @@ export class PropertySignature extends OptionalType { } /** - * @since 0.67.0 + * @since 3.10.0 */ export type Parameter = StringKeyword | SymbolKeyword | TemplateLiteral | Refinement /** - * @since 0.67.0 + * @since 3.10.0 */ export const isParameter = (ast: AST): ast is Parameter => { switch (ast._tag) { @@ -1296,11 +1346,11 @@ export const isParameter = (ast: AST): ast is Parameter => { /** * @category model - * @since 0.67.0 + * @since 3.10.0 */ export class IndexSignature { /** - * @since 0.67.0 + * @since 3.10.0 */ readonly parameter: Parameter constructor( @@ -1315,13 +1365,13 @@ export class IndexSignature { } } /** - * @since 0.68.18 + * @since 3.10.0 */ toString(): string { return (this.isReadonly ? "readonly " : "") + `[x: ${this.parameter}]: ${this.type}` } /** - * @since 0.67.0 + * @since 3.10.0 */ toJSON(): object { return { @@ -1334,19 +1384,19 @@ export class IndexSignature { /** * @category model - * @since 0.67.0 + * @since 3.10.0 */ export class TypeLiteral implements Annotated { /** - * @since 0.67.0 + * @since 3.10.0 */ readonly _tag = "TypeLiteral" /** - * @since 0.67.0 + * @since 3.10.0 */ readonly propertySignatures: ReadonlyArray /** - * @since 0.67.0 + * @since 3.10.0 */ readonly indexSignatures: ReadonlyArray constructor( @@ -1387,13 +1437,13 @@ export class TypeLiteral implements Annotated { this.indexSignatures = indexSignatures } /** - * @since 0.67.0 + * @since 3.10.0 */ toString() { return Option.getOrElse(getExpected(this), () => formatTypeLiteral(this)) } /** - * @since 0.67.0 + * @since 3.10.0 */ toJSON(): object { return { @@ -1426,12 +1476,12 @@ const formatTypeLiteral = (ast: TypeLiteral): string => { /** * @category guards - * @since 0.67.0 + * @since 3.10.0 */ export const isTypeLiteral: (ast: AST) => ast is TypeLiteral = createASTGuard("TypeLiteral") /** - * @since 0.67.0 + * @since 3.10.0 */ export type Members = readonly [A, A, ...Array] @@ -1553,7 +1603,7 @@ export const unify = (candidates: ReadonlyArray): Array => { /** * @category model - * @since 0.67.0 + * @since 3.10.0 */ export class Union implements Annotated { static make = (types: ReadonlyArray, annotations?: Annotations): AST => { @@ -1564,12 +1614,12 @@ export class Union implements Annotated { return Union.make(unify(flatten(candidates)), annotations) } /** - * @since 0.67.0 + * @since 3.10.0 */ readonly _tag = "Union" private constructor(readonly types: Members, readonly annotations: Annotations = {}) {} /** - * @since 0.67.0 + * @since 3.10.0 */ toString() { return Option.getOrElse( @@ -1578,7 +1628,7 @@ export class Union implements Annotated { ) } /** - * @since 0.67.0 + * @since 3.10.0 */ toJSON(): object { return { @@ -1597,29 +1647,29 @@ export const isMembers = (as: ReadonlyArray): as is Members => as.lengt /** * @category guards - * @since 0.67.0 + * @since 3.10.0 */ export const isUnion: (ast: AST) => ast is Union = createASTGuard("Union") const toJSONMemoMap = globalValue( - Symbol.for("@effect/schema/AST/toJSONMemoMap"), + Symbol.for("effect/Schema/AST/toJSONMemoMap"), () => new WeakMap() ) /** * @category model - * @since 0.67.0 + * @since 3.10.0 */ export class Suspend implements Annotated { /** - * @since 0.67.0 + * @since 3.10.0 */ readonly _tag = "Suspend" constructor(readonly f: () => AST, readonly annotations: Annotations = {}) { this.f = util_.memoizeThunk(f) } /** - * @since 0.67.0 + * @since 3.10.0 */ toString() { return getExpected(this).pipe( @@ -1633,7 +1683,7 @@ export class Suspend implements Annotated { ) } /** - * @since 0.67.0 + * @since 3.10.0 */ toJSON(): object { const ast = this.f() @@ -1654,17 +1704,17 @@ export class Suspend implements Annotated { /** * @category guards - * @since 0.67.0 + * @since 3.10.0 */ export const isSuspend: (ast: AST) => ast is Suspend = createASTGuard("Suspend") /** * @category model - * @since 0.67.0 + * @since 3.10.0 */ export class Refinement implements Annotated { /** - * @since 0.67.0 + * @since 3.10.0 */ readonly _tag = "Refinement" constructor( @@ -1677,13 +1727,13 @@ export class Refinement implements Annotated { readonly annotations: Annotations = {} ) {} /** - * @since 0.67.0 + * @since 3.10.0 */ toString() { return Option.getOrElse(getExpected(this), () => `{ ${this.from} | filter }`) } /** - * @since 0.67.0 + * @since 3.10.0 */ toJSON(): object { return { @@ -1696,13 +1746,13 @@ export class Refinement implements Annotated { /** * @category guards - * @since 0.67.0 + * @since 3.10.0 */ export const isRefinement: (ast: AST) => ast is Refinement = createASTGuard("Refinement") /** * @category model - * @since 0.67.0 + * @since 3.10.0 */ export interface ParseOptions { /** @@ -1714,7 +1764,7 @@ export interface ParseOptions { * * default: "first" * - * @since 0.67.0 + * @since 3.10.0 */ readonly errors?: "first" | "all" | undefined /** @@ -1733,7 +1783,7 @@ export interface ParseOptions { * * default: "ignore" * - * @since 0.67.0 + * @since 3.10.0 */ readonly onExcessProperty?: "ignore" | "error" | "preserve" | undefined /** @@ -1753,7 +1803,7 @@ export interface ParseOptions { * * default: "none" * - * @since 0.67.20 + * @since 3.10.0 */ readonly propertyOrder?: "none" | "original" | undefined /** @@ -1765,23 +1815,23 @@ export interface ParseOptions { * * default: false * - * @since 0.67.24 + * @since 3.10.0 */ readonly exact?: boolean | undefined } /** - * @since 0.67.0 + * @since 3.10.0 */ export const defaultParseOption: ParseOptions = {} /** * @category model - * @since 0.67.0 + * @since 3.10.0 */ export class Transformation implements Annotated { /** - * @since 0.67.0 + * @since 3.10.0 */ readonly _tag = "Transformation" constructor( @@ -1791,7 +1841,7 @@ export class Transformation implements Annotated { readonly annotations: Annotations = {} ) {} /** - * @since 0.67.0 + * @since 3.10.0 */ toString() { return Option.getOrElse( @@ -1800,7 +1850,7 @@ export class Transformation implements Annotated { ) } /** - * @since 0.67.0 + * @since 3.10.0 */ toJSON(): object { return { @@ -1814,13 +1864,13 @@ export class Transformation implements Annotated { /** * @category guards - * @since 0.67.0 + * @since 3.10.0 */ export const isTransformation: (ast: AST) => ast is Transformation = createASTGuard("Transformation") /** * @category model - * @since 0.67.0 + * @since 3.10.0 */ export type TransformationKind = | FinalTransformation @@ -1829,11 +1879,11 @@ export type TransformationKind = /** * @category model - * @since 0.67.0 + * @since 3.10.0 */ export class FinalTransformation { /** - * @since 0.67.0 + * @since 3.10.0 */ readonly _tag = "FinalTransformation" constructor( @@ -1853,7 +1903,7 @@ const createTransformationGuard = /** * @category guards - * @since 0.67.0 + * @since 3.10.0 */ export const isFinalTransformation: (ast: TransformationKind) => ast is FinalTransformation = createTransformationGuard( "FinalTransformation" @@ -1861,24 +1911,24 @@ export const isFinalTransformation: (ast: TransformationKind) => ast is FinalTra /** * @category model - * @since 0.67.0 + * @since 3.10.0 */ export class ComposeTransformation { /** - * @since 0.67.0 + * @since 3.10.0 */ readonly _tag = "ComposeTransformation" } /** * @category constructors - * @since 0.67.0 + * @since 3.10.0 */ export const composeTransformation: ComposeTransformation = new ComposeTransformation() /** * @category guards - * @since 0.67.0 + * @since 3.10.0 */ export const isComposeTransformation: (ast: TransformationKind) => ast is ComposeTransformation = createTransformationGuard( @@ -1897,7 +1947,7 @@ export const isComposeTransformation: (ast: TransformationKind) => ast is Compos * - `some(value)` you want to output the key/value pair * * @category model - * @since 0.67.0 + * @since 3.10.0 */ export class PropertySignatureTransformation { constructor( @@ -1913,11 +1963,11 @@ const isRenamingPropertySignatureTransformation = (t: PropertySignatureTransform /** * @category model - * @since 0.67.0 + * @since 3.10.0 */ export class TypeLiteralTransformation { /** - * @since 0.67.0 + * @since 3.10.0 */ readonly _tag = "TypeLiteralTransformation" constructor( @@ -1945,7 +1995,7 @@ export class TypeLiteralTransformation { /** * @category guards - * @since 0.67.0 + * @since 3.10.0 */ export const isTypeLiteralTransformation: (ast: TransformationKind) => ast is TypeLiteralTransformation = createTransformationGuard("TypeLiteralTransformation") @@ -1958,7 +2008,7 @@ export const isTypeLiteralTransformation: (ast: TransformationKind) => ast is Ty * Merges a set of new annotations with existing ones, potentially overwriting * any duplicates. * - * @since 0.67.0 + * @since 3.10.0 */ export const annotations = (ast: AST, annotations: Annotations): AST => { const d = Object.getOwnPropertyDescriptors(ast) @@ -1969,7 +2019,7 @@ export const annotations = (ast: AST, annotations: Annotations): AST => { /** * Equivalent at runtime to the TypeScript type-level `keyof` operator. * - * @since 0.67.0 + * @since 3.10.0 */ export const keyof = (ast: AST): AST => Union.unify(_keyof(ast)) @@ -1977,7 +2027,7 @@ const STRING_KEYWORD_PATTERN = ".*" const NUMBER_KEYWORD_PATTERN = "[+-]?\\d*\\.?\\d+(?:[Ee][+-]?\\d+)?" /** - * @since 0.67.0 + * @since 3.10.0 */ export const getTemplateLiteralRegExp = (ast: TemplateLiteral): RegExp => { let pattern = `^${regexp.escape(ast.head)}` @@ -1996,7 +2046,7 @@ export const getTemplateLiteralRegExp = (ast: TemplateLiteral): RegExp => { } /** - * @since 0.70.1 + * @since 3.10.0 */ export const getTemplateLiteralCapturingRegExp = (ast: TemplateLiteral): RegExp => { let pattern = `^` @@ -2020,7 +2070,7 @@ export const getTemplateLiteralCapturingRegExp = (ast: TemplateLiteral): RegExp } /** - * @since 0.67.0 + * @since 3.10.0 */ export const getPropertySignatures = (ast: AST): Array => { switch (ast._tag) { @@ -2207,7 +2257,7 @@ export const record = (key: AST, value: AST): { /** * Equivalent at runtime to the built-in TypeScript utility type `Pick`. * - * @since 0.67.0 + * @since 3.10.0 */ export const pick = (ast: AST, keys: ReadonlyArray): TypeLiteral | Transformation => { const annotation = getSurrogateAnnotation(ast) @@ -2277,7 +2327,7 @@ export const pick = (ast: AST, keys: ReadonlyArray): TypeLiteral | /** * Equivalent at runtime to the built-in TypeScript utility type `Omit`. * - * @since 0.67.0 + * @since 3.10.0 */ export const omit = (ast: AST, keys: ReadonlyArray): TypeLiteral | Transformation => pick(ast, getPropertyKeys(ast).filter((name) => !keys.includes(name))) @@ -2288,7 +2338,7 @@ export const orUndefined = (ast: AST): AST => Union.make([ast, undefinedKeyword] /** * Equivalent at runtime to the built-in TypeScript utility type `Partial`. * - * @since 0.67.0 + * @since 3.10.0 */ export const partial = (ast: AST, options?: { readonly exact: true }): AST => { const exact = options?.exact === true @@ -2333,7 +2383,7 @@ export const partial = (ast: AST, options?: { readonly exact: true }): AST => { /** * Equivalent at runtime to the built-in TypeScript utility type `Required`. * - * @since 0.67.0 + * @since 3.10.0 */ export const required = (ast: AST): AST => { switch (ast._tag) { @@ -2374,7 +2424,7 @@ export const required = (ast: AST): AST => { * * @param ast - The original AST to make properties mutable (shallowly). * - * @since 0.67.0 + * @since 3.10.0 */ export const mutable = (ast: AST): AST => { switch (ast._tag) { @@ -2420,19 +2470,19 @@ export const mutable = (ast: AST): AST => { // ------------------------------------------------------------------------------------- /** - * @since 0.67.0 + * @since 3.10.0 */ export type Compiler = (ast: AST, path: ReadonlyArray) => A /** - * @since 0.67.0 + * @since 3.10.0 */ export type Match = { [K in AST["_tag"]]: (ast: Extract, compile: Compiler, path: ReadonlyArray) => A } /** - * @since 0.67.0 + * @since 3.10.0 */ export const getCompiler = (match: Match): Compiler => { const compile = (ast: AST, path: ReadonlyArray): A => match[ast._tag](ast as any, compile, path) @@ -2440,7 +2490,7 @@ export const getCompiler = (match: Match): Compiler => { } /** - * @since 0.67.0 + * @since 3.10.0 */ export const typeAST = (ast: AST): AST => { switch (ast._tag) { @@ -2517,10 +2567,6 @@ export const blackListAnnotations = return out } -/** @internal */ -export const getJSONIdentifier = (annotated: Annotated) => - Option.orElse(getJSONIdentifierAnnotation(annotated), () => getIdentifierAnnotation(annotated)) - // To generate a JSON Schema from a recursive schema, an `identifier` annotation // is required. So, when we calculate the encodedAST, we need to preserve the // annotation in the form of an internal custom annotation that acts as a @@ -2614,12 +2660,12 @@ const encodedAST_ = (ast: AST, isBound: boolean): AST => { } /** - * @since 0.67.0 + * @since 3.10.0 */ export const encodedAST = (ast: AST): AST => encodedAST_(ast, false) /** - * @since 0.67.0 + * @since 3.10.0 */ export const encodedBoundAST = (ast: AST): AST => encodedAST_(ast, true) diff --git a/packages/effect/src/index.ts b/packages/effect/src/index.ts index a57bd513ed..52f1a01328 100644 --- a/packages/effect/src/index.ts +++ b/packages/effect/src/index.ts @@ -29,6 +29,11 @@ export { unsafeCoerce } from "./Function.js" +/** + * @since 3.10.0 + */ +export * as Arbitrary from "./Arbitrary.js" + /** * This module provides utility functions for working with arrays in TypeScript. * @@ -262,6 +267,11 @@ export * as ExecutionStrategy from "./ExecutionStrategy.js" */ export * as Exit from "./Exit.js" +/** + * @since 3.10.0 + */ +export * as FastCheck from "./FastCheck.js" + /** * @since 2.0.0 */ @@ -354,6 +364,11 @@ export * as Inspectable from "./Inspectable.js" */ export * as Iterable from "./Iterable.js" +/** + * @since 3.10.0 + */ +export * as JSONSchema from "./JSONSchema.js" + /** * @since 2.0.0 */ @@ -574,6 +589,11 @@ export * as Order from "./Order.js" */ export * as Ordering from "./Ordering.js" +/** + * @since 3.10.0 + */ +export * as ParseResult from "./ParseResult.js" + /** * @since 2.0.0 */ @@ -589,6 +609,11 @@ export * as Pool from "./Pool.js" */ export * as Predicate from "./Predicate.js" +/** + * @since 3.10.0 + */ +export * as Pretty from "./Pretty.js" + /** * @since 2.0.0 */ @@ -735,6 +760,16 @@ export * as ScheduleIntervals from "./ScheduleIntervals.js" */ export * as Scheduler from "./Scheduler.js" +/** + * @since 3.10.0 + */ +export * as Schema from "./Schema.js" + +/** + * @since 3.10.0 + */ +export * as SchemaAST from "./SchemaAST.js" + /** * @since 2.0.0 */ diff --git a/packages/schema/src/internal/errors.ts b/packages/effect/src/internal/schema/errors.ts similarity index 99% rename from packages/schema/src/internal/errors.ts rename to packages/effect/src/internal/schema/errors.ts index 4a8de668fa..628df011c1 100644 --- a/packages/schema/src/internal/errors.ts +++ b/packages/effect/src/internal/schema/errors.ts @@ -1,5 +1,5 @@ import * as array_ from "effect/Array" -import type * as AST from "../AST.js" +import type * as AST from "../../SchemaAST.js" import * as util_ from "./util.js" const getErrorMessage = ( diff --git a/packages/effect/src/internal/schema/filters.ts b/packages/effect/src/internal/schema/filters.ts new file mode 100644 index 0000000000..710373d7b4 --- /dev/null +++ b/packages/effect/src/internal/schema/filters.ts @@ -0,0 +1,86 @@ +import type * as Schema from "../../Schema.js" + +/** @internal */ +export const GreaterThanSchemaId: Schema.GreaterThanSchemaId = Symbol.for( + "effect/schema/GreaterThan" +) as Schema.GreaterThanSchemaId + +/** @internal */ +export const GreaterThanOrEqualToSchemaId: Schema.GreaterThanOrEqualToSchemaId = Symbol.for( + "effect/schema/GreaterThanOrEqualTo" +) as Schema.GreaterThanOrEqualToSchemaId + +/** @internal */ +export const LessThanSchemaId: Schema.LessThanSchemaId = Symbol.for( + "effect/schema/LessThan" +) as Schema.LessThanSchemaId + +/** @internal */ +export const LessThanOrEqualToSchemaId: Schema.LessThanOrEqualToSchemaId = Symbol.for( + "effect/schema/LessThanOrEqualTo" +) as Schema.LessThanOrEqualToSchemaId + +/** @internal */ +export const IntSchemaId: Schema.IntSchemaId = Symbol.for( + "effect/schema/Int" +) as Schema.IntSchemaId + +/** @internal */ +export const BetweenSchemaId: Schema.BetweenSchemaId = Symbol.for( + "effect/schema/Between" +) as Schema.BetweenSchemaId + +/** @internal */ +export const GreaterThanBigintSchemaId: Schema.GreaterThanBigIntSchemaId = Symbol.for( + "effect/schema/GreaterThanBigint" +) as Schema.GreaterThanBigIntSchemaId + +/** @internal */ +export const GreaterThanOrEqualToBigIntSchemaId: Schema.GreaterThanOrEqualToBigIntSchemaId = Symbol.for( + "effect/schema/GreaterThanOrEqualToBigint" +) as Schema.GreaterThanOrEqualToBigIntSchemaId + +/** @internal */ +export const LessThanBigIntSchemaId: Schema.LessThanBigIntSchemaId = Symbol.for( + "effect/schema/LessThanBigint" +) as Schema.LessThanBigIntSchemaId + +/** @internal */ +export const LessThanOrEqualToBigIntSchemaId: Schema.LessThanOrEqualToBigIntSchemaId = Symbol.for( + "effect/schema/LessThanOrEqualToBigint" +) as Schema.LessThanOrEqualToBigIntSchemaId + +/** @internal */ +export const BetweenBigintSchemaId: Schema.BetweenBigIntSchemaId = Symbol.for( + "effect/schema/BetweenBigint" +) as Schema.BetweenBigIntSchemaId + +/** @internal */ +export const MinLengthSchemaId: Schema.MinLengthSchemaId = Symbol.for( + "effect/schema/MinLength" +) as Schema.MinLengthSchemaId + +/** @internal */ +export const MaxLengthSchemaId: Schema.MaxLengthSchemaId = Symbol.for( + "effect/schema/MaxLength" +) as Schema.MaxLengthSchemaId + +/** @internal */ +export const LengthSchemaId: Schema.LengthSchemaId = Symbol.for( + "effect/schema/Length" +) as Schema.LengthSchemaId + +/** @internal */ +export const MinItemsSchemaId: Schema.MinItemsSchemaId = Symbol.for( + "effect/schema/MinItems" +) as Schema.MinItemsSchemaId + +/** @internal */ +export const MaxItemsSchemaId: Schema.MaxItemsSchemaId = Symbol.for( + "effect/schema/MaxItems" +) as Schema.MaxItemsSchemaId + +/** @internal */ +export const ItemsCountSchemaId: Schema.ItemsCountSchemaId = Symbol.for( + "effect/schema/ItemsCount" +) as Schema.ItemsCountSchemaId diff --git a/packages/schema/src/internal/util.ts b/packages/effect/src/internal/schema/util.ts similarity index 96% rename from packages/schema/src/internal/util.ts rename to packages/effect/src/internal/schema/util.ts index 3e6ef905f0..d7dcfb600a 100644 --- a/packages/schema/src/internal/util.ts +++ b/packages/effect/src/internal/schema/util.ts @@ -1,7 +1,7 @@ import * as array_ from "effect/Array" import * as Predicate from "effect/Predicate" -import type * as AST from "../AST.js" -import type * as ParseResult from "../ParseResult.js" +import type * as ParseResult from "../../ParseResult.js" +import type * as AST from "../../SchemaAST.js" /** @internal */ export const getKeysForIndexSignature = ( diff --git a/packages/schema/test/Arbitrary/Arbitrary.test.ts b/packages/effect/test/Schema/Arbitrary/Arbitrary.test.ts similarity index 97% rename from packages/schema/test/Arbitrary/Arbitrary.test.ts rename to packages/effect/test/Schema/Arbitrary/Arbitrary.test.ts index f8ea825cf4..1c4f7c4ef5 100644 --- a/packages/schema/test/Arbitrary/Arbitrary.test.ts +++ b/packages/effect/test/Schema/Arbitrary/Arbitrary.test.ts @@ -1,8 +1,8 @@ -import * as Arbitrary from "@effect/schema/Arbitrary" -import * as S from "@effect/schema/Schema" -import { expectValidArbitrary } from "@effect/schema/test/TestUtils" +import * as Arbitrary from "effect/Arbitrary" import * as Order from "effect/Order" import { isUnknown } from "effect/Predicate" +import * as S from "effect/Schema" +import { expectValidArbitrary } from "effect/test/Schema/TestUtils" import * as fc from "fast-check" import { describe, expect, it } from "vitest" @@ -139,7 +139,7 @@ schema (NeverKeyword): never`) }) it("uniqueSymbolFromSelf", () => { - const a = Symbol.for("@effect/schema/test/a") + const a = Symbol.for("effect/Schema/test/a") const schema = S.UniqueSymbolFromSelf(a) expectValidArbitrary(schema) }) @@ -256,7 +256,7 @@ details: Generating an Arbitrary for this schema requires at least one enum`) const schema = S.Struct({ a: S.String, as: S.Array( - S.suspend((): S.Schema => schema).pipe(Arbitrary.arbitrary(() => () => arb)) + S.suspend((): S.Schema => schema).annotations({ arbitrary: () => () => arb }) ) }) expectValidArbitrary(schema) @@ -620,7 +620,7 @@ details: Generating an Arbitrary for this schema requires at least one enum`) describe("should handle annotations", () => { const expectHook = (source: S.Schema) => { - const schema = source.pipe(Arbitrary.arbitrary(() => (fc) => fc.constant("custom arbitrary") as any)) + const schema = source.annotations({ arbitrary: () => (fc) => fc.constant("custom arbitrary") as any }) const arb = Arbitrary.makeLazy(schema)(fc) expect(fc.sample(arb, 1)[0]).toEqual("custom arbitrary") } diff --git a/packages/schema/test/Arbitrary/Class.test.ts b/packages/effect/test/Schema/Arbitrary/Class.test.ts similarity index 87% rename from packages/schema/test/Arbitrary/Class.test.ts rename to packages/effect/test/Schema/Arbitrary/Class.test.ts index b16d995232..92c80ac1bd 100644 --- a/packages/schema/test/Arbitrary/Class.test.ts +++ b/packages/effect/test/Schema/Arbitrary/Class.test.ts @@ -1,8 +1,8 @@ -import * as S from "@effect/schema/Schema" -import { expectValidArbitrary } from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import { expectValidArbitrary } from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" -describe("class", () => { +describe("Class", () => { it("required property signature", () => { class Class extends S.Class("Class")({ a: S.Number diff --git a/packages/schema/test/Arbitrary/getConstraints.test.ts b/packages/effect/test/Schema/Arbitrary/getConstraints.test.ts similarity index 97% rename from packages/schema/test/Arbitrary/getConstraints.test.ts rename to packages/effect/test/Schema/Arbitrary/getConstraints.test.ts index beedcf58b4..c4bce6b119 100644 --- a/packages/schema/test/Arbitrary/getConstraints.test.ts +++ b/packages/effect/test/Schema/Arbitrary/getConstraints.test.ts @@ -1,12 +1,12 @@ -import * as A from "@effect/schema/Arbitrary" -import * as S from "@effect/schema/Schema" +import * as A from "effect/Arbitrary" +import * as S from "effect/Schema" import { describe, expect, it } from "vitest" const expectConstraints = (schema: S.Schema, constraints: A.Constraints) => { expect(A.getConstraints(schema.ast as any)).toEqual(constraints) } -describe("Arbitrary > getConstraints", () => { +describe("getConstraints", () => { describe("number", () => { it("GreaterThanTypeId", () => { expectConstraints(S.Number.pipe(S.greaterThan(0)), new A.NumberConstraints({ min: 0 })) diff --git a/packages/schema/test/JSONSchema.test.ts b/packages/effect/test/Schema/JSONSchema.test.ts similarity index 99% rename from packages/schema/test/JSONSchema.test.ts rename to packages/effect/test/Schema/JSONSchema.test.ts index bb92bdecbe..dfbc21738a 100644 --- a/packages/schema/test/JSONSchema.test.ts +++ b/packages/effect/test/Schema/JSONSchema.test.ts @@ -1,9 +1,9 @@ -import * as A from "@effect/schema/Arbitrary" -import * as AST from "@effect/schema/AST" -import * as JSONSchema from "@effect/schema/JSONSchema" -import * as Schema from "@effect/schema/Schema" import AjvNonEsm from "ajv" +import * as A from "effect/Arbitrary" +import * as JSONSchema from "effect/JSONSchema" import * as Predicate from "effect/Predicate" +import * as Schema from "effect/Schema" +import * as AST from "effect/SchemaAST" import * as fc from "fast-check" import { describe, expect, it } from "vitest" @@ -104,10 +104,10 @@ schema (SymbolKeyword): symbol` it("a unique symbol should raise an error", () => { expectError( - Schema.UniqueSymbolFromSelf(Symbol.for("@effect/schema/test/a")), + Schema.UniqueSymbolFromSelf(Symbol.for("effect/Schema/test/a")), `Missing annotation details: Generating a JSON Schema for this schema requires a "jsonSchema" annotation -schema (UniqueSymbol): Symbol(@effect/schema/test/a)` +schema (UniqueSymbol): Symbol(effect/Schema/test/a)` ) }) @@ -789,11 +789,11 @@ schema (Declaration): DateFromSelf` }) it("should raise an error if there is a property named with a symbol", () => { - const a = Symbol.for("@effect/schema/test/a") + const a = Symbol.for("effect/Schema/test/a") expectError( Schema.Struct({ [a]: Schema.String }), `Unsupported key -details: Cannot encode Symbol(@effect/schema/test/a) key to JSON Schema` +details: Cannot encode Symbol(effect/Schema/test/a) key to JSON Schema` ) }) diff --git a/packages/schema/test/ParseResult.test.ts b/packages/effect/test/Schema/ParseResult.test.ts similarity index 99% rename from packages/schema/test/ParseResult.test.ts rename to packages/effect/test/Schema/ParseResult.test.ts index 2558e5ee3c..7655d6d0a1 100644 --- a/packages/schema/test/ParseResult.test.ts +++ b/packages/effect/test/Schema/ParseResult.test.ts @@ -1,7 +1,7 @@ -import * as AST from "@effect/schema/AST" -import * as P from "@effect/schema/ParseResult" -import * as S from "@effect/schema/Schema" import { Effect, Either, Exit } from "effect" +import * as P from "effect/ParseResult" +import * as S from "effect/Schema" +import * as AST from "effect/SchemaAST" import { inspect } from "node:util" import { describe, expect, it } from "vitest" diff --git a/packages/schema/test/Formatter.test.ts b/packages/effect/test/Schema/ParseResultFormatter.test.ts similarity index 97% rename from packages/schema/test/Formatter.test.ts rename to packages/effect/test/Schema/ParseResultFormatter.test.ts index 15c62552cc..2864187894 100644 --- a/packages/schema/test/Formatter.test.ts +++ b/packages/effect/test/Schema/ParseResultFormatter.test.ts @@ -1,27 +1,25 @@ -import * as ArrayFormatter from "@effect/schema/ArrayFormatter" -import type { ParseOptions } from "@effect/schema/AST" -import * as AST from "@effect/schema/AST" -import * as ParseResult from "@effect/schema/ParseResult" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" -import * as TreeFormatter from "@effect/schema/TreeFormatter" import * as Context from "effect/Context" import * as Effect from "effect/Effect" import * as Either from "effect/Either" import { identity, pipe } from "effect/Function" import * as Option from "effect/Option" +import * as ParseResult from "effect/ParseResult" +import * as S from "effect/Schema" +import type { ParseOptions } from "effect/SchemaAST" +import * as AST from "effect/SchemaAST" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" const options: ParseOptions = { errors: "all", onExcessProperty: "error" } -const expectIssues = (schema: S.Schema, input: unknown, issues: Array) => { +const expectIssues = (schema: S.Schema, input: unknown, issues: Array) => { const result = S.decodeUnknownEither(schema)(input, options).pipe( - Either.mapLeft((e) => ArrayFormatter.formatIssueSync(e.issue)) + Either.mapLeft((e) => ParseResult.ArrayFormatter.formatIssueSync(e.issue)) ) expect(result).toStrictEqual(Either.left(issues)) } -describe("Formatter", () => { +describe("ParseResultFormatter", () => { describe("Forbidden", () => { it("default message", () => { const schema = Util.effectify(S.String) @@ -1278,7 +1276,7 @@ it("Effect as message", () => { const result = S.decodeUnknownEither(Name)("") // no service - expect(Either.mapLeft(result, (error) => Effect.runSync(TreeFormatter.formatError(error)))) + expect(Either.mapLeft(result, (error) => Effect.runSync(ParseResult.TreeFormatter.formatError(error)))) .toStrictEqual(Either.left("Invalid string")) // it locale @@ -1287,7 +1285,7 @@ it("Effect as message", () => { result, (error) => Effect.runSync( - TreeFormatter.formatError(error).pipe(Effect.provideService(Translator, { + ParseResult.TreeFormatter.formatError(error).pipe(Effect.provideService(Translator, { locale: "it", translations })) @@ -1301,7 +1299,7 @@ it("Effect as message", () => { result, (error) => Effect.runSync( - TreeFormatter.formatError(error).pipe(Effect.provideService(Translator, { + ParseResult.TreeFormatter.formatError(error).pipe(Effect.provideService(Translator, { locale: "en", translations })) diff --git a/packages/schema/test/Pretty.test.ts b/packages/effect/test/Schema/Pretty.test.ts similarity index 97% rename from packages/schema/test/Pretty.test.ts rename to packages/effect/test/Schema/Pretty.test.ts index cb13c36955..1a25058339 100644 --- a/packages/schema/test/Pretty.test.ts +++ b/packages/effect/test/Schema/Pretty.test.ts @@ -1,7 +1,7 @@ -import * as AST from "@effect/schema/AST" -import * as Pretty from "@effect/schema/Pretty" -import * as S from "@effect/schema/Schema" import { isUnknown } from "effect/Predicate" +import * as Pretty from "effect/Pretty" +import * as S from "effect/Schema" +import * as AST from "effect/SchemaAST" import { describe, expect, it } from "vitest" describe("Pretty", () => { @@ -127,10 +127,10 @@ schema (Declaration): `) }) it("uniqueSymbolFromSelf", () => { - const a = Symbol.for("@effect/schema/test/a") + const a = Symbol.for("effect/Schema/test/a") const schema = S.UniqueSymbolFromSelf(a) const pretty = Pretty.make(schema) - expect(pretty(a)).toEqual("Symbol(@effect/schema/test/a)") + expect(pretty(a)).toEqual("Symbol(effect/Schema/test/a)") }) describe("enums", () => { @@ -256,11 +256,11 @@ schema (Declaration): `) }) it("record(symbol, string)", () => { - const a = Symbol.for("@effect/schema/test/a") + const a = Symbol.for("effect/Schema/test/a") const schema = S.Record({ key: S.SymbolFromSelf, value: S.String }) const pretty = Pretty.make(schema) expect(pretty({ [a]: "a" })).toEqual( - `{ Symbol(@effect/schema/test/a): "a" }` + `{ Symbol(effect/Schema/test/a): "a" }` ) }) }) @@ -434,7 +434,7 @@ schema (Declaration): `) describe("should handle annotations", () => { const expectHook = (source: S.Schema) => { - const schema = source.pipe(Pretty.pretty(() => () => "custom pretty")) + const schema = source.annotations({ pretty: () => () => "custom pretty" }) const pretty = Pretty.make(schema) expect(pretty(null as any)).toEqual("custom pretty") } diff --git a/packages/schema/test/Schema/Any/Any.test.ts b/packages/effect/test/Schema/Schema/Any/Any.test.ts similarity index 84% rename from packages/schema/test/Schema/Any/Any.test.ts rename to packages/effect/test/Schema/Schema/Any/Any.test.ts index 9c9c84964b..45271ff5b6 100644 --- a/packages/schema/test/Schema/Any/Any.test.ts +++ b/packages/effect/test/Schema/Schema/Any/Any.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("Any", () => { diff --git a/packages/schema/test/Schema/Array/Array.test.ts b/packages/effect/test/Schema/Schema/Array/Array.test.ts similarity index 90% rename from packages/schema/test/Schema/Array/Array.test.ts rename to packages/effect/test/Schema/Schema/Array/Array.test.ts index 75ebbcd413..0c640642af 100644 --- a/packages/schema/test/Schema/Array/Array.test.ts +++ b/packages/effect/test/Schema/Schema/Array/Array.test.ts @@ -1,7 +1,7 @@ -import * as AST from "@effect/schema/AST" -import * as ParseResult from "@effect/schema/ParseResult" -import * as S from "@effect/schema/Schema" import * as Either from "effect/Either" +import * as ParseResult from "effect/ParseResult" +import * as S from "effect/Schema" +import * as AST from "effect/SchemaAST" import { assert, describe, expect, it } from "vitest" describe("Array", () => { diff --git a/packages/schema/test/Schema/Array/head.test.ts b/packages/effect/test/Schema/Schema/Array/head.test.ts similarity index 90% rename from packages/schema/test/Schema/Array/head.test.ts rename to packages/effect/test/Schema/Schema/Array/head.test.ts index 00f867e401..805a8a1744 100644 --- a/packages/schema/test/Schema/Array/head.test.ts +++ b/packages/effect/test/Schema/Schema/Array/head.test.ts @@ -1,6 +1,6 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import * as Option from "effect/Option" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("head", () => { diff --git a/packages/schema/test/Schema/Array/headOrElse.test.ts b/packages/effect/test/Schema/Schema/Array/headOrElse.test.ts similarity index 95% rename from packages/schema/test/Schema/Array/headOrElse.test.ts rename to packages/effect/test/Schema/Schema/Array/headOrElse.test.ts index ed5274808a..6e95765fe2 100644 --- a/packages/schema/test/Schema/Array/headOrElse.test.ts +++ b/packages/effect/test/Schema/Schema/Array/headOrElse.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("headOrElse", () => { diff --git a/packages/schema/test/Schema/Array/itemsCount.test.ts b/packages/effect/test/Schema/Schema/Array/itemsCount.test.ts similarity index 89% rename from packages/schema/test/Schema/Array/itemsCount.test.ts rename to packages/effect/test/Schema/Schema/Array/itemsCount.test.ts index 650bc8acff..5167fbb64e 100644 --- a/packages/schema/test/Schema/Array/itemsCount.test.ts +++ b/packages/effect/test/Schema/Schema/Array/itemsCount.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("itemsCount", () => { diff --git a/packages/schema/test/Schema/Array/maxItems.test.ts b/packages/effect/test/Schema/Schema/Array/maxItems.test.ts similarity index 83% rename from packages/schema/test/Schema/Array/maxItems.test.ts rename to packages/effect/test/Schema/Schema/Array/maxItems.test.ts index b803cf8168..036c7e6869 100644 --- a/packages/schema/test/Schema/Array/maxItems.test.ts +++ b/packages/effect/test/Schema/Schema/Array/maxItems.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("maxItems", () => { diff --git a/packages/schema/test/Schema/Array/minItems.test.ts b/packages/effect/test/Schema/Schema/Array/minItems.test.ts similarity index 88% rename from packages/schema/test/Schema/Array/minItems.test.ts rename to packages/effect/test/Schema/Schema/Array/minItems.test.ts index dce6d99e3b..4d6de3d485 100644 --- a/packages/schema/test/Schema/Array/minItems.test.ts +++ b/packages/effect/test/Schema/Schema/Array/minItems.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("minItems", () => { diff --git a/packages/schema/test/Schema/ArrayEnsure.test.ts b/packages/effect/test/Schema/Schema/ArrayEnsure.test.ts similarity index 96% rename from packages/schema/test/Schema/ArrayEnsure.test.ts rename to packages/effect/test/Schema/Schema/ArrayEnsure.test.ts index 1567ed127f..c69c6622b9 100644 --- a/packages/schema/test/Schema/ArrayEnsure.test.ts +++ b/packages/effect/test/Schema/Schema/ArrayEnsure.test.ts @@ -1,5 +1,5 @@ -import * as AST from "@effect/schema/AST" -import * as S from "@effect/schema/Schema" +import * as S from "effect/Schema" +import * as AST from "effect/SchemaAST" import { describe, expect, it } from "vitest" import { expectDecodeUnknownFailure, expectDecodeUnknownSuccess, expectEncodeSuccess } from "../TestUtils.js" diff --git a/packages/schema/test/Schema/BigDecimal/BigDecimal.test.ts b/packages/effect/test/Schema/Schema/BigDecimal/BigDecimal.test.ts similarity index 91% rename from packages/schema/test/Schema/BigDecimal/BigDecimal.test.ts rename to packages/effect/test/Schema/Schema/BigDecimal/BigDecimal.test.ts index 2adb7be3a5..6810b88c26 100644 --- a/packages/schema/test/Schema/BigDecimal/BigDecimal.test.ts +++ b/packages/effect/test/Schema/Schema/BigDecimal/BigDecimal.test.ts @@ -1,6 +1,6 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import { BigDecimal } from "effect" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("BigDecimal", () => { diff --git a/packages/schema/test/Schema/BigDecimal/BigDecimalFromNumber.test.ts b/packages/effect/test/Schema/Schema/BigDecimal/BigDecimalFromNumber.test.ts similarity index 91% rename from packages/schema/test/Schema/BigDecimal/BigDecimalFromNumber.test.ts rename to packages/effect/test/Schema/Schema/BigDecimal/BigDecimalFromNumber.test.ts index 26b583dc6d..d36a602562 100644 --- a/packages/schema/test/Schema/BigDecimal/BigDecimalFromNumber.test.ts +++ b/packages/effect/test/Schema/Schema/BigDecimal/BigDecimalFromNumber.test.ts @@ -1,6 +1,6 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import { BigDecimal } from "effect" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("BigDecimalFromNumber", () => { diff --git a/packages/schema/test/Schema/BigDecimal/BigDecimalFromSelf.test.ts b/packages/effect/test/Schema/Schema/BigDecimal/BigDecimalFromSelf.test.ts similarity index 86% rename from packages/schema/test/Schema/BigDecimal/BigDecimalFromSelf.test.ts rename to packages/effect/test/Schema/Schema/BigDecimal/BigDecimalFromSelf.test.ts index e764008ac5..81967aac85 100644 --- a/packages/schema/test/Schema/BigDecimal/BigDecimalFromSelf.test.ts +++ b/packages/effect/test/Schema/Schema/BigDecimal/BigDecimalFromSelf.test.ts @@ -1,8 +1,7 @@ -import * as Equivalence from "@effect/schema/Equivalence" -import * as Pretty from "@effect/schema/Pretty" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import { BigDecimal } from "effect" +import * as Pretty from "effect/Pretty" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("BigDecimalFromSelf", () => { @@ -43,7 +42,7 @@ describe("BigDecimalFromSelf", () => { it("equivalence", () => { const schema = S.BigDecimalFromSelf - const equivalence = Equivalence.make(schema) + const equivalence = S.equivalence(schema) expect(equivalence(BigDecimal.fromNumber(1), BigDecimal.unsafeFromString("1"))).toBe(true) expect(equivalence(BigDecimal.fromNumber(2), BigDecimal.unsafeFromString("1"))).toBe(false) diff --git a/packages/schema/test/Schema/BigDecimal/NegativeBigDecimalFromSelf.test.ts b/packages/effect/test/Schema/Schema/BigDecimal/NegativeBigDecimalFromSelf.test.ts similarity index 90% rename from packages/schema/test/Schema/BigDecimal/NegativeBigDecimalFromSelf.test.ts rename to packages/effect/test/Schema/Schema/BigDecimal/NegativeBigDecimalFromSelf.test.ts index 10d79c0c92..00e582fd3f 100644 --- a/packages/schema/test/Schema/BigDecimal/NegativeBigDecimalFromSelf.test.ts +++ b/packages/effect/test/Schema/Schema/BigDecimal/NegativeBigDecimalFromSelf.test.ts @@ -1,6 +1,6 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import { BigDecimal } from "effect" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("NegativeBigDecimalFromSelf", () => { diff --git a/packages/schema/test/Schema/BigDecimal/NonNegativeBigDecimalFromSelf.test.ts b/packages/effect/test/Schema/Schema/BigDecimal/NonNegativeBigDecimalFromSelf.test.ts similarity index 89% rename from packages/schema/test/Schema/BigDecimal/NonNegativeBigDecimalFromSelf.test.ts rename to packages/effect/test/Schema/Schema/BigDecimal/NonNegativeBigDecimalFromSelf.test.ts index db065c4377..1f325b386c 100644 --- a/packages/schema/test/Schema/BigDecimal/NonNegativeBigDecimalFromSelf.test.ts +++ b/packages/effect/test/Schema/Schema/BigDecimal/NonNegativeBigDecimalFromSelf.test.ts @@ -1,6 +1,6 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import { BigDecimal } from "effect" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("NonNegativeBigDecimalFromSelf", () => { diff --git a/packages/schema/test/Schema/BigDecimal/NonPositiveBigDecimalFromSelf.test.ts b/packages/effect/test/Schema/Schema/BigDecimal/NonPositiveBigDecimalFromSelf.test.ts similarity index 89% rename from packages/schema/test/Schema/BigDecimal/NonPositiveBigDecimalFromSelf.test.ts rename to packages/effect/test/Schema/Schema/BigDecimal/NonPositiveBigDecimalFromSelf.test.ts index 81b1ed6138..54df079698 100644 --- a/packages/schema/test/Schema/BigDecimal/NonPositiveBigDecimalFromSelf.test.ts +++ b/packages/effect/test/Schema/Schema/BigDecimal/NonPositiveBigDecimalFromSelf.test.ts @@ -1,6 +1,6 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import { BigDecimal } from "effect" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("NonPositiveBigDecimalFromSelf", () => { diff --git a/packages/schema/test/Schema/BigDecimal/PositiveBigDecimalFromSelf.test.ts b/packages/effect/test/Schema/Schema/BigDecimal/PositiveBigDecimalFromSelf.test.ts similarity index 90% rename from packages/schema/test/Schema/BigDecimal/PositiveBigDecimalFromSelf.test.ts rename to packages/effect/test/Schema/Schema/BigDecimal/PositiveBigDecimalFromSelf.test.ts index aab686c7f0..2bc8ba4d6c 100644 --- a/packages/schema/test/Schema/BigDecimal/PositiveBigDecimalFromSelf.test.ts +++ b/packages/effect/test/Schema/Schema/BigDecimal/PositiveBigDecimalFromSelf.test.ts @@ -1,6 +1,6 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import { BigDecimal } from "effect" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("PositiveBigDecimalFromSelf", () => { diff --git a/packages/schema/test/Schema/BigDecimal/betweenBigDecimal.test.ts b/packages/effect/test/Schema/Schema/BigDecimal/betweenBigDecimal.test.ts similarity index 92% rename from packages/schema/test/Schema/BigDecimal/betweenBigDecimal.test.ts rename to packages/effect/test/Schema/Schema/BigDecimal/betweenBigDecimal.test.ts index 4d045188e7..86e3e04670 100644 --- a/packages/schema/test/Schema/BigDecimal/betweenBigDecimal.test.ts +++ b/packages/effect/test/Schema/Schema/BigDecimal/betweenBigDecimal.test.ts @@ -1,6 +1,6 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import { BigDecimal } from "effect" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" const max = BigDecimal.make(1n, 0) diff --git a/packages/schema/test/Schema/BigDecimal/clampBigDecimal.test.ts b/packages/effect/test/Schema/Schema/BigDecimal/clampBigDecimal.test.ts similarity index 86% rename from packages/schema/test/Schema/BigDecimal/clampBigDecimal.test.ts rename to packages/effect/test/Schema/Schema/BigDecimal/clampBigDecimal.test.ts index b581a16c17..f849de1da0 100644 --- a/packages/schema/test/Schema/BigDecimal/clampBigDecimal.test.ts +++ b/packages/effect/test/Schema/Schema/BigDecimal/clampBigDecimal.test.ts @@ -1,6 +1,6 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import { BigDecimal } from "effect" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("clampBigDecimal", () => { diff --git a/packages/schema/test/Schema/BigDecimal/greaterThanBigDecimal.test.ts b/packages/effect/test/Schema/Schema/BigDecimal/greaterThanBigDecimal.test.ts similarity index 89% rename from packages/schema/test/Schema/BigDecimal/greaterThanBigDecimal.test.ts rename to packages/effect/test/Schema/Schema/BigDecimal/greaterThanBigDecimal.test.ts index b5e1135907..d8ba56fec3 100644 --- a/packages/schema/test/Schema/BigDecimal/greaterThanBigDecimal.test.ts +++ b/packages/effect/test/Schema/Schema/BigDecimal/greaterThanBigDecimal.test.ts @@ -1,6 +1,6 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import { BigDecimal } from "effect" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("greaterThanBigDecimal", () => { diff --git a/packages/schema/test/Schema/BigDecimal/greaterThanOrEqualToBigDecimal.test.ts b/packages/effect/test/Schema/Schema/BigDecimal/greaterThanOrEqualToBigDecimal.test.ts similarity index 88% rename from packages/schema/test/Schema/BigDecimal/greaterThanOrEqualToBigDecimal.test.ts rename to packages/effect/test/Schema/Schema/BigDecimal/greaterThanOrEqualToBigDecimal.test.ts index 70be1ea007..624b6ab6ee 100644 --- a/packages/schema/test/Schema/BigDecimal/greaterThanOrEqualToBigDecimal.test.ts +++ b/packages/effect/test/Schema/Schema/BigDecimal/greaterThanOrEqualToBigDecimal.test.ts @@ -1,6 +1,6 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import { BigDecimal } from "effect" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("greaterThanOrEqualToBigDecimal", () => { diff --git a/packages/schema/test/Schema/BigDecimal/lessThanBigDecimal.test.ts b/packages/effect/test/Schema/Schema/BigDecimal/lessThanBigDecimal.test.ts similarity index 89% rename from packages/schema/test/Schema/BigDecimal/lessThanBigDecimal.test.ts rename to packages/effect/test/Schema/Schema/BigDecimal/lessThanBigDecimal.test.ts index b08eb5a1ad..36c51e0b36 100644 --- a/packages/schema/test/Schema/BigDecimal/lessThanBigDecimal.test.ts +++ b/packages/effect/test/Schema/Schema/BigDecimal/lessThanBigDecimal.test.ts @@ -1,6 +1,6 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import { BigDecimal } from "effect" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("lessThanBigDecimal", () => { diff --git a/packages/schema/test/Schema/BigDecimal/lessThanOrEqualToBigDecimal.test.ts b/packages/effect/test/Schema/Schema/BigDecimal/lessThanOrEqualToBigDecimal.test.ts similarity index 88% rename from packages/schema/test/Schema/BigDecimal/lessThanOrEqualToBigDecimal.test.ts rename to packages/effect/test/Schema/Schema/BigDecimal/lessThanOrEqualToBigDecimal.test.ts index 4b5f147c75..9834468dce 100644 --- a/packages/schema/test/Schema/BigDecimal/lessThanOrEqualToBigDecimal.test.ts +++ b/packages/effect/test/Schema/Schema/BigDecimal/lessThanOrEqualToBigDecimal.test.ts @@ -1,6 +1,6 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import { BigDecimal } from "effect" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("lessThanOrEqualToBigDecimal", () => { diff --git a/packages/schema/test/Schema/BigInt/BigInt.test.ts b/packages/effect/test/Schema/Schema/BigInt/BigInt.test.ts similarity index 94% rename from packages/schema/test/Schema/BigInt/BigInt.test.ts rename to packages/effect/test/Schema/Schema/BigInt/BigInt.test.ts index e2b4f8555f..824ad81618 100644 --- a/packages/schema/test/Schema/BigInt/BigInt.test.ts +++ b/packages/effect/test/Schema/Schema/BigInt/BigInt.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("BigInt", () => { diff --git a/packages/schema/test/Schema/BigInt/BigIntFromNumber.test.ts b/packages/effect/test/Schema/Schema/BigInt/BigIntFromNumber.test.ts similarity index 94% rename from packages/schema/test/Schema/BigInt/BigIntFromNumber.test.ts rename to packages/effect/test/Schema/Schema/BigInt/BigIntFromNumber.test.ts index 423d27c790..a131dea9e2 100644 --- a/packages/schema/test/Schema/BigInt/BigIntFromNumber.test.ts +++ b/packages/effect/test/Schema/Schema/BigInt/BigIntFromNumber.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("BigIntFromNumber", () => { diff --git a/packages/schema/test/Schema/BigInt/BigIntFromSelf.test.ts b/packages/effect/test/Schema/Schema/BigInt/BigIntFromSelf.test.ts similarity index 85% rename from packages/schema/test/Schema/BigInt/BigIntFromSelf.test.ts rename to packages/effect/test/Schema/Schema/BigInt/BigIntFromSelf.test.ts index 6c38a8c80c..b7a925b7a5 100644 --- a/packages/schema/test/Schema/BigInt/BigIntFromSelf.test.ts +++ b/packages/effect/test/Schema/Schema/BigInt/BigIntFromSelf.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("BigIntFromSelf", () => { diff --git a/packages/schema/test/Schema/BigInt/NegativeBigIntFromSelf.test.ts b/packages/effect/test/Schema/Schema/BigInt/NegativeBigIntFromSelf.test.ts similarity index 86% rename from packages/schema/test/Schema/BigInt/NegativeBigIntFromSelf.test.ts rename to packages/effect/test/Schema/Schema/BigInt/NegativeBigIntFromSelf.test.ts index 22c696631c..7956c3d6a8 100644 --- a/packages/schema/test/Schema/BigInt/NegativeBigIntFromSelf.test.ts +++ b/packages/effect/test/Schema/Schema/BigInt/NegativeBigIntFromSelf.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("NegativeBigIntFromSelf", () => { diff --git a/packages/schema/test/Schema/BigInt/NonNegativeBigIntFromSelf.test.ts b/packages/effect/test/Schema/Schema/BigInt/NonNegativeBigIntFromSelf.test.ts similarity index 83% rename from packages/schema/test/Schema/BigInt/NonNegativeBigIntFromSelf.test.ts rename to packages/effect/test/Schema/Schema/BigInt/NonNegativeBigIntFromSelf.test.ts index 845948ba8a..35d533a1c9 100644 --- a/packages/schema/test/Schema/BigInt/NonNegativeBigIntFromSelf.test.ts +++ b/packages/effect/test/Schema/Schema/BigInt/NonNegativeBigIntFromSelf.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("NonNegativeBigIntFromSelf", () => { diff --git a/packages/schema/test/Schema/BigInt/NonPositiveBigIntFromSelf.test.ts b/packages/effect/test/Schema/Schema/BigInt/NonPositiveBigIntFromSelf.test.ts similarity index 84% rename from packages/schema/test/Schema/BigInt/NonPositiveBigIntFromSelf.test.ts rename to packages/effect/test/Schema/Schema/BigInt/NonPositiveBigIntFromSelf.test.ts index 6c3b274a30..c9f3f789b1 100644 --- a/packages/schema/test/Schema/BigInt/NonPositiveBigIntFromSelf.test.ts +++ b/packages/effect/test/Schema/Schema/BigInt/NonPositiveBigIntFromSelf.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("NonPositiveBigIntFromSelf", () => { diff --git a/packages/schema/test/Schema/BigInt/PositiveBigIntFromSelf.test.ts b/packages/effect/test/Schema/Schema/BigInt/PositiveBigIntFromSelf.test.ts similarity index 86% rename from packages/schema/test/Schema/BigInt/PositiveBigIntFromSelf.test.ts rename to packages/effect/test/Schema/Schema/BigInt/PositiveBigIntFromSelf.test.ts index 40ced3e458..81478046b4 100644 --- a/packages/schema/test/Schema/BigInt/PositiveBigIntFromSelf.test.ts +++ b/packages/effect/test/Schema/Schema/BigInt/PositiveBigIntFromSelf.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("PositiveBigIntFromSelf", () => { diff --git a/packages/schema/test/Schema/BigInt/betweenBigInt.test.ts b/packages/effect/test/Schema/Schema/BigInt/betweenBigInt.test.ts similarity index 88% rename from packages/schema/test/Schema/BigInt/betweenBigInt.test.ts rename to packages/effect/test/Schema/Schema/BigInt/betweenBigInt.test.ts index 2b6534212c..4682a1a31b 100644 --- a/packages/schema/test/Schema/BigInt/betweenBigInt.test.ts +++ b/packages/effect/test/Schema/Schema/BigInt/betweenBigInt.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("betweenBigInt", () => { diff --git a/packages/schema/test/Schema/BigInt/clampBigInt.test.ts b/packages/effect/test/Schema/Schema/BigInt/clampBigInt.test.ts similarity index 78% rename from packages/schema/test/Schema/BigInt/clampBigInt.test.ts rename to packages/effect/test/Schema/Schema/BigInt/clampBigInt.test.ts index 81bf61e7c7..59ea24aa2f 100644 --- a/packages/schema/test/Schema/BigInt/clampBigInt.test.ts +++ b/packages/effect/test/Schema/Schema/BigInt/clampBigInt.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("clampBigInt", () => { diff --git a/packages/schema/test/Schema/BigInt/greaterThanBigInt.test.ts b/packages/effect/test/Schema/Schema/BigInt/greaterThanBigInt.test.ts similarity index 86% rename from packages/schema/test/Schema/BigInt/greaterThanBigInt.test.ts rename to packages/effect/test/Schema/Schema/BigInt/greaterThanBigInt.test.ts index 8253809b61..46b61d9cc3 100644 --- a/packages/schema/test/Schema/BigInt/greaterThanBigInt.test.ts +++ b/packages/effect/test/Schema/Schema/BigInt/greaterThanBigInt.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("greaterThanBigInt", () => { diff --git a/packages/schema/test/Schema/BigInt/greaterThanOrEqualToBigInt.test.ts b/packages/effect/test/Schema/Schema/BigInt/greaterThanOrEqualToBigInt.test.ts similarity index 84% rename from packages/schema/test/Schema/BigInt/greaterThanOrEqualToBigInt.test.ts rename to packages/effect/test/Schema/Schema/BigInt/greaterThanOrEqualToBigInt.test.ts index 6e0ee92197..1694c7aa5c 100644 --- a/packages/schema/test/Schema/BigInt/greaterThanOrEqualToBigInt.test.ts +++ b/packages/effect/test/Schema/Schema/BigInt/greaterThanOrEqualToBigInt.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("greaterThanOrEqualToBigInt", () => { diff --git a/packages/schema/test/Schema/BigInt/lessThanBigInt.test.ts b/packages/effect/test/Schema/Schema/BigInt/lessThanBigInt.test.ts similarity index 86% rename from packages/schema/test/Schema/BigInt/lessThanBigInt.test.ts rename to packages/effect/test/Schema/Schema/BigInt/lessThanBigInt.test.ts index 1533c17f31..312491807a 100644 --- a/packages/schema/test/Schema/BigInt/lessThanBigInt.test.ts +++ b/packages/effect/test/Schema/Schema/BigInt/lessThanBigInt.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("lessThanBigInt", () => { diff --git a/packages/schema/test/Schema/BigInt/lessThanOrEqualToBigInt.test.ts b/packages/effect/test/Schema/Schema/BigInt/lessThanOrEqualToBigInt.test.ts similarity index 84% rename from packages/schema/test/Schema/BigInt/lessThanOrEqualToBigInt.test.ts rename to packages/effect/test/Schema/Schema/BigInt/lessThanOrEqualToBigInt.test.ts index 2e5c410eb7..cec7a7cbcb 100644 --- a/packages/schema/test/Schema/BigInt/lessThanOrEqualToBigInt.test.ts +++ b/packages/effect/test/Schema/Schema/BigInt/lessThanOrEqualToBigInt.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("lessThanOrEqualToBigInt", () => { diff --git a/packages/schema/test/Schema/Boolean/Boolean.test.ts b/packages/effect/test/Schema/Schema/Boolean/Boolean.test.ts similarity index 83% rename from packages/schema/test/Schema/Boolean/Boolean.test.ts rename to packages/effect/test/Schema/Schema/Boolean/Boolean.test.ts index 80f3612ea0..36da773376 100644 --- a/packages/schema/test/Schema/Boolean/Boolean.test.ts +++ b/packages/effect/test/Schema/Schema/Boolean/Boolean.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("Boolean", () => { diff --git a/packages/schema/test/Schema/Boolean/BooleanFromUnknown.test.ts b/packages/effect/test/Schema/Schema/Boolean/BooleanFromUnknown.test.ts similarity index 89% rename from packages/schema/test/Schema/Boolean/BooleanFromUnknown.test.ts rename to packages/effect/test/Schema/Schema/Boolean/BooleanFromUnknown.test.ts index e3a1294156..cd72e66bbf 100644 --- a/packages/schema/test/Schema/Boolean/BooleanFromUnknown.test.ts +++ b/packages/effect/test/Schema/Schema/Boolean/BooleanFromUnknown.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("BooleanFromUnknown", () => { diff --git a/packages/schema/test/Schema/Boolean/Not.test.ts b/packages/effect/test/Schema/Schema/Boolean/Not.test.ts similarity index 80% rename from packages/schema/test/Schema/Boolean/Not.test.ts rename to packages/effect/test/Schema/Schema/Boolean/Not.test.ts index 87300e914a..ef1e6c1275 100644 --- a/packages/schema/test/Schema/Boolean/Not.test.ts +++ b/packages/effect/test/Schema/Schema/Boolean/Not.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("Not", () => { diff --git a/packages/schema/test/Schema/Cause/Cause.test.ts b/packages/effect/test/Schema/Schema/Cause/Cause.test.ts similarity index 98% rename from packages/schema/test/Schema/Cause/Cause.test.ts rename to packages/effect/test/Schema/Schema/Cause/Cause.test.ts index 639828e56a..2876be68c1 100644 --- a/packages/schema/test/Schema/Cause/Cause.test.ts +++ b/packages/effect/test/Schema/Schema/Cause/Cause.test.ts @@ -1,6 +1,6 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import { Cause, FiberId } from "effect" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { assert, describe, it } from "vitest" describe("Cause", () => { diff --git a/packages/schema/test/Schema/Cause/CauseFromSelf.test.ts b/packages/effect/test/Schema/Schema/Cause/CauseFromSelf.test.ts similarity index 95% rename from packages/schema/test/Schema/Cause/CauseFromSelf.test.ts rename to packages/effect/test/Schema/Schema/Cause/CauseFromSelf.test.ts index 2a6a4f240f..1290a0d87b 100644 --- a/packages/schema/test/Schema/Cause/CauseFromSelf.test.ts +++ b/packages/effect/test/Schema/Schema/Cause/CauseFromSelf.test.ts @@ -1,8 +1,8 @@ -import * as Pretty from "@effect/schema/Pretty" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import * as Cause from "effect/Cause" import * as FiberId from "effect/FiberId" +import * as Pretty from "effect/Pretty" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("CauseFromSelf", () => { diff --git a/packages/schema/test/Schema/Chunk/Chunk.test.ts b/packages/effect/test/Schema/Schema/Chunk/Chunk.test.ts similarity index 91% rename from packages/schema/test/Schema/Chunk/Chunk.test.ts rename to packages/effect/test/Schema/Schema/Chunk/Chunk.test.ts index 519a953fbb..f00e156959 100644 --- a/packages/schema/test/Schema/Chunk/Chunk.test.ts +++ b/packages/effect/test/Schema/Schema/Chunk/Chunk.test.ts @@ -1,6 +1,6 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import * as C from "effect/Chunk" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("Chunk", () => { diff --git a/packages/schema/test/Schema/Chunk/ChunkFromSelf.test.ts b/packages/effect/test/Schema/Schema/Chunk/ChunkFromSelf.test.ts similarity index 86% rename from packages/schema/test/Schema/Chunk/ChunkFromSelf.test.ts rename to packages/effect/test/Schema/Schema/Chunk/ChunkFromSelf.test.ts index 2b470ec48d..1d20f5f6d2 100644 --- a/packages/schema/test/Schema/Chunk/ChunkFromSelf.test.ts +++ b/packages/effect/test/Schema/Schema/Chunk/ChunkFromSelf.test.ts @@ -1,8 +1,8 @@ -import * as P from "@effect/schema/ParseResult" -import * as Pretty from "@effect/schema/Pretty" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import * as C from "effect/Chunk" +import * as P from "effect/ParseResult" +import * as Pretty from "effect/Pretty" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("ChunkFromSelf", () => { @@ -53,7 +53,7 @@ describe("ChunkFromSelf", () => { expect(is(C.fromIterable(["a", "b", "c"]))).toEqual(true) expect(is(C.fromIterable(["a", "b", 1]))).toEqual(false) - expect(is({ _id: Symbol.for("@effect/schema/test/FakeChunk") })).toEqual(false) + expect(is({ _id: Symbol.for("effect/Schema/test/FakeChunk") })).toEqual(false) }) it("pretty", () => { diff --git a/packages/schema/test/Schema/Chunk/NonEmptyChunk.test.ts b/packages/effect/test/Schema/Schema/Chunk/NonEmptyChunk.test.ts similarity index 91% rename from packages/schema/test/Schema/Chunk/NonEmptyChunk.test.ts rename to packages/effect/test/Schema/Schema/Chunk/NonEmptyChunk.test.ts index 700514feda..a5313fb68f 100644 --- a/packages/schema/test/Schema/Chunk/NonEmptyChunk.test.ts +++ b/packages/effect/test/Schema/Schema/Chunk/NonEmptyChunk.test.ts @@ -1,6 +1,6 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import * as C from "effect/Chunk" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("NonEmptyChunk", () => { diff --git a/packages/schema/test/Schema/Chunk/NonEmptyChunkFromSelf.test.ts b/packages/effect/test/Schema/Schema/Chunk/NonEmptyChunkFromSelf.test.ts similarity index 85% rename from packages/schema/test/Schema/Chunk/NonEmptyChunkFromSelf.test.ts rename to packages/effect/test/Schema/Schema/Chunk/NonEmptyChunkFromSelf.test.ts index 0d54017004..620dff6f5e 100644 --- a/packages/schema/test/Schema/Chunk/NonEmptyChunkFromSelf.test.ts +++ b/packages/effect/test/Schema/Schema/Chunk/NonEmptyChunkFromSelf.test.ts @@ -1,10 +1,9 @@ -import * as Arbitrary from "@effect/schema/Arbitrary" -import * as Equivalence from "@effect/schema/Equivalence" -import * as FastCheck from "@effect/schema/FastCheck" -import * as Pretty from "@effect/schema/Pretty" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as Arbitrary from "effect/Arbitrary" import * as C from "effect/Chunk" +import * as FastCheck from "effect/FastCheck" +import * as Pretty from "effect/Pretty" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("NonEmptyChunkFromSelf", () => { @@ -64,7 +63,7 @@ describe("NonEmptyChunkFromSelf", () => { it("equivalence", () => { const schema = S.NonEmptyChunkFromSelf(S.String) - const equivalence = Equivalence.make(schema) + const equivalence = S.equivalence(schema) expect(equivalence(C.make("a", "b"), C.make("a", "b"))).toEqual(true) expect(equivalence(C.make("a", "b"), C.make("a", "c"))).toEqual(false) expect(equivalence(C.make("a", "b"), C.make("a"))).toEqual(false) diff --git a/packages/schema/test/Schema/Class/Class.test.ts b/packages/effect/test/Schema/Schema/Class/Class.test.ts similarity index 98% rename from packages/schema/test/Schema/Class/Class.test.ts rename to packages/effect/test/Schema/Schema/Class/Class.test.ts index dce446e28c..33f2ded843 100644 --- a/packages/schema/test/Schema/Class/Class.test.ts +++ b/packages/effect/test/Schema/Schema/Class/Class.test.ts @@ -1,11 +1,11 @@ -import * as AST from "@effect/schema/AST" -import * as ParseResult from "@effect/schema/ParseResult" -import * as Pretty from "@effect/schema/Pretty" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import { Context, Effect } from "effect" import * as Data from "effect/Data" import * as Equal from "effect/Equal" +import * as ParseResult from "effect/ParseResult" +import * as Pretty from "effect/Pretty" +import * as S from "effect/Schema" +import * as AST from "effect/SchemaAST" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" class Person extends S.Class("Person")({ diff --git a/packages/schema/test/Schema/Class/TaggedClass.test.ts b/packages/effect/test/Schema/Schema/Class/TaggedClass.test.ts similarity index 97% rename from packages/schema/test/Schema/Class/TaggedClass.test.ts rename to packages/effect/test/Schema/Schema/Class/TaggedClass.test.ts index 57f25ca24e..31f501f903 100644 --- a/packages/schema/test/Schema/Class/TaggedClass.test.ts +++ b/packages/effect/test/Schema/Schema/Class/TaggedClass.test.ts @@ -1,7 +1,6 @@ -import * as Equivalence from "@effect/schema/Equivalence" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import { pipe, Struct } from "effect" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("TaggedClass", () => { @@ -153,7 +152,7 @@ details: Duplicate key "_tag"`) class A extends S.TaggedClass()("A", { a: S.String }) {} - const eqA = Equivalence.make(A) + const eqA = S.equivalence(A) expect(eqA(new A({ a: "a" }), new A({ a: "a" }))).toBe(true) expect(eqA(new A({ a: "a" }), new A({ a: "b" }))).toBe(false) @@ -161,7 +160,7 @@ details: Duplicate key "_tag"`) b: S.Number, as: S.Array(A) }) {} - const eqB = Equivalence.make(B) + const eqB = S.equivalence(B) expect(eqB(new B({ b: 1, as: [] }), new B({ b: 1, as: [] }))).toBe(true) expect(eqB(new B({ b: 1, as: [] }), new B({ b: 2, as: [] }))).toBe(false) expect(eqB(new B({ b: 1, as: [new A({ a: "a" })] }), new B({ b: 1, as: [new A({ a: "a" })] }))).toBe(true) diff --git a/packages/schema/test/Schema/Class/TaggedError.test.ts b/packages/effect/test/Schema/Schema/Class/TaggedError.test.ts similarity index 95% rename from packages/schema/test/Schema/Class/TaggedError.test.ts rename to packages/effect/test/Schema/Schema/Class/TaggedError.test.ts index f14173d099..e1877097e5 100644 --- a/packages/schema/test/Schema/Class/TaggedError.test.ts +++ b/packages/effect/test/Schema/Schema/Class/TaggedError.test.ts @@ -1,7 +1,6 @@ -import { Schema } from "@effect/schema" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" -import { Cause, Effect, Inspectable } from "effect" +import { Cause, Effect, Inspectable, Schema } from "effect" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("TaggedError", () => { diff --git a/packages/schema/test/Schema/Class/TaggedRequest.test.ts b/packages/effect/test/Schema/Schema/Class/TaggedRequest.test.ts similarity index 83% rename from packages/schema/test/Schema/Class/TaggedRequest.test.ts rename to packages/effect/test/Schema/Schema/Class/TaggedRequest.test.ts index 003cfc3da2..b8a976ee78 100644 --- a/packages/schema/test/Schema/Class/TaggedRequest.test.ts +++ b/packages/effect/test/Schema/Schema/Class/TaggedRequest.test.ts @@ -1,10 +1,9 @@ -import * as ParseResult from "@effect/schema/ParseResult" -import * as S from "@effect/schema/Schema" -import * as Serializable from "@effect/schema/Serializable" -import * as Util from "@effect/schema/test/TestUtils" import { Context, Effect, Exit } from "effect" import * as Equal from "effect/Equal" +import * as ParseResult from "effect/ParseResult" import * as Request from "effect/Request" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { assert, describe, expect, it } from "vitest" const Name = Context.GenericTag<"Name", string>("Name") @@ -112,28 +111,28 @@ describe("TaggedRequest", () => { const req = new MyRequest({ id: 1 }) assert.deepStrictEqual( - Serializable.serialize(req).pipe(Effect.runSync), + S.serialize(req).pipe(Effect.runSync), { _tag: "MyRequest", id: 1 } ) assert(Equal.equals( - Serializable.deserialize(req, { _tag: "MyRequest", id: 1 }).pipe(Effect.runSync), + S.deserialize(req, { _tag: "MyRequest", id: 1 }).pipe(Effect.runSync), req )) assert.deepStrictEqual( - Serializable.serializeExit(req, Exit.fail("fail")).pipe(Effect.runSync), + S.serializeExit(req, Exit.fail("fail")).pipe(Effect.runSync), { _tag: "Failure", cause: { _tag: "Fail", error: "fail" } } ) assert.deepStrictEqual( - Serializable.deserializeExit(req, { _tag: "Failure", cause: { _tag: "Fail", error: "fail" } }) + S.deserializeExit(req, { _tag: "Failure", cause: { _tag: "Fail", error: "fail" } }) .pipe(Effect.runSync), Exit.fail("fail") ) assert.deepStrictEqual( - Serializable.serializeExit(req, Exit.succeed(123)).pipe(Effect.runSync), + S.serializeExit(req, Exit.succeed(123)).pipe(Effect.runSync), { _tag: "Success", value: "123" } ) assert.deepStrictEqual( - Serializable.deserializeExit(req, { _tag: "Success", value: "123" }).pipe(Effect.runSync), + S.deserializeExit(req, { _tag: "Success", value: "123" }).pipe(Effect.runSync), Exit.succeed(123) ) }) @@ -157,28 +156,28 @@ describe("TaggedRequest", () => { expect(String(req)).toEqual(`MyRequest({ "_tag": "MyRequest", "id": 1 })`) assert.deepStrictEqual( - Serializable.serialize(req).pipe( + S.serialize(req).pipe( Effect.provideService(Id, 1), Effect.runSync ), { _tag: "MyRequest", id: 1 } ) assert.deepStrictEqual( - Serializable.deserialize(req, { _tag: "MyRequest", id: 1 }).pipe( + S.deserialize(req, { _tag: "MyRequest", id: 1 }).pipe( Effect.provideService(Id, 1), Effect.runSync ), req ) assert.deepStrictEqual( - Serializable.serializeExit(req, Exit.fail("fail")).pipe( + S.serializeExit(req, Exit.fail("fail")).pipe( Effect.provideService(Name, "fail"), Effect.runSync ), { _tag: "Failure", cause: { _tag: "Fail", error: "fail" } } ) assert.deepStrictEqual( - Serializable.deserializeExit(req, { _tag: "Failure", cause: { _tag: "Fail", error: "fail" } }) + S.deserializeExit(req, { _tag: "Failure", cause: { _tag: "Fail", error: "fail" } }) .pipe( Effect.provideService(Name, "fail"), Effect.runSync diff --git a/packages/schema/test/Schema/Class/extend.test.ts b/packages/effect/test/Schema/Schema/Class/extend.test.ts similarity index 97% rename from packages/schema/test/Schema/Class/extend.test.ts rename to packages/effect/test/Schema/Schema/Class/extend.test.ts index 58507d7ed3..fa2853d501 100644 --- a/packages/schema/test/Schema/Class/extend.test.ts +++ b/packages/effect/test/Schema/Schema/Class/extend.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" class Person extends S.Class("Person")({ diff --git a/packages/schema/test/Schema/Class/transformOrFail.test.ts b/packages/effect/test/Schema/Schema/Class/transformOrFail.test.ts similarity index 94% rename from packages/schema/test/Schema/Class/transformOrFail.test.ts rename to packages/effect/test/Schema/Schema/Class/transformOrFail.test.ts index 3146b2ba42..6b5391a0aa 100644 --- a/packages/schema/test/Schema/Class/transformOrFail.test.ts +++ b/packages/effect/test/Schema/Schema/Class/transformOrFail.test.ts @@ -1,7 +1,7 @@ -import * as ParseResult from "@effect/schema/ParseResult" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import * as Option from "effect/Option" +import * as ParseResult from "effect/ParseResult" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" class Person extends S.Class("Person")({ diff --git a/packages/schema/test/Schema/Class/transformOrFailFrom.test.ts b/packages/effect/test/Schema/Schema/Class/transformOrFailFrom.test.ts similarity index 94% rename from packages/schema/test/Schema/Class/transformOrFailFrom.test.ts rename to packages/effect/test/Schema/Schema/Class/transformOrFailFrom.test.ts index c795c53913..bf6c52f066 100644 --- a/packages/schema/test/Schema/Class/transformOrFailFrom.test.ts +++ b/packages/effect/test/Schema/Schema/Class/transformOrFailFrom.test.ts @@ -1,7 +1,7 @@ -import * as ParseResult from "@effect/schema/ParseResult" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import * as Option from "effect/Option" +import * as ParseResult from "effect/ParseResult" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" class Person extends S.Class("Person")({ diff --git a/packages/schema/test/Schema/Config/Config.test.ts b/packages/effect/test/Schema/Schema/Config/Config.test.ts similarity index 97% rename from packages/schema/test/Schema/Config/Config.test.ts rename to packages/effect/test/Schema/Schema/Config/Config.test.ts index 7aca6f90ca..4196525f79 100644 --- a/packages/schema/test/Schema/Config/Config.test.ts +++ b/packages/effect/test/Schema/Schema/Config/Config.test.ts @@ -1,9 +1,9 @@ -import * as Schema from "@effect/schema/Schema" import type * as Config from "effect/Config" import * as ConfigError from "effect/ConfigError" import * as ConfigProvider from "effect/ConfigProvider" import * as Effect from "effect/Effect" import * as Exit from "effect/Exit" +import * as Schema from "effect/Schema" import { describe, expect, it } from "vitest" /** diff --git a/packages/schema/test/Schema/Data/Data.test.ts b/packages/effect/test/Schema/Schema/Data/Data.test.ts similarity index 91% rename from packages/schema/test/Schema/Data/Data.test.ts rename to packages/effect/test/Schema/Schema/Data/Data.test.ts index 345e92c0c4..2541336109 100644 --- a/packages/schema/test/Schema/Data/Data.test.ts +++ b/packages/effect/test/Schema/Schema/Data/Data.test.ts @@ -1,6 +1,6 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import * as Data from "effect/Data" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("Data", () => { diff --git a/packages/schema/test/Schema/Data/DataFromSelf.test.ts b/packages/effect/test/Schema/Schema/Data/DataFromSelf.test.ts similarity index 90% rename from packages/schema/test/Schema/Data/DataFromSelf.test.ts rename to packages/effect/test/Schema/Schema/Data/DataFromSelf.test.ts index bfc7164860..367a406a96 100644 --- a/packages/schema/test/Schema/Data/DataFromSelf.test.ts +++ b/packages/effect/test/Schema/Schema/Data/DataFromSelf.test.ts @@ -1,8 +1,8 @@ -import * as P from "@effect/schema/ParseResult" -import * as Pretty from "@effect/schema/Pretty" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import * as Data from "effect/Data" +import * as P from "effect/ParseResult" +import * as Pretty from "effect/Pretty" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("DataFromSelf", () => { diff --git a/packages/schema/test/Schema/Date/Date.test.ts b/packages/effect/test/Schema/Schema/Date/Date.test.ts similarity index 88% rename from packages/schema/test/Schema/Date/Date.test.ts rename to packages/effect/test/Schema/Schema/Date/Date.test.ts index d81e9bc997..e43619d0e1 100644 --- a/packages/schema/test/Schema/Date/Date.test.ts +++ b/packages/effect/test/Schema/Schema/Date/Date.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("Date", () => { diff --git a/packages/schema/test/Schema/Date/DateFromNumber.test.ts b/packages/effect/test/Schema/Schema/Date/DateFromNumber.test.ts similarity index 91% rename from packages/schema/test/Schema/Date/DateFromNumber.test.ts rename to packages/effect/test/Schema/Schema/Date/DateFromNumber.test.ts index b040f7e7d3..bd3a69b4eb 100644 --- a/packages/schema/test/Schema/Date/DateFromNumber.test.ts +++ b/packages/effect/test/Schema/Schema/Date/DateFromNumber.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("DateFromNumber", () => { diff --git a/packages/schema/test/Schema/Date/DateFromSelf.test.ts b/packages/effect/test/Schema/Schema/Date/DateFromSelf.test.ts similarity index 85% rename from packages/schema/test/Schema/Date/DateFromSelf.test.ts rename to packages/effect/test/Schema/Schema/Date/DateFromSelf.test.ts index 26e1133f21..1f370f39c1 100644 --- a/packages/schema/test/Schema/Date/DateFromSelf.test.ts +++ b/packages/effect/test/Schema/Schema/Date/DateFromSelf.test.ts @@ -1,6 +1,6 @@ -import * as Pretty from "@effect/schema/Pretty" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as Pretty from "effect/Pretty" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("DateFromSelf", () => { diff --git a/packages/schema/test/Schema/Date/betweenDate.test.ts b/packages/effect/test/Schema/Schema/Date/betweenDate.test.ts similarity index 91% rename from packages/schema/test/Schema/Date/betweenDate.test.ts rename to packages/effect/test/Schema/Schema/Date/betweenDate.test.ts index af988250d1..7a20928808 100644 --- a/packages/schema/test/Schema/Date/betweenDate.test.ts +++ b/packages/effect/test/Schema/Schema/Date/betweenDate.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("betweenDate", () => { diff --git a/packages/schema/test/Schema/Date/greaterThanDate.test.ts b/packages/effect/test/Schema/Schema/Date/greaterThanDate.test.ts similarity index 88% rename from packages/schema/test/Schema/Date/greaterThanDate.test.ts rename to packages/effect/test/Schema/Schema/Date/greaterThanDate.test.ts index a62ca4ec7f..27f350b576 100644 --- a/packages/schema/test/Schema/Date/greaterThanDate.test.ts +++ b/packages/effect/test/Schema/Schema/Date/greaterThanDate.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("greaterThanDate", () => { diff --git a/packages/schema/test/Schema/Date/greaterThanOrEqualToDate.test.ts b/packages/effect/test/Schema/Schema/Date/greaterThanOrEqualToDate.test.ts similarity index 86% rename from packages/schema/test/Schema/Date/greaterThanOrEqualToDate.test.ts rename to packages/effect/test/Schema/Schema/Date/greaterThanOrEqualToDate.test.ts index 28943ed5c7..3c6bee0783 100644 --- a/packages/schema/test/Schema/Date/greaterThanOrEqualToDate.test.ts +++ b/packages/effect/test/Schema/Schema/Date/greaterThanOrEqualToDate.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("greaterThanOrEqualToDate", () => { diff --git a/packages/schema/test/Schema/Date/lessThanDate.test.ts b/packages/effect/test/Schema/Schema/Date/lessThanDate.test.ts similarity index 88% rename from packages/schema/test/Schema/Date/lessThanDate.test.ts rename to packages/effect/test/Schema/Schema/Date/lessThanDate.test.ts index d7c20cc515..b346dcece9 100644 --- a/packages/schema/test/Schema/Date/lessThanDate.test.ts +++ b/packages/effect/test/Schema/Schema/Date/lessThanDate.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("lessThanDate", () => { diff --git a/packages/schema/test/Schema/Date/lessThanOrEqualToDate.test.ts b/packages/effect/test/Schema/Schema/Date/lessThanOrEqualToDate.test.ts similarity index 86% rename from packages/schema/test/Schema/Date/lessThanOrEqualToDate.test.ts rename to packages/effect/test/Schema/Schema/Date/lessThanOrEqualToDate.test.ts index 4e43756e62..c096f6a836 100644 --- a/packages/schema/test/Schema/Date/lessThanOrEqualToDate.test.ts +++ b/packages/effect/test/Schema/Schema/Date/lessThanOrEqualToDate.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("lessThanOrEqualToDate", () => { diff --git a/packages/schema/test/Schema/DateTime/DateTime.test.ts b/packages/effect/test/Schema/Schema/DateTime/DateTime.test.ts similarity index 94% rename from packages/schema/test/Schema/DateTime/DateTime.test.ts rename to packages/effect/test/Schema/Schema/DateTime/DateTime.test.ts index 75138c2d2b..71ea3f092d 100644 --- a/packages/schema/test/Schema/DateTime/DateTime.test.ts +++ b/packages/effect/test/Schema/Schema/DateTime/DateTime.test.ts @@ -1,6 +1,6 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import { DateTime } from "effect" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("DateTime.Utc", () => { diff --git a/packages/schema/test/Schema/DecodingFallbackAnnotation.test.ts b/packages/effect/test/Schema/Schema/DecodingFallbackAnnotation.test.ts similarity index 95% rename from packages/schema/test/Schema/DecodingFallbackAnnotation.test.ts rename to packages/effect/test/Schema/Schema/DecodingFallbackAnnotation.test.ts index d8e1938553..6beaebea7b 100644 --- a/packages/schema/test/Schema/DecodingFallbackAnnotation.test.ts +++ b/packages/effect/test/Schema/Schema/DecodingFallbackAnnotation.test.ts @@ -1,6 +1,6 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import { Effect, Either } from "effect" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("DecodingFallbackAnnotation", () => { diff --git a/packages/schema/test/Schema/Defect/Defect.test.ts b/packages/effect/test/Schema/Schema/Defect/Defect.test.ts similarity index 94% rename from packages/schema/test/Schema/Defect/Defect.test.ts rename to packages/effect/test/Schema/Schema/Defect/Defect.test.ts index b4fa8f5573..e764af6e7b 100644 --- a/packages/schema/test/Schema/Defect/Defect.test.ts +++ b/packages/effect/test/Schema/Schema/Defect/Defect.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("Defect", () => { diff --git a/packages/schema/test/Schema/Duration/Duration.test.ts b/packages/effect/test/Schema/Schema/Duration/Duration.test.ts similarity index 95% rename from packages/schema/test/Schema/Duration/Duration.test.ts rename to packages/effect/test/Schema/Schema/Duration/Duration.test.ts index f6d7d6087d..c5cecff6dd 100644 --- a/packages/schema/test/Schema/Duration/Duration.test.ts +++ b/packages/effect/test/Schema/Schema/Duration/Duration.test.ts @@ -1,6 +1,6 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import { Duration } from "effect" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("Duration", () => { diff --git a/packages/schema/test/Schema/Duration/DurationFromMillis.test.ts b/packages/effect/test/Schema/Schema/Duration/DurationFromMillis.test.ts similarity index 88% rename from packages/schema/test/Schema/Duration/DurationFromMillis.test.ts rename to packages/effect/test/Schema/Schema/Duration/DurationFromMillis.test.ts index d68eb56933..7528016aba 100644 --- a/packages/schema/test/Schema/Duration/DurationFromMillis.test.ts +++ b/packages/effect/test/Schema/Schema/Duration/DurationFromMillis.test.ts @@ -1,6 +1,6 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import { Duration } from "effect" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("DurationFromMillis", () => { diff --git a/packages/schema/test/Schema/Duration/DurationFromNanos.test.ts b/packages/effect/test/Schema/Schema/Duration/DurationFromNanos.test.ts similarity index 85% rename from packages/schema/test/Schema/Duration/DurationFromNanos.test.ts rename to packages/effect/test/Schema/Schema/Duration/DurationFromNanos.test.ts index b2fa196020..c0a7e7dc12 100644 --- a/packages/schema/test/Schema/Duration/DurationFromNanos.test.ts +++ b/packages/effect/test/Schema/Schema/Duration/DurationFromNanos.test.ts @@ -1,6 +1,6 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import { Duration } from "effect" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("DurationFromNanos", () => { diff --git a/packages/schema/test/Schema/Duration/DurationFromSelf.test.ts b/packages/effect/test/Schema/Schema/Duration/DurationFromSelf.test.ts similarity index 88% rename from packages/schema/test/Schema/Duration/DurationFromSelf.test.ts rename to packages/effect/test/Schema/Schema/Duration/DurationFromSelf.test.ts index e39fe41286..41501f82ff 100644 --- a/packages/schema/test/Schema/Duration/DurationFromSelf.test.ts +++ b/packages/effect/test/Schema/Schema/Duration/DurationFromSelf.test.ts @@ -1,7 +1,7 @@ -import * as Pretty from "@effect/schema/Pretty" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import { Duration } from "effect" +import * as Pretty from "effect/Pretty" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("DurationFromSelf", () => { diff --git a/packages/schema/test/Schema/Duration/betweenDuration.test.ts b/packages/effect/test/Schema/Schema/Duration/betweenDuration.test.ts similarity index 91% rename from packages/schema/test/Schema/Duration/betweenDuration.test.ts rename to packages/effect/test/Schema/Schema/Duration/betweenDuration.test.ts index 472c617aa8..93827985cc 100644 --- a/packages/schema/test/Schema/Duration/betweenDuration.test.ts +++ b/packages/effect/test/Schema/Schema/Duration/betweenDuration.test.ts @@ -1,6 +1,6 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import { Duration } from "effect" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("betweenDuration", () => { diff --git a/packages/schema/test/Schema/Duration/clampDuration.test.ts b/packages/effect/test/Schema/Schema/Duration/clampDuration.test.ts similarity index 86% rename from packages/schema/test/Schema/Duration/clampDuration.test.ts rename to packages/effect/test/Schema/Schema/Duration/clampDuration.test.ts index a87e2e034a..0fc3c87474 100644 --- a/packages/schema/test/Schema/Duration/clampDuration.test.ts +++ b/packages/effect/test/Schema/Schema/Duration/clampDuration.test.ts @@ -1,6 +1,6 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import { Duration } from "effect" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("clampDuration", () => { diff --git a/packages/schema/test/Schema/Duration/greaterThanDuration.test.ts b/packages/effect/test/Schema/Schema/Duration/greaterThanDuration.test.ts similarity index 91% rename from packages/schema/test/Schema/Duration/greaterThanDuration.test.ts rename to packages/effect/test/Schema/Schema/Duration/greaterThanDuration.test.ts index 81ec4844f5..170a08e8b0 100644 --- a/packages/schema/test/Schema/Duration/greaterThanDuration.test.ts +++ b/packages/effect/test/Schema/Schema/Duration/greaterThanDuration.test.ts @@ -1,6 +1,6 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import { Duration } from "effect" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("greaterThanDuration", () => { diff --git a/packages/schema/test/Schema/Duration/greaterThanOrEqualToDuration.test.ts b/packages/effect/test/Schema/Schema/Duration/greaterThanOrEqualToDuration.test.ts similarity index 90% rename from packages/schema/test/Schema/Duration/greaterThanOrEqualToDuration.test.ts rename to packages/effect/test/Schema/Schema/Duration/greaterThanOrEqualToDuration.test.ts index 3258c34afd..37ff0c4373 100644 --- a/packages/schema/test/Schema/Duration/greaterThanOrEqualToDuration.test.ts +++ b/packages/effect/test/Schema/Schema/Duration/greaterThanOrEqualToDuration.test.ts @@ -1,6 +1,6 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import { Duration } from "effect" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("greaterThanOrEqualToDuration", () => { diff --git a/packages/schema/test/Schema/Duration/lessThanDuration.test.ts b/packages/effect/test/Schema/Schema/Duration/lessThanDuration.test.ts similarity index 91% rename from packages/schema/test/Schema/Duration/lessThanDuration.test.ts rename to packages/effect/test/Schema/Schema/Duration/lessThanDuration.test.ts index b07825dd57..7b34399312 100644 --- a/packages/schema/test/Schema/Duration/lessThanDuration.test.ts +++ b/packages/effect/test/Schema/Schema/Duration/lessThanDuration.test.ts @@ -1,6 +1,6 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import { Duration } from "effect" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("lessThanDuration", () => { diff --git a/packages/schema/test/Schema/Duration/lessThanOrEqualToDuration.test.ts b/packages/effect/test/Schema/Schema/Duration/lessThanOrEqualToDuration.test.ts similarity index 90% rename from packages/schema/test/Schema/Duration/lessThanOrEqualToDuration.test.ts rename to packages/effect/test/Schema/Schema/Duration/lessThanOrEqualToDuration.test.ts index 7dcb1c75cc..2b26498e74 100644 --- a/packages/schema/test/Schema/Duration/lessThanOrEqualToDuration.test.ts +++ b/packages/effect/test/Schema/Schema/Duration/lessThanOrEqualToDuration.test.ts @@ -1,6 +1,6 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import { Duration } from "effect" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("lessThanOrEqualToDuration", () => { diff --git a/packages/schema/test/Schema/Either/Either.test.ts b/packages/effect/test/Schema/Schema/Either/Either.test.ts similarity index 89% rename from packages/schema/test/Schema/Either/Either.test.ts rename to packages/effect/test/Schema/Schema/Either/Either.test.ts index 69bff5ac50..a397e96b78 100644 --- a/packages/schema/test/Schema/Either/Either.test.ts +++ b/packages/effect/test/Schema/Schema/Either/Either.test.ts @@ -1,6 +1,6 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import * as E from "effect/Either" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("Either", () => { diff --git a/packages/schema/test/Schema/Either/EitherFromSelf.test.ts b/packages/effect/test/Schema/Schema/Either/EitherFromSelf.test.ts similarity index 91% rename from packages/schema/test/Schema/Either/EitherFromSelf.test.ts rename to packages/effect/test/Schema/Schema/Either/EitherFromSelf.test.ts index ca9e5b343b..885e61346a 100644 --- a/packages/schema/test/Schema/Either/EitherFromSelf.test.ts +++ b/packages/effect/test/Schema/Schema/Either/EitherFromSelf.test.ts @@ -1,8 +1,8 @@ -import * as P from "@effect/schema/ParseResult" -import * as Pretty from "@effect/schema/Pretty" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import * as E from "effect/Either" +import * as P from "effect/ParseResult" +import * as Pretty from "effect/Pretty" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("EitherFromSelf", () => { diff --git a/packages/schema/test/Schema/Either/EitherFromUnion.test.ts b/packages/effect/test/Schema/Schema/Either/EitherFromUnion.test.ts similarity index 98% rename from packages/schema/test/Schema/Either/EitherFromUnion.test.ts rename to packages/effect/test/Schema/Schema/Either/EitherFromUnion.test.ts index 8a36880520..1368c92e1c 100644 --- a/packages/schema/test/Schema/Either/EitherFromUnion.test.ts +++ b/packages/effect/test/Schema/Schema/Either/EitherFromUnion.test.ts @@ -1,6 +1,6 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import * as E from "effect/Either" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("EitherFromUnion", () => { diff --git a/packages/schema/test/Schema/Enums/Enums.test.ts b/packages/effect/test/Schema/Schema/Enums/Enums.test.ts similarity index 96% rename from packages/schema/test/Schema/Enums/Enums.test.ts rename to packages/effect/test/Schema/Schema/Enums/Enums.test.ts index 3a4fc85300..c2abbda15c 100644 --- a/packages/schema/test/Schema/Enums/Enums.test.ts +++ b/packages/effect/test/Schema/Schema/Enums/Enums.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("Enums", () => { diff --git a/packages/schema/test/Schema/Exit/Exit.test.ts b/packages/effect/test/Schema/Schema/Exit/Exit.test.ts similarity index 94% rename from packages/schema/test/Schema/Exit/Exit.test.ts rename to packages/effect/test/Schema/Schema/Exit/Exit.test.ts index 1d66b5d397..bcdd537a8c 100644 --- a/packages/schema/test/Schema/Exit/Exit.test.ts +++ b/packages/effect/test/Schema/Schema/Exit/Exit.test.ts @@ -1,6 +1,6 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import { Exit } from "effect" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("Exit", () => { diff --git a/packages/schema/test/Schema/Exit/ExitFromSelf.test.ts b/packages/effect/test/Schema/Schema/Exit/ExitFromSelf.test.ts similarity index 95% rename from packages/schema/test/Schema/Exit/ExitFromSelf.test.ts rename to packages/effect/test/Schema/Schema/Exit/ExitFromSelf.test.ts index 48487fc7be..b05e1a7463 100644 --- a/packages/schema/test/Schema/Exit/ExitFromSelf.test.ts +++ b/packages/effect/test/Schema/Schema/Exit/ExitFromSelf.test.ts @@ -1,6 +1,6 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import * as Exit from "effect/Exit" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("ExitFromSelf", () => { diff --git a/packages/schema/test/Schema/FiberId/FiberId.test.ts b/packages/effect/test/Schema/Schema/FiberId/FiberId.test.ts similarity index 92% rename from packages/schema/test/Schema/FiberId/FiberId.test.ts rename to packages/effect/test/Schema/Schema/FiberId/FiberId.test.ts index c9d22be199..1b70acf402 100644 --- a/packages/schema/test/Schema/FiberId/FiberId.test.ts +++ b/packages/effect/test/Schema/Schema/FiberId/FiberId.test.ts @@ -1,6 +1,6 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import * as FiberId from "effect/FiberId" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("FiberId", () => { diff --git a/packages/schema/test/Schema/FiberId/FiberIdFromSelf.test.ts b/packages/effect/test/Schema/Schema/FiberId/FiberIdFromSelf.test.ts similarity index 88% rename from packages/schema/test/Schema/FiberId/FiberIdFromSelf.test.ts rename to packages/effect/test/Schema/Schema/FiberId/FiberIdFromSelf.test.ts index 2627c9c228..286bd7e3eb 100644 --- a/packages/schema/test/Schema/FiberId/FiberIdFromSelf.test.ts +++ b/packages/effect/test/Schema/Schema/FiberId/FiberIdFromSelf.test.ts @@ -1,7 +1,7 @@ -import * as Pretty from "@effect/schema/Pretty" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import * as FiberId from "effect/FiberId" +import * as Pretty from "effect/Pretty" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("FiberIdFromSelf", () => { diff --git a/packages/schema/test/Schema/HashMap/HashMap.test.ts b/packages/effect/test/Schema/Schema/HashMap/HashMap.test.ts similarity index 94% rename from packages/schema/test/Schema/HashMap/HashMap.test.ts rename to packages/effect/test/Schema/Schema/HashMap/HashMap.test.ts index f4d70b85a9..ad64e3d176 100644 --- a/packages/schema/test/Schema/HashMap/HashMap.test.ts +++ b/packages/effect/test/Schema/Schema/HashMap/HashMap.test.ts @@ -1,6 +1,6 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import * as HashMap from "effect/HashMap" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("HashMap", () => { diff --git a/packages/schema/test/Schema/HashMap/HashMapFromSelf.test.ts b/packages/effect/test/Schema/Schema/HashMap/HashMapFromSelf.test.ts similarity index 93% rename from packages/schema/test/Schema/HashMap/HashMapFromSelf.test.ts rename to packages/effect/test/Schema/Schema/HashMap/HashMapFromSelf.test.ts index 6637f636a9..aba34425e1 100644 --- a/packages/schema/test/Schema/HashMap/HashMapFromSelf.test.ts +++ b/packages/effect/test/Schema/Schema/HashMap/HashMapFromSelf.test.ts @@ -1,8 +1,8 @@ -import * as P from "@effect/schema/ParseResult" -import * as Pretty from "@effect/schema/Pretty" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import * as HashMap from "effect/HashMap" +import * as P from "effect/ParseResult" +import * as Pretty from "effect/Pretty" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("HashMapFromSelf", () => { diff --git a/packages/schema/test/Schema/HashSet/HashSet.test.ts b/packages/effect/test/Schema/Schema/HashSet/HashSet.test.ts similarity index 92% rename from packages/schema/test/Schema/HashSet/HashSet.test.ts rename to packages/effect/test/Schema/Schema/HashSet/HashSet.test.ts index b1516c7fb3..2561b30ae8 100644 --- a/packages/schema/test/Schema/HashSet/HashSet.test.ts +++ b/packages/effect/test/Schema/Schema/HashSet/HashSet.test.ts @@ -1,6 +1,6 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import * as HashSet from "effect/HashSet" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("HashSet", () => { diff --git a/packages/schema/test/Schema/HashSet/HashSetFromSelf.test.ts b/packages/effect/test/Schema/Schema/HashSet/HashSetFromSelf.test.ts similarity index 87% rename from packages/schema/test/Schema/HashSet/HashSetFromSelf.test.ts rename to packages/effect/test/Schema/Schema/HashSet/HashSetFromSelf.test.ts index b12d5311d4..82f41b9fac 100644 --- a/packages/schema/test/Schema/HashSet/HashSetFromSelf.test.ts +++ b/packages/effect/test/Schema/Schema/HashSet/HashSetFromSelf.test.ts @@ -1,8 +1,8 @@ -import * as P from "@effect/schema/ParseResult" -import * as Pretty from "@effect/schema/Pretty" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import * as HashSet from "effect/HashSet" +import * as P from "effect/ParseResult" +import * as Pretty from "effect/Pretty" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("HashSetFromSelf", () => { @@ -53,7 +53,7 @@ describe("HashSetFromSelf", () => { expect(is(HashSet.fromIterable(["a", "b", "c"]))).toEqual(true) expect(is(HashSet.fromIterable(["a", "b", 1]))).toEqual(false) - expect(is({ _id: Symbol.for("@effect/schema/test/FakeHashSet") })).toEqual(false) + expect(is({ _id: Symbol.for("effect/Schema/test/FakeHashSet") })).toEqual(false) }) it("pretty", () => { diff --git a/packages/schema/test/Schema/List/List.test.ts b/packages/effect/test/Schema/Schema/List/List.test.ts similarity index 91% rename from packages/schema/test/Schema/List/List.test.ts rename to packages/effect/test/Schema/Schema/List/List.test.ts index 6b69a1640e..b0555fa150 100644 --- a/packages/schema/test/Schema/List/List.test.ts +++ b/packages/effect/test/Schema/Schema/List/List.test.ts @@ -1,6 +1,6 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import * as List from "effect/List" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("List", () => { diff --git a/packages/schema/test/Schema/List/ListFromSelf.test.ts b/packages/effect/test/Schema/Schema/List/ListFromSelf.test.ts similarity index 86% rename from packages/schema/test/Schema/List/ListFromSelf.test.ts rename to packages/effect/test/Schema/Schema/List/ListFromSelf.test.ts index 55deb9107b..08ee65bcf4 100644 --- a/packages/schema/test/Schema/List/ListFromSelf.test.ts +++ b/packages/effect/test/Schema/Schema/List/ListFromSelf.test.ts @@ -1,8 +1,8 @@ -import * as P from "@effect/schema/ParseResult" -import * as Pretty from "@effect/schema/Pretty" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import * as List from "effect/List" +import * as P from "effect/ParseResult" +import * as Pretty from "effect/Pretty" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("ListFromSelf", () => { @@ -53,7 +53,7 @@ describe("ListFromSelf", () => { expect(is(List.fromIterable(["a", "b", "c"]))).toEqual(true) expect(is(List.fromIterable(["a", "b", 1]))).toEqual(false) - expect(is({ _id: Symbol.for("@effect/schema/test/FakeList") })).toEqual(false) + expect(is({ _id: Symbol.for("effect/Schema/test/FakeList") })).toEqual(false) }) it("pretty", () => { diff --git a/packages/schema/test/Schema/Literal/Literal.test.ts b/packages/effect/test/Schema/Schema/Literal/Literal.test.ts similarity index 93% rename from packages/schema/test/Schema/Literal/Literal.test.ts rename to packages/effect/test/Schema/Schema/Literal/Literal.test.ts index e619b4aac6..5f6f39e1be 100644 --- a/packages/schema/test/Schema/Literal/Literal.test.ts +++ b/packages/effect/test/Schema/Schema/Literal/Literal.test.ts @@ -1,6 +1,6 @@ -import * as AST from "@effect/schema/AST" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as AST from "effect/SchemaAST" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("Literal", () => { diff --git a/packages/schema/test/Schema/Map/Map.test.ts b/packages/effect/test/Schema/Schema/Map/Map.test.ts similarity index 86% rename from packages/schema/test/Schema/Map/Map.test.ts rename to packages/effect/test/Schema/Schema/Map/Map.test.ts index 4c740103a4..3b2096c5de 100644 --- a/packages/schema/test/Schema/Map/Map.test.ts +++ b/packages/effect/test/Schema/Schema/Map/Map.test.ts @@ -1,4 +1,4 @@ -import * as S from "@effect/schema/Schema" +import * as S from "effect/Schema" import { describe, expect, it } from "vitest" describe("Map", () => { diff --git a/packages/schema/test/Schema/Map/MapFromRecord.test.ts b/packages/effect/test/Schema/Schema/Map/MapFromRecord.test.ts similarity index 95% rename from packages/schema/test/Schema/Map/MapFromRecord.test.ts rename to packages/effect/test/Schema/Schema/Map/MapFromRecord.test.ts index 03d275951e..d1caa17bc5 100644 --- a/packages/schema/test/Schema/Map/MapFromRecord.test.ts +++ b/packages/effect/test/Schema/Schema/Map/MapFromRecord.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("MapFromRecord", () => { diff --git a/packages/schema/test/Schema/Map/MapFromSelf.test.ts b/packages/effect/test/Schema/Schema/Map/MapFromSelf.test.ts similarity index 83% rename from packages/schema/test/Schema/Map/MapFromSelf.test.ts rename to packages/effect/test/Schema/Schema/Map/MapFromSelf.test.ts index ef2b5be81f..0239d6850e 100644 --- a/packages/schema/test/Schema/Map/MapFromSelf.test.ts +++ b/packages/effect/test/Schema/Schema/Map/MapFromSelf.test.ts @@ -1,4 +1,4 @@ -import * as S from "@effect/schema/Schema" +import * as S from "effect/Schema" import { describe, expect, it } from "vitest" describe("MapFromSelf", () => { diff --git a/packages/schema/test/Schema/Never/Never.test.ts b/packages/effect/test/Schema/Schema/Never/Never.test.ts similarity index 77% rename from packages/schema/test/Schema/Never/Never.test.ts rename to packages/effect/test/Schema/Schema/Never/Never.test.ts index 4dbc09519f..b78555b6a2 100644 --- a/packages/schema/test/Schema/Never/Never.test.ts +++ b/packages/effect/test/Schema/Schema/Never/Never.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("Never", () => { diff --git a/packages/schema/test/Schema/NonEmptyArrayEnsure.test.ts b/packages/effect/test/Schema/Schema/NonEmptyArrayEnsure.test.ts similarity index 97% rename from packages/schema/test/Schema/NonEmptyArrayEnsure.test.ts rename to packages/effect/test/Schema/Schema/NonEmptyArrayEnsure.test.ts index 24d66fecdc..7eb4955840 100644 --- a/packages/schema/test/Schema/NonEmptyArrayEnsure.test.ts +++ b/packages/effect/test/Schema/Schema/NonEmptyArrayEnsure.test.ts @@ -1,5 +1,5 @@ -import * as AST from "@effect/schema/AST" -import * as S from "@effect/schema/Schema" +import * as S from "effect/Schema" +import * as AST from "effect/SchemaAST" import { describe, expect, it } from "vitest" import { expectDecodeUnknownFailure, expectDecodeUnknownSuccess, expectEncodeSuccess } from "../TestUtils.js" diff --git a/packages/schema/test/Schema/Number/JsonNumber.test.ts b/packages/effect/test/Schema/Schema/Number/JsonNumber.test.ts similarity index 93% rename from packages/schema/test/Schema/Number/JsonNumber.test.ts rename to packages/effect/test/Schema/Schema/Number/JsonNumber.test.ts index 6d3e10017e..c4574a39da 100644 --- a/packages/schema/test/Schema/Number/JsonNumber.test.ts +++ b/packages/effect/test/Schema/Schema/Number/JsonNumber.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("JsonNumber", () => { diff --git a/packages/schema/test/Schema/Number/Number.test.ts b/packages/effect/test/Schema/Schema/Number/Number.test.ts similarity index 85% rename from packages/schema/test/Schema/Number/Number.test.ts rename to packages/effect/test/Schema/Schema/Number/Number.test.ts index bb5faaccb3..79898fe2cf 100644 --- a/packages/schema/test/Schema/Number/Number.test.ts +++ b/packages/effect/test/Schema/Schema/Number/Number.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("Number", () => { diff --git a/packages/schema/test/Schema/Number/between.test.ts b/packages/effect/test/Schema/Schema/Number/between.test.ts similarity index 87% rename from packages/schema/test/Schema/Number/between.test.ts rename to packages/effect/test/Schema/Schema/Number/between.test.ts index e210e73dff..376e38a372 100644 --- a/packages/schema/test/Schema/Number/between.test.ts +++ b/packages/effect/test/Schema/Schema/Number/between.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("between", () => { diff --git a/packages/schema/test/Schema/Number/clamp.test.ts b/packages/effect/test/Schema/Schema/Number/clamp.test.ts similarity index 86% rename from packages/schema/test/Schema/Number/clamp.test.ts rename to packages/effect/test/Schema/Schema/Number/clamp.test.ts index 4add28070b..7f1f7d52da 100644 --- a/packages/schema/test/Schema/Number/clamp.test.ts +++ b/packages/effect/test/Schema/Schema/Number/clamp.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("clamp", () => { diff --git a/packages/schema/test/Schema/Number/finite.test.ts b/packages/effect/test/Schema/Schema/Number/finite.test.ts similarity index 86% rename from packages/schema/test/Schema/Number/finite.test.ts rename to packages/effect/test/Schema/Schema/Number/finite.test.ts index 08521b07dc..433646d3f4 100644 --- a/packages/schema/test/Schema/Number/finite.test.ts +++ b/packages/effect/test/Schema/Schema/Number/finite.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("Finite", () => { diff --git a/packages/schema/test/Schema/Number/greaterThan.test.ts b/packages/effect/test/Schema/Schema/Number/greaterThan.test.ts similarity index 82% rename from packages/schema/test/Schema/Number/greaterThan.test.ts rename to packages/effect/test/Schema/Schema/Number/greaterThan.test.ts index 62013e503c..a403e7f2b3 100644 --- a/packages/schema/test/Schema/Number/greaterThan.test.ts +++ b/packages/effect/test/Schema/Schema/Number/greaterThan.test.ts @@ -1,7 +1,7 @@ -import * as P from "@effect/schema/ParseResult" -import * as Pretty from "@effect/schema/Pretty" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as P from "effect/ParseResult" +import * as Pretty from "effect/Pretty" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("greaterThan", () => { diff --git a/packages/schema/test/Schema/Number/greaterThanOrEqualTo.test.ts b/packages/effect/test/Schema/Schema/Number/greaterThanOrEqualTo.test.ts similarity index 80% rename from packages/schema/test/Schema/Number/greaterThanOrEqualTo.test.ts rename to packages/effect/test/Schema/Schema/Number/greaterThanOrEqualTo.test.ts index 9684c87e71..b4a3af9351 100644 --- a/packages/schema/test/Schema/Number/greaterThanOrEqualTo.test.ts +++ b/packages/effect/test/Schema/Schema/Number/greaterThanOrEqualTo.test.ts @@ -1,7 +1,7 @@ -import * as P from "@effect/schema/ParseResult" -import * as Pretty from "@effect/schema/Pretty" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as P from "effect/ParseResult" +import * as Pretty from "effect/Pretty" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("greaterThanOrEqualTo", () => { diff --git a/packages/schema/test/Schema/Number/int.test.ts b/packages/effect/test/Schema/Schema/Number/int.test.ts similarity index 81% rename from packages/schema/test/Schema/Number/int.test.ts rename to packages/effect/test/Schema/Schema/Number/int.test.ts index 69e3376287..d74bd8d517 100644 --- a/packages/schema/test/Schema/Number/int.test.ts +++ b/packages/effect/test/Schema/Schema/Number/int.test.ts @@ -1,7 +1,7 @@ -import * as P from "@effect/schema/ParseResult" -import * as Pretty from "@effect/schema/Pretty" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as P from "effect/ParseResult" +import * as Pretty from "effect/Pretty" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("Int", () => { diff --git a/packages/schema/test/Schema/Number/lessThan.test.ts b/packages/effect/test/Schema/Schema/Number/lessThan.test.ts similarity index 83% rename from packages/schema/test/Schema/Number/lessThan.test.ts rename to packages/effect/test/Schema/Schema/Number/lessThan.test.ts index 42617cc16c..b95806444f 100644 --- a/packages/schema/test/Schema/Number/lessThan.test.ts +++ b/packages/effect/test/Schema/Schema/Number/lessThan.test.ts @@ -1,7 +1,7 @@ -import * as P from "@effect/schema/ParseResult" -import * as Pretty from "@effect/schema/Pretty" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as P from "effect/ParseResult" +import * as Pretty from "effect/Pretty" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("lessThan", () => { diff --git a/packages/schema/test/Schema/Number/lessThanOrEqualTo.test.ts b/packages/effect/test/Schema/Schema/Number/lessThanOrEqualTo.test.ts similarity index 81% rename from packages/schema/test/Schema/Number/lessThanOrEqualTo.test.ts rename to packages/effect/test/Schema/Schema/Number/lessThanOrEqualTo.test.ts index 77cb03ba3d..1b0d1547a0 100644 --- a/packages/schema/test/Schema/Number/lessThanOrEqualTo.test.ts +++ b/packages/effect/test/Schema/Schema/Number/lessThanOrEqualTo.test.ts @@ -1,7 +1,7 @@ -import * as P from "@effect/schema/ParseResult" -import * as Pretty from "@effect/schema/Pretty" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as P from "effect/ParseResult" +import * as Pretty from "effect/Pretty" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("lessThanOrEqualTo", () => { diff --git a/packages/schema/test/Schema/Number/multipleOf.test.ts b/packages/effect/test/Schema/Schema/Number/multipleOf.test.ts similarity index 89% rename from packages/schema/test/Schema/Number/multipleOf.test.ts rename to packages/effect/test/Schema/Schema/Number/multipleOf.test.ts index 8ca97c441f..e88e91d050 100644 --- a/packages/schema/test/Schema/Number/multipleOf.test.ts +++ b/packages/effect/test/Schema/Schema/Number/multipleOf.test.ts @@ -1,6 +1,6 @@ -import * as P from "@effect/schema/ParseResult" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as P from "effect/ParseResult" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("multipleOf", () => { diff --git a/packages/schema/test/Schema/Number/negative.test.ts b/packages/effect/test/Schema/Schema/Number/negative.test.ts similarity index 84% rename from packages/schema/test/Schema/Number/negative.test.ts rename to packages/effect/test/Schema/Schema/Number/negative.test.ts index 22c8a3e52d..daf55316a8 100644 --- a/packages/schema/test/Schema/Number/negative.test.ts +++ b/packages/effect/test/Schema/Schema/Number/negative.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("Negative", () => { diff --git a/packages/schema/test/Schema/Number/nonNaN.test.ts b/packages/effect/test/Schema/Schema/Number/nonNaN.test.ts similarity index 77% rename from packages/schema/test/Schema/Number/nonNaN.test.ts rename to packages/effect/test/Schema/Schema/Number/nonNaN.test.ts index 80a257de30..b6cac9ba8f 100644 --- a/packages/schema/test/Schema/Number/nonNaN.test.ts +++ b/packages/effect/test/Schema/Schema/Number/nonNaN.test.ts @@ -1,7 +1,7 @@ -import * as P from "@effect/schema/ParseResult" -import * as Pretty from "@effect/schema/Pretty" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as P from "effect/ParseResult" +import * as Pretty from "effect/Pretty" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("NonNaN", () => { diff --git a/packages/schema/test/Schema/Number/nonNegative.test.ts b/packages/effect/test/Schema/Schema/Number/nonNegative.test.ts similarity index 82% rename from packages/schema/test/Schema/Number/nonNegative.test.ts rename to packages/effect/test/Schema/Schema/Number/nonNegative.test.ts index 4c15616193..1e72ae9208 100644 --- a/packages/schema/test/Schema/Number/nonNegative.test.ts +++ b/packages/effect/test/Schema/Schema/Number/nonNegative.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("NonNegative", () => { diff --git a/packages/schema/test/Schema/Number/nonPositive.test.ts b/packages/effect/test/Schema/Schema/Number/nonPositive.test.ts similarity index 82% rename from packages/schema/test/Schema/Number/nonPositive.test.ts rename to packages/effect/test/Schema/Schema/Number/nonPositive.test.ts index 54cdb42953..e1a2f996e3 100644 --- a/packages/schema/test/Schema/Number/nonPositive.test.ts +++ b/packages/effect/test/Schema/Schema/Number/nonPositive.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("NonPositive", () => { diff --git a/packages/schema/test/Schema/Number/numberFromString.test.ts b/packages/effect/test/Schema/Schema/Number/numberFromString.test.ts similarity index 95% rename from packages/schema/test/Schema/Number/numberFromString.test.ts rename to packages/effect/test/Schema/Schema/Number/numberFromString.test.ts index f72b9c344b..d729a133fd 100644 --- a/packages/schema/test/Schema/Number/numberFromString.test.ts +++ b/packages/effect/test/Schema/Schema/Number/numberFromString.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("NumberFromString", () => { diff --git a/packages/schema/test/Schema/Number/positive.test.ts b/packages/effect/test/Schema/Schema/Number/positive.test.ts similarity index 84% rename from packages/schema/test/Schema/Number/positive.test.ts rename to packages/effect/test/Schema/Schema/Number/positive.test.ts index 09e6dc8cd7..2dc468cadb 100644 --- a/packages/schema/test/Schema/Number/positive.test.ts +++ b/packages/effect/test/Schema/Schema/Number/positive.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("Positive", () => { diff --git a/packages/schema/test/Schema/Object/Object.test.ts b/packages/effect/test/Schema/Schema/Object/Object.test.ts similarity index 90% rename from packages/schema/test/Schema/Object/Object.test.ts rename to packages/effect/test/Schema/Schema/Object/Object.test.ts index 6c5ac3cce7..562cd4218c 100644 --- a/packages/schema/test/Schema/Object/Object.test.ts +++ b/packages/effect/test/Schema/Schema/Object/Object.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("object", () => { diff --git a/packages/schema/test/Schema/Option/Option.test.ts b/packages/effect/test/Schema/Schema/Option/Option.test.ts similarity index 87% rename from packages/schema/test/Schema/Option/Option.test.ts rename to packages/effect/test/Schema/Schema/Option/Option.test.ts index a23a0683b6..78f1997495 100644 --- a/packages/schema/test/Schema/Option/Option.test.ts +++ b/packages/effect/test/Schema/Schema/Option/Option.test.ts @@ -1,6 +1,6 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import * as O from "effect/Option" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("Option", () => { diff --git a/packages/schema/test/Schema/Option/OptionFromNonEmptyTrimmedString.test.ts b/packages/effect/test/Schema/Schema/Option/OptionFromNonEmptyTrimmedString.test.ts similarity index 93% rename from packages/schema/test/Schema/Option/OptionFromNonEmptyTrimmedString.test.ts rename to packages/effect/test/Schema/Schema/Option/OptionFromNonEmptyTrimmedString.test.ts index 25a9339725..f372a66d75 100644 --- a/packages/schema/test/Schema/Option/OptionFromNonEmptyTrimmedString.test.ts +++ b/packages/effect/test/Schema/Schema/Option/OptionFromNonEmptyTrimmedString.test.ts @@ -1,6 +1,6 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import * as O from "effect/Option" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("OptionFromNonEmptyTrimmedString", () => { diff --git a/packages/schema/test/Schema/Option/OptionFromNullOr.test.ts b/packages/effect/test/Schema/Schema/Option/OptionFromNullOr.test.ts similarity index 94% rename from packages/schema/test/Schema/Option/OptionFromNullOr.test.ts rename to packages/effect/test/Schema/Schema/Option/OptionFromNullOr.test.ts index d03ed295b8..ce58a65d06 100644 --- a/packages/schema/test/Schema/Option/OptionFromNullOr.test.ts +++ b/packages/effect/test/Schema/Schema/Option/OptionFromNullOr.test.ts @@ -1,6 +1,6 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import * as O from "effect/Option" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("OptionFromNullOr", () => { diff --git a/packages/schema/test/Schema/Option/OptionFromNullishOr.test.ts b/packages/effect/test/Schema/Schema/Option/OptionFromNullishOr.test.ts similarity index 94% rename from packages/schema/test/Schema/Option/OptionFromNullishOr.test.ts rename to packages/effect/test/Schema/Schema/Option/OptionFromNullishOr.test.ts index e1bf9c2e40..eedb0550b5 100644 --- a/packages/schema/test/Schema/Option/OptionFromNullishOr.test.ts +++ b/packages/effect/test/Schema/Schema/Option/OptionFromNullishOr.test.ts @@ -1,6 +1,6 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import * as O from "effect/Option" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("OptionFromNullishOr", () => { diff --git a/packages/schema/test/Schema/Option/OptionFromSelf.test.ts b/packages/effect/test/Schema/Schema/Option/OptionFromSelf.test.ts similarity index 86% rename from packages/schema/test/Schema/Option/OptionFromSelf.test.ts rename to packages/effect/test/Schema/Schema/Option/OptionFromSelf.test.ts index 207eced194..5b3c023a81 100644 --- a/packages/schema/test/Schema/Option/OptionFromSelf.test.ts +++ b/packages/effect/test/Schema/Schema/Option/OptionFromSelf.test.ts @@ -1,8 +1,8 @@ -import * as P from "@effect/schema/ParseResult" -import * as Pretty from "@effect/schema/Pretty" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import * as O from "effect/Option" +import * as P from "effect/ParseResult" +import * as Pretty from "effect/Pretty" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("OptionFromSelf", () => { diff --git a/packages/schema/test/Schema/Option/OptionFromUndefinedOr.test.ts b/packages/effect/test/Schema/Schema/Option/OptionFromUndefinedOr.test.ts similarity index 94% rename from packages/schema/test/Schema/Option/OptionFromUndefinedOr.test.ts rename to packages/effect/test/Schema/Schema/Option/OptionFromUndefinedOr.test.ts index 0bbd44d46f..88f2516a98 100644 --- a/packages/schema/test/Schema/Option/OptionFromUndefinedOr.test.ts +++ b/packages/effect/test/Schema/Schema/Option/OptionFromUndefinedOr.test.ts @@ -1,6 +1,6 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import * as O from "effect/Option" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("OptionFromUndefinedOr", () => { diff --git a/packages/schema/test/Schema/ParseOptions-errors.test.ts b/packages/effect/test/Schema/Schema/ParseOptions-errors.test.ts similarity index 98% rename from packages/schema/test/Schema/ParseOptions-errors.test.ts rename to packages/effect/test/Schema/Schema/ParseOptions-errors.test.ts index c869ee8919..797daed627 100644 --- a/packages/schema/test/Schema/ParseOptions-errors.test.ts +++ b/packages/effect/test/Schema/Schema/ParseOptions-errors.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("`errors` option", () => { diff --git a/packages/schema/test/Schema/ParseOptions-exact.test.ts b/packages/effect/test/Schema/Schema/ParseOptions-exact.test.ts similarity index 92% rename from packages/schema/test/Schema/ParseOptions-exact.test.ts rename to packages/effect/test/Schema/Schema/ParseOptions-exact.test.ts index 9fcc7c8ff6..45d65e7408 100644 --- a/packages/schema/test/Schema/ParseOptions-exact.test.ts +++ b/packages/effect/test/Schema/Schema/ParseOptions-exact.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("`exact` option", () => { diff --git a/packages/schema/test/Schema/ParseOptions-onExcessProperty.test.ts b/packages/effect/test/Schema/Schema/ParseOptions-onExcessProperty.test.ts similarity index 94% rename from packages/schema/test/Schema/ParseOptions-onExcessProperty.test.ts rename to packages/effect/test/Schema/Schema/ParseOptions-onExcessProperty.test.ts index ecc4a6beef..e71c714fa4 100644 --- a/packages/schema/test/Schema/ParseOptions-onExcessProperty.test.ts +++ b/packages/effect/test/Schema/Schema/ParseOptions-onExcessProperty.test.ts @@ -1,7 +1,7 @@ -import * as ParseResult from "@effect/schema/ParseResult" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import * as Either from "effect/Either" +import * as ParseResult from "effect/ParseResult" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("`onExcessProperty` option", () => { @@ -186,35 +186,35 @@ describe("`onExcessProperty` option", () => { }) it("struct with string excess keys", async () => { - const c = Symbol.for("@effect/schema/test/c") + const c = Symbol.for("effect/Schema/test/c") const schema = S.Struct({ a: S.String }) const input = { a: "a", b: 1, [c]: true } await Util.expectDecodeUnknownSuccess(schema, input, input, Util.onExcessPropertyPreserve) }) it("struct with symbol excess keys", async () => { - const c = Symbol.for("@effect/schema/test/c") + const c = Symbol.for("effect/Schema/test/c") const schema = S.Struct({ [c]: S.Boolean }) const input = { a: "a", b: 1, [c]: true } await Util.expectDecodeUnknownSuccess(schema, input, input, Util.onExcessPropertyPreserve) }) it("struct with both string and symbol excess keys", async () => { - const c = Symbol.for("@effect/schema/test/c") + const c = Symbol.for("effect/Schema/test/c") const schema = S.Struct({ a: S.String, [c]: S.Boolean }) const input = { a: "a", b: 1, [c]: true } await Util.expectDecodeUnknownSuccess(schema, input, input, Util.onExcessPropertyPreserve) }) it("record(string, string)", async () => { - const c = Symbol.for("@effect/schema/test/c") + const c = Symbol.for("effect/Schema/test/c") const schema = S.Struct({ a: S.String }) const input = { a: "a", [c]: true } await Util.expectDecodeUnknownSuccess(schema, input, input, Util.onExcessPropertyPreserve) }) it("record(symbol, boolean)", async () => { - const c = Symbol.for("@effect/schema/test/c") + const c = Symbol.for("effect/Schema/test/c") const schema = S.Struct({ [c]: S.Boolean }) const input = { a: "a", [c]: true } await Util.expectDecodeUnknownSuccess(schema, input, input, Util.onExcessPropertyPreserve) diff --git a/packages/schema/test/Schema/ParseOptions-preserveKeyOrder.test.ts b/packages/effect/test/Schema/Schema/ParseOptions-preserveKeyOrder.test.ts similarity index 95% rename from packages/schema/test/Schema/ParseOptions-preserveKeyOrder.test.ts rename to packages/effect/test/Schema/Schema/ParseOptions-preserveKeyOrder.test.ts index 76bb3e02f1..7d0dddb021 100644 --- a/packages/schema/test/Schema/ParseOptions-preserveKeyOrder.test.ts +++ b/packages/effect/test/Schema/Schema/ParseOptions-preserveKeyOrder.test.ts @@ -1,11 +1,11 @@ -import * as ParseResult from "@effect/schema/ParseResult" -import * as S from "@effect/schema/Schema" import type { Duration } from "effect" import * as Effect from "effect/Effect" +import * as ParseResult from "effect/ParseResult" +import * as S from "effect/Schema" import { describe, expect, it } from "vitest" describe("`preserveKeyOrder` option", () => { - const b = Symbol.for("@effect/schema/test/b") + const b = Symbol.for("effect/Schema/test/b") const Sync = S.Struct({ a: S.Literal("a"), [b]: S.Array(S.String), diff --git a/packages/schema/test/Schema/ParseOptionsAnnotation.test.ts b/packages/effect/test/Schema/Schema/ParseOptionsAnnotation.test.ts similarity index 94% rename from packages/schema/test/Schema/ParseOptionsAnnotation.test.ts rename to packages/effect/test/Schema/Schema/ParseOptionsAnnotation.test.ts index c70ac310b9..82d2ed4d10 100644 --- a/packages/schema/test/Schema/ParseOptionsAnnotation.test.ts +++ b/packages/effect/test/Schema/Schema/ParseOptionsAnnotation.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" const String = S.transform(S.NonEmptyString, S.String, { strict: true, decode: (s) => s, encode: (s) => s }) diff --git a/packages/schema/test/Schema/PropertySignature.test.ts b/packages/effect/test/Schema/Schema/PropertySignature.test.ts similarity index 96% rename from packages/schema/test/Schema/PropertySignature.test.ts rename to packages/effect/test/Schema/Schema/PropertySignature.test.ts index 8b21bb90ca..9f37db82a2 100644 --- a/packages/schema/test/Schema/PropertySignature.test.ts +++ b/packages/effect/test/Schema/Schema/PropertySignature.test.ts @@ -1,8 +1,8 @@ -import * as AST from "@effect/schema/AST" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import { identity } from "effect/Function" import * as Option from "effect/Option" +import * as S from "effect/Schema" +import * as AST from "effect/SchemaAST" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("PropertySignature", () => { @@ -197,14 +197,14 @@ describe("PropertySignature", () => { }) it("symbol key", async () => { - const a = Symbol.for("@effect/schema/test/a") + const a = Symbol.for("effect/Schema/test/a") const ps = S.propertySignature(S.Symbol).pipe(S.fromKey(a)) const transform = S.Struct({ a: ps }) const rename = S.asSchema(transform) const schema = S.Struct({ b: S.Number }).pipe(S.extend(rename)) - await Util.expectDecodeUnknownSuccess(schema, { [a]: "@effect/schema/test/a", b: 1 }, { a, b: 1 }) - await Util.expectEncodeSuccess(schema, { a, b: 1 }, { [a]: "@effect/schema/test/a", b: 1 }) + await Util.expectDecodeUnknownSuccess(schema, { [a]: "effect/Schema/test/a", b: 1 }, { a, b: 1 }) + await Util.expectEncodeSuccess(schema, { a, b: 1 }, { [a]: "effect/Schema/test/a", b: 1 }) }) }) }) diff --git a/packages/schema/test/Schema/ReadonlyMap/ReadonlyMap.test.ts b/packages/effect/test/Schema/Schema/ReadonlyMap/ReadonlyMap.test.ts similarity index 93% rename from packages/schema/test/Schema/ReadonlyMap/ReadonlyMap.test.ts rename to packages/effect/test/Schema/Schema/ReadonlyMap/ReadonlyMap.test.ts index cb27f5b80a..abf898f14b 100644 --- a/packages/schema/test/Schema/ReadonlyMap/ReadonlyMap.test.ts +++ b/packages/effect/test/Schema/Schema/ReadonlyMap/ReadonlyMap.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("ReadonlyMap", () => { diff --git a/packages/schema/test/Schema/ReadonlyMap/ReadonlyMapFromRecord.test.ts b/packages/effect/test/Schema/Schema/ReadonlyMap/ReadonlyMapFromRecord.test.ts similarity index 95% rename from packages/schema/test/Schema/ReadonlyMap/ReadonlyMapFromRecord.test.ts rename to packages/effect/test/Schema/Schema/ReadonlyMap/ReadonlyMapFromRecord.test.ts index 74d5d0b00e..632fa48391 100644 --- a/packages/schema/test/Schema/ReadonlyMap/ReadonlyMapFromRecord.test.ts +++ b/packages/effect/test/Schema/Schema/ReadonlyMap/ReadonlyMapFromRecord.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("ReadonlyMapFromRecord", () => { diff --git a/packages/schema/test/Schema/ReadonlyMap/ReadonlyMapFromSelf.test.ts b/packages/effect/test/Schema/Schema/ReadonlyMap/ReadonlyMapFromSelf.test.ts similarity index 92% rename from packages/schema/test/Schema/ReadonlyMap/ReadonlyMapFromSelf.test.ts rename to packages/effect/test/Schema/Schema/ReadonlyMap/ReadonlyMapFromSelf.test.ts index c4f74c5d6e..44870dbc36 100644 --- a/packages/schema/test/Schema/ReadonlyMap/ReadonlyMapFromSelf.test.ts +++ b/packages/effect/test/Schema/Schema/ReadonlyMap/ReadonlyMapFromSelf.test.ts @@ -1,7 +1,7 @@ -import * as P from "@effect/schema/ParseResult" -import * as Pretty from "@effect/schema/Pretty" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as P from "effect/ParseResult" +import * as Pretty from "effect/Pretty" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("ReadonlyMapFromSelf", () => { diff --git a/packages/schema/test/Schema/ReadonlySet/ReadonlySet.test.ts b/packages/effect/test/Schema/Schema/ReadonlySet/ReadonlySet.test.ts similarity index 91% rename from packages/schema/test/Schema/ReadonlySet/ReadonlySet.test.ts rename to packages/effect/test/Schema/Schema/ReadonlySet/ReadonlySet.test.ts index 9ab3409b65..a251aebcc9 100644 --- a/packages/schema/test/Schema/ReadonlySet/ReadonlySet.test.ts +++ b/packages/effect/test/Schema/Schema/ReadonlySet/ReadonlySet.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("ReadonlySet", () => { diff --git a/packages/schema/test/Schema/ReadonlySet/ReadonlySetFromSelf.test.ts b/packages/effect/test/Schema/Schema/ReadonlySet/ReadonlySetFromSelf.test.ts similarity index 90% rename from packages/schema/test/Schema/ReadonlySet/ReadonlySetFromSelf.test.ts rename to packages/effect/test/Schema/Schema/ReadonlySet/ReadonlySetFromSelf.test.ts index 2561faffea..43a82d7400 100644 --- a/packages/schema/test/Schema/ReadonlySet/ReadonlySetFromSelf.test.ts +++ b/packages/effect/test/Schema/Schema/ReadonlySet/ReadonlySetFromSelf.test.ts @@ -1,7 +1,7 @@ -import * as P from "@effect/schema/ParseResult" -import * as Pretty from "@effect/schema/Pretty" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as P from "effect/ParseResult" +import * as Pretty from "effect/Pretty" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("ReadonlySetFromSelf", () => { diff --git a/packages/schema/test/Schema/Record/Record.test.ts b/packages/effect/test/Schema/Schema/Record/Record.test.ts similarity index 93% rename from packages/schema/test/Schema/Record/Record.test.ts rename to packages/effect/test/Schema/Schema/Record/Record.test.ts index 940ddc39e4..37757221a3 100644 --- a/packages/schema/test/Schema/Record/Record.test.ts +++ b/packages/effect/test/Schema/Schema/Record/Record.test.ts @@ -1,8 +1,8 @@ -import * as AST from "@effect/schema/AST" -import * as ParseResult from "@effect/schema/ParseResult" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import * as Either from "effect/Either" +import * as ParseResult from "effect/ParseResult" +import * as S from "effect/Schema" +import * as AST from "effect/SchemaAST" +import * as Util from "effect/test/Schema/TestUtils" import { assert, describe, expect, it } from "vitest" describe("record", () => { @@ -107,20 +107,20 @@ describe("record", () => { └─ ["a"] └─ Expected number, actual "a"` ) - const b = Symbol.for("@effect/schema/test/b") + const b = Symbol.for("effect/Schema/test/b") await Util.expectDecodeUnknownSuccess(schema, { a: 1, [b]: "b" }, { a: 1 }) await Util.expectDecodeUnknownFailure( schema, { a: 1, [b]: "b" }, `{ readonly [x: string]: number } -└─ [Symbol(@effect/schema/test/b)] +└─ [Symbol(effect/Schema/test/b)] └─ is unexpected, expected: string`, Util.onExcessPropertyError ) }) it("Record(symbol, number)", async () => { - const a = Symbol.for("@effect/schema/test/a") + const a = Symbol.for("effect/Schema/test/a") const schema = S.Record({ key: S.SymbolFromSelf, value: S.Number }) await Util.expectDecodeUnknownSuccess(schema, {}) await Util.expectDecodeUnknownSuccess(schema, { [a]: 1 }) @@ -134,7 +134,7 @@ describe("record", () => { schema, { [a]: "a" }, `{ readonly [x: symbol]: number } -└─ [Symbol(@effect/schema/test/a)] +└─ [Symbol(effect/Schema/test/a)] └─ Expected number, actual "a"` ) await Util.expectDecodeUnknownSuccess( @@ -237,30 +237,30 @@ describe("record", () => { }) it("Record(Symbol('a') | Symbol('b'), number)", async () => { - const a = Symbol.for("@effect/schema/test/a") - const b = Symbol.for("@effect/schema/test/b") + const a = Symbol.for("effect/Schema/test/a") + const b = Symbol.for("effect/Schema/test/b") const schema = S.Record({ key: S.Union(S.UniqueSymbolFromSelf(a), S.UniqueSymbolFromSelf(b)), value: S.Number }) await Util.expectDecodeUnknownSuccess(schema, { [a]: 1, [b]: 2 }) await Util.expectDecodeUnknownFailure( schema, {}, - `{ readonly Symbol(@effect/schema/test/a): number; readonly Symbol(@effect/schema/test/b): number } -└─ [Symbol(@effect/schema/test/a)] + `{ readonly Symbol(effect/Schema/test/a): number; readonly Symbol(effect/Schema/test/b): number } +└─ [Symbol(effect/Schema/test/a)] └─ is missing` ) await Util.expectDecodeUnknownFailure( schema, { [a]: 1 }, - `{ readonly Symbol(@effect/schema/test/a): number; readonly Symbol(@effect/schema/test/b): number } -└─ [Symbol(@effect/schema/test/b)] + `{ readonly Symbol(effect/Schema/test/a): number; readonly Symbol(effect/Schema/test/b): number } +└─ [Symbol(effect/Schema/test/b)] └─ is missing` ) await Util.expectDecodeUnknownFailure( schema, { [b]: 2 }, - `{ readonly Symbol(@effect/schema/test/a): number; readonly Symbol(@effect/schema/test/b): number } -└─ [Symbol(@effect/schema/test/a)] + `{ readonly Symbol(effect/Schema/test/a): number; readonly Symbol(effect/Schema/test/b): number } +└─ [Symbol(effect/Schema/test/a)] └─ is missing` ) }) diff --git a/packages/schema/test/Schema/Redacted/Redacted.test.ts b/packages/effect/test/Schema/Schema/Redacted/Redacted.test.ts similarity index 86% rename from packages/schema/test/Schema/Redacted/Redacted.test.ts rename to packages/effect/test/Schema/Schema/Redacted/Redacted.test.ts index b4b9d471a3..d7eb32de4c 100644 --- a/packages/schema/test/Schema/Redacted/Redacted.test.ts +++ b/packages/effect/test/Schema/Schema/Redacted/Redacted.test.ts @@ -1,7 +1,7 @@ -import * as Pretty from "@effect/schema/Pretty" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import { Redacted } from "effect" +import * as Pretty from "effect/Pretty" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("Redacted", () => { diff --git a/packages/schema/test/Schema/Redacted/RedactedFromSelf.test.ts b/packages/effect/test/Schema/Schema/Redacted/RedactedFromSelf.test.ts similarity index 86% rename from packages/schema/test/Schema/Redacted/RedactedFromSelf.test.ts rename to packages/effect/test/Schema/Schema/Redacted/RedactedFromSelf.test.ts index 06d3d88f29..1bb12faff7 100644 --- a/packages/schema/test/Schema/Redacted/RedactedFromSelf.test.ts +++ b/packages/effect/test/Schema/Schema/Redacted/RedactedFromSelf.test.ts @@ -1,7 +1,7 @@ -import * as Pretty from "@effect/schema/Pretty" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import { Redacted } from "effect" +import * as Pretty from "effect/Pretty" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("RedactedFromSelf", () => { diff --git a/packages/schema/test/Schema/Set/Set.test.ts b/packages/effect/test/Schema/Schema/Set/Set.test.ts similarity index 82% rename from packages/schema/test/Schema/Set/Set.test.ts rename to packages/effect/test/Schema/Schema/Set/Set.test.ts index d90344212a..7ac771c82d 100644 --- a/packages/schema/test/Schema/Set/Set.test.ts +++ b/packages/effect/test/Schema/Schema/Set/Set.test.ts @@ -1,4 +1,4 @@ -import * as S from "@effect/schema/Schema" +import * as S from "effect/Schema" import { describe, expect, it } from "vitest" describe("Set", () => { diff --git a/packages/schema/test/Schema/Set/SetFromSelf.test.ts b/packages/effect/test/Schema/Schema/Set/SetFromSelf.test.ts similarity index 81% rename from packages/schema/test/Schema/Set/SetFromSelf.test.ts rename to packages/effect/test/Schema/Schema/Set/SetFromSelf.test.ts index 9c28f9e175..3f0abf847a 100644 --- a/packages/schema/test/Schema/Set/SetFromSelf.test.ts +++ b/packages/effect/test/Schema/Schema/Set/SetFromSelf.test.ts @@ -1,4 +1,4 @@ -import * as S from "@effect/schema/Schema" +import * as S from "effect/Schema" import { describe, expect, it } from "vitest" describe("SetFromSelf", () => { diff --git a/packages/schema/test/Schema/SortedSet/SortedSet.test.ts b/packages/effect/test/Schema/Schema/SortedSet/SortedSet.test.ts similarity index 93% rename from packages/schema/test/Schema/SortedSet/SortedSet.test.ts rename to packages/effect/test/Schema/Schema/SortedSet/SortedSet.test.ts index e3955a39de..894217b6bf 100644 --- a/packages/schema/test/Schema/SortedSet/SortedSet.test.ts +++ b/packages/effect/test/Schema/Schema/SortedSet/SortedSet.test.ts @@ -1,7 +1,7 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import * as N from "effect/Number" +import * as S from "effect/Schema" import * as SortedSet from "effect/SortedSet" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("SortedSet", () => { diff --git a/packages/schema/test/Schema/SortedSet/SortedSetFromSelf.test.ts b/packages/effect/test/Schema/Schema/SortedSet/SortedSetFromSelf.test.ts similarity index 90% rename from packages/schema/test/Schema/SortedSet/SortedSetFromSelf.test.ts rename to packages/effect/test/Schema/Schema/SortedSet/SortedSetFromSelf.test.ts index db62237503..bdb84b5ac1 100644 --- a/packages/schema/test/Schema/SortedSet/SortedSetFromSelf.test.ts +++ b/packages/effect/test/Schema/Schema/SortedSet/SortedSetFromSelf.test.ts @@ -1,11 +1,10 @@ -import * as Equivalence from "@effect/schema/Equivalence" -import * as P from "@effect/schema/ParseResult" -import * as Pretty from "@effect/schema/Pretty" -import * as Schema from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import * as N from "effect/Number" +import * as P from "effect/ParseResult" +import * as Pretty from "effect/Pretty" +import * as Schema from "effect/Schema" import * as SortedSet from "effect/SortedSet" import * as S from "effect/String" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("SortedSetFromSelf", () => { @@ -79,7 +78,7 @@ describe("SortedSetFromSelf", () => { it("equivalence", () => { const schema = Schema.SortedSetFromSelf(Schema.String, S.Order, S.Order) - const eq = Equivalence.make(schema) + const eq = Schema.equivalence(schema) const a = SortedSet.fromIterable([] as Array, S.Order) const b = SortedSet.fromIterable(["a"] as Array, S.Order) diff --git a/packages/schema/test/Schema/String/NonEmptyTrimmedString.test.ts b/packages/effect/test/Schema/Schema/String/NonEmptyTrimmedString.test.ts similarity index 93% rename from packages/schema/test/Schema/String/NonEmptyTrimmedString.test.ts rename to packages/effect/test/Schema/Schema/String/NonEmptyTrimmedString.test.ts index ba9b2d68f4..dc31c6691e 100644 --- a/packages/schema/test/Schema/String/NonEmptyTrimmedString.test.ts +++ b/packages/effect/test/Schema/Schema/String/NonEmptyTrimmedString.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("NonEmptyTrimmedString", () => { diff --git a/packages/schema/test/Schema/String/String.test.ts b/packages/effect/test/Schema/Schema/String/String.test.ts similarity index 78% rename from packages/schema/test/Schema/String/String.test.ts rename to packages/effect/test/Schema/Schema/String/String.test.ts index 6722fcc845..8f2d319675 100644 --- a/packages/schema/test/Schema/String/String.test.ts +++ b/packages/effect/test/Schema/Schema/String/String.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("String", () => { diff --git a/packages/schema/test/Schema/String/StringFromBase64.test.ts b/packages/effect/test/Schema/Schema/String/StringFromBase64.test.ts similarity index 91% rename from packages/schema/test/Schema/String/StringFromBase64.test.ts rename to packages/effect/test/Schema/Schema/String/StringFromBase64.test.ts index 4a5e3384f9..a783595055 100644 --- a/packages/schema/test/Schema/String/StringFromBase64.test.ts +++ b/packages/effect/test/Schema/Schema/String/StringFromBase64.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("StringFromBase64", () => { diff --git a/packages/schema/test/Schema/String/StringFromBase64Url.test.ts b/packages/effect/test/Schema/Schema/String/StringFromBase64Url.test.ts similarity index 91% rename from packages/schema/test/Schema/String/StringFromBase64Url.test.ts rename to packages/effect/test/Schema/Schema/String/StringFromBase64Url.test.ts index e72b188b55..bc9a21afb9 100644 --- a/packages/schema/test/Schema/String/StringFromBase64Url.test.ts +++ b/packages/effect/test/Schema/Schema/String/StringFromBase64Url.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("StringFromBase64Url", () => { diff --git a/packages/schema/test/Schema/String/StringFromHex.test.ts b/packages/effect/test/Schema/Schema/String/StringFromHex.test.ts similarity index 93% rename from packages/schema/test/Schema/String/StringFromHex.test.ts rename to packages/effect/test/Schema/Schema/String/StringFromHex.test.ts index c7cd22d656..93bb461d3d 100644 --- a/packages/schema/test/Schema/String/StringFromHex.test.ts +++ b/packages/effect/test/Schema/Schema/String/StringFromHex.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("StringFromHex", () => { diff --git a/packages/schema/test/Schema/String/capitalize.test.ts b/packages/effect/test/Schema/Schema/String/capitalize.test.ts similarity index 90% rename from packages/schema/test/Schema/String/capitalize.test.ts rename to packages/effect/test/Schema/Schema/String/capitalize.test.ts index 32043fd0b6..483a5d937f 100644 --- a/packages/schema/test/Schema/String/capitalize.test.ts +++ b/packages/effect/test/Schema/Schema/String/capitalize.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("Capitalize", () => { diff --git a/packages/schema/test/Schema/String/endsWith.test.ts b/packages/effect/test/Schema/Schema/String/endsWith.test.ts similarity index 86% rename from packages/schema/test/Schema/String/endsWith.test.ts rename to packages/effect/test/Schema/Schema/String/endsWith.test.ts index 015426fbf4..b10ba13576 100644 --- a/packages/schema/test/Schema/String/endsWith.test.ts +++ b/packages/effect/test/Schema/Schema/String/endsWith.test.ts @@ -1,6 +1,6 @@ -import * as P from "@effect/schema/ParseResult" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as P from "effect/ParseResult" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("endsWith", () => { diff --git a/packages/schema/test/Schema/String/includes.test.ts b/packages/effect/test/Schema/Schema/String/includes.test.ts similarity index 83% rename from packages/schema/test/Schema/String/includes.test.ts rename to packages/effect/test/Schema/Schema/String/includes.test.ts index 3d5a9402c5..430f86a2ea 100644 --- a/packages/schema/test/Schema/String/includes.test.ts +++ b/packages/effect/test/Schema/Schema/String/includes.test.ts @@ -1,7 +1,7 @@ -import * as P from "@effect/schema/ParseResult" -import * as Pretty from "@effect/schema/Pretty" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as P from "effect/ParseResult" +import * as Pretty from "effect/Pretty" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("includes", () => { diff --git a/packages/schema/test/Schema/String/length.test.ts b/packages/effect/test/Schema/Schema/String/length.test.ts similarity index 96% rename from packages/schema/test/Schema/String/length.test.ts rename to packages/effect/test/Schema/Schema/String/length.test.ts index 6772b60100..6fefb2859c 100644 --- a/packages/schema/test/Schema/String/length.test.ts +++ b/packages/effect/test/Schema/Schema/String/length.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("length", () => { diff --git a/packages/schema/test/Schema/String/lowercase.test.ts b/packages/effect/test/Schema/Schema/String/lowercase.test.ts similarity index 89% rename from packages/schema/test/Schema/String/lowercase.test.ts rename to packages/effect/test/Schema/Schema/String/lowercase.test.ts index a765395850..8a523d990d 100644 --- a/packages/schema/test/Schema/String/lowercase.test.ts +++ b/packages/effect/test/Schema/Schema/String/lowercase.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("Lowercase", () => { diff --git a/packages/schema/test/Schema/String/maxLength.test.ts b/packages/effect/test/Schema/Schema/String/maxLength.test.ts similarity index 81% rename from packages/schema/test/Schema/String/maxLength.test.ts rename to packages/effect/test/Schema/Schema/String/maxLength.test.ts index 71959f3409..86634ece00 100644 --- a/packages/schema/test/Schema/String/maxLength.test.ts +++ b/packages/effect/test/Schema/Schema/String/maxLength.test.ts @@ -1,7 +1,7 @@ -import * as P from "@effect/schema/ParseResult" -import * as Pretty from "@effect/schema/Pretty" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as P from "effect/ParseResult" +import * as Pretty from "effect/Pretty" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("maxLength", () => { diff --git a/packages/schema/test/Schema/String/minLength.test.ts b/packages/effect/test/Schema/Schema/String/minLength.test.ts similarity index 81% rename from packages/schema/test/Schema/String/minLength.test.ts rename to packages/effect/test/Schema/Schema/String/minLength.test.ts index 73e5cd0361..3556a17dc9 100644 --- a/packages/schema/test/Schema/String/minLength.test.ts +++ b/packages/effect/test/Schema/Schema/String/minLength.test.ts @@ -1,7 +1,7 @@ -import * as P from "@effect/schema/ParseResult" -import * as Pretty from "@effect/schema/Pretty" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as P from "effect/ParseResult" +import * as Pretty from "effect/Pretty" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("minLength", () => { diff --git a/packages/schema/test/Schema/String/nonEmptyString.test.ts b/packages/effect/test/Schema/Schema/String/nonEmptyString.test.ts similarity index 87% rename from packages/schema/test/Schema/String/nonEmptyString.test.ts rename to packages/effect/test/Schema/Schema/String/nonEmptyString.test.ts index 7f371acc4b..da56c33225 100644 --- a/packages/schema/test/Schema/String/nonEmptyString.test.ts +++ b/packages/effect/test/Schema/Schema/String/nonEmptyString.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("nonEmptyString", () => { diff --git a/packages/schema/test/Schema/String/pattern.test.ts b/packages/effect/test/Schema/Schema/String/pattern.test.ts similarity index 92% rename from packages/schema/test/Schema/String/pattern.test.ts rename to packages/effect/test/Schema/Schema/String/pattern.test.ts index 3d1992aa14..46c0c1fbe3 100644 --- a/packages/schema/test/Schema/String/pattern.test.ts +++ b/packages/effect/test/Schema/Schema/String/pattern.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("pattern", () => { diff --git a/packages/schema/test/Schema/String/split.test.ts b/packages/effect/test/Schema/Schema/String/split.test.ts similarity index 91% rename from packages/schema/test/Schema/String/split.test.ts rename to packages/effect/test/Schema/Schema/String/split.test.ts index f1c986474a..a514b780b1 100644 --- a/packages/schema/test/Schema/String/split.test.ts +++ b/packages/effect/test/Schema/Schema/String/split.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("string/split", () => { diff --git a/packages/schema/test/Schema/String/startsWith.test.ts b/packages/effect/test/Schema/Schema/String/startsWith.test.ts similarity index 86% rename from packages/schema/test/Schema/String/startsWith.test.ts rename to packages/effect/test/Schema/Schema/String/startsWith.test.ts index 51a8681b94..79bb934e76 100644 --- a/packages/schema/test/Schema/String/startsWith.test.ts +++ b/packages/effect/test/Schema/Schema/String/startsWith.test.ts @@ -1,6 +1,6 @@ -import * as P from "@effect/schema/ParseResult" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as P from "effect/ParseResult" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("startsWith", () => { diff --git a/packages/schema/test/Schema/String/trim.test.ts b/packages/effect/test/Schema/Schema/String/trim.test.ts similarity index 96% rename from packages/schema/test/Schema/String/trim.test.ts rename to packages/effect/test/Schema/Schema/String/trim.test.ts index d7dbf8b4a6..fd9a1ea993 100644 --- a/packages/schema/test/Schema/String/trim.test.ts +++ b/packages/effect/test/Schema/Schema/String/trim.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("trim", () => { diff --git a/packages/schema/test/Schema/String/uncapitalize.test.ts b/packages/effect/test/Schema/Schema/String/uncapitalize.test.ts similarity index 90% rename from packages/schema/test/Schema/String/uncapitalize.test.ts rename to packages/effect/test/Schema/Schema/String/uncapitalize.test.ts index c8ff2a888b..5b908966bd 100644 --- a/packages/schema/test/Schema/String/uncapitalize.test.ts +++ b/packages/effect/test/Schema/Schema/String/uncapitalize.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("Uncapitalize", () => { diff --git a/packages/schema/test/Schema/String/uppercase.test.ts b/packages/effect/test/Schema/Schema/String/uppercase.test.ts similarity index 89% rename from packages/schema/test/Schema/String/uppercase.test.ts rename to packages/effect/test/Schema/Schema/String/uppercase.test.ts index 8d821d6d3e..0141859433 100644 --- a/packages/schema/test/Schema/String/uppercase.test.ts +++ b/packages/effect/test/Schema/Schema/String/uppercase.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("Uppercase", () => { diff --git a/packages/schema/test/Schema/Struct/Struct.test.ts b/packages/effect/test/Schema/Schema/Struct/Struct.test.ts similarity index 97% rename from packages/schema/test/Schema/Struct/Struct.test.ts rename to packages/effect/test/Schema/Schema/Struct/Struct.test.ts index ee63597192..6b3385db50 100644 --- a/packages/schema/test/Schema/Struct/Struct.test.ts +++ b/packages/effect/test/Schema/Schema/Struct/Struct.test.ts @@ -1,6 +1,6 @@ -import * as AST from "@effect/schema/AST" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as AST from "effect/SchemaAST" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("Struct", () => { @@ -199,7 +199,7 @@ describe("Struct", () => { }) it.skip("should preserve the order of properties (sync)", () => { - const b = Symbol.for("@effect/schema/test/b") + const b = Symbol.for("effect/Schema/test/b") const schema = S.Struct({ a: S.Literal("a"), [b]: S.Array(S.String), @@ -286,7 +286,7 @@ describe("Struct", () => { }) it("should handle symbols as keys", async () => { - const a = Symbol.for("@effect/schema/test/a") + const a = Symbol.for("effect/Schema/test/a") const schema = S.Struct({ [a]: S.String }) await Util.expectEncodeSuccess(schema, { [a]: "a" }, { [a]: "a" }) }) diff --git a/packages/schema/test/Schema/Struct/make.test.ts b/packages/effect/test/Schema/Schema/Struct/make.test.ts similarity index 97% rename from packages/schema/test/Schema/Struct/make.test.ts rename to packages/effect/test/Schema/Schema/Struct/make.test.ts index 3def2e308e..3a29f12c10 100644 --- a/packages/schema/test/Schema/Struct/make.test.ts +++ b/packages/effect/test/Schema/Schema/Struct/make.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("make", () => { diff --git a/packages/schema/test/Schema/Struct/omit.test.ts b/packages/effect/test/Schema/Schema/Struct/omit.test.ts similarity index 85% rename from packages/schema/test/Schema/Struct/omit.test.ts rename to packages/effect/test/Schema/Schema/Struct/omit.test.ts index b054f83b36..3a24e19154 100644 --- a/packages/schema/test/Schema/Struct/omit.test.ts +++ b/packages/effect/test/Schema/Schema/Struct/omit.test.ts @@ -1,4 +1,4 @@ -import * as S from "@effect/schema/Schema" +import * as S from "effect/Schema" import { describe, expect, it } from "vitest" describe("omit", () => { diff --git a/packages/schema/test/Schema/Struct/pick.test.ts b/packages/effect/test/Schema/Schema/Struct/pick.test.ts similarity index 86% rename from packages/schema/test/Schema/Struct/pick.test.ts rename to packages/effect/test/Schema/Schema/Struct/pick.test.ts index 9860fedb39..2dbd2c0f1e 100644 --- a/packages/schema/test/Schema/Struct/pick.test.ts +++ b/packages/effect/test/Schema/Schema/Struct/pick.test.ts @@ -1,4 +1,4 @@ -import * as S from "@effect/schema/Schema" +import * as S from "effect/Schema" import { describe, expect, it } from "vitest" describe("pick", () => { diff --git a/packages/schema/test/Schema/Symbol/Symbol.test.ts b/packages/effect/test/Schema/Schema/Symbol/Symbol.test.ts similarity index 88% rename from packages/schema/test/Schema/Symbol/Symbol.test.ts rename to packages/effect/test/Schema/Schema/Symbol/Symbol.test.ts index 81742e8f33..e93233335c 100644 --- a/packages/schema/test/Schema/Symbol/Symbol.test.ts +++ b/packages/effect/test/Schema/Schema/Symbol/Symbol.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("Symbol", () => { diff --git a/packages/schema/test/Schema/Symbol/SymbolFromSelf.test.ts b/packages/effect/test/Schema/Schema/Symbol/SymbolFromSelf.test.ts similarity index 66% rename from packages/schema/test/Schema/Symbol/SymbolFromSelf.test.ts rename to packages/effect/test/Schema/Schema/Symbol/SymbolFromSelf.test.ts index 51f0dd5f72..2ffd94d361 100644 --- a/packages/schema/test/Schema/Symbol/SymbolFromSelf.test.ts +++ b/packages/effect/test/Schema/Schema/Symbol/SymbolFromSelf.test.ts @@ -1,11 +1,11 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("SymbolFromSelf", () => { const schema = S.SymbolFromSelf it("decoding", async () => { - const a = Symbol.for("@effect/schema/test/a") + const a = Symbol.for("effect/Schema/test/a") await Util.expectDecodeUnknownSuccess(schema, a) await Util.expectDecodeUnknownFailure( schema, @@ -15,7 +15,7 @@ describe("SymbolFromSelf", () => { }) it("encoding", async () => { - const a = Symbol.for("@effect/schema/test/a") + const a = Symbol.for("effect/Schema/test/a") await Util.expectEncodeSuccess(schema, a, a) }) }) diff --git a/packages/schema/test/Schema/TaggedStruct/make.test.ts b/packages/effect/test/Schema/Schema/TaggedStruct/make.test.ts similarity index 89% rename from packages/schema/test/Schema/TaggedStruct/make.test.ts rename to packages/effect/test/Schema/Schema/TaggedStruct/make.test.ts index 5ffe5f07b6..4889c13451 100644 --- a/packages/schema/test/Schema/TaggedStruct/make.test.ts +++ b/packages/effect/test/Schema/Schema/TaggedStruct/make.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("make", () => { diff --git a/packages/schema/test/Schema/TemplateLiteral/TemplateLiteral.test.ts b/packages/effect/test/Schema/Schema/TemplateLiteral/TemplateLiteral.test.ts similarity index 98% rename from packages/schema/test/Schema/TemplateLiteral/TemplateLiteral.test.ts rename to packages/effect/test/Schema/Schema/TemplateLiteral/TemplateLiteral.test.ts index f0151f3e08..8c9b0ec77f 100644 --- a/packages/schema/test/Schema/TemplateLiteral/TemplateLiteral.test.ts +++ b/packages/effect/test/Schema/Schema/TemplateLiteral/TemplateLiteral.test.ts @@ -1,6 +1,6 @@ -import * as AST from "@effect/schema/AST" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as AST from "effect/SchemaAST" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("TemplateLiteral", () => { diff --git a/packages/schema/test/Schema/TemplateLiteralParser.test.ts b/packages/effect/test/Schema/Schema/TemplateLiteralParser.test.ts similarity index 97% rename from packages/schema/test/Schema/TemplateLiteralParser.test.ts rename to packages/effect/test/Schema/Schema/TemplateLiteralParser.test.ts index fdb8a682bc..876369b776 100644 --- a/packages/schema/test/Schema/TemplateLiteralParser.test.ts +++ b/packages/effect/test/Schema/Schema/TemplateLiteralParser.test.ts @@ -1,5 +1,5 @@ -import * as Schema from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as Schema from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("TemplateLiteralParser", () => { diff --git a/packages/schema/test/Schema/Trimmed/Trimmed.test.ts b/packages/effect/test/Schema/Schema/Trimmed/Trimmed.test.ts similarity index 92% rename from packages/schema/test/Schema/Trimmed/Trimmed.test.ts rename to packages/effect/test/Schema/Schema/Trimmed/Trimmed.test.ts index f9c1b9fd0c..9420ce7b83 100644 --- a/packages/schema/test/Schema/Trimmed/Trimmed.test.ts +++ b/packages/effect/test/Schema/Schema/Trimmed/Trimmed.test.ts @@ -1,9 +1,9 @@ -import * as AST from "@effect/schema/AST" -import * as P from "@effect/schema/ParseResult" -import * as Pretty from "@effect/schema/Pretty" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import { Option, Predicate } from "effect" +import * as P from "effect/ParseResult" +import * as Pretty from "effect/Pretty" +import * as S from "effect/Schema" +import * as AST from "effect/SchemaAST" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("Trimmed", () => { diff --git a/packages/schema/test/Schema/Tuple/Tuple.test.ts b/packages/effect/test/Schema/Schema/Tuple/Tuple.test.ts similarity index 99% rename from packages/schema/test/Schema/Tuple/Tuple.test.ts rename to packages/effect/test/Schema/Schema/Tuple/Tuple.test.ts index 2ca3e04802..b099a6332f 100644 --- a/packages/schema/test/Schema/Tuple/Tuple.test.ts +++ b/packages/effect/test/Schema/Schema/Tuple/Tuple.test.ts @@ -1,6 +1,6 @@ -import * as AST from "@effect/schema/AST" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as AST from "effect/SchemaAST" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("Tuple", () => { diff --git a/packages/schema/test/Schema/ULID.test.ts b/packages/effect/test/Schema/Schema/ULID.test.ts similarity index 81% rename from packages/schema/test/Schema/ULID.test.ts rename to packages/effect/test/Schema/Schema/ULID.test.ts index 79fadc91a5..d2d64bac3f 100644 --- a/packages/schema/test/Schema/ULID.test.ts +++ b/packages/effect/test/Schema/Schema/ULID.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("ULID", () => { diff --git a/packages/schema/test/Schema/UUID.test.ts b/packages/effect/test/Schema/Schema/UUID.test.ts similarity index 82% rename from packages/schema/test/Schema/UUID.test.ts rename to packages/effect/test/Schema/Schema/UUID.test.ts index 6cf41c7bf0..78356992fc 100644 --- a/packages/schema/test/Schema/UUID.test.ts +++ b/packages/effect/test/Schema/Schema/UUID.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("string/UUID", () => { diff --git a/packages/schema/test/Schema/Uint8Array/Uint8Array.test.ts b/packages/effect/test/Schema/Schema/Uint8Array/Uint8Array.test.ts similarity index 90% rename from packages/schema/test/Schema/Uint8Array/Uint8Array.test.ts rename to packages/effect/test/Schema/Schema/Uint8Array/Uint8Array.test.ts index c4130d8537..da162d0d77 100644 --- a/packages/schema/test/Schema/Uint8Array/Uint8Array.test.ts +++ b/packages/effect/test/Schema/Schema/Uint8Array/Uint8Array.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("Uint8Array > Uint8Array", () => { diff --git a/packages/schema/test/Schema/Uint8Array/Uint8ArrayFromBase64.test.ts b/packages/effect/test/Schema/Schema/Uint8Array/Uint8ArrayFromBase64.test.ts similarity index 91% rename from packages/schema/test/Schema/Uint8Array/Uint8ArrayFromBase64.test.ts rename to packages/effect/test/Schema/Schema/Uint8Array/Uint8ArrayFromBase64.test.ts index a6eb8e04ef..92acdd31f4 100644 --- a/packages/schema/test/Schema/Uint8Array/Uint8ArrayFromBase64.test.ts +++ b/packages/effect/test/Schema/Schema/Uint8Array/Uint8ArrayFromBase64.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("Uint8ArrayFromBase64", () => { diff --git a/packages/schema/test/Schema/Uint8Array/Uint8ArrayFromBase64Url.test.ts b/packages/effect/test/Schema/Schema/Uint8Array/Uint8ArrayFromBase64Url.test.ts similarity index 92% rename from packages/schema/test/Schema/Uint8Array/Uint8ArrayFromBase64Url.test.ts rename to packages/effect/test/Schema/Schema/Uint8Array/Uint8ArrayFromBase64Url.test.ts index 998a8aa787..6f12f7a7db 100644 --- a/packages/schema/test/Schema/Uint8Array/Uint8ArrayFromBase64Url.test.ts +++ b/packages/effect/test/Schema/Schema/Uint8Array/Uint8ArrayFromBase64Url.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("Uint8ArrayFromBase64Url", () => { diff --git a/packages/schema/test/Schema/Uint8Array/Uint8ArrayFromHex.test.ts b/packages/effect/test/Schema/Schema/Uint8Array/Uint8ArrayFromHex.test.ts similarity index 93% rename from packages/schema/test/Schema/Uint8Array/Uint8ArrayFromHex.test.ts rename to packages/effect/test/Schema/Schema/Uint8Array/Uint8ArrayFromHex.test.ts index bebd38cfe0..dd46959fbf 100644 --- a/packages/schema/test/Schema/Uint8Array/Uint8ArrayFromHex.test.ts +++ b/packages/effect/test/Schema/Schema/Uint8Array/Uint8ArrayFromHex.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("Uint8ArrayFromHex", () => { diff --git a/packages/schema/test/Schema/Uint8Array/Uint8ArrayFromSelf.test.ts b/packages/effect/test/Schema/Schema/Uint8Array/Uint8ArrayFromSelf.test.ts similarity index 84% rename from packages/schema/test/Schema/Uint8Array/Uint8ArrayFromSelf.test.ts rename to packages/effect/test/Schema/Schema/Uint8Array/Uint8ArrayFromSelf.test.ts index 32c1ec1d0a..e7b3511115 100644 --- a/packages/schema/test/Schema/Uint8Array/Uint8ArrayFromSelf.test.ts +++ b/packages/effect/test/Schema/Schema/Uint8Array/Uint8ArrayFromSelf.test.ts @@ -1,6 +1,6 @@ -import * as Pretty from "@effect/schema/Pretty" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as Pretty from "effect/Pretty" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("Uint8Array > Uint8ArrayFromSelf", () => { diff --git a/packages/schema/test/Schema/Union/Union.test.ts b/packages/effect/test/Schema/Schema/Union/Union.test.ts similarity index 98% rename from packages/schema/test/Schema/Union/Union.test.ts rename to packages/effect/test/Schema/Schema/Union/Union.test.ts index 525279b316..dd77590ee4 100644 --- a/packages/schema/test/Schema/Union/Union.test.ts +++ b/packages/effect/test/Schema/Schema/Union/Union.test.ts @@ -1,6 +1,6 @@ -import * as AST from "@effect/schema/AST" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as AST from "effect/SchemaAST" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("Union", () => { diff --git a/packages/effect/test/Schema/Schema/UniqueSymbol/UniqueSymbolFromSelf.test.ts b/packages/effect/test/Schema/Schema/UniqueSymbol/UniqueSymbolFromSelf.test.ts new file mode 100644 index 0000000000..eb98685b4a --- /dev/null +++ b/packages/effect/test/Schema/Schema/UniqueSymbol/UniqueSymbolFromSelf.test.ts @@ -0,0 +1,17 @@ +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" +import { describe, it } from "vitest" + +describe("UniqueSymbolFromSelf", () => { + const a = Symbol.for("effect/Schema/test/a") + const schema = S.UniqueSymbolFromSelf(a) + it("decoding", async () => { + await Util.expectDecodeUnknownSuccess(schema, a) + await Util.expectDecodeUnknownSuccess(schema, Symbol.for("effect/Schema/test/a")) + await Util.expectDecodeUnknownFailure( + schema, + "Symbol(effect/Schema/test/a)", + `Expected Symbol(effect/Schema/test/a), actual "Symbol(effect/Schema/test/a)"` + ) + }) +}) diff --git a/packages/schema/test/Schema/Unknown/Unknown.test.ts b/packages/effect/test/Schema/Schema/Unknown/Unknown.test.ts similarity index 84% rename from packages/schema/test/Schema/Unknown/Unknown.test.ts rename to packages/effect/test/Schema/Schema/Unknown/Unknown.test.ts index d50ff8f052..9646355fb3 100644 --- a/packages/schema/test/Schema/Unknown/Unknown.test.ts +++ b/packages/effect/test/Schema/Schema/Unknown/Unknown.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("Unknown", () => { diff --git a/packages/schema/test/Schema/Void/Void.test.ts b/packages/effect/test/Schema/Schema/Void/Void.test.ts similarity index 85% rename from packages/schema/test/Schema/Void/Void.test.ts rename to packages/effect/test/Schema/Schema/Void/Void.test.ts index a253307a14..737873e5df 100644 --- a/packages/schema/test/Schema/Void/Void.test.ts +++ b/packages/effect/test/Schema/Schema/Void/Void.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("Void", () => { diff --git a/packages/schema/test/Schema/annotations.test.ts b/packages/effect/test/Schema/Schema/annotations.test.ts similarity index 89% rename from packages/schema/test/Schema/annotations.test.ts rename to packages/effect/test/Schema/Schema/annotations.test.ts index 18f0707246..29de6d2d77 100644 --- a/packages/schema/test/Schema/annotations.test.ts +++ b/packages/effect/test/Schema/Schema/annotations.test.ts @@ -1,8 +1,8 @@ -import * as AST from "@effect/schema/AST" -import type * as ParseResult from "@effect/schema/ParseResult" -import * as Pretty from "@effect/schema/Pretty" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import type * as ParseResult from "effect/ParseResult" +import * as Pretty from "effect/Pretty" +import * as S from "effect/Schema" +import * as AST from "effect/SchemaAST" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe(".annotations()", () => { @@ -142,3 +142,16 @@ describe(".annotations()", () => { expect(Pretty.make(AFromSelf)(new A("value"))).toEqual(`new A("value")`) }) }) + +declare module "effect/Schema" { + namespace Annotations { + interface Schema extends Doc { + formName?: string + } + } +} + +it("should support custom annotations", () => { + const schema = S.String.annotations({ formName: "a" }) + expect(schema.ast.annotations["formName"]).toEqual("a") +}) diff --git a/packages/schema/test/Schema/asserts.test.ts b/packages/effect/test/Schema/Schema/asserts.test.ts similarity index 93% rename from packages/schema/test/Schema/asserts.test.ts rename to packages/effect/test/Schema/Schema/asserts.test.ts index 58ad48c9ad..800f109d96 100644 --- a/packages/schema/test/Schema/asserts.test.ts +++ b/packages/effect/test/Schema/Schema/asserts.test.ts @@ -1,6 +1,6 @@ -import * as ParseResult from "@effect/schema/ParseResult" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as ParseResult from "effect/ParseResult" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("asserts", () => { diff --git a/packages/schema/test/Schema/attachPropertySignature.test.ts b/packages/effect/test/Schema/Schema/attachPropertySignature.test.ts similarity index 91% rename from packages/schema/test/Schema/attachPropertySignature.test.ts rename to packages/effect/test/Schema/Schema/attachPropertySignature.test.ts index e5dc888741..c821d47408 100644 --- a/packages/schema/test/Schema/attachPropertySignature.test.ts +++ b/packages/effect/test/Schema/Schema/attachPropertySignature.test.ts @@ -1,6 +1,6 @@ -import * as ParseResult from "@effect/schema/ParseResult" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as ParseResult from "effect/ParseResult" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("attachPropertySignature", () => { @@ -21,7 +21,7 @@ describe("attachPropertySignature", () => { it("symbol keys literal values", async () => { const Circle = S.Struct({ radius: S.Number }) const Square = S.Struct({ sideLength: S.Number }) - const kind = Symbol.for("@effect/schema/test/kind") + const kind = Symbol.for("effect/Schema/test/kind") const schema = S.Union( Circle.pipe(S.attachPropertySignature(kind, "circle")), Square.pipe(S.attachPropertySignature(kind, "square")) @@ -36,9 +36,9 @@ describe("attachPropertySignature", () => { it("string keys unique symbols", async () => { const Circle = S.Struct({ radius: S.Number }) const Square = S.Struct({ sideLength: S.Number }) - const kind = Symbol.for("@effect/schema/test/kind") - const circle = Symbol.for("@effect/schema/test/circle") - const square = Symbol.for("@effect/schema/test/square") + const kind = Symbol.for("effect/Schema/test/kind") + const circle = Symbol.for("effect/Schema/test/circle") + const square = Symbol.for("effect/Schema/test/square") const schema = S.Union( Circle.pipe(S.attachPropertySignature(kind, circle)), Square.pipe(S.attachPropertySignature(kind, square)) @@ -53,8 +53,8 @@ describe("attachPropertySignature", () => { it("symbol keys unique symbols", async () => { const Circle = S.Struct({ radius: S.Number }) const Square = S.Struct({ sideLength: S.Number }) - const circle = Symbol.for("@effect/schema/test/circle") - const square = Symbol.for("@effect/schema/test/square") + const circle = Symbol.for("effect/Schema/test/circle") + const square = Symbol.for("effect/Schema/test/square") const schema = S.Union( Circle.pipe(S.attachPropertySignature("kind", circle)), Square.pipe(S.attachPropertySignature("kind", square)) diff --git a/packages/schema/test/Schema/brand.test.ts b/packages/effect/test/Schema/Schema/brand.test.ts similarity index 94% rename from packages/schema/test/Schema/brand.test.ts rename to packages/effect/test/Schema/Schema/brand.test.ts index 6232b08caa..541fabeee8 100644 --- a/packages/schema/test/Schema/brand.test.ts +++ b/packages/effect/test/Schema/Schema/brand.test.ts @@ -1,6 +1,6 @@ -import * as AST from "@effect/schema/AST" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as AST from "effect/SchemaAST" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("brand", () => { @@ -61,7 +61,7 @@ describe("brand", () => { ) expect(schema.ast.annotations).toEqual({ - [AST.TypeAnnotationId]: S.IntTypeId, + [AST.SchemaIdAnnotationId]: S.IntSchemaId, [AST.BrandAnnotationId]: ["A"], [AST.TitleAnnotationId]: `integer & Brand<"A">`, [AST.DescriptionAnnotationId]: "an A brand", @@ -79,7 +79,7 @@ describe("brand", () => { ) expect(schema.ast.annotations).toEqual({ - [AST.TypeAnnotationId]: S.IntTypeId, + [AST.SchemaIdAnnotationId]: S.IntSchemaId, [AST.BrandAnnotationId]: ["A", "B"], [AST.TitleAnnotationId]: `integer & Brand<"A"> & Brand<"B">`, [AST.DescriptionAnnotationId]: "a B brand", @@ -98,7 +98,7 @@ describe("brand", () => { }) ) expect(schema.ast.annotations).toEqual({ - [AST.TypeAnnotationId]: S.IntTypeId, + [AST.SchemaIdAnnotationId]: S.IntSchemaId, [AST.BrandAnnotationId]: [A, B], [AST.TitleAnnotationId]: "integer & Brand & Brand", [AST.DescriptionAnnotationId]: "a B brand", diff --git a/packages/schema/test/Schema/compose.test.ts b/packages/effect/test/Schema/Schema/compose.test.ts similarity index 96% rename from packages/schema/test/Schema/compose.test.ts rename to packages/effect/test/Schema/Schema/compose.test.ts index bf4dc62ead..624dea76ed 100644 --- a/packages/schema/test/Schema/compose.test.ts +++ b/packages/effect/test/Schema/Schema/compose.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("compose", async () => { diff --git a/packages/schema/test/Schema/decode.test.ts b/packages/effect/test/Schema/Schema/decode.test.ts similarity index 92% rename from packages/schema/test/Schema/decode.test.ts rename to packages/effect/test/Schema/Schema/decode.test.ts index 7400cc9cbc..5b59b16e66 100644 --- a/packages/schema/test/Schema/decode.test.ts +++ b/packages/effect/test/Schema/Schema/decode.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("decode", () => { diff --git a/packages/schema/test/Schema/decodeEither.test.ts b/packages/effect/test/Schema/Schema/decodeEither.test.ts similarity index 93% rename from packages/schema/test/Schema/decodeEither.test.ts rename to packages/effect/test/Schema/Schema/decodeEither.test.ts index 17266c10ba..f80284f2f7 100644 --- a/packages/schema/test/Schema/decodeEither.test.ts +++ b/packages/effect/test/Schema/Schema/decodeEither.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("decodeEither", () => { diff --git a/packages/schema/test/Schema/decodeOption.test.ts b/packages/effect/test/Schema/Schema/decodeOption.test.ts similarity index 89% rename from packages/schema/test/Schema/decodeOption.test.ts rename to packages/effect/test/Schema/Schema/decodeOption.test.ts index 7779795799..b6331f2900 100644 --- a/packages/schema/test/Schema/decodeOption.test.ts +++ b/packages/effect/test/Schema/Schema/decodeOption.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("decodeOption", () => { diff --git a/packages/schema/test/Schema/decodePromise.test.ts b/packages/effect/test/Schema/Schema/decodePromise.test.ts similarity index 92% rename from packages/schema/test/Schema/decodePromise.test.ts rename to packages/effect/test/Schema/Schema/decodePromise.test.ts index 1558d3b579..e10727d76b 100644 --- a/packages/schema/test/Schema/decodePromise.test.ts +++ b/packages/effect/test/Schema/Schema/decodePromise.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("decodePromise", () => { diff --git a/packages/schema/test/Schema/decodeSync.test.ts b/packages/effect/test/Schema/Schema/decodeSync.test.ts similarity index 93% rename from packages/schema/test/Schema/decodeSync.test.ts rename to packages/effect/test/Schema/Schema/decodeSync.test.ts index 8440bc5f28..996966761f 100644 --- a/packages/schema/test/Schema/decodeSync.test.ts +++ b/packages/effect/test/Schema/Schema/decodeSync.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("decodeSync", () => { diff --git a/packages/schema/test/Schema/decodeUnknownEither.test.ts b/packages/effect/test/Schema/Schema/decodeUnknownEither.test.ts similarity index 78% rename from packages/schema/test/Schema/decodeUnknownEither.test.ts rename to packages/effect/test/Schema/Schema/decodeUnknownEither.test.ts index ecc07f6f05..2529cde6db 100644 --- a/packages/schema/test/Schema/decodeUnknownEither.test.ts +++ b/packages/effect/test/Schema/Schema/decodeUnknownEither.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("decodeUnknownEither", () => { diff --git a/packages/schema/test/Schema/decodeUnknownOption.test.ts b/packages/effect/test/Schema/Schema/decodeUnknownOption.test.ts similarity index 67% rename from packages/schema/test/Schema/decodeUnknownOption.test.ts rename to packages/effect/test/Schema/Schema/decodeUnknownOption.test.ts index 1f801c9efb..777d94406a 100644 --- a/packages/schema/test/Schema/decodeUnknownOption.test.ts +++ b/packages/effect/test/Schema/Schema/decodeUnknownOption.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("decodeUnknownOption", () => { diff --git a/packages/schema/test/Schema/decodeUnknownSync.test.ts b/packages/effect/test/Schema/Schema/decodeUnknownSync.test.ts similarity index 84% rename from packages/schema/test/Schema/decodeUnknownSync.test.ts rename to packages/effect/test/Schema/Schema/decodeUnknownSync.test.ts index 6f84d3823b..a0968fc0a0 100644 --- a/packages/schema/test/Schema/decodeUnknownSync.test.ts +++ b/packages/effect/test/Schema/Schema/decodeUnknownSync.test.ts @@ -1,6 +1,6 @@ -import * as ParseResult from "@effect/schema/ParseResult" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as ParseResult from "effect/ParseResult" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("decodeUnknownSync", () => { diff --git a/packages/schema/test/Schema/encode.test.ts b/packages/effect/test/Schema/Schema/encode.test.ts similarity index 92% rename from packages/schema/test/Schema/encode.test.ts rename to packages/effect/test/Schema/Schema/encode.test.ts index c70198b09f..63a90342f0 100644 --- a/packages/schema/test/Schema/encode.test.ts +++ b/packages/effect/test/Schema/Schema/encode.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("encode", () => { diff --git a/packages/schema/test/Schema/encodeEither.test.ts b/packages/effect/test/Schema/Schema/encodeEither.test.ts similarity index 93% rename from packages/schema/test/Schema/encodeEither.test.ts rename to packages/effect/test/Schema/Schema/encodeEither.test.ts index bbdfcd0629..eed8a87efa 100644 --- a/packages/schema/test/Schema/encodeEither.test.ts +++ b/packages/effect/test/Schema/Schema/encodeEither.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("encodeEither", () => { diff --git a/packages/schema/test/Schema/encodeOption.test.ts b/packages/effect/test/Schema/Schema/encodeOption.test.ts similarity index 89% rename from packages/schema/test/Schema/encodeOption.test.ts rename to packages/effect/test/Schema/Schema/encodeOption.test.ts index 19784ac864..98e9b69063 100644 --- a/packages/schema/test/Schema/encodeOption.test.ts +++ b/packages/effect/test/Schema/Schema/encodeOption.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("encodeOption", () => { diff --git a/packages/schema/test/Schema/encodePromise.test.ts b/packages/effect/test/Schema/Schema/encodePromise.test.ts similarity index 92% rename from packages/schema/test/Schema/encodePromise.test.ts rename to packages/effect/test/Schema/Schema/encodePromise.test.ts index d15ed38466..39bc804074 100644 --- a/packages/schema/test/Schema/encodePromise.test.ts +++ b/packages/effect/test/Schema/Schema/encodePromise.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("encodePromise", () => { diff --git a/packages/schema/test/Schema/encodeSync.test.ts b/packages/effect/test/Schema/Schema/encodeSync.test.ts similarity index 93% rename from packages/schema/test/Schema/encodeSync.test.ts rename to packages/effect/test/Schema/Schema/encodeSync.test.ts index 6466dafc76..b40c25e80b 100644 --- a/packages/schema/test/Schema/encodeSync.test.ts +++ b/packages/effect/test/Schema/Schema/encodeSync.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("encodeSync", () => { diff --git a/packages/schema/test/Schema/encodeUnknownEither.test.ts b/packages/effect/test/Schema/Schema/encodeUnknownEither.test.ts similarity index 78% rename from packages/schema/test/Schema/encodeUnknownEither.test.ts rename to packages/effect/test/Schema/Schema/encodeUnknownEither.test.ts index 50e9d7633e..0fecdd901c 100644 --- a/packages/schema/test/Schema/encodeUnknownEither.test.ts +++ b/packages/effect/test/Schema/Schema/encodeUnknownEither.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("encodeUnknownEither", () => { diff --git a/packages/schema/test/Schema/encodeUnknownOption.test.ts b/packages/effect/test/Schema/Schema/encodeUnknownOption.test.ts similarity index 67% rename from packages/schema/test/Schema/encodeUnknownOption.test.ts rename to packages/effect/test/Schema/Schema/encodeUnknownOption.test.ts index f2acc345de..0017712d7f 100644 --- a/packages/schema/test/Schema/encodeUnknownOption.test.ts +++ b/packages/effect/test/Schema/Schema/encodeUnknownOption.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("encodeUnknownOption", () => { diff --git a/packages/schema/test/Schema/encodeUnknownSync.test.ts b/packages/effect/test/Schema/Schema/encodeUnknownSync.test.ts similarity index 79% rename from packages/schema/test/Schema/encodeUnknownSync.test.ts rename to packages/effect/test/Schema/Schema/encodeUnknownSync.test.ts index 0f6fe49054..95d39f3106 100644 --- a/packages/schema/test/Schema/encodeUnknownSync.test.ts +++ b/packages/effect/test/Schema/Schema/encodeUnknownSync.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("encodeUnknownSync", () => { diff --git a/packages/schema/test/Schema/encodedBoundSchema.test.ts b/packages/effect/test/Schema/Schema/encodedBoundSchema.test.ts similarity index 97% rename from packages/schema/test/Schema/encodedBoundSchema.test.ts rename to packages/effect/test/Schema/Schema/encodedBoundSchema.test.ts index 6a19529b55..cddfa1a9ba 100644 --- a/packages/schema/test/Schema/encodedBoundSchema.test.ts +++ b/packages/effect/test/Schema/Schema/encodedBoundSchema.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("encodedBoundSchema", () => { diff --git a/packages/schema/test/Schema/encodedSchema.test.ts b/packages/effect/test/Schema/Schema/encodedSchema.test.ts similarity index 92% rename from packages/schema/test/Schema/encodedSchema.test.ts rename to packages/effect/test/Schema/Schema/encodedSchema.test.ts index 82fe267362..d88325ce35 100644 --- a/packages/schema/test/Schema/encodedSchema.test.ts +++ b/packages/effect/test/Schema/Schema/encodedSchema.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("encodedSchema", () => { diff --git a/packages/schema/test/Equivalence.test.ts b/packages/effect/test/Schema/Schema/equivalence.test.ts similarity index 89% rename from packages/schema/test/Equivalence.test.ts rename to packages/effect/test/Schema/Schema/equivalence.test.ts index a074e6125b..af314bae85 100644 --- a/packages/schema/test/Equivalence.test.ts +++ b/packages/effect/test/Schema/Schema/equivalence.test.ts @@ -1,6 +1,4 @@ -import * as A from "@effect/schema/Arbitrary" -import * as E from "@effect/schema/Equivalence" -import * as S from "@effect/schema/Schema" +import * as A from "effect/Arbitrary" import * as Chunk from "effect/Chunk" import * as Data from "effect/Data" import * as Either from "effect/Either" @@ -9,6 +7,7 @@ import * as Equivalence from "effect/Equivalence" import * as Hash from "effect/Hash" import * as Option from "effect/Option" import { isUnknown } from "effect/Predicate" +import * as S from "effect/Schema" import * as fc from "fast-check" import { describe, expect, it } from "vitest" @@ -21,7 +20,7 @@ export const propertyType = ( ) => { const arb = A.makeLazy(schema)(fc) // console.log(fc.sample(arb, 10)) - const equivalence = E.make(schema) + const equivalence = S.equivalence(schema) const reflexivity = fc.property(arb, (a) => equivalence(a, a)) const symmetry = fc.property(arb, arb, (a, b) => equivalence(a, b) === equivalence(b, a)) @@ -71,15 +70,15 @@ const MySymbol = S.SymbolFromSelf.annotations({ } }) -describe("Equivalence", () => { +describe("SchemaEquivalence", () => { it("the errors should disply a path", () => { - expect(() => E.make(S.Tuple(S.Never as any))).toThrow( + expect(() => S.equivalence(S.Tuple(S.Never as any))).toThrow( new Error(`Unsupported schema at path: [0] details: Cannot build an Equivalence schema (NeverKeyword): never`) ) - expect(() => E.make(S.Struct({ a: S.Never as any }))).toThrow( + expect(() => S.equivalence(S.Struct({ a: S.Never as any }))).toThrow( new Error(`Unsupported schema at path: ["a"] details: Cannot build an Equivalence @@ -89,16 +88,16 @@ schema (NeverKeyword): never`) it("transformation", () => { const schema = S.NumberFromString - const equivalence = E.make(schema) + const equivalence = S.equivalence(schema) expect(equivalence(1, 1)).toBe(true) expect(equivalence(1, 2)).toBe(false) }) - it("E.make(S.encodedSchema(schema))", () => { + it("S.equivalence(S.encodedSchema(schema))", () => { const schema = S.NumberFromString - const equivalence = E.make(S.encodedSchema(schema)) + const equivalence = S.equivalence(S.encodedSchema(schema)) expect(equivalence("a", "a")).toBe(true) @@ -106,7 +105,7 @@ schema (NeverKeyword): never`) }) it("never", () => { - expect(() => E.make(S.Never)).toThrow( + expect(() => S.equivalence(S.Never)).toThrow( new Error(`Unsupported schema details: Cannot build an Equivalence schema (NeverKeyword): never`) @@ -115,7 +114,7 @@ schema (NeverKeyword): never`) it("string", () => { const schema = MyString - const equivalence = E.make(schema) + const equivalence = S.equivalence(schema) expect(equivalence("a", "a")).toBe(true) @@ -126,7 +125,7 @@ schema (NeverKeyword): never`) it("Refinement", () => { const schema = S.NonEmptyString - const equivalence = E.make(schema) + const equivalence = S.equivalence(schema) expect(equivalence("a", "a")).toBe(true) @@ -138,7 +137,7 @@ schema (NeverKeyword): never`) describe("declaration", () => { it("should return Equal.equals when an annotation doesn't exist", () => { const schema = S.declare(isUnknown) - const equivalence = E.make(schema) + const equivalence = S.equivalence(schema) expect(equivalence).toStrictEqual(Equal.equals) const make = (id: number, s: string) => { @@ -161,7 +160,7 @@ schema (NeverKeyword): never`) it("Chunk", () => { const schema = S.ChunkFromSelf(MyNumber) - const equivalence = E.make(schema) + const equivalence = S.equivalence(schema) expect(equivalence(Chunk.empty(), Chunk.empty())).toBe(true) expect(equivalence(Chunk.make(1, 2, 3), Chunk.make(1, 2, 3))).toBe(true) @@ -174,7 +173,7 @@ schema (NeverKeyword): never`) it("Date", () => { const schema = S.DateFromSelf - const equivalence = E.make(schema) + const equivalence = S.equivalence(schema) const now = new Date() expect(equivalence(now, now)).toBe(true) @@ -187,7 +186,7 @@ schema (NeverKeyword): never`) it("Data", () => { const schema = S.DataFromSelf(S.Struct({ a: MyString, b: MyNumber })) - const equivalence = E.make(schema) + const equivalence = S.equivalence(schema) expect(equivalence(Data.struct({ a: "ok", b: 0 }), Data.struct({ a: "ok", b: 0 }))).toBe(true) @@ -196,7 +195,7 @@ schema (NeverKeyword): never`) it("Either", () => { const schema = S.EitherFromSelf({ left: MyString, right: MyNumber }) - const equivalence = E.make(schema) + const equivalence = S.equivalence(schema) expect(equivalence(Either.right(1), Either.right(1))).toBe(true) expect(equivalence(Either.left("a"), Either.left("a"))).toBe(true) @@ -209,7 +208,7 @@ schema (NeverKeyword): never`) it("Option", () => { const schema = S.OptionFromSelf(MyNumber) - const equivalence = E.make(schema) + const equivalence = S.equivalence(schema) expect(equivalence(Option.none(), Option.none())).toBe(true) expect(equivalence(Option.some(1), Option.some(1))).toBe(true) @@ -221,7 +220,7 @@ schema (NeverKeyword): never`) it("ReadonlySet", () => { const schema = S.ReadonlySetFromSelf(MyNumber) - const equivalence = E.make(schema) + const equivalence = S.equivalence(schema) expect(equivalence(new Set(), new Set())).toBe(true) expect(equivalence(new Set([1, 2, 3]), new Set([1, 2, 3]))).toBe(true) @@ -233,7 +232,7 @@ schema (NeverKeyword): never`) it("ReadonlyMap", () => { const schema = S.ReadonlyMapFromSelf({ key: MyString, value: MyNumber }) - const equivalence = E.make(schema) + const equivalence = S.equivalence(schema) expect(equivalence(new Map(), new Map())).toBe(true) expect(equivalence(new Map([["a", 1], ["b", 2]]), new Map([["a", 1], ["b", 2]]))).toBe(true) @@ -246,7 +245,7 @@ schema (NeverKeyword): never`) it("Uint8Array", () => { const schema = S.Uint8ArrayFromSelf - const equivalence = E.make(schema) + const equivalence = S.equivalence(schema) expect(equivalence(new Uint8Array(), new Uint8Array())).toBe(true) expect( @@ -264,7 +263,7 @@ schema (NeverKeyword): never`) const schema = S.instanceOf(URL, { equivalence: () => Equivalence.make((a, b) => a.href === b.href) }) - const equivalence = E.make(schema) + const equivalence = S.equivalence(schema) expect(equivalence(new URL("https://example.com/page"), new URL("https://example.com/page"))) .toBe(true) @@ -277,7 +276,7 @@ schema (NeverKeyword): never`) describe("union", () => { it("primitives", () => { const schema = S.Union(MyString, MyNumber) - const equivalence = E.make(schema) + const equivalence = S.equivalence(schema) expect(equivalence("a", "a")).toBe(true) expect(equivalence(1, 1)).toBe(true) @@ -292,7 +291,7 @@ schema (NeverKeyword): never`) const a = S.Struct({ a: MyString }) const ab = S.Struct({ a: MyString, b: S.Number }) const schema = S.Union(a, ab) - const equivalence = E.make(schema) + const equivalence = S.equivalence(schema) expect(equivalence({ a: "a", b: 1 }, { a: "a", b: 1 })).toBe(true) expect(equivalence({ a: "a", b: 1 }, { a: "a", b: 2 })).toBe(true) @@ -307,7 +306,7 @@ schema (NeverKeyword): never`) S.Struct({ tag: S.Literal("a"), a: MyString }), S.Struct({ tag: S.Literal("b"), b: S.Number }) ) - const equivalence = E.make(schema) + const equivalence = S.equivalence(schema) expect(equivalence({ tag: "a", a: "a" }, { tag: "a", a: "a" })).toBe(true) expect(equivalence({ tag: "b", b: 1 }, { tag: "b", b: 1 })).toBe(true) @@ -337,14 +336,14 @@ schema (NeverKeyword): never`) describe("tuple", () => { it("empty", () => { const schema = S.Tuple() - const equivalence = E.make(schema) + const equivalence = S.equivalence(schema) expect(equivalence([], [])).toBe(true) }) it("e", () => { const schema = S.Tuple(MyString, MyNumber) - const equivalence = E.make(schema) + const equivalence = S.equivalence(schema) expect(equivalence(["a", 1], ["a", 1])).toBe(true) @@ -356,7 +355,7 @@ schema (NeverKeyword): never`) it("e r", () => { const schema = S.Tuple([S.String], S.Number) - const equivalence = E.make(schema) + const equivalence = S.equivalence(schema) expect(equivalence(["a"], ["a"])).toBe(true) expect(equivalence(["a", 1], ["a", 1])).toBe(true) @@ -370,7 +369,7 @@ schema (NeverKeyword): never`) it("r", () => { const schema = S.Array(MyNumber) - const equivalence = E.make(schema) + const equivalence = S.equivalence(schema) expect(equivalence([], [])).toBe(true) expect(equivalence([1], [1])).toBe(true) @@ -384,7 +383,7 @@ schema (NeverKeyword): never`) it("r e", () => { const schema = S.Tuple([], MyString, MyNumber) - const equivalence = E.make(schema) + const equivalence = S.equivalence(schema) expect(equivalence([1], [1])).toBe(true) expect(equivalence(["a", 1], ["a", 1])).toBe(true) @@ -400,7 +399,7 @@ schema (NeverKeyword): never`) describe("optional element support", () => { it("e?", () => { const schema = S.Tuple(S.optionalElement(MyString)) - const equivalence = E.make(schema) + const equivalence = S.equivalence(schema) expect(equivalence([], [])).toBe(true) expect(equivalence(["a"], ["a"])).toBe(true) @@ -414,7 +413,7 @@ schema (NeverKeyword): never`) it("e? e?", () => { const schema = S.Tuple(S.optionalElement(MyString), S.optionalElement(MyNumber)) - const equivalence = E.make(schema) + const equivalence = S.equivalence(schema) expect(equivalence([], [])).toBe(true) expect(equivalence(["a"], ["a"])).toBe(true) @@ -432,7 +431,7 @@ schema (NeverKeyword): never`) it("e e?", () => { const schema = S.Tuple(MyString, S.optionalElement(MyNumber)) - const equivalence = E.make(schema) + const equivalence = S.equivalence(schema) expect(equivalence(["a"], ["a"])).toBe(true) expect(equivalence(["a", 1], ["a", 1])).toBe(true) @@ -446,7 +445,7 @@ schema (NeverKeyword): never`) it("e? r", () => { const schema = S.Tuple([S.optionalElement(S.String)], S.Number) - const equivalence = E.make(schema) + const equivalence = S.equivalence(schema) expect(equivalence([], [])).toBe(true) expect(equivalence(["a"], ["a"])).toBe(true) @@ -465,18 +464,18 @@ schema (NeverKeyword): never`) describe("struct", () => { it("empty", () => { const schema = S.Struct({}) - const equivalence = E.make(schema) + const equivalence = S.equivalence(schema) expect(equivalence({}, {})).toBe(false) }) it("string keys", () => { const schema = S.Struct({ a: MyString, b: MyNumber }) - const equivalence = E.make(schema) + const equivalence = S.equivalence(schema) expect(equivalence({ a: "a", b: 1 }, { a: "a", b: 1 })).toBe(true) // should ignore excess properties - const d = Symbol.for("@effect/schema/test/d") + const d = Symbol.for("effect/Schema/test/d") const excess = { a: "a", b: 1, @@ -492,14 +491,14 @@ schema (NeverKeyword): never`) }) it("symbol keys", () => { - const a = Symbol.for("@effect/schema/test/a") - const b = Symbol.for("@effect/schema/test/b") + const a = Symbol.for("effect/Schema/test/a") + const b = Symbol.for("effect/Schema/test/b") const schema = S.Struct({ [a]: MyString, [b]: MyNumber }) - const equivalence = E.make(schema) + const equivalence = S.equivalence(schema) expect(equivalence({ [a]: "a", [b]: 1 }, { [a]: "a", [b]: 1 })).toBe(true) // should ignore excess properties - const d = Symbol.for("@effect/schema/test/d") + const d = Symbol.for("effect/Schema/test/d") const excess = { [a]: "a", [b]: 1, @@ -519,7 +518,7 @@ schema (NeverKeyword): never`) a: S.optionalWith(MyString, { exact: true }), b: S.optionalWith(S.Union(MyNumber, S.Undefined), { exact: true }) }) - const equivalence = E.make(schema) + const equivalence = S.equivalence(schema) expect(equivalence({ a: "a", b: 1 }, { a: "a", b: 1 })).toBe(true) expect(equivalence({ b: 1 }, { b: 1 })).toBe(true) @@ -541,7 +540,7 @@ schema (NeverKeyword): never`) describe("record", () => { it("record(never, number)", () => { const schema = S.Record({ key: S.Never, value: MyNumber }) - const equivalence = E.make(schema) + const equivalence = S.equivalence(schema) const input = {} expect(equivalence(input, input)).toBe(true) @@ -550,13 +549,13 @@ schema (NeverKeyword): never`) it("record(string, number)", () => { const schema = S.Record({ key: MyString, value: MyNumber }) - const equivalence = E.make(schema) + const equivalence = S.equivalence(schema) expect(equivalence({}, {})).toBe(true) expect(equivalence({ a: 1 }, { a: 1 })).toBe(true) expect(equivalence({ a: 1, b: 2 }, { a: 1, b: 2 })).toBe(true) // should ignore symbol excess properties - const d = Symbol.for("@effect/schema/test/d") + const d = Symbol.for("effect/Schema/test/d") expect(equivalence({ a: 1, b: 2 }, { a: 1, b: 2, [d]: "d" })).toBe(true) expect(equivalence({ a: 1 }, { a: 2 })).toBe(false) @@ -569,10 +568,10 @@ schema (NeverKeyword): never`) it("record(symbol, number)", () => { const schema = S.Record({ key: MySymbol, value: MyNumber }) - const equivalence = E.make(schema) + const equivalence = S.equivalence(schema) - const a = Symbol.for("@effect/schema/test/a") - const b = Symbol.for("@effect/schema/test/b") + const a = Symbol.for("effect/Schema/test/a") + const b = Symbol.for("effect/Schema/test/b") expect(equivalence({}, {})).toBe(true) expect(equivalence({ [a]: 1 }, { [a]: 1 })).toBe(true) expect(equivalence({ [a]: 1, [b]: 2 }, { [a]: 1, [b]: 2 })).toBe(true) @@ -590,7 +589,7 @@ schema (NeverKeyword): never`) it("struct record", () => { const schema = S.Struct({ a: MyString, b: MyString }, S.Record({ key: MyString, value: MyString })) - const equivalence = E.make(schema) + const equivalence = S.equivalence(schema) expect(equivalence({ a: "a", b: "b" }, { a: "a", b: "b" })).toBe(true) expect(equivalence({ a: "a", b: "b", c: "c" }, { a: "a", b: "b", c: "c" })).toBe(true) @@ -606,7 +605,7 @@ schema (NeverKeyword): never`) const schema = S.Struct({ a: MyString, b: MyString }).annotations({ equivalence: () => Equivalence.make((x, y) => x.a === y.a) }) - const equivalence = E.make(schema) + const equivalence = S.equivalence(schema) expect(equivalence({ a: "a", b: "b" }, { a: "a", b: "b" })).toBe(true) expect(equivalence({ a: "a", b: "b" }, { a: "a", b: "c" })).toBe(true) @@ -628,7 +627,7 @@ schema (NeverKeyword): never`) as: S.Array(S.suspend((): S.Schema => schema)) }) - const equivalence = E.make(schema) + const equivalence = S.equivalence(schema) const a1: A = { a: "a1", as: [] } expect(equivalence(a1, a1)).toBe(true) @@ -669,7 +668,7 @@ schema (NeverKeyword): never`) right: Expression }) - const equivalence = E.make(Operation) + const equivalence = S.equivalence(Operation) const a1: Operation = { type: "operation", @@ -727,8 +726,8 @@ schema (NeverKeyword): never`) describe("should handle annotations", () => { const expectHook = (source: S.Schema) => { - const schema = source.pipe(E.equivalence(() => () => true)) - const eq = E.make(schema) + const schema = source.annotations({ equivalence: () => () => true }) + const eq = S.equivalence(schema) expect(eq("a" as any, "b" as any)).toEqual(true) } diff --git a/packages/effect/test/Schema/Schema/exports.test.ts b/packages/effect/test/Schema/Schema/exports.test.ts new file mode 100644 index 0000000000..c982f96eda --- /dev/null +++ b/packages/effect/test/Schema/Schema/exports.test.ts @@ -0,0 +1,51 @@ +import * as S from "effect/Schema" +import { expect, it } from "vitest" + +it("exports", () => { + expect(S.decodeUnknown).exist + expect(S.decodeUnknownSync).exist + expect(S.decodeUnknownOption).exist + expect(S.decodeUnknownEither).exist + + expect(S.decode).exist + expect(S.decodeSync).exist + expect(S.decodeOption).exist + expect(S.decodeEither).exist + + expect(S.encode).exist + expect(S.encodeSync).exist + expect(S.encodeOption).exist + expect(S.encodeEither).exist + + expect(S.validate).exist + expect(S.validateSync).exist + expect(S.validateOption).exist + expect(S.validateEither).exist + + expect(S.GreaterThanBigIntSchemaId).exist + expect(S.GreaterThanOrEqualToBigIntSchemaId).exist + expect(S.LessThanBigIntSchemaId).exist + expect(S.LessThanOrEqualToBigIntSchemaId).exist + expect(S.BetweenBigIntSchemaId).exist + expect(S.BrandSchemaId).exist + expect(S.FiniteSchemaId).exist + expect(S.GreaterThanSchemaId).exist + expect(S.GreaterThanOrEqualToSchemaId).exist + expect(S.MultipleOfSchemaId).exist + expect(S.IntSchemaId).exist + expect(S.LessThanSchemaId).exist + expect(S.LessThanOrEqualToSchemaId).exist + expect(S.BetweenSchemaId).exist + expect(S.NonNaNSchemaId).exist + expect(S.InstanceOfSchemaId).exist + expect(S.MinItemsSchemaId).exist + expect(S.MaxItemsSchemaId).exist + expect(S.ItemsCountSchemaId).exist + expect(S.TrimmedSchemaId).exist + expect(S.PatternSchemaId).exist + expect(S.StartsWithSchemaId).exist + expect(S.EndsWithSchemaId).exist + expect(S.IncludesSchemaId).exist + expect(S.UUIDSchemaId).exist + expect(S.ULIDSchemaId).exist +}) diff --git a/packages/schema/test/Schema/extend.test.ts b/packages/effect/test/Schema/Schema/extend.test.ts similarity index 98% rename from packages/schema/test/Schema/extend.test.ts rename to packages/effect/test/Schema/Schema/extend.test.ts index 3b08b556c9..edf6d033aa 100644 --- a/packages/schema/test/Schema/extend.test.ts +++ b/packages/effect/test/Schema/Schema/extend.test.ts @@ -1,8 +1,8 @@ -import * as Arbitrary from "@effect/schema/Arbitrary" -import * as AST from "@effect/schema/AST" -import * as FastCheck from "@effect/schema/FastCheck" -import * as Schema from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as Arbitrary from "effect/Arbitrary" +import * as FastCheck from "effect/FastCheck" +import * as Schema from "effect/Schema" +import * as AST from "effect/SchemaAST" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("extend", () => { diff --git a/packages/schema/test/Schema/filter.test.ts b/packages/effect/test/Schema/Schema/filter.test.ts similarity index 96% rename from packages/schema/test/Schema/filter.test.ts rename to packages/effect/test/Schema/Schema/filter.test.ts index 4a76babde6..5d3e627e8e 100644 --- a/packages/schema/test/Schema/filter.test.ts +++ b/packages/effect/test/Schema/Schema/filter.test.ts @@ -1,14 +1,14 @@ -import * as AST from "@effect/schema/AST" -import * as ParseResult from "@effect/schema/ParseResult" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as ParseResult from "effect/ParseResult" +import * as S from "effect/Schema" +import * as AST from "effect/SchemaAST" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("filter", () => { it("annotation options", () => { const schema = S.String.pipe( S.filter((s): s is string => s.length === 1, { - typeId: Symbol.for("Char"), + schemaId: Symbol.for("Char"), description: "description", documentation: "documentation", examples: ["examples"], @@ -18,7 +18,7 @@ describe("filter", () => { }) ) expect(schema.ast.annotations).toEqual({ - [AST.TypeAnnotationId]: Symbol.for("Char"), + [AST.SchemaIdAnnotationId]: Symbol.for("Char"), [AST.DescriptionAnnotationId]: "description", [AST.DocumentationAnnotationId]: "documentation", [AST.ExamplesAnnotationId]: [ diff --git a/packages/schema/test/Schema/filterEffect.test.ts b/packages/effect/test/Schema/Schema/filterEffect.test.ts similarity index 97% rename from packages/schema/test/Schema/filterEffect.test.ts rename to packages/effect/test/Schema/Schema/filterEffect.test.ts index cd8b961164..3412692174 100644 --- a/packages/schema/test/Schema/filterEffect.test.ts +++ b/packages/effect/test/Schema/Schema/filterEffect.test.ts @@ -1,7 +1,7 @@ -import * as ParseResult from "@effect/schema/ParseResult" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import * as Effect from "effect/Effect" +import * as ParseResult from "effect/ParseResult" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("filterEffect", () => { diff --git a/packages/schema/test/Schema/format.test.ts b/packages/effect/test/Schema/Schema/format.test.ts similarity index 90% rename from packages/schema/test/Schema/format.test.ts rename to packages/effect/test/Schema/Schema/format.test.ts index 109a94cbb4..bf4210b27b 100644 --- a/packages/schema/test/Schema/format.test.ts +++ b/packages/effect/test/Schema/Schema/format.test.ts @@ -1,5 +1,5 @@ -import { format } from "@effect/schema/Schema" -import * as S from "@effect/schema/Schema" +import { format } from "effect/Schema" +import * as S from "effect/Schema" import { describe, expect, it } from "vitest" describe("format", () => { diff --git a/packages/schema/test/Schema/fromBrand.test.ts b/packages/effect/test/Schema/Schema/fromBrand.test.ts similarity index 95% rename from packages/schema/test/Schema/fromBrand.test.ts rename to packages/effect/test/Schema/Schema/fromBrand.test.ts index 725e6b942c..b21b087647 100644 --- a/packages/schema/test/Schema/fromBrand.test.ts +++ b/packages/effect/test/Schema/Schema/fromBrand.test.ts @@ -1,6 +1,6 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import * as Brand from "effect/Brand" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" type Int = number & Brand.Brand<"Int"> diff --git a/packages/schema/test/Schema/getNumberIndexedAccess.test.ts b/packages/effect/test/Schema/Schema/getNumberIndexedAccess.test.ts similarity index 94% rename from packages/schema/test/Schema/getNumberIndexedAccess.test.ts rename to packages/effect/test/Schema/Schema/getNumberIndexedAccess.test.ts index 5049e567ab..ecb6d39640 100644 --- a/packages/schema/test/Schema/getNumberIndexedAccess.test.ts +++ b/packages/effect/test/Schema/Schema/getNumberIndexedAccess.test.ts @@ -1,6 +1,6 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import * as Duration from "effect/Duration" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("getNumberIndexedAccess", () => { diff --git a/packages/schema/test/Schema/instanceOf.test.ts b/packages/effect/test/Schema/Schema/instanceOf.test.ts similarity index 80% rename from packages/schema/test/Schema/instanceOf.test.ts rename to packages/effect/test/Schema/Schema/instanceOf.test.ts index 02607da2ab..5de4eb4a0d 100644 --- a/packages/schema/test/Schema/instanceOf.test.ts +++ b/packages/effect/test/Schema/Schema/instanceOf.test.ts @@ -1,8 +1,8 @@ -import * as AST from "@effect/schema/AST" -import * as P from "@effect/schema/ParseResult" -import * as Pretty from "@effect/schema/Pretty" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as P from "effect/ParseResult" +import * as Pretty from "effect/Pretty" +import * as S from "effect/Schema" +import * as AST from "effect/SchemaAST" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("instanceOf", () => { @@ -17,7 +17,7 @@ describe("instanceOf", () => { it("annotations", () => { const schema = S.instanceOf(Set, { description: "my description" }) expect(schema.ast.annotations[AST.DescriptionAnnotationId]).toEqual("my description") - expect(schema.ast.annotations[S.InstanceOfTypeId]).toEqual({ constructor: Set }) + expect(schema.ast.annotations[S.InstanceOfSchemaId]).toEqual({ constructor: Set }) }) it("decoding", async () => { diff --git a/packages/schema/test/Schema/is.test.ts b/packages/effect/test/Schema/Schema/is.test.ts similarity index 96% rename from packages/schema/test/Schema/is.test.ts rename to packages/effect/test/Schema/Schema/is.test.ts index bbff33b8da..372d543338 100644 --- a/packages/schema/test/Schema/is.test.ts +++ b/packages/effect/test/Schema/Schema/is.test.ts @@ -1,6 +1,6 @@ -import * as P from "@effect/schema/ParseResult" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as P from "effect/ParseResult" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("is", () => { @@ -41,10 +41,10 @@ describe("is", () => { }) it("symbol", () => { - const a = Symbol.for("@effect/schema/test/a") + const a = Symbol.for("effect/Schema/test/a") const is = P.is(S.SymbolFromSelf) expect(is(a)).toEqual(true) - expect(is("@effect/schema/test/a")).toEqual(false) + expect(is("effect/Schema/test/a")).toEqual(false) }) it("object", () => { @@ -74,12 +74,12 @@ describe("is", () => { }) it("uniqueSymbolFromSelf", () => { - const a = Symbol.for("@effect/schema/test/a") + const a = Symbol.for("effect/Schema/test/a") const schema = S.UniqueSymbolFromSelf(a) const is = P.is(schema) expect(is(a)).toEqual(true) - expect(is(Symbol.for("@effect/schema/test/a"))).toEqual(true) - expect(is("Symbol(@effect/schema/test/a)")).toEqual(false) + expect(is(Symbol.for("effect/Schema/test/a"))).toEqual(true) + expect(is("Symbol(effect/Schema/test/a)")).toEqual(false) }) it("Numeric enums", () => { @@ -315,7 +315,7 @@ describe("is", () => { }) it("record(string, string)", () => { - const a = Symbol.for("@effect/schema/test/a") + const a = Symbol.for("effect/Schema/test/a") const schema = S.Record({ key: S.String, value: S.String }) const is = P.is(schema) expect(is(null)).toEqual(false) @@ -329,8 +329,8 @@ describe("is", () => { }) it("record(symbol, string)", () => { - const a = Symbol.for("@effect/schema/test/a") - const b = Symbol.for("@effect/schema/test/b") + const a = Symbol.for("effect/Schema/test/a") + const b = Symbol.for("effect/Schema/test/b") const schema = S.Record({ key: S.SymbolFromSelf, value: S.String }) const is = P.is(schema) expect(is(null)).toEqual(false) @@ -372,8 +372,8 @@ describe("is", () => { }) it("record(Symbol('a') | Symbol('b'), number)", () => { - const a = Symbol.for("@effect/schema/test/a") - const b = Symbol.for("@effect/schema/test/b") + const a = Symbol.for("effect/Schema/test/a") + const b = Symbol.for("effect/Schema/test/b") const schema = S.Record({ key: S.Union(S.UniqueSymbolFromSelf(a), S.UniqueSymbolFromSelf(b)), value: S.Number }) const is = P.is(schema) expect(is({ [a]: 1, [b]: 2 })).toEqual(true) diff --git a/packages/schema/test/Schema/isSchema.test.ts b/packages/effect/test/Schema/Schema/isSchema.test.ts similarity index 92% rename from packages/schema/test/Schema/isSchema.test.ts rename to packages/effect/test/Schema/Schema/isSchema.test.ts index 4c4bc3b6c7..0ed96dcb70 100644 --- a/packages/schema/test/Schema/isSchema.test.ts +++ b/packages/effect/test/Schema/Schema/isSchema.test.ts @@ -1,4 +1,4 @@ -import * as S from "@effect/schema/Schema" +import * as S from "effect/Schema" import { describe, expect, it } from "vitest" describe("isSchema", () => { diff --git a/packages/schema/test/Schema/keyof.test.ts b/packages/effect/test/Schema/Schema/keyof.test.ts similarity index 93% rename from packages/schema/test/Schema/keyof.test.ts rename to packages/effect/test/Schema/Schema/keyof.test.ts index b41493e4a0..5b23669547 100644 --- a/packages/schema/test/Schema/keyof.test.ts +++ b/packages/effect/test/Schema/Schema/keyof.test.ts @@ -1,6 +1,6 @@ -import * as AST from "@effect/schema/AST" -import * as P from "@effect/schema/ParseResult" -import * as S from "@effect/schema/Schema" +import * as P from "effect/ParseResult" +import * as S from "effect/Schema" +import * as AST from "effect/SchemaAST" import { describe, expect, it } from "vitest" describe("keyof", () => { @@ -11,7 +11,7 @@ describe("keyof", () => { }) it("should unify symbol literals with symbol", () => { - const a = Symbol.for("@effect/schema/test/a") + const a = Symbol.for("effect/Schema/test/a") const schema = S.Struct({ [a]: S.String }, S.Record({ key: S.SymbolFromSelf, value: S.String })) const keyof = S.keyof(schema) expect(keyof.ast).toEqual(S.SymbolFromSelf.ast) @@ -32,8 +32,8 @@ describe("keyof", () => { }) it("symbol keys", () => { - const a = Symbol.for("@effect/schema/test/a") - const b = Symbol.for("@effect/schema/test/b") + const a = Symbol.for("effect/Schema/test/a") + const b = Symbol.for("effect/Schema/test/b") const schema = S.Struct({ [a]: S.String, [b]: S.Number diff --git a/packages/schema/test/Schema/mutable.test.ts b/packages/effect/test/Schema/Schema/mutable.test.ts similarity index 96% rename from packages/schema/test/Schema/mutable.test.ts rename to packages/effect/test/Schema/Schema/mutable.test.ts index 03408156bf..ea7c6c5eb1 100644 --- a/packages/schema/test/Schema/mutable.test.ts +++ b/packages/effect/test/Schema/Schema/mutable.test.ts @@ -1,6 +1,6 @@ -import * as AST from "@effect/schema/AST" -import * as S from "@effect/schema/Schema" import { identity } from "effect" +import * as S from "effect/Schema" +import * as AST from "effect/SchemaAST" import { describe, expect, it } from "vitest" describe("mutable", () => { diff --git a/packages/schema/test/Schema/nonEmptyArray.test.ts b/packages/effect/test/Schema/Schema/nonEmptyArray.test.ts similarity index 85% rename from packages/schema/test/Schema/nonEmptyArray.test.ts rename to packages/effect/test/Schema/Schema/nonEmptyArray.test.ts index 6a9aede7d4..f22978eca8 100644 --- a/packages/schema/test/Schema/nonEmptyArray.test.ts +++ b/packages/effect/test/Schema/Schema/nonEmptyArray.test.ts @@ -1,5 +1,5 @@ -import * as AST from "@effect/schema/AST" -import * as S from "@effect/schema/Schema" +import * as S from "effect/Schema" +import * as AST from "effect/SchemaAST" import { describe, expect, it } from "vitest" describe("nonEmptyArray", () => { diff --git a/packages/schema/test/Schema/omit.test.ts b/packages/effect/test/Schema/Schema/omit.test.ts similarity index 89% rename from packages/schema/test/Schema/omit.test.ts rename to packages/effect/test/Schema/Schema/omit.test.ts index a349548f3f..99d4f3675d 100644 --- a/packages/schema/test/Schema/omit.test.ts +++ b/packages/effect/test/Schema/Schema/omit.test.ts @@ -1,10 +1,10 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("omit", () => { it("Struct", async () => { - const a = Symbol.for("@effect/schema/test/a") + const a = Symbol.for("effect/Schema/test/a") const schema = S.Struct({ [a]: S.String, b: S.NumberFromString, c: S.Boolean }).pipe( S.omit("c") ) @@ -13,20 +13,20 @@ describe("omit", () => { await Util.expectDecodeUnknownFailure( schema, null, - "Expected { readonly b: NumberFromString; readonly Symbol(@effect/schema/test/a): string }, actual null" + "Expected { readonly b: NumberFromString; readonly Symbol(effect/Schema/test/a): string }, actual null" ) await Util.expectDecodeUnknownFailure( schema, { [a]: "a" }, - `{ readonly b: NumberFromString; readonly Symbol(@effect/schema/test/a): string } + `{ readonly b: NumberFromString; readonly Symbol(effect/Schema/test/a): string } └─ ["b"] └─ is missing` ) await Util.expectDecodeUnknownFailure( schema, { b: "1" }, - `{ readonly b: NumberFromString; readonly Symbol(@effect/schema/test/a): string } -└─ [Symbol(@effect/schema/test/a)] + `{ readonly b: NumberFromString; readonly Symbol(effect/Schema/test/a): string } +└─ [Symbol(effect/Schema/test/a)] └─ is missing` ) }) diff --git a/packages/schema/test/Schema/optional.test.ts b/packages/effect/test/Schema/Schema/optional.test.ts similarity index 96% rename from packages/schema/test/Schema/optional.test.ts rename to packages/effect/test/Schema/Schema/optional.test.ts index 8444cfe546..f9870a57ee 100644 --- a/packages/schema/test/Schema/optional.test.ts +++ b/packages/effect/test/Schema/Schema/optional.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("optional", () => { diff --git a/packages/schema/test/Schema/optionalToRequired.test.ts b/packages/effect/test/Schema/Schema/optionalToRequired.test.ts similarity index 87% rename from packages/schema/test/Schema/optionalToRequired.test.ts rename to packages/effect/test/Schema/Schema/optionalToRequired.test.ts index 300eb60e56..b69c6a03c8 100644 --- a/packages/schema/test/Schema/optionalToRequired.test.ts +++ b/packages/effect/test/Schema/Schema/optionalToRequired.test.ts @@ -1,6 +1,6 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import * as Option from "effect/Option" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("optionalToRequired", () => { diff --git a/packages/schema/test/Schema/optionalWith.test.ts b/packages/effect/test/Schema/Schema/optionalWith.test.ts similarity index 99% rename from packages/schema/test/Schema/optionalWith.test.ts rename to packages/effect/test/Schema/Schema/optionalWith.test.ts index b573c69d6b..57cc68572e 100644 --- a/packages/schema/test/Schema/optionalWith.test.ts +++ b/packages/effect/test/Schema/Schema/optionalWith.test.ts @@ -1,7 +1,7 @@ -import * as AST from "@effect/schema/AST" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import * as O from "effect/Option" +import * as S from "effect/Schema" +import * as AST from "effect/SchemaAST" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("optionalWith", () => { diff --git a/packages/schema/test/Schema/parseJson.test.ts b/packages/effect/test/Schema/Schema/parseJson.test.ts similarity index 97% rename from packages/schema/test/Schema/parseJson.test.ts rename to packages/effect/test/Schema/Schema/parseJson.test.ts index 0a936e27bc..cbc910e0ca 100644 --- a/packages/schema/test/Schema/parseJson.test.ts +++ b/packages/effect/test/Schema/Schema/parseJson.test.ts @@ -1,6 +1,6 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import * as Exit from "effect/Exit" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("parseJson", () => { diff --git a/packages/schema/test/Schema/partial.test.ts b/packages/effect/test/Schema/Schema/partial.test.ts similarity index 97% rename from packages/schema/test/Schema/partial.test.ts rename to packages/effect/test/Schema/Schema/partial.test.ts index e828442b41..2c60179904 100644 --- a/packages/schema/test/Schema/partial.test.ts +++ b/packages/effect/test/Schema/Schema/partial.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("partial", () => { diff --git a/packages/schema/test/Schema/partialWith.test.ts b/packages/effect/test/Schema/Schema/partialWith.test.ts similarity index 98% rename from packages/schema/test/Schema/partialWith.test.ts rename to packages/effect/test/Schema/Schema/partialWith.test.ts index 46fa558e9c..b7502cc06d 100644 --- a/packages/schema/test/Schema/partialWith.test.ts +++ b/packages/effect/test/Schema/Schema/partialWith.test.ts @@ -1,6 +1,6 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import { identity } from "effect/Function" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("partialWith", () => { diff --git a/packages/schema/test/Schema/pick.test.ts b/packages/effect/test/Schema/Schema/pick.test.ts similarity index 89% rename from packages/schema/test/Schema/pick.test.ts rename to packages/effect/test/Schema/Schema/pick.test.ts index 02392f48c6..03563b7d09 100644 --- a/packages/schema/test/Schema/pick.test.ts +++ b/packages/effect/test/Schema/Schema/pick.test.ts @@ -1,10 +1,10 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("pick", () => { it("Struct", async () => { - const a = Symbol.for("@effect/schema/test/a") + const a = Symbol.for("effect/Schema/test/a") const schema = S.Struct({ [a]: S.String, b: S.NumberFromString, c: S.Boolean }).pipe( S.pick(a, "b") ) @@ -113,22 +113,22 @@ describe("pick", () => { }) it("Record(symbol, number)", async () => { - const a = Symbol.for("@effect/schema/test/a") - const b = Symbol.for("@effect/schema/test/b") + const a = Symbol.for("effect/Schema/test/a") + const b = Symbol.for("effect/Schema/test/b") const schema = S.Record({ key: S.SymbolFromSelf, value: S.Number }).pipe(S.pick(a, b)) await Util.expectDecodeUnknownSuccess(schema, { [a]: 1, [b]: 2 }) await Util.expectDecodeUnknownFailure( schema, { [a]: "a", [b]: 2 }, - `{ readonly Symbol(@effect/schema/test/a): number; readonly Symbol(@effect/schema/test/b): number } -└─ [Symbol(@effect/schema/test/a)] + `{ readonly Symbol(effect/Schema/test/a): number; readonly Symbol(effect/Schema/test/b): number } +└─ [Symbol(effect/Schema/test/a)] └─ Expected number, actual "a"` ) await Util.expectDecodeUnknownFailure( schema, { [a]: 1, [b]: "b" }, - `{ readonly Symbol(@effect/schema/test/a): number; readonly Symbol(@effect/schema/test/b): number } -└─ [Symbol(@effect/schema/test/b)] + `{ readonly Symbol(effect/Schema/test/a): number; readonly Symbol(effect/Schema/test/b): number } +└─ [Symbol(effect/Schema/test/b)] └─ Expected number, actual "b"` ) }) diff --git a/packages/schema/test/Schema/pickLiteral.test.ts b/packages/effect/test/Schema/Schema/pickLiteral.test.ts similarity index 90% rename from packages/schema/test/Schema/pickLiteral.test.ts rename to packages/effect/test/Schema/Schema/pickLiteral.test.ts index f09e34fef5..df257533fa 100644 --- a/packages/schema/test/Schema/pickLiteral.test.ts +++ b/packages/effect/test/Schema/Schema/pickLiteral.test.ts @@ -1,6 +1,6 @@ -import * as AST from "@effect/schema/AST" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as AST from "effect/SchemaAST" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("pickLiteral", () => { diff --git a/packages/schema/test/Schema/pipe.test.ts b/packages/effect/test/Schema/Schema/pipe.test.ts similarity index 92% rename from packages/schema/test/Schema/pipe.test.ts rename to packages/effect/test/Schema/Schema/pipe.test.ts index 5e17642bc1..c430d910a8 100644 --- a/packages/schema/test/Schema/pipe.test.ts +++ b/packages/effect/test/Schema/Schema/pipe.test.ts @@ -1,4 +1,4 @@ -import * as S from "@effect/schema/Schema" +import * as S from "effect/Schema" import { describe, expect, it } from "vitest" describe("pipe", () => { diff --git a/packages/schema/test/Schema/pluck.test.ts b/packages/effect/test/Schema/Schema/pluck.test.ts similarity index 97% rename from packages/schema/test/Schema/pluck.test.ts rename to packages/effect/test/Schema/Schema/pluck.test.ts index bc8d1fca9b..5385452634 100644 --- a/packages/schema/test/Schema/pluck.test.ts +++ b/packages/effect/test/Schema/Schema/pluck.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("pluck", () => { diff --git a/packages/schema/test/Schema/rename.test.ts b/packages/effect/test/Schema/Schema/rename.test.ts similarity index 92% rename from packages/schema/test/Schema/rename.test.ts rename to packages/effect/test/Schema/Schema/rename.test.ts index 7de14c6065..bfcb6bccf1 100644 --- a/packages/schema/test/Schema/rename.test.ts +++ b/packages/effect/test/Schema/Schema/rename.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("rename", () => { @@ -13,7 +13,7 @@ describe("rename", () => { }) it("from string key to symbol key", async () => { - const c = Symbol.for("@effect/schema/test/c") + const c = Symbol.for("effect/Schema/test/c") const schema = S.Struct({ a: S.String, b: S.Number }) const renamed = S.rename(schema, { a: c }) @@ -22,7 +22,7 @@ describe("rename", () => { }) it("from symbol key to string key", async () => { - const a = Symbol.for("@effect/schema/test/a") + const a = Symbol.for("effect/Schema/test/a") const schema = S.Struct({ [a]: S.String, b: S.Number }) const renamed = S.rename(schema, { [a]: "c" }) @@ -31,8 +31,8 @@ describe("rename", () => { }) it("from symbol key to symbol key", async () => { - const a = Symbol.for("@effect/schema/test/a") - const c = Symbol.for("@effect/schema/test/c") + const a = Symbol.for("effect/Schema/test/a") + const c = Symbol.for("effect/Schema/test/c") const schema = S.Struct({ [a]: S.String, b: S.Number }) const renamed = S.rename(schema, { [a]: c }) diff --git a/packages/schema/test/Schema/required.test.ts b/packages/effect/test/Schema/Schema/required.test.ts similarity index 98% rename from packages/schema/test/Schema/required.test.ts rename to packages/effect/test/Schema/Schema/required.test.ts index 05d3738ab5..d311453422 100644 --- a/packages/schema/test/Schema/required.test.ts +++ b/packages/effect/test/Schema/Schema/required.test.ts @@ -1,6 +1,6 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import { identity } from "effect/Function" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("required", () => { diff --git a/packages/schema/test/Schema/requiredToOptional.test.ts b/packages/effect/test/Schema/Schema/requiredToOptional.test.ts similarity index 87% rename from packages/schema/test/Schema/requiredToOptional.test.ts rename to packages/effect/test/Schema/Schema/requiredToOptional.test.ts index 4abdfb336a..f4f69d7bd2 100644 --- a/packages/schema/test/Schema/requiredToOptional.test.ts +++ b/packages/effect/test/Schema/Schema/requiredToOptional.test.ts @@ -1,6 +1,6 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" import * as Option from "effect/Option" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("requiredToOptional", () => { diff --git a/packages/schema/test/Schema/suspend.test.ts b/packages/effect/test/Schema/Schema/suspend.test.ts similarity index 97% rename from packages/schema/test/Schema/suspend.test.ts rename to packages/effect/test/Schema/Schema/suspend.test.ts index c34afcfa3f..6e7dbe5dd0 100644 --- a/packages/schema/test/Schema/suspend.test.ts +++ b/packages/effect/test/Schema/Schema/suspend.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("suspend", () => { diff --git a/packages/schema/test/Schema/toString.test.ts b/packages/effect/test/Schema/Schema/toString.test.ts similarity index 95% rename from packages/schema/test/Schema/toString.test.ts rename to packages/effect/test/Schema/Schema/toString.test.ts index 3c8fa3da58..c5729b5c01 100644 --- a/packages/schema/test/Schema/toString.test.ts +++ b/packages/effect/test/Schema/Schema/toString.test.ts @@ -1,4 +1,4 @@ -import * as S from "@effect/schema/Schema" +import * as S from "effect/Schema" import { describe, expect, it } from "vitest" describe("toString", () => { diff --git a/packages/schema/test/Schema/transform.test.ts b/packages/effect/test/Schema/Schema/transform.test.ts similarity index 86% rename from packages/schema/test/Schema/transform.test.ts rename to packages/effect/test/Schema/Schema/transform.test.ts index f12f2fec01..c563978587 100644 --- a/packages/schema/test/Schema/transform.test.ts +++ b/packages/effect/test/Schema/Schema/transform.test.ts @@ -1,5 +1,5 @@ -import * as Schema from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as Schema from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("transform", () => { diff --git a/packages/schema/test/Schema/transformLiterals.test.ts b/packages/effect/test/Schema/Schema/transformLiterals.test.ts similarity index 92% rename from packages/schema/test/Schema/transformLiterals.test.ts rename to packages/effect/test/Schema/Schema/transformLiterals.test.ts index b60dd20664..1c8f51ade0 100644 --- a/packages/schema/test/Schema/transformLiterals.test.ts +++ b/packages/effect/test/Schema/Schema/transformLiterals.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("transformLiteral", () => { diff --git a/packages/schema/test/Schema/transformOrFail.test.ts b/packages/effect/test/Schema/Schema/transformOrFail.test.ts similarity index 81% rename from packages/schema/test/Schema/transformOrFail.test.ts rename to packages/effect/test/Schema/Schema/transformOrFail.test.ts index 61928723b0..6be641db0e 100644 --- a/packages/schema/test/Schema/transformOrFail.test.ts +++ b/packages/effect/test/Schema/Schema/transformOrFail.test.ts @@ -1,6 +1,6 @@ -import * as ParseResult from "@effect/schema/ParseResult" -import * as Schema from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as ParseResult from "effect/ParseResult" +import * as Schema from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("transformOrFail", () => { diff --git a/packages/schema/test/Schema/typeSchema.test.ts b/packages/effect/test/Schema/Schema/typeSchema.test.ts similarity index 93% rename from packages/schema/test/Schema/typeSchema.test.ts rename to packages/effect/test/Schema/Schema/typeSchema.test.ts index 4503561aba..50730fdcb9 100644 --- a/packages/schema/test/Schema/typeSchema.test.ts +++ b/packages/effect/test/Schema/Schema/typeSchema.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("typeSchema", () => { diff --git a/packages/schema/test/Schema/validate.test.ts b/packages/effect/test/Schema/Schema/validate.test.ts similarity index 96% rename from packages/schema/test/Schema/validate.test.ts rename to packages/effect/test/Schema/Schema/validate.test.ts index d1db486e62..9378256e22 100644 --- a/packages/schema/test/Schema/validate.test.ts +++ b/packages/effect/test/Schema/Schema/validate.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" const expectValidateSuccess = async ( diff --git a/packages/schema/test/Schema/validateEither.test.ts b/packages/effect/test/Schema/Schema/validateEither.test.ts similarity index 93% rename from packages/schema/test/Schema/validateEither.test.ts rename to packages/effect/test/Schema/Schema/validateEither.test.ts index bff1e432e4..287aff8fb6 100644 --- a/packages/schema/test/Schema/validateEither.test.ts +++ b/packages/effect/test/Schema/Schema/validateEither.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("validateEither", () => { diff --git a/packages/schema/test/Schema/validateOption.test.ts b/packages/effect/test/Schema/Schema/validateOption.test.ts similarity index 89% rename from packages/schema/test/Schema/validateOption.test.ts rename to packages/effect/test/Schema/Schema/validateOption.test.ts index c3a1331789..d601961847 100644 --- a/packages/schema/test/Schema/validateOption.test.ts +++ b/packages/effect/test/Schema/Schema/validateOption.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("validateOption", () => { diff --git a/packages/schema/test/Schema/validatePromise.test.ts b/packages/effect/test/Schema/Schema/validatePromise.test.ts similarity index 92% rename from packages/schema/test/Schema/validatePromise.test.ts rename to packages/effect/test/Schema/Schema/validatePromise.test.ts index e2cea9793c..ba32a11f9f 100644 --- a/packages/schema/test/Schema/validatePromise.test.ts +++ b/packages/effect/test/Schema/Schema/validatePromise.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("validatePromise", () => { diff --git a/packages/schema/test/Schema/validateSync.test.ts b/packages/effect/test/Schema/Schema/validateSync.test.ts similarity index 93% rename from packages/schema/test/Schema/validateSync.test.ts rename to packages/effect/test/Schema/Schema/validateSync.test.ts index 2d46713226..6fac05c279 100644 --- a/packages/schema/test/Schema/validateSync.test.ts +++ b/packages/effect/test/Schema/Schema/validateSync.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("validateSync", () => { diff --git a/packages/schema/test/Schema/withConstructorDefault.test.ts b/packages/effect/test/Schema/Schema/withConstructorDefault.test.ts similarity index 95% rename from packages/schema/test/Schema/withConstructorDefault.test.ts rename to packages/effect/test/Schema/Schema/withConstructorDefault.test.ts index 15a621774e..d94cd59a82 100644 --- a/packages/schema/test/Schema/withConstructorDefault.test.ts +++ b/packages/effect/test/Schema/Schema/withConstructorDefault.test.ts @@ -1,4 +1,4 @@ -import * as S from "@effect/schema/Schema" +import * as S from "effect/Schema" import { describe, expect, it } from "vitest" describe("withConstructorDefault", () => { diff --git a/packages/schema/test/Schema/withDecodingDefault.test.ts b/packages/effect/test/Schema/Schema/withDecodingDefault.test.ts similarity index 94% rename from packages/schema/test/Schema/withDecodingDefault.test.ts rename to packages/effect/test/Schema/Schema/withDecodingDefault.test.ts index e6fb853a7d..2ac911a408 100644 --- a/packages/schema/test/Schema/withDecodingDefault.test.ts +++ b/packages/effect/test/Schema/Schema/withDecodingDefault.test.ts @@ -1,5 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import * as Util from "effect/test/Schema/TestUtils" import { describe, it } from "vitest" describe("withDecodingDefault", () => { diff --git a/packages/schema/test/AST/IndexSignature.test.ts b/packages/effect/test/Schema/SchemaAST/IndexSignature.test.ts similarity index 92% rename from packages/schema/test/AST/IndexSignature.test.ts rename to packages/effect/test/Schema/SchemaAST/IndexSignature.test.ts index 3d5d00af15..d6d3c8b886 100644 --- a/packages/schema/test/AST/IndexSignature.test.ts +++ b/packages/effect/test/Schema/SchemaAST/IndexSignature.test.ts @@ -1,4 +1,4 @@ -import * as AST from "@effect/schema/AST" +import * as AST from "effect/SchemaAST" import { describe, expect, it } from "vitest" describe("AST.IndexSignature", () => { diff --git a/packages/schema/test/AST/Tuple.test.ts b/packages/effect/test/Schema/SchemaAST/Tuple.test.ts similarity index 95% rename from packages/schema/test/AST/Tuple.test.ts rename to packages/effect/test/Schema/SchemaAST/Tuple.test.ts index c41e928802..6af7a2db6b 100644 --- a/packages/schema/test/AST/Tuple.test.ts +++ b/packages/effect/test/Schema/SchemaAST/Tuple.test.ts @@ -1,4 +1,4 @@ -import * as AST from "@effect/schema/AST" +import * as AST from "effect/SchemaAST" import { describe, expect, it } from "vitest" describe("AST.Tuple", () => { diff --git a/packages/schema/test/AST/TypeLiteral.test.ts b/packages/effect/test/Schema/SchemaAST/TypeLiteral.test.ts similarity index 84% rename from packages/schema/test/AST/TypeLiteral.test.ts rename to packages/effect/test/Schema/SchemaAST/TypeLiteral.test.ts index 643ac9be13..472fbc31cc 100644 --- a/packages/schema/test/AST/TypeLiteral.test.ts +++ b/packages/effect/test/Schema/SchemaAST/TypeLiteral.test.ts @@ -1,5 +1,5 @@ -import * as AST from "@effect/schema/AST" -import * as S from "@effect/schema/Schema" +import * as S from "effect/Schema" +import * as AST from "effect/SchemaAST" import { describe, expect, it } from "vitest" describe("AST.TypeLiteral", () => { diff --git a/packages/schema/test/AST/TypeLiteralTransformation.test.ts b/packages/effect/test/Schema/SchemaAST/TypeLiteralTransformation.test.ts similarity index 95% rename from packages/schema/test/AST/TypeLiteralTransformation.test.ts rename to packages/effect/test/Schema/SchemaAST/TypeLiteralTransformation.test.ts index de4447784b..00407feee3 100644 --- a/packages/schema/test/AST/TypeLiteralTransformation.test.ts +++ b/packages/effect/test/Schema/SchemaAST/TypeLiteralTransformation.test.ts @@ -1,5 +1,5 @@ -import * as AST from "@effect/schema/AST" import { identity } from "effect/Function" +import * as AST from "effect/SchemaAST" import { describe, expect, it } from "vitest" describe("AST.TypeLiteralTransformation", () => { diff --git a/packages/schema/test/AST/Union.test.ts b/packages/effect/test/Schema/SchemaAST/Union.test.ts similarity index 95% rename from packages/schema/test/AST/Union.test.ts rename to packages/effect/test/Schema/SchemaAST/Union.test.ts index 1b0ae8385f..b099a1a974 100644 --- a/packages/schema/test/AST/Union.test.ts +++ b/packages/effect/test/Schema/SchemaAST/Union.test.ts @@ -1,5 +1,5 @@ -import * as AST from "@effect/schema/AST" -import * as S from "@effect/schema/Schema" +import * as S from "effect/Schema" +import * as AST from "effect/SchemaAST" import { describe, expect, it } from "vitest" describe("AST.Union", () => { diff --git a/packages/schema/test/AST/annotations.test.ts b/packages/effect/test/Schema/SchemaAST/annotations.test.ts similarity index 88% rename from packages/schema/test/AST/annotations.test.ts rename to packages/effect/test/Schema/SchemaAST/annotations.test.ts index 73619aee85..6506f24bbe 100644 --- a/packages/schema/test/AST/annotations.test.ts +++ b/packages/effect/test/Schema/SchemaAST/annotations.test.ts @@ -1,8 +1,8 @@ -import * as AST from "@effect/schema/AST" +import * as AST from "effect/SchemaAST" import { describe, expect, it } from "vitest" describe("annotations", () => { - it("should ad annotations", () => { + it("should add annotations", () => { const symA = Symbol.for("a") const ast = AST.annotations(AST.stringKeyword, { [symA]: "A" }) expect(ast instanceof AST.StringKeyword).toBe(true) diff --git a/packages/schema/test/AST/encodedAST.test.ts b/packages/effect/test/Schema/SchemaAST/encodedAST.test.ts similarity index 96% rename from packages/schema/test/AST/encodedAST.test.ts rename to packages/effect/test/Schema/SchemaAST/encodedAST.test.ts index d27c642178..c1d416250a 100644 --- a/packages/schema/test/AST/encodedAST.test.ts +++ b/packages/effect/test/Schema/SchemaAST/encodedAST.test.ts @@ -1,5 +1,5 @@ -import * as AST from "@effect/schema/AST" -import * as S from "@effect/schema/Schema" +import * as S from "effect/Schema" +import * as AST from "effect/SchemaAST" import { describe, expect, it } from "vitest" describe("encodedAST", () => { diff --git a/packages/schema/test/AST/encodedBoundAST.test.ts b/packages/effect/test/Schema/SchemaAST/encodedBoundAST.test.ts similarity index 96% rename from packages/schema/test/AST/encodedBoundAST.test.ts rename to packages/effect/test/Schema/SchemaAST/encodedBoundAST.test.ts index 443b7ec7d8..630a3463e7 100644 --- a/packages/schema/test/AST/encodedBoundAST.test.ts +++ b/packages/effect/test/Schema/SchemaAST/encodedBoundAST.test.ts @@ -1,5 +1,5 @@ -import * as AST from "@effect/schema/AST" -import * as S from "@effect/schema/Schema" +import * as S from "effect/Schema" +import * as AST from "effect/SchemaAST" import { describe, expect, it } from "vitest" describe("encodedBoundAST", () => { diff --git a/packages/schema/test/AST/getPropertySignatures.test.ts b/packages/effect/test/Schema/SchemaAST/getPropertySignatures.test.ts similarity index 92% rename from packages/schema/test/AST/getPropertySignatures.test.ts rename to packages/effect/test/Schema/SchemaAST/getPropertySignatures.test.ts index 301643125e..239b5a4996 100644 --- a/packages/schema/test/AST/getPropertySignatures.test.ts +++ b/packages/effect/test/Schema/SchemaAST/getPropertySignatures.test.ts @@ -1,5 +1,5 @@ -import * as AST from "@effect/schema/AST" -import * as S from "@effect/schema/Schema" +import * as S from "effect/Schema" +import * as AST from "effect/SchemaAST" import { describe, expect, it } from "vitest" describe("getPropertySignatures", () => { diff --git a/packages/schema/test/AST/guards.test.ts b/packages/effect/test/Schema/SchemaAST/guards.test.ts similarity index 96% rename from packages/schema/test/AST/guards.test.ts rename to packages/effect/test/Schema/SchemaAST/guards.test.ts index 9176c83fbd..a59846b08c 100644 --- a/packages/schema/test/AST/guards.test.ts +++ b/packages/effect/test/Schema/SchemaAST/guards.test.ts @@ -1,5 +1,5 @@ -import * as AST from "@effect/schema/AST" -import * as S from "@effect/schema/Schema" +import * as S from "effect/Schema" +import * as AST from "effect/SchemaAST" import { describe, expect, it } from "vitest" describe("guards", () => { @@ -62,7 +62,7 @@ describe("guards", () => { }) it("isUniqueSymbol", () => { - expect(AST.isUniqueSymbol(S.UniqueSymbolFromSelf(Symbol.for("@effect/schema/test/a")).ast)).toEqual( + expect(AST.isUniqueSymbol(S.UniqueSymbolFromSelf(Symbol.for("effect/Schema/test/a")).ast)).toEqual( true ) expect(AST.isUniqueSymbol(S.Unknown.ast)).toEqual(false) diff --git a/packages/schema/test/AST/mutable.test.ts b/packages/effect/test/Schema/SchemaAST/mutable.test.ts similarity index 92% rename from packages/schema/test/AST/mutable.test.ts rename to packages/effect/test/Schema/SchemaAST/mutable.test.ts index e999b88168..43c14e0d4e 100644 --- a/packages/schema/test/AST/mutable.test.ts +++ b/packages/effect/test/Schema/SchemaAST/mutable.test.ts @@ -1,6 +1,6 @@ -import * as AST from "@effect/schema/AST" -import * as S from "@effect/schema/Schema" import { identity } from "effect" +import * as S from "effect/Schema" +import * as AST from "effect/SchemaAST" import { describe, expect, it } from "vitest" const expectSameReference = (schema: S.Schema.Any) => { diff --git a/packages/schema/test/AST/partial.test.ts b/packages/effect/test/Schema/SchemaAST/partial.test.ts similarity index 97% rename from packages/schema/test/AST/partial.test.ts rename to packages/effect/test/Schema/SchemaAST/partial.test.ts index 7a873cfdb8..9f9c8b249e 100644 --- a/packages/schema/test/AST/partial.test.ts +++ b/packages/effect/test/Schema/SchemaAST/partial.test.ts @@ -1,5 +1,5 @@ -import * as AST from "@effect/schema/AST" -import * as S from "@effect/schema/Schema" +import * as S from "effect/Schema" +import * as AST from "effect/SchemaAST" import { describe, expect, it } from "vitest" describe("partial", () => { diff --git a/packages/schema/test/AST/pick.test.ts b/packages/effect/test/Schema/SchemaAST/pick.test.ts similarity index 97% rename from packages/schema/test/AST/pick.test.ts rename to packages/effect/test/Schema/SchemaAST/pick.test.ts index 7f5701ddd6..7ff262af08 100644 --- a/packages/schema/test/AST/pick.test.ts +++ b/packages/effect/test/Schema/SchemaAST/pick.test.ts @@ -1,5 +1,5 @@ -import * as AST from "@effect/schema/AST" -import * as S from "@effect/schema/Schema" +import * as S from "effect/Schema" +import * as AST from "effect/SchemaAST" import { describe, expect, it } from "vitest" describe("pick", () => { diff --git a/packages/schema/test/AST/record.test.ts b/packages/effect/test/Schema/SchemaAST/record.test.ts similarity index 94% rename from packages/schema/test/AST/record.test.ts rename to packages/effect/test/Schema/SchemaAST/record.test.ts index 5ad696888e..46647ab3b9 100644 --- a/packages/schema/test/AST/record.test.ts +++ b/packages/effect/test/Schema/SchemaAST/record.test.ts @@ -1,4 +1,4 @@ -import * as AST from "@effect/schema/AST" +import * as AST from "effect/SchemaAST" import { describe, expect, it } from "vitest" describe("record", () => { diff --git a/packages/schema/test/AST/suspend.test.ts b/packages/effect/test/Schema/SchemaAST/suspend.test.ts similarity index 85% rename from packages/schema/test/AST/suspend.test.ts rename to packages/effect/test/Schema/SchemaAST/suspend.test.ts index b96fd968f6..8096266f57 100644 --- a/packages/schema/test/AST/suspend.test.ts +++ b/packages/effect/test/Schema/SchemaAST/suspend.test.ts @@ -1,6 +1,6 @@ -import type * as AST from "@effect/schema/AST" -import * as S from "@effect/schema/Schema" -import * as Util from "@effect/schema/test/TestUtils" +import * as S from "effect/Schema" +import type * as AST from "effect/SchemaAST" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" describe("AST.Suspend", () => { diff --git a/packages/schema/test/AST/toString.test.ts b/packages/effect/test/Schema/SchemaAST/toString.test.ts similarity index 95% rename from packages/schema/test/AST/toString.test.ts rename to packages/effect/test/Schema/SchemaAST/toString.test.ts index 809f9d0078..c7971e3809 100644 --- a/packages/schema/test/AST/toString.test.ts +++ b/packages/effect/test/Schema/SchemaAST/toString.test.ts @@ -1,4 +1,4 @@ -import * as S from "@effect/schema/Schema" +import * as S from "effect/Schema" import { describe, expect, it } from "vitest" describe("toString", () => { diff --git a/packages/schema/test/AST/typeAST.test.ts b/packages/effect/test/Schema/SchemaAST/typeAST.test.ts similarity index 96% rename from packages/schema/test/AST/typeAST.test.ts rename to packages/effect/test/Schema/SchemaAST/typeAST.test.ts index e386663da5..937ba1879f 100644 --- a/packages/schema/test/AST/typeAST.test.ts +++ b/packages/effect/test/Schema/SchemaAST/typeAST.test.ts @@ -1,5 +1,5 @@ -import * as AST from "@effect/schema/AST" -import * as S from "@effect/schema/Schema" +import * as S from "effect/Schema" +import * as AST from "effect/SchemaAST" import { describe, expect, it } from "vitest" describe("typeAST", () => { diff --git a/packages/schema/test/AST/unify.test.ts b/packages/effect/test/Schema/SchemaAST/unify.test.ts similarity index 96% rename from packages/schema/test/AST/unify.test.ts rename to packages/effect/test/Schema/SchemaAST/unify.test.ts index 283be60d63..65a5d1a051 100644 --- a/packages/schema/test/AST/unify.test.ts +++ b/packages/effect/test/Schema/SchemaAST/unify.test.ts @@ -1,5 +1,5 @@ -import * as AST from "@effect/schema/AST" -import * as S from "@effect/schema/Schema" +import * as S from "effect/Schema" +import * as AST from "effect/SchemaAST" import { describe, expect, it } from "vitest" const expectUnify = (input: Array, expected: Array) => { diff --git a/packages/effect/test/Schema/SchemaInternal.test.ts b/packages/effect/test/Schema/SchemaInternal.test.ts new file mode 100644 index 0000000000..612e2e7bd8 --- /dev/null +++ b/packages/effect/test/Schema/SchemaInternal.test.ts @@ -0,0 +1,39 @@ +import * as util from "effect/internal/schema/util" +import { describe, expect, it } from "vitest" + +describe("effect/internal/schema/util", () => { + it("ownKeys", () => { + expect(util.ownKeys({})).toStrictEqual([]) + expect(util.ownKeys({ a: 1 })).toStrictEqual(["a"]) + expect(util.ownKeys({ a: 1, b: 2 })).toStrictEqual(["a", "b"]) + const a = Symbol.for("effect/Schema/test/a") + const b = Symbol.for("effect/Schema/test/b") + expect(util.ownKeys({ [a]: 3, [b]: 4 })).toStrictEqual([a, b]) + expect(util.ownKeys({ a: 1, [a]: 3, b: 2, [b]: 4 })).toStrictEqual(["a", "b", a, b]) + }) + + describe("formatUnknown", () => { + it("should format symbol property signatures", () => { + expect(util.formatUnknown({ [Symbol.for("a")]: 1 })).toEqual("{Symbol(a):1}") + }) + + it("should handle unexpected errors", () => { + const circular: any = { a: null } + circular.a = circular + expect(util.formatUnknown(circular)).toEqual("[object Object]") + }) + + it("should detect data types with a custom `toString` implementation", () => { + const noToString = { a: 1 } + expect(util.formatUnknown(noToString)).toEqual(`{"a":1}`) + const ToString = Object.create({ + toString() { + return "toString custom implementation" + } + }) + expect(util.formatUnknown(ToString)).toEqual("toString custom implementation") + // should not detect arrays + expect(util.formatUnknown([1, 2, 3])).toEqual("[1,2,3]") + }) + }) +}) diff --git a/packages/schema/test/userland.test.ts b/packages/effect/test/Schema/SchemaUserland.test.ts similarity index 94% rename from packages/schema/test/userland.test.ts rename to packages/effect/test/Schema/SchemaUserland.test.ts index ca2ad618d1..17904941a7 100644 --- a/packages/schema/test/userland.test.ts +++ b/packages/effect/test/Schema/SchemaUserland.test.ts @@ -1,9 +1,8 @@ /** * It contains a collection of user-defined APIs to keep track of what might break in the event of breaking changes. */ -import { AST, Schema } from "@effect/schema" -import * as Util from "@effect/schema/test/TestUtils" -import { Record } from "effect" +import { Record, Schema, SchemaAST as AST } from "effect" +import * as Util from "effect/test/Schema/TestUtils" import { describe, expect, it } from "vitest" const structTypeSchema = ( @@ -20,7 +19,7 @@ const structTypeSchema = ( } })) as any -describe("userland", () => { +describe("SchemaUserland", () => { it("structTypeSchema", () => { // Discord: https://discordapp.com/channels/795981131316985866/847382157861060618/1266533881788502096 // goal: `Schema.typeSchema` for structs, retaining the type diff --git a/packages/schema/test/Serializable.test.ts b/packages/effect/test/Schema/Serializable.test.ts similarity index 71% rename from packages/schema/test/Serializable.test.ts rename to packages/effect/test/Schema/Serializable.test.ts index 4c78b2132c..df403bc1e3 100644 --- a/packages/schema/test/Serializable.test.ts +++ b/packages/effect/test/Schema/Serializable.test.ts @@ -1,6 +1,5 @@ -import * as S from "@effect/schema/Schema" -import * as Serializable from "@effect/schema/Serializable" import { Effect, Exit } from "effect" +import * as S from "effect/Schema" import { assert, describe, test } from "vitest" class Person extends S.Class("Person")({ @@ -11,10 +10,10 @@ class Person extends S.Class("Person")({ class GetPersonById extends S.Class("GetPersonById")({ id: S.Number }) { - get [Serializable.symbol]() { + get [S.symbolSerializable]() { return GetPersonById } - get [Serializable.symbolResult]() { + get [S.symbolWithResult]() { return { success: Person, failure: S.String, @@ -26,7 +25,7 @@ class GetPersonById extends S.Class("GetPersonById")({ describe("Serializable", () => { test("serialize", () => { const req = new GetPersonById({ id: 123 }) - assert.deepStrictEqual(Effect.runSync(Serializable.serialize(req)), { + assert.deepStrictEqual(Effect.runSync(S.serialize(req)), { id: 123 }) }) @@ -34,7 +33,7 @@ describe("Serializable", () => { test("deserialize", () => { const req = new GetPersonById({ id: 123 }) assert.deepStrictEqual( - Effect.runSync(Serializable.deserialize(req, { + Effect.runSync(S.deserialize(req, { id: 456 })), new GetPersonById({ id: 456 }) @@ -45,7 +44,7 @@ describe("Serializable", () => { const req = new GetPersonById({ id: 123 }) assert.deepStrictEqual( Effect.runSync( - Serializable.serializeFailure(req, "fail") + S.serializeFailure(req, "fail") ), "fail" ) @@ -55,7 +54,7 @@ describe("Serializable", () => { const req = new GetPersonById({ id: 123 }) assert.deepStrictEqual( Effect.runSync( - Serializable.serializeSuccess(req, new Person({ id: 123, name: "foo" })) + S.serializeSuccess(req, new Person({ id: 123, name: "foo" })) ), { id: 123, name: "foo" } ) @@ -65,13 +64,13 @@ describe("Serializable", () => { const req = new GetPersonById({ id: 123 }) assert.deepStrictEqual( Effect.runSync( - Serializable.serializeExit(req, Exit.succeed(new Person({ id: 123, name: "foo" }))) + S.serializeExit(req, Exit.succeed(new Person({ id: 123, name: "foo" }))) ), { _tag: "Success", value: { id: 123, name: "foo" } } ) assert.deepStrictEqual( Effect.runSync( - Serializable.serializeExit(req, Exit.fail("fail")) + S.serializeExit(req, Exit.fail("fail")) ), { _tag: "Failure", cause: { _tag: "Fail", error: "fail" } } ) @@ -81,7 +80,7 @@ describe("Serializable", () => { const req = new GetPersonById({ id: 123 }) assert.deepStrictEqual( Effect.runSync( - Serializable.deserializeFailure(req, "fail") + S.deserializeFailure(req, "fail") ), "fail" ) @@ -91,7 +90,7 @@ describe("Serializable", () => { const req = new GetPersonById({ id: 123 }) assert.deepStrictEqual( Effect.runSync( - Serializable.deserializeSuccess(req, { id: 123, name: "foo" }) + S.deserializeSuccess(req, { id: 123, name: "foo" }) ), new Person({ id: 123, name: "foo" }) ) @@ -101,13 +100,13 @@ describe("Serializable", () => { const req = new GetPersonById({ id: 123 }) assert.deepStrictEqual( Effect.runSync( - Serializable.deserializeExit(req, { _tag: "Success", value: { id: 123, name: "foo" } }) + S.deserializeExit(req, { _tag: "Success", value: { id: 123, name: "foo" } }) ), Exit.succeed(new Person({ id: 123, name: "foo" })) ) assert.deepStrictEqual( Effect.runSync( - Serializable.deserializeExit(req, { + S.deserializeExit(req, { _tag: "Failure", cause: { _tag: "Fail", error: "fail" } }) diff --git a/packages/schema/test/TestUtils.ts b/packages/effect/test/Schema/TestUtils.ts similarity index 95% rename from packages/schema/test/TestUtils.ts rename to packages/effect/test/Schema/TestUtils.ts index fcd5da4191..ed9a1492df 100644 --- a/packages/schema/test/TestUtils.ts +++ b/packages/effect/test/Schema/TestUtils.ts @@ -1,16 +1,15 @@ -import * as A from "@effect/schema/Arbitrary" -import type { ParseOptions } from "@effect/schema/AST" -import * as AST from "@effect/schema/AST" -import { getFinalTransformation } from "@effect/schema/ParseResult" -import * as ParseResult from "@effect/schema/ParseResult" -import * as S from "@effect/schema/Schema" -import { formatErrorSync } from "@effect/schema/TreeFormatter" +import * as A from "effect/Arbitrary" import * as Context from "effect/Context" import * as Duration from "effect/Duration" import * as Effect from "effect/Effect" import * as Either from "effect/Either" import * as Option from "effect/Option" +import { getFinalTransformation } from "effect/ParseResult" +import * as ParseResult from "effect/ParseResult" import * as Runtime from "effect/Runtime" +import * as S from "effect/Schema" +import type { ParseOptions } from "effect/SchemaAST" +import * as AST from "effect/SchemaAST" import * as fc from "fast-check" import { assert, expect } from "vitest" @@ -298,9 +297,10 @@ export const expectEffectFailure = async ( effect: Effect.Effect, message: string ) => { - expect(await Effect.runPromise(Effect.either(Effect.mapError(effect, formatErrorSync)))).toStrictEqual( - Either.left(message) - ) + expect(await Effect.runPromise(Effect.either(Effect.mapError(effect, ParseResult.TreeFormatter.formatErrorSync)))) + .toStrictEqual( + Either.left(message) + ) } export const expectEffectSuccess = async (effect: Effect.Effect, a: A) => { @@ -311,7 +311,7 @@ export const expectEffectSuccess = async (effect: Effect.Effect, a: export const expectEitherLeft = (e: Either.Either, message: string) => { if (Either.isLeft(e)) { - expect(formatErrorSync(e.left)).toStrictEqual(message) + expect(ParseResult.TreeFormatter.formatErrorSync(e.left)).toStrictEqual(message) } else { // eslint-disable-next-line no-console console.log(e.right) diff --git a/packages/experimental/examples/redis/resolver.ts b/packages/experimental/examples/redis/resolver.ts index e9b08ea2db..ae8190c586 100644 --- a/packages/experimental/examples/redis/resolver.ts +++ b/packages/experimental/examples/redis/resolver.ts @@ -1,8 +1,7 @@ import * as Redis from "@effect/experimental/Persistence/Redis" import { persisted } from "@effect/experimental/RequestResolver" import { runMain } from "@effect/platform-node/NodeRuntime" -import { Schema } from "@effect/schema" -import { Array, Effect, Exit, pipe, PrimaryKey, RequestResolver } from "effect" +import { Array, Effect, Exit, pipe, PrimaryKey, RequestResolver, Schema } from "effect" class User extends Schema.Class("User")({ id: Schema.Number, diff --git a/packages/experimental/examples/serializable-machine.ts b/packages/experimental/examples/serializable-machine.ts index f261bc51de..dcad3a59d5 100644 --- a/packages/experimental/examples/serializable-machine.ts +++ b/packages/experimental/examples/serializable-machine.ts @@ -1,7 +1,6 @@ import { Machine } from "@effect/experimental" import { runMain } from "@effect/platform-node/NodeRuntime" -import { Schema } from "@effect/schema" -import { Effect, List, pipe, Schedule } from "effect" +import { Effect, List, pipe, Schedule, Schema } from "effect" class SendError extends Schema.TaggedError()( "SendError", diff --git a/packages/experimental/package.json b/packages/experimental/package.json index 1452f80aa7..41db5c028a 100644 --- a/packages/experimental/package.json +++ b/packages/experimental/package.json @@ -44,7 +44,6 @@ "peerDependencies": { "@effect/platform": "workspace:^", "@effect/platform-node": "workspace:^", - "@effect/schema": "workspace:^", "effect": "workspace:^", "ioredis": "^5", "lmdb": "^3", diff --git a/packages/experimental/src/ChannelSchema.ts b/packages/experimental/src/ChannelSchema.ts index 988fe5ceed..033d980387 100644 --- a/packages/experimental/src/ChannelSchema.ts +++ b/packages/experimental/src/ChannelSchema.ts @@ -1,12 +1,12 @@ /** * @since 1.0.0 */ -import type { ParseError } from "@effect/schema/ParseResult" -import * as Schema from "@effect/schema/Schema" import type * as Cause from "effect/Cause" import * as Channel from "effect/Channel" import type * as Chunk from "effect/Chunk" import { dual, pipe } from "effect/Function" +import type { ParseError } from "effect/ParseResult" +import * as Schema from "effect/Schema" /** * @since 1.0.0 diff --git a/packages/experimental/src/DevTools/Domain.ts b/packages/experimental/src/DevTools/Domain.ts index 0771bac1f9..7b859b4d59 100644 --- a/packages/experimental/src/DevTools/Domain.ts +++ b/packages/experimental/src/DevTools/Domain.ts @@ -1,8 +1,8 @@ /** * @since 1.0.0 */ -import * as Schema from "@effect/schema/Schema" import type { Option } from "effect/Option" +import * as Schema from "effect/Schema" /** * @since 1.0.0 diff --git a/packages/experimental/src/Machine.ts b/packages/experimental/src/Machine.ts index b61dabd741..ae155e17d8 100644 --- a/packages/experimental/src/Machine.ts +++ b/packages/experimental/src/Machine.ts @@ -1,9 +1,6 @@ /** * @since 1.0.0 */ -import type * as ParseResult from "@effect/schema/ParseResult" -import * as Schema from "@effect/schema/Schema" -import * as Serializable from "@effect/schema/Serializable" import * as Arr from "effect/Array" import * as Cause from "effect/Cause" import * as Context from "effect/Context" @@ -17,6 +14,7 @@ import * as FiberSet from "effect/FiberSet" import { dual, identity, pipe } from "effect/Function" import { globalValue } from "effect/GlobalValue" import * as Option from "effect/Option" +import type * as ParseResult from "effect/ParseResult" import type { Pipeable } from "effect/Pipeable" import { pipeArguments } from "effect/Pipeable" import * as PubSub from "effect/PubSub" @@ -24,6 +22,7 @@ import * as Queue from "effect/Queue" import * as Readable from "effect/Readable" import type { Request } from "effect/Request" import type * as Schedule from "effect/Schedule" +import * as Schema from "effect/Schema" import type * as Scope from "effect/Scope" import * as Stream from "effect/Stream" import * as Subscribable from "effect/Subscribable" @@ -586,7 +585,7 @@ export const boot = < Effect.flatMap((req) => Effect.flatMap( Effect.exit(send(req)), - (exit) => Serializable.serializeExit(req, exit) + (exit) => Schema.serializeExit(req, exit) ) ), Effect.provide(context) diff --git a/packages/experimental/src/Machine/Procedure.ts b/packages/experimental/src/Machine/Procedure.ts index b85a1daebb..3dec66d6b5 100644 --- a/packages/experimental/src/Machine/Procedure.ts +++ b/packages/experimental/src/Machine/Procedure.ts @@ -1,13 +1,12 @@ /** * @since 1.0.0 */ -import type * as Schema from "@effect/schema/Schema" -import type * as Serializable from "@effect/schema/Serializable" import type * as Deferred from "effect/Deferred" import type * as Effect from "effect/Effect" import { type Pipeable, pipeArguments } from "effect/Pipeable" import * as Predicate from "effect/Predicate" import type { Request } from "effect/Request" +import type * as Schema from "effect/Schema" /** * @since 1.0.0 @@ -243,7 +242,7 @@ export const makeSerializable = < >( schema: Schema.Schema & { readonly _tag: Req["_tag"] }, handler: Handler -): SerializableProcedure> => ({ +): SerializableProcedure> => ({ [TypeId]: TypeId, [SerializableTypeId]: SerializableTypeId, schema: schema as any, diff --git a/packages/experimental/src/Machine/SerializableProcedureList.ts b/packages/experimental/src/Machine/SerializableProcedureList.ts index 99ba09b2fd..644d4502d2 100644 --- a/packages/experimental/src/Machine/SerializableProcedureList.ts +++ b/packages/experimental/src/Machine/SerializableProcedureList.ts @@ -1,10 +1,9 @@ /** * @since 1.0.0 */ -import type * as Schema from "@effect/schema/Schema" -import type * as Serializable from "@effect/schema/Serializable" import type * as Effect from "effect/Effect" import { dual } from "effect/Function" +import type * as Schema from "effect/Schema" import type * as Types from "effect/Types" import * as Procedure from "./Procedure.js" import * as ProcedureList from "./ProcedureList.js" @@ -59,7 +58,7 @@ export const add: { State, Req | Public, Private, - R | R2 | Serializable.SerializableWithResult.Context + R | R2 | Schema.SerializableWithResult.Context > < State, @@ -74,7 +73,7 @@ export const add: { self: SerializableProcedureList, schema: Schema.Schema & { readonly _tag: Req["_tag"] }, handler: Procedure.Handler, Types.NoInfer | Types.NoInfer, R2> - ): SerializableProcedureList> + ): SerializableProcedureList> } = dual( 3, < @@ -94,7 +93,7 @@ export const add: { State, Req | Public, Private, - R | R2 | Serializable.SerializableWithResult.Context + R | R2 | Schema.SerializableWithResult.Context > => ProcedureList.addProcedure(self, Procedure.makeSerializable()(schema, handler)) as any ) @@ -120,7 +119,7 @@ export const addPrivate: { State, Public, Private | Req, - R | R2 | Serializable.SerializableWithResult.Context + R | R2 | Schema.SerializableWithResult.Context > < State, @@ -135,7 +134,7 @@ export const addPrivate: { self: SerializableProcedureList, schema: Schema.Schema & { readonly _tag: Req["_tag"] }, handler: Procedure.Handler, Types.NoInfer | Types.NoInfer, R2> - ): SerializableProcedureList> + ): SerializableProcedureList> } = dual( 3, < @@ -155,7 +154,7 @@ export const addPrivate: { State, Public, Private | Req, - R | R2 | Serializable.SerializableWithResult.Context + R | R2 | Schema.SerializableWithResult.Context > => ProcedureList.addProcedurePrivate(self, Procedure.makeSerializable()(schema, handler)) as any ) diff --git a/packages/experimental/src/MsgPack.ts b/packages/experimental/src/MsgPack.ts index 5a1070ff9a..3352e233c8 100644 --- a/packages/experimental/src/MsgPack.ts +++ b/packages/experimental/src/MsgPack.ts @@ -1,13 +1,13 @@ /** * @since 1.0.0 */ -import type { ParseError } from "@effect/schema/ParseResult" -import type * as Schema from "@effect/schema/Schema" import * as Channel from "effect/Channel" import * as Chunk from "effect/Chunk" import * as Data from "effect/Data" import * as Effect from "effect/Effect" import { dual } from "effect/Function" +import type { ParseError } from "effect/ParseResult" +import type * as Schema from "effect/Schema" import { Packr, Unpackr } from "msgpackr" import * as ChannelSchema from "./ChannelSchema.js" diff --git a/packages/experimental/src/Ndjson.ts b/packages/experimental/src/Ndjson.ts index 6bbb9df31d..cd950499ec 100644 --- a/packages/experimental/src/Ndjson.ts +++ b/packages/experimental/src/Ndjson.ts @@ -2,13 +2,13 @@ * @since 1.0.0 */ import { TypeIdError } from "@effect/platform/Error" -import type { ParseError } from "@effect/schema/ParseResult" -import type * as Schema from "@effect/schema/Schema" import type * as Cause from "effect/Cause" import * as Channel from "effect/Channel" import * as Chunk from "effect/Chunk" import * as Effect from "effect/Effect" import { dual, identity } from "effect/Function" +import type { ParseError } from "effect/ParseResult" +import type * as Schema from "effect/Schema" import * as ChannelSchema from "./ChannelSchema.js" /** diff --git a/packages/experimental/src/PersistedCache.ts b/packages/experimental/src/PersistedCache.ts index 63a7a16c6f..e4fe7777d0 100644 --- a/packages/experimental/src/PersistedCache.ts +++ b/packages/experimental/src/PersistedCache.ts @@ -1,7 +1,6 @@ /** * @since 1.0.0 */ -import type * as Serializable from "@effect/schema/Serializable" import * as Cache from "effect/Cache" import * as Data from "effect/Data" import type * as Duration from "effect/Duration" @@ -10,6 +9,7 @@ import * as Equal from "effect/Equal" import { identity, pipe } from "effect/Function" import * as Hash from "effect/Hash" import * as Option from "effect/Option" +import type * as Schema from "effect/Schema" import type * as Scope from "effect/Scope" import * as Tracer from "effect/Tracer" import * as Persistence from "./Persistence.js" @@ -34,8 +34,8 @@ export interface PersistedCache readonly get: ( key: K ) => Effect.Effect< - Serializable.WithResult.Success, - Serializable.WithResult.Failure | Persistence.PersistenceError + Schema.WithResult.Success, + Schema.WithResult.Failure | Persistence.PersistenceError > readonly invalidate: (key: K) => Effect.Effect } @@ -46,14 +46,14 @@ export interface PersistedCache */ export const make = (options: { readonly storeId: string - readonly lookup: (key: K) => Effect.Effect, Serializable.WithResult.Failure, R> + readonly lookup: (key: K) => Effect.Effect, Schema.WithResult.Failure, R> readonly timeToLive: (...args: Persistence.ResultPersistence.TimeToLiveArgs) => Duration.DurationInput readonly inMemoryCapacity?: number | undefined readonly inMemoryTTL?: Duration.DurationInput | undefined }): Effect.Effect< PersistedCache, never, - Serializable.SerializableWithResult.Context | R | Persistence.ResultPersistence | Scope.Scope + Schema.SerializableWithResult.Context | R | Persistence.ResultPersistence | Scope.Scope > => Persistence.ResultPersistence.pipe( Effect.flatMap((_) => @@ -67,9 +67,9 @@ export const make = (options: Cache.make({ lookup: (request: CacheRequest) => { const effect: Effect.Effect< - Serializable.WithResult.Success, - Serializable.WithResult.Failure | Persistence.PersistenceError, - Serializable.SerializableWithResult.Context | R + Schema.WithResult.Success, + Schema.WithResult.Failure | Persistence.PersistenceError, + Schema.SerializableWithResult.Context | R > = pipe( store.get(request.key as any), Effect.flatMap(Option.match({ diff --git a/packages/experimental/src/Persistence.ts b/packages/experimental/src/Persistence.ts index 109bd073e8..6af3103f47 100644 --- a/packages/experimental/src/Persistence.ts +++ b/packages/experimental/src/Persistence.ts @@ -3,9 +3,6 @@ */ import { TypeIdError } from "@effect/platform/Error" import * as KeyValueStore from "@effect/platform/KeyValueStore" -import type * as ParseResult from "@effect/schema/ParseResult" -import * as Serializable from "@effect/schema/Serializable" -import * as TreeFormatter from "@effect/schema/TreeFormatter" import type * as Clock from "effect/Clock" import * as Context from "effect/Context" import * as Duration from "effect/Duration" @@ -14,7 +11,9 @@ import type * as Exit from "effect/Exit" import { identity } from "effect/Function" import * as Layer from "effect/Layer" import * as Option from "effect/Option" +import * as ParseResult from "effect/ParseResult" import * as PrimaryKey from "effect/PrimaryKey" +import * as Schema from "effect/Schema" import type * as Scope from "effect/Scope" /** @@ -52,7 +51,7 @@ export class PersistenceParseError extends TypeIdError(ErrorTypeId, "Persistence } get message() { - return TreeFormatter.formatIssueSync(this.error) + return ParseResult.TreeFormatter.formatIssueSync(this.error) } } @@ -178,7 +177,7 @@ export declare namespace ResultPersistence { * @since 1.0.0 * @category models */ - export interface Key extends Serializable.WithResult, PrimaryKey.PrimaryKey {} + export interface Key extends Schema.WithResult, PrimaryKey.PrimaryKey {} /** * @since 1.0.0 @@ -226,7 +225,7 @@ export const layerResult = Layer.effect( value: unknown ) => Effect.mapError( - Serializable.deserializeExit(key, value), + Schema.deserializeExit(key, value), (_) => PersistenceParseError.make(method, _.issue) ) const encode = ( @@ -235,7 +234,7 @@ export const layerResult = Layer.effect( value: Exit.Exit ) => Effect.mapError( - Serializable.serializeExit(key, value), + Schema.serializeExit(key, value), (_) => PersistenceParseError.make(method, _.issue) ) const makeKey = ( diff --git a/packages/experimental/src/RequestResolver.ts b/packages/experimental/src/RequestResolver.ts index 64bc85f9cd..de84d47f5f 100644 --- a/packages/experimental/src/RequestResolver.ts +++ b/packages/experimental/src/RequestResolver.ts @@ -1,7 +1,6 @@ /** * @since 1.0.0 */ -import type * as Serializable from "@effect/schema/Serializable" import * as Arr from "effect/Array" import * as Deferred from "effect/Deferred" import type * as Duration from "effect/Duration" @@ -12,6 +11,7 @@ import { dual, pipe } from "effect/Function" import * as Option from "effect/Option" import * as Request from "effect/Request" import * as RequestResolver from "effect/RequestResolver" +import type * as Schema from "effect/Schema" import type * as Scope from "effect/Scope" import * as Persistence from "./Persistence.js" @@ -110,9 +110,7 @@ export const dataLoader = dual< * @since 1.0.0 * @category model */ -export interface PersistedRequest - extends Request.Request, Serializable.WithResult -{} +export interface PersistedRequest extends Request.Request, Schema.WithResult {} /** * @since 1.0.0 @@ -137,7 +135,7 @@ export const persisted: { }): ( self: RequestResolver.RequestResolver ) => Effect.Effect< - RequestResolver.RequestResolver>, + RequestResolver.RequestResolver>, never, Persistence.ResultPersistence | Scope.Scope > @@ -148,7 +146,7 @@ export const persisted: { readonly timeToLive: (...args: Persistence.ResultPersistence.TimeToLiveArgs) => Duration.DurationInput } ): Effect.Effect< - RequestResolver.RequestResolver>, + RequestResolver.RequestResolver>, never, Persistence.ResultPersistence | Scope.Scope > @@ -159,7 +157,7 @@ export const persisted: { readonly timeToLive: (...args: Persistence.ResultPersistence.TimeToLiveArgs) => Duration.DurationInput } ): Effect.Effect< - RequestResolver.RequestResolver>, + RequestResolver.RequestResolver>, never, Persistence.ResultPersistence | Scope.Scope > => diff --git a/packages/experimental/src/VariantSchema.ts b/packages/experimental/src/VariantSchema.ts index baa072dfae..c3bfa43e86 100644 --- a/packages/experimental/src/VariantSchema.ts +++ b/packages/experimental/src/VariantSchema.ts @@ -1,15 +1,15 @@ /** * @since 1.0.0 */ -import type * as AST from "@effect/schema/AST" -import * as ParseResult from "@effect/schema/ParseResult" -import * as Schema from "@effect/schema/Schema" import type { Brand } from "effect/Brand" import type * as Effect from "effect/Effect" import { constUndefined, dual } from "effect/Function" import * as Option from "effect/Option" +import * as ParseResult from "effect/ParseResult" import { type Pipeable, pipeArguments } from "effect/Pipeable" import * as Predicate from "effect/Predicate" +import * as Schema from "effect/Schema" +import type * as AST from "effect/SchemaAST" import * as Struct_ from "effect/Struct" /** diff --git a/packages/experimental/test/Machine.test.ts b/packages/experimental/test/Machine.test.ts index 35ad6c528d..d4379b6c94 100644 --- a/packages/experimental/test/Machine.test.ts +++ b/packages/experimental/test/Machine.test.ts @@ -1,7 +1,6 @@ import * as DevTools from "@effect/experimental/DevTools" import * as Machine from "@effect/experimental/Machine" -import { Schema } from "@effect/schema" -import { Cause, Chunk, Context, Deferred, Effect, Exit, Layer, Stream } from "effect" +import { Cause, Chunk, Context, Deferred, Effect, Exit, Layer, Schema, Stream } from "effect" import { assert, describe, test } from "vitest" class Increment diff --git a/packages/experimental/test/PersistedCache.test.ts b/packages/experimental/test/PersistedCache.test.ts index 4932ce7eee..7835031fd5 100644 --- a/packages/experimental/test/PersistedCache.test.ts +++ b/packages/experimental/test/PersistedCache.test.ts @@ -1,9 +1,8 @@ import * as PersistedCache from "@effect/experimental/PersistedCache" import * as Persistence from "@effect/experimental/Persistence" import { KeyValueStore } from "@effect/platform" -import { Schema } from "@effect/schema" import * as it from "@effect/vitest" -import { Effect, Exit, Layer, Option, PrimaryKey } from "effect" +import { Effect, Exit, Layer, Option, PrimaryKey, Schema } from "effect" import { assert, describe } from "vitest" class User extends Schema.Class("User")({ diff --git a/packages/experimental/test/RequestResolver.test.ts b/packages/experimental/test/RequestResolver.test.ts index 3b4c6567ff..4919e661d9 100644 --- a/packages/experimental/test/RequestResolver.test.ts +++ b/packages/experimental/test/RequestResolver.test.ts @@ -1,9 +1,8 @@ import * as Persistence from "@effect/experimental/Persistence" import * as RequestResolverX from "@effect/experimental/RequestResolver" import { KeyValueStore } from "@effect/platform" -import { Schema } from "@effect/schema" import * as it from "@effect/vitest" -import { Array, Effect, Exit, Layer, PrimaryKey, Request, RequestResolver, TestClock } from "effect" +import { Array, Effect, Exit, Layer, PrimaryKey, Request, RequestResolver, Schema, TestClock } from "effect" import type { NonEmptyArray } from "effect/Array" import { assert, describe } from "vitest" diff --git a/packages/experimental/tsconfig.build.json b/packages/experimental/tsconfig.build.json index 91a6b15dd1..7c11a4a9a2 100644 --- a/packages/experimental/tsconfig.build.json +++ b/packages/experimental/tsconfig.build.json @@ -2,7 +2,6 @@ "extends": "./tsconfig.src.json", "references": [ { "path": "../effect/tsconfig.build.json" }, - { "path": "../schema/tsconfig.build.json" }, { "path": "../platform/tsconfig.build.json" }, { "path": "../platform-node/tsconfig.build.json" } ], diff --git a/packages/experimental/tsconfig.src.json b/packages/experimental/tsconfig.src.json index b69f2cb4a2..b9a4b19b34 100644 --- a/packages/experimental/tsconfig.src.json +++ b/packages/experimental/tsconfig.src.json @@ -3,7 +3,6 @@ "include": ["src"], "references": [ { "path": "../effect" }, - { "path": "../schema" }, { "path": "../platform" }, { "path": "../platform-node" } ], diff --git a/packages/experimental/tsconfig.test.json b/packages/experimental/tsconfig.test.json index a08c5c9767..fc764a2b8b 100644 --- a/packages/experimental/tsconfig.test.json +++ b/packages/experimental/tsconfig.test.json @@ -4,7 +4,6 @@ "references": [ { "path": "tsconfig.src.json" }, { "path": "../effect" }, - { "path": "../schema" }, { "path": "../platform-node" }, { "path": "../vitest" } ], diff --git a/packages/platform-browser/package.json b/packages/platform-browser/package.json index d28a12daac..dfa297fd4e 100644 --- a/packages/platform-browser/package.json +++ b/packages/platform-browser/package.json @@ -46,7 +46,6 @@ }, "devDependencies": { "@effect/platform": "workspace:^", - "@effect/schema": "workspace:^", "effect": "workspace:^", "happy-dom": "^14.12.3", "mock-xmlhttprequest": "^8.3.0" diff --git a/packages/platform-browser/test/fixtures/schema.ts b/packages/platform-browser/test/fixtures/schema.ts index 41dc3e098a..b1875d4910 100644 --- a/packages/platform-browser/test/fixtures/schema.ts +++ b/packages/platform-browser/test/fixtures/schema.ts @@ -1,5 +1,5 @@ import * as Transferable from "@effect/platform/Transferable" -import * as Schema from "@effect/schema/Schema" +import * as Schema from "effect/Schema" export class User extends Schema.Class("User")({ id: Schema.Number, diff --git a/packages/platform-browser/tsconfig.build.json b/packages/platform-browser/tsconfig.build.json index 6c869dff9b..29b272747c 100644 --- a/packages/platform-browser/tsconfig.build.json +++ b/packages/platform-browser/tsconfig.build.json @@ -2,8 +2,7 @@ "extends": "./tsconfig.src.json", "references": [ { "path": "../platform/tsconfig.build.json" }, - { "path": "../effect/tsconfig.build.json" }, - { "path": "../schema/tsconfig.build.json" } + { "path": "../effect/tsconfig.build.json" } ], "compilerOptions": { "tsBuildInfoFile": ".tsbuildinfo/build.tsbuildinfo", diff --git a/packages/platform-browser/tsconfig.examples.json b/packages/platform-browser/tsconfig.examples.json index 6381f808cf..5bfd607147 100644 --- a/packages/platform-browser/tsconfig.examples.json +++ b/packages/platform-browser/tsconfig.examples.json @@ -1,11 +1,7 @@ { "extends": "../../tsconfig.base.json", "include": ["examples"], - "references": [ - { "path": "tsconfig.src.json" }, - { "path": "../effect" }, - { "path": "../schema" } - ], + "references": [{ "path": "tsconfig.src.json" }, { "path": "../effect" }], "compilerOptions": { "tsBuildInfoFile": ".tsbuildinfo/examples.tsbuildinfo", "rootDir": "examples", diff --git a/packages/platform-browser/tsconfig.src.json b/packages/platform-browser/tsconfig.src.json index 9f8bba5ff1..3ee0560b5b 100644 --- a/packages/platform-browser/tsconfig.src.json +++ b/packages/platform-browser/tsconfig.src.json @@ -1,11 +1,7 @@ { "extends": "../../tsconfig.base.json", "include": ["src"], - "references": [ - { "path": "../platform" }, - { "path": "../effect" }, - { "path": "../schema" } - ], + "references": [{ "path": "../platform" }, { "path": "../effect" }], "compilerOptions": { "tsBuildInfoFile": ".tsbuildinfo/src.tsbuildinfo", "rootDir": "src", diff --git a/packages/platform-browser/tsconfig.test.json b/packages/platform-browser/tsconfig.test.json index 2cc45b5004..d18d744cb9 100644 --- a/packages/platform-browser/tsconfig.test.json +++ b/packages/platform-browser/tsconfig.test.json @@ -4,7 +4,6 @@ "references": [ { "path": "tsconfig.src.json" }, { "path": "../effect" }, - { "path": "../schema" }, { "path": "../vitest" } ], "compilerOptions": { diff --git a/packages/platform-bun/examples/http-client.ts b/packages/platform-bun/examples/http-client.ts index eeaab80b82..7c27e3e633 100644 --- a/packages/platform-bun/examples/http-client.ts +++ b/packages/platform-bun/examples/http-client.ts @@ -1,9 +1,9 @@ import { FetchHttpClient, HttpClient, HttpClientRequest, HttpClientResponse } from "@effect/platform" import type { HttpBody, HttpClientError } from "@effect/platform" import { BunRuntime } from "@effect/platform-bun" -import type * as ParseResult from "@effect/schema/ParseResult" -import * as Schema from "@effect/schema/Schema" import { Context, Effect, Layer } from "effect" +import type * as ParseResult from "effect/ParseResult" +import * as Schema from "effect/Schema" class Todo extends Schema.Class("Todo")({ userId: Schema.Number, diff --git a/packages/platform-bun/examples/http-router.ts b/packages/platform-bun/examples/http-router.ts index a72d892c56..ffc3636074 100644 --- a/packages/platform-bun/examples/http-router.ts +++ b/packages/platform-bun/examples/http-router.ts @@ -8,8 +8,7 @@ import { Multipart } from "@effect/platform" import { BunHttpServer, BunRuntime } from "@effect/platform-bun" -import { Schema } from "@effect/schema" -import { Effect, Layer, Schedule, Stream } from "effect" +import { Effect, Layer, Schedule, Schema, Stream } from "effect" const ServerLive = BunHttpServer.layer({ port: 3000 }) diff --git a/packages/platform-bun/package.json b/packages/platform-bun/package.json index 940cbedd1c..c12a0714e9 100644 --- a/packages/platform-bun/package.json +++ b/packages/platform-bun/package.json @@ -49,7 +49,6 @@ }, "devDependencies": { "@effect/platform": "workspace:^", - "@effect/schema": "workspace:^", "bun-types": "1.1.22", "effect": "workspace:^" } diff --git a/packages/platform-node-shared/package.json b/packages/platform-node-shared/package.json index 759ecba6ba..75793e3850 100644 --- a/packages/platform-node-shared/package.json +++ b/packages/platform-node-shared/package.json @@ -50,7 +50,6 @@ }, "devDependencies": { "@effect/platform": "workspace:^", - "@effect/schema": "workspace:^", "@types/node": "^20.14.10", "@types/tar": "^6.1.12", "effect": "workspace:^", diff --git a/packages/platform-node-shared/tsconfig.build.json b/packages/platform-node-shared/tsconfig.build.json index 3daf2f819b..8326d06ca2 100644 --- a/packages/platform-node-shared/tsconfig.build.json +++ b/packages/platform-node-shared/tsconfig.build.json @@ -2,8 +2,7 @@ "extends": "./tsconfig.src.json", "references": [ { "path": "../platform/tsconfig.build.json" }, - { "path": "../effect/tsconfig.build.json" }, - { "path": "../schema/tsconfig.build.json" } + { "path": "../effect/tsconfig.build.json" } ], "compilerOptions": { "tsBuildInfoFile": ".tsbuildinfo/build.tsbuildinfo", diff --git a/packages/platform-node-shared/tsconfig.src.json b/packages/platform-node-shared/tsconfig.src.json index 9f8bba5ff1..3ee0560b5b 100644 --- a/packages/platform-node-shared/tsconfig.src.json +++ b/packages/platform-node-shared/tsconfig.src.json @@ -1,11 +1,7 @@ { "extends": "../../tsconfig.base.json", "include": ["src"], - "references": [ - { "path": "../platform" }, - { "path": "../effect" }, - { "path": "../schema" } - ], + "references": [{ "path": "../platform" }, { "path": "../effect" }], "compilerOptions": { "tsBuildInfoFile": ".tsbuildinfo/src.tsbuildinfo", "rootDir": "src", diff --git a/packages/platform-node-shared/tsconfig.test.json b/packages/platform-node-shared/tsconfig.test.json index 83ffe0b19d..5a2ff4b794 100644 --- a/packages/platform-node-shared/tsconfig.test.json +++ b/packages/platform-node-shared/tsconfig.test.json @@ -4,8 +4,7 @@ "references": [ { "path": "tsconfig.src.json" }, { "path": "../platform" }, - { "path": "../effect" }, - { "path": "../schema" } + { "path": "../effect" } ], "compilerOptions": { "tsBuildInfoFile": ".tsbuildinfo/test.tsbuildinfo", diff --git a/packages/platform-node/docgen.json b/packages/platform-node/docgen.json index 7eb6dd18b3..800dd65617 100644 --- a/packages/platform-node/docgen.json +++ b/packages/platform-node/docgen.json @@ -21,9 +21,7 @@ ], "@effect/platform-node-shared/*": [ "../../../platform-node-shared/src/*.js" - ], - "@effect/schema": ["../../../schema/src/index.js"], - "@effect/schema/*": ["../../../schema/src/*.js"] + ] } } } diff --git a/packages/platform-node/examples/api.ts b/packages/platform-node/examples/api.ts index 31f9da08fd..a985c091e1 100644 --- a/packages/platform-node/examples/api.ts +++ b/packages/platform-node/examples/api.ts @@ -13,8 +13,7 @@ import { OpenApi } from "@effect/platform" import { NodeHttpServer, NodeRuntime } from "@effect/platform-node" -import { Schema } from "@effect/schema" -import { Context, Effect, Layer, Redacted } from "effect" +import { Context, Effect, Layer, Redacted, Schema } from "effect" import { createServer } from "node:http" class User extends Schema.Class("User")({ diff --git a/packages/platform-node/examples/http-client.ts b/packages/platform-node/examples/http-client.ts index abcaf80891..5c65d4503e 100644 --- a/packages/platform-node/examples/http-client.ts +++ b/packages/platform-node/examples/http-client.ts @@ -2,11 +2,11 @@ import type { HttpBody, HttpClientError } from "@effect/platform" import { HttpClient, HttpClientRequest, HttpClientResponse } from "@effect/platform" import { NodeHttpClient } from "@effect/platform-node" import { runMain } from "@effect/platform-node/NodeRuntime" -import type * as ParseResult from "@effect/schema/ParseResult" -import * as Schema from "@effect/schema/Schema" import * as Context from "effect/Context" import * as Effect from "effect/Effect" import * as Layer from "effect/Layer" +import type * as ParseResult from "effect/ParseResult" +import * as Schema from "effect/Schema" class Todo extends Schema.Class("Todo")({ userId: Schema.Number, diff --git a/packages/platform-node/examples/http-router.ts b/packages/platform-node/examples/http-router.ts index f656e19343..67c0ca34f9 100644 --- a/packages/platform-node/examples/http-router.ts +++ b/packages/platform-node/examples/http-router.ts @@ -7,8 +7,8 @@ import { Multipart } from "@effect/platform" import { NodeHttpServer, NodeRuntime } from "@effect/platform-node" -import * as Schema from "@effect/schema/Schema" import { Effect, Layer, Schedule, Stream } from "effect" +import * as Schema from "effect/Schema" import { createServer } from "node:http" const ServerLive = NodeHttpServer.layer(() => createServer(), { port: 3000 }) diff --git a/packages/platform-node/package.json b/packages/platform-node/package.json index 9e9caf44b4..8b673c6643 100644 --- a/packages/platform-node/package.json +++ b/packages/platform-node/package.json @@ -55,7 +55,6 @@ }, "devDependencies": { "@effect/platform": "workspace:^", - "@effect/schema": "workspace:^", "@types/mime": "^3.0.4", "@types/node": "^20.14.10", "@types/ws": "^8.5.12", diff --git a/packages/platform-node/test/HttpApi.test.ts b/packages/platform-node/test/HttpApi.test.ts index a9a513ccea..8b3b6aaca4 100644 --- a/packages/platform-node/test/HttpApi.test.ts +++ b/packages/platform-node/test/HttpApi.test.ts @@ -15,9 +15,8 @@ import { OpenApi } from "@effect/platform" import { NodeHttpServer } from "@effect/platform-node" -import { Schema } from "@effect/schema" import { assert, describe, it } from "@effect/vitest" -import { Context, DateTime, Effect, Layer, Redacted, Ref, Struct } from "effect" +import { Context, DateTime, Effect, Layer, Redacted, Ref, Schema, Struct } from "effect" import OpenApiFixture from "./fixtures/openapi.json" describe("HttpApi", () => { diff --git a/packages/platform-node/test/HttpClient.test.ts b/packages/platform-node/test/HttpClient.test.ts index 80e116a31f..29768f8a0b 100644 --- a/packages/platform-node/test/HttpClient.test.ts +++ b/packages/platform-node/test/HttpClient.test.ts @@ -1,11 +1,11 @@ import { HttpClient, HttpClientRequest, HttpClientResponse } from "@effect/platform" import * as NodeClient from "@effect/platform-node/NodeHttpClient" -import * as Schema from "@effect/schema/Schema" import { describe, expect, it } from "@effect/vitest" import { Struct } from "effect" import * as Context from "effect/Context" import * as Effect from "effect/Effect" import * as Layer from "effect/Layer" +import * as Schema from "effect/Schema" import * as Stream from "effect/Stream" const Todo = Schema.Struct({ diff --git a/packages/platform-node/test/HttpServer.test.ts b/packages/platform-node/test/HttpServer.test.ts index ebbd9877f4..69c8bf1927 100644 --- a/packages/platform-node/test/HttpServer.test.ts +++ b/packages/platform-node/test/HttpServer.test.ts @@ -16,11 +16,11 @@ import { UrlParams } from "@effect/platform" import { NodeHttpServer } from "@effect/platform-node" -import * as Schema from "@effect/schema/Schema" import { assert, describe, expect, it } from "@effect/vitest" import { Deferred, Duration, Fiber, Stream } from "effect" import * as Effect from "effect/Effect" import * as Option from "effect/Option" +import * as Schema from "effect/Schema" import * as Tracer from "effect/Tracer" import * as Buffer from "node:buffer" diff --git a/packages/platform-node/tsconfig.build.json b/packages/platform-node/tsconfig.build.json index adf744ff0b..8c484b04df 100644 --- a/packages/platform-node/tsconfig.build.json +++ b/packages/platform-node/tsconfig.build.json @@ -3,8 +3,7 @@ "references": [ { "path": "../platform/tsconfig.build.json" }, { "path": "../platform-node-shared/tsconfig.build.json" }, - { "path": "../effect/tsconfig.build.json" }, - { "path": "../schema/tsconfig.build.json" } + { "path": "../effect/tsconfig.build.json" } ], "compilerOptions": { "tsBuildInfoFile": ".tsbuildinfo/build.tsbuildinfo", diff --git a/packages/platform-node/tsconfig.src.json b/packages/platform-node/tsconfig.src.json index 230a9a264f..cf9e9e7e52 100644 --- a/packages/platform-node/tsconfig.src.json +++ b/packages/platform-node/tsconfig.src.json @@ -4,8 +4,7 @@ "references": [ { "path": "../platform" }, { "path": "../platform-node-shared" }, - { "path": "../effect" }, - { "path": "../schema" } + { "path": "../effect" } ], "compilerOptions": { "tsBuildInfoFile": ".tsbuildinfo/src.tsbuildinfo", diff --git a/packages/platform-node/tsconfig.test.json b/packages/platform-node/tsconfig.test.json index 5eae292c72..40f0a8ec7d 100644 --- a/packages/platform-node/tsconfig.test.json +++ b/packages/platform-node/tsconfig.test.json @@ -6,7 +6,6 @@ { "path": "../platform" }, { "path": "../platform-node-shared" }, { "path": "../effect" }, - { "path": "../schema" }, { "path": "../vitest" } ], "compilerOptions": { diff --git a/packages/platform/README.md b/packages/platform/README.md index 7c960f3362..c03df934ce 100644 --- a/packages/platform/README.md +++ b/packages/platform/README.md @@ -32,7 +32,7 @@ Let's define a simple CRUD API for managing users. First, we need to make an ```ts import { HttpApiEndpoint, HttpApiGroup } from "@effect/platform" -import { Schema } from "@effect/schema" +import { Schema } from "effect" // Our domain "User" Schema class User extends Schema.Class("User")({ @@ -306,8 +306,7 @@ import { HttpApiEndpoint, HttpApiGroup } from "@effect/platform" -import { Schema } from "@effect/schema" -import { DateTime, Effect } from "effect" +import { DateTime, Effect, Schema } from "effect" // here is our api definition class User extends Schema.Class("User")({ @@ -1161,7 +1160,7 @@ string { ### Decoding Data with Schemas -A common use case when fetching data is to validate the received format. For this purpose, the `HttpClientResponse` module is integrated with `@effect/schema`. +A common use case when fetching data is to validate the received format. For this purpose, the `HttpClientResponse` module is integrated with `effect/Schema`. ```ts import { @@ -1170,8 +1169,7 @@ import { HttpClientResponse } from "@effect/platform" import { NodeRuntime } from "@effect/platform-node" -import { Schema } from "@effect/schema" -import { Console, Effect } from "effect" +import { Console, Effect, Schema } from "effect" const Post = Schema.Struct({ id: Schema.Number, @@ -1329,7 +1327,7 @@ Output: ### Decoding Data with Schemas -A common use case when fetching data is to validate the received format. For this purpose, the `HttpClientResponse` module is integrated with `@effect/schema`. +A common use case when fetching data is to validate the received format. For this purpose, the `HttpClientResponse` module is integrated with `effect/Schema`. ```ts import { @@ -1339,8 +1337,7 @@ import { HttpClientResponse } from "@effect/platform" import { NodeRuntime } from "@effect/platform-node" -import { Schema } from "@effect/schema" -import { Console, Effect } from "effect" +import { Console, Effect, Schema } from "effect" const Post = Schema.Struct({ id: Schema.Number, @@ -1717,8 +1714,7 @@ To define routes with parameters, include the parameter names in the path and us ```ts import { HttpRouter, HttpServer, HttpServerResponse } from "@effect/platform" -import { Schema } from "@effect/schema" -import { Effect } from "effect" +import { Effect, Schema } from "effect" import { listen } from "./listen.js" // Define the schema for route parameters @@ -2408,7 +2404,7 @@ curl -i http://localhost:3000/fail ## Validations -Validation is a critical aspect of handling HTTP requests to ensure that the data your server receives is as expected. We'll explore how to validate headers and cookies using the `@effect/platform` and `@effect/schema` libraries, which provide structured and robust methods for these tasks. +Validation is a critical aspect of handling HTTP requests to ensure that the data your server receives is as expected. We'll explore how to validate headers and cookies using the `@effect/platform` and `effect/Schema` libraries, which provide structured and robust methods for these tasks. ### Headers @@ -2421,8 +2417,7 @@ import { HttpServerRequest, HttpServerResponse } from "@effect/platform" -import { Schema } from "@effect/schema" -import { Effect } from "effect" +import { Effect, Schema } from "effect" import { listen } from "./listen.js" const router = HttpRouter.empty.pipe( @@ -2472,8 +2467,7 @@ import { HttpServerRequest, HttpServerResponse } from "@effect/platform" -import { Schema } from "@effect/schema" -import { Effect } from "effect" +import { Effect, Schema } from "effect" import { listen } from "./listen.js" const router = HttpRouter.empty.pipe( diff --git a/packages/platform/docgen.json b/packages/platform/docgen.json index c9859259e4..42c17df2c0 100644 --- a/packages/platform/docgen.json +++ b/packages/platform/docgen.json @@ -1,8 +1,6 @@ { "$schema": "../../node_modules/@effect/docgen/schema.json", - "exclude": [ - "src/internal/**/*.ts" - ], + "exclude": ["src/internal/**/*.ts"], "examplesCompilerOptions": { "noEmit": true, "strict": true, @@ -10,48 +8,22 @@ "moduleResolution": "Bundler", "module": "ES2022", "target": "ES2022", - "lib": [ - "ES2022", - "DOM", - "DOM.Iterable" - ], + "lib": ["ES2022", "DOM", "DOM.Iterable"], "paths": { - "effect": [ - "../../../effect/src/index.js" - ], - "effect/*": [ - "../../../effect/src/*.js" - ], - "@effect/platform": [ - "../../../platform/src/index.js" - ], - "@effect/platform/*": [ - "../../../platform/src/*.js" - ], - "@effect/platform-node": [ - "../../../platform-node/src/index.js" - ], - "@effect/platform-node/*": [ - "../../../platform-node/src/*.js" - ], + "effect": ["../../../effect/src/index.js"], + "effect/*": ["../../../effect/src/*.js"], + "@effect/platform": ["../../../platform/src/index.js"], + "@effect/platform/*": ["../../../platform/src/*.js"], + "@effect/platform-node": ["../../../platform-node/src/index.js"], + "@effect/platform-node/*": ["../../../platform-node/src/*.js"], "@effect/platform-node-shared": [ "../../../platform-node-shared/src/index.js" ], "@effect/platform-node-shared/*": [ "../../../platform-node-shared/src/*.js" ], - "@effect/schema": [ - "../../../schema/src/index.js" - ], - "@effect/schema/*": [ - "../../../schema/src/*.js" - ], - "@effect/typeclass": [ - "../../../typeclass/src/index.js" - ], - "@effect/typeclass/*": [ - "../../../typeclass/src/*.js" - ] + "@effect/typeclass": ["../../../typeclass/src/index.js"], + "@effect/typeclass/*": ["../../../typeclass/src/*.js"] } } } diff --git a/packages/platform/package.json b/packages/platform/package.json index 5ae4eac301..ff3ea5efbf 100644 --- a/packages/platform/package.json +++ b/packages/platform/package.json @@ -44,11 +44,9 @@ "multipasta": "^0.2.5" }, "peerDependencies": { - "@effect/schema": "workspace:^", "effect": "workspace:^" }, "devDependencies": { - "@effect/schema": "workspace:^", "ajv": "^8.17.1", "effect": "workspace:^" } diff --git a/packages/platform/src/Headers.ts b/packages/platform/src/Headers.ts index 844c751552..ec2508e5fd 100644 --- a/packages/platform/src/Headers.ts +++ b/packages/platform/src/Headers.ts @@ -1,7 +1,6 @@ /** * @since 1.0.0 */ -import * as Schema from "@effect/schema/Schema" import * as FiberRef from "effect/FiberRef" import { dual, identity } from "effect/Function" import { globalValue } from "effect/GlobalValue" @@ -9,6 +8,7 @@ import type * as Option from "effect/Option" import * as Predicate from "effect/Predicate" import * as Record from "effect/Record" import * as Redacted from "effect/Redacted" +import * as Schema from "effect/Schema" import * as String from "effect/String" import type { Mutable } from "effect/Types" diff --git a/packages/platform/src/HttpApi.ts b/packages/platform/src/HttpApi.ts index dc361cf102..2a941edf7f 100644 --- a/packages/platform/src/HttpApi.ts +++ b/packages/platform/src/HttpApi.ts @@ -1,8 +1,6 @@ /** * @since 1.0.0 */ -import * as AST from "@effect/schema/AST" -import type * as Schema from "@effect/schema/Schema" import * as Chunk from "effect/Chunk" import * as Context from "effect/Context" import { dual } from "effect/Function" @@ -10,6 +8,8 @@ import * as Option from "effect/Option" import type { Pipeable } from "effect/Pipeable" import { pipeArguments } from "effect/Pipeable" import * as Predicate from "effect/Predicate" +import type * as Schema from "effect/Schema" +import * as AST from "effect/SchemaAST" import * as HttpApiEndpoint from "./HttpApiEndpoint.js" import { HttpApiDecodeError } from "./HttpApiError.js" import * as HttpApiGroup from "./HttpApiGroup.js" diff --git a/packages/platform/src/HttpApiBuilder.ts b/packages/platform/src/HttpApiBuilder.ts index 1ead6c5cad..79c45b0ac2 100644 --- a/packages/platform/src/HttpApiBuilder.ts +++ b/packages/platform/src/HttpApiBuilder.ts @@ -1,9 +1,6 @@ /** * @since 1.0.0 */ -import * as AST from "@effect/schema/AST" -import * as ParseResult from "@effect/schema/ParseResult" -import * as Schema from "@effect/schema/Schema" import * as Chunk from "effect/Chunk" import * as Context from "effect/Context" import * as Effect from "effect/Effect" @@ -14,9 +11,12 @@ import { globalValue } from "effect/GlobalValue" import * as Layer from "effect/Layer" import type { ManagedRuntime } from "effect/ManagedRuntime" import * as Option from "effect/Option" +import * as ParseResult from "effect/ParseResult" import { type Pipeable, pipeArguments } from "effect/Pipeable" import type { ReadonlyRecord } from "effect/Record" import * as Redacted from "effect/Redacted" +import * as Schema from "effect/Schema" +import * as AST from "effect/SchemaAST" import type { Scope } from "effect/Scope" import type { Covariant, Mutable, NoInfer } from "effect/Types" import { unify } from "effect/Unify" @@ -690,8 +690,7 @@ export const securitySetCookie = ( * @category middleware * @example * import { HttpApiBuilder, HttpApiSecurity } from "@effect/platform" - * import { Schema } from "@effect/schema" - * import { Context, Effect, Redacted } from "effect" + * import { Context, Effect, Redacted, Schema } from "effect" * * class User extends Schema.Class("User")({ * id: Schema.Number diff --git a/packages/platform/src/HttpApiClient.ts b/packages/platform/src/HttpApiClient.ts index ee98f97d48..48d7cbf241 100644 --- a/packages/platform/src/HttpApiClient.ts +++ b/packages/platform/src/HttpApiClient.ts @@ -1,12 +1,12 @@ /** * @since 1.0.0 */ -import * as ParseResult from "@effect/schema/ParseResult" -import * as Schema from "@effect/schema/Schema" import * as Context from "effect/Context" import * as Effect from "effect/Effect" import { identity } from "effect/Function" import * as Option from "effect/Option" +import * as ParseResult from "effect/ParseResult" +import * as Schema from "effect/Schema" import type { Simplify } from "effect/Types" import * as HttpApi from "./HttpApi.js" import type { HttpApiEndpoint } from "./HttpApiEndpoint.js" diff --git a/packages/platform/src/HttpApiEndpoint.ts b/packages/platform/src/HttpApiEndpoint.ts index 941168537e..0135dbaf6f 100644 --- a/packages/platform/src/HttpApiEndpoint.ts +++ b/packages/platform/src/HttpApiEndpoint.ts @@ -1,7 +1,6 @@ /** * @since 1.0.0 */ -import * as Schema from "@effect/schema/Schema" import type { Brand } from "effect/Brand" import * as Context from "effect/Context" import type { Effect } from "effect/Effect" @@ -10,6 +9,7 @@ import * as Option from "effect/Option" import { type Pipeable, pipeArguments } from "effect/Pipeable" import * as Predicate from "effect/Predicate" import type { Redacted } from "effect/Redacted" +import * as Schema from "effect/Schema" import type * as Types from "effect/Types" import * as HttpApiSchema from "./HttpApiSchema.js" import type { HttpMethod } from "./HttpMethod.js" diff --git a/packages/platform/src/HttpApiError.ts b/packages/platform/src/HttpApiError.ts index 10c414fbdc..af486fd5df 100644 --- a/packages/platform/src/HttpApiError.ts +++ b/packages/platform/src/HttpApiError.ts @@ -1,12 +1,10 @@ /** * @since 1.0.0 */ -import * as ArrayFormatter from "@effect/schema/ArrayFormatter" -import type * as ParseResult from "@effect/schema/ParseResult" -import * as Schema from "@effect/schema/Schema" -import * as TreeFormatter from "@effect/schema/TreeFormatter" import * as Effect from "effect/Effect" import { identity } from "effect/Function" +import * as ParseResult from "effect/ParseResult" +import * as Schema from "effect/Schema" import * as HttpApiSchema from "./HttpApiSchema.js" /** @@ -99,8 +97,8 @@ export class HttpApiDecodeError extends Schema.TaggedError() * @since 1.0.0 */ static fromParseError(error: ParseResult.ParseError): Effect.Effect { - return ArrayFormatter.formatError(error).pipe( - Effect.zip(TreeFormatter.formatError(error)), + return ParseResult.ArrayFormatter.formatError(error).pipe( + Effect.zip(ParseResult.TreeFormatter.formatError(error)), Effect.map(([issues, message]) => new HttpApiDecodeError({ issues, message })) ) } diff --git a/packages/platform/src/HttpApiGroup.ts b/packages/platform/src/HttpApiGroup.ts index d64550c609..0275037cac 100644 --- a/packages/platform/src/HttpApiGroup.ts +++ b/packages/platform/src/HttpApiGroup.ts @@ -1,12 +1,12 @@ /** * @since 1.0.0 */ -import * as Schema from "@effect/schema/Schema" import * as Chunk from "effect/Chunk" import * as Context from "effect/Context" import { dual } from "effect/Function" import { type Pipeable, pipeArguments } from "effect/Pipeable" import * as Predicate from "effect/Predicate" +import * as Schema from "effect/Schema" import * as HttpApiEndpoint from "./HttpApiEndpoint.js" import type { HttpApiDecodeError } from "./HttpApiError.js" import * as HttpApiSchema from "./HttpApiSchema.js" diff --git a/packages/platform/src/HttpApiSchema.ts b/packages/platform/src/HttpApiSchema.ts index 96774b3656..b471b86ff7 100644 --- a/packages/platform/src/HttpApiSchema.ts +++ b/packages/platform/src/HttpApiSchema.ts @@ -1,11 +1,11 @@ /** * @since 1.0.0 */ -import * as AST from "@effect/schema/AST" -import * as Schema from "@effect/schema/Schema" import type { Brand } from "effect/Brand" import type { LazyArg } from "effect/Function" import { constVoid, dual } from "effect/Function" +import * as Schema from "effect/Schema" +import * as AST from "effect/SchemaAST" import * as Struct from "effect/Struct" /** diff --git a/packages/platform/src/HttpBody.ts b/packages/platform/src/HttpBody.ts index 8aeeabf834..29e89ec427 100644 --- a/packages/platform/src/HttpBody.ts +++ b/packages/platform/src/HttpBody.ts @@ -1,11 +1,11 @@ /** * @since 1.0.0 */ -import type * as ParseResult from "@effect/schema/ParseResult" -import type * as Schema from "@effect/schema/Schema" import type * as Effect from "effect/Effect" import type { Inspectable } from "effect/Inspectable" +import type * as ParseResult from "effect/ParseResult" import * as Predicate from "effect/Predicate" +import type * as Schema from "effect/Schema" import type * as Stream_ from "effect/Stream" import type * as PlatformError from "./Error.js" import type * as FileSystem from "./FileSystem.js" diff --git a/packages/platform/src/HttpClientRequest.ts b/packages/platform/src/HttpClientRequest.ts index 68d511f51a..2a9b188458 100644 --- a/packages/platform/src/HttpClientRequest.ts +++ b/packages/platform/src/HttpClientRequest.ts @@ -1,13 +1,13 @@ /** * @since 1.0.0 */ -import type { ParseOptions } from "@effect/schema/AST" -import type * as Schema from "@effect/schema/Schema" import type * as Effect from "effect/Effect" import type { Inspectable } from "effect/Inspectable" import type * as Option from "effect/Option" import type { Pipeable } from "effect/Pipeable" import type { Redacted } from "effect/Redacted" +import type * as Schema from "effect/Schema" +import type { ParseOptions } from "effect/SchemaAST" import type * as Stream from "effect/Stream" import type * as PlatformError from "./Error.js" import type * as FileSystem from "./FileSystem.js" diff --git a/packages/platform/src/HttpClientResponse.ts b/packages/platform/src/HttpClientResponse.ts index 8455e36a82..6aa820bc18 100644 --- a/packages/platform/src/HttpClientResponse.ts +++ b/packages/platform/src/HttpClientResponse.ts @@ -1,10 +1,10 @@ /** * @since 1.0.0 */ -import type { ParseOptions } from "@effect/schema/AST" -import type * as ParseResult from "@effect/schema/ParseResult" -import type * as Schema from "@effect/schema/Schema" import type * as Effect from "effect/Effect" +import type * as ParseResult from "effect/ParseResult" +import type * as Schema from "effect/Schema" +import type { ParseOptions } from "effect/SchemaAST" import type * as Scope from "effect/Scope" import type * as Stream from "effect/Stream" import type { Unify } from "effect/Unify" diff --git a/packages/platform/src/HttpIncomingMessage.ts b/packages/platform/src/HttpIncomingMessage.ts index e217a94ebc..0422d1ab3f 100644 --- a/packages/platform/src/HttpIncomingMessage.ts +++ b/packages/platform/src/HttpIncomingMessage.ts @@ -1,15 +1,15 @@ /** * @since 1.0.0 */ -import type { ParseOptions } from "@effect/schema/AST" -import type * as ParseResult from "@effect/schema/ParseResult" -import * as Schema from "@effect/schema/Schema" import * as Effect from "effect/Effect" import * as FiberRef from "effect/FiberRef" import { dual } from "effect/Function" import * as Global from "effect/GlobalValue" import type { Inspectable } from "effect/Inspectable" import * as Option from "effect/Option" +import type * as ParseResult from "effect/ParseResult" +import * as Schema from "effect/Schema" +import type { ParseOptions } from "effect/SchemaAST" import type * as Stream from "effect/Stream" import * as FileSystem from "./FileSystem.js" import type * as Headers from "./Headers.js" diff --git a/packages/platform/src/HttpRouter.ts b/packages/platform/src/HttpRouter.ts index 174833405a..565a007c77 100644 --- a/packages/platform/src/HttpRouter.ts +++ b/packages/platform/src/HttpRouter.ts @@ -1,9 +1,6 @@ /** * @since 1.0.0 */ -import type { ParseOptions } from "@effect/schema/AST" -import type * as ParseResult from "@effect/schema/ParseResult" -import type * as Schema from "@effect/schema/Schema" import type * as Cause from "effect/Cause" import type * as Chunk from "effect/Chunk" import type * as Context from "effect/Context" @@ -12,6 +9,9 @@ import type { FiberRef } from "effect/FiberRef" import type { Inspectable } from "effect/Inspectable" import type * as Layer from "effect/Layer" import type * as Option from "effect/Option" +import type * as ParseResult from "effect/ParseResult" +import type * as Schema from "effect/Schema" +import type { ParseOptions } from "effect/SchemaAST" import type * as Scope from "effect/Scope" import type { RouterConfig } from "find-my-way-ts" import type * as Etag from "./Etag.js" diff --git a/packages/platform/src/HttpServerRequest.ts b/packages/platform/src/HttpServerRequest.ts index 3944778ca2..27bc396554 100644 --- a/packages/platform/src/HttpServerRequest.ts +++ b/packages/platform/src/HttpServerRequest.ts @@ -1,15 +1,15 @@ /** * @since 1.0.0 */ -import type { ParseOptions } from "@effect/schema/AST" -import type * as ParseResult from "@effect/schema/ParseResult" -import type * as Schema from "@effect/schema/Schema" import type { Channel } from "effect/Channel" import type { Chunk } from "effect/Chunk" import type * as Context from "effect/Context" import type * as Effect from "effect/Effect" import type { Option } from "effect/Option" +import type * as ParseResult from "effect/ParseResult" import type { ReadonlyRecord } from "effect/Record" +import type * as Schema from "effect/Schema" +import type { ParseOptions } from "effect/SchemaAST" import type * as Scope from "effect/Scope" import type * as Stream from "effect/Stream" import type * as FileSystem from "./FileSystem.js" diff --git a/packages/platform/src/HttpServerRespondable.ts b/packages/platform/src/HttpServerRespondable.ts index b18d0de6e1..d6f809d295 100644 --- a/packages/platform/src/HttpServerRespondable.ts +++ b/packages/platform/src/HttpServerRespondable.ts @@ -1,9 +1,9 @@ /** * @since 1.0.0 */ -import * as ParseResult from "@effect/schema/ParseResult" import * as Cause from "effect/Cause" import * as Effect from "effect/Effect" +import * as ParseResult from "effect/ParseResult" import { hasProperty } from "effect/Predicate" import type { HttpServerResponse } from "./HttpServerResponse.js" import * as ServerResponse from "./HttpServerResponse.js" diff --git a/packages/platform/src/HttpServerResponse.ts b/packages/platform/src/HttpServerResponse.ts index 3a2ed00f8f..283de3adf0 100644 --- a/packages/platform/src/HttpServerResponse.ts +++ b/packages/platform/src/HttpServerResponse.ts @@ -1,11 +1,11 @@ /** * @since 1.0.0 */ -import type { ParseOptions } from "@effect/schema/AST" -import type * as Schema from "@effect/schema/Schema" import type * as Effect from "effect/Effect" import type { Inspectable } from "effect/Inspectable" import type * as Runtime from "effect/Runtime" +import type * as Schema from "effect/Schema" +import type { ParseOptions } from "effect/SchemaAST" import type * as Stream from "effect/Stream" import type { Cookie, Cookies, CookiesError } from "./Cookies.js" import type * as PlatformError from "./Error.js" diff --git a/packages/platform/src/KeyValueStore.ts b/packages/platform/src/KeyValueStore.ts index 113bbcdec0..d92d2a5c87 100644 --- a/packages/platform/src/KeyValueStore.ts +++ b/packages/platform/src/KeyValueStore.ts @@ -1,13 +1,13 @@ /** * @since 1.0.0 */ -import type * as ParseResult from "@effect/schema/ParseResult" -import type * as Schema from "@effect/schema/Schema" import type * as Context from "effect/Context" import type * as Effect from "effect/Effect" import type { LazyArg } from "effect/Function" import type * as Layer from "effect/Layer" import type * as Option from "effect/Option" +import type * as ParseResult from "effect/ParseResult" +import type * as Schema from "effect/Schema" import type * as PlatformError from "./Error.js" import type * as FileSystem from "./FileSystem.js" import * as internal from "./internal/keyValueStore.js" diff --git a/packages/platform/src/Multipart.ts b/packages/platform/src/Multipart.ts index 9dfab4386c..ee0dce2c45 100644 --- a/packages/platform/src/Multipart.ts +++ b/packages/platform/src/Multipart.ts @@ -1,9 +1,6 @@ /** * @since 1.0.0 */ -import type { ParseOptions } from "@effect/schema/AST" -import type * as ParseResult from "@effect/schema/ParseResult" -import type * as Schema from "@effect/schema/Schema" import type { YieldableError } from "effect/Cause" import type * as Channel from "effect/Channel" import type * as Chunk from "effect/Chunk" @@ -11,6 +8,9 @@ import type * as Effect from "effect/Effect" import type * as FiberRef from "effect/FiberRef" import type { Inspectable } from "effect/Inspectable" import type * as Option from "effect/Option" +import type * as ParseResult from "effect/ParseResult" +import type * as Schema from "effect/Schema" +import type { ParseOptions } from "effect/SchemaAST" import type * as Scope from "effect/Scope" import type * as Stream from "effect/Stream" import type * as Multipasta from "multipasta" diff --git a/packages/platform/src/OpenApi.ts b/packages/platform/src/OpenApi.ts index 2e51812423..f447d2a282 100644 --- a/packages/platform/src/OpenApi.ts +++ b/packages/platform/src/OpenApi.ts @@ -1,12 +1,12 @@ /** * @since 1.0.0 */ -import * as AST from "@effect/schema/AST" -import * as Schema from "@effect/schema/Schema" import * as Context from "effect/Context" import { dual } from "effect/Function" import * as Option from "effect/Option" import type { ReadonlyRecord } from "effect/Record" +import * as Schema from "effect/Schema" +import * as AST from "effect/SchemaAST" import type { DeepMutable, Mutable } from "effect/Types" import * as HttpApi from "./HttpApi.js" import * as HttpApiSchema from "./HttpApiSchema.js" diff --git a/packages/platform/src/OpenApiJsonSchema.ts b/packages/platform/src/OpenApiJsonSchema.ts index aa376b821f..8a7e2487a5 100644 --- a/packages/platform/src/OpenApiJsonSchema.ts +++ b/packages/platform/src/OpenApiJsonSchema.ts @@ -1,13 +1,13 @@ /** * @since 1.0.0 */ -import * as AST from "@effect/schema/AST" -import type * as ParseResult from "@effect/schema/ParseResult" -import type * as Schema from "@effect/schema/Schema" import * as Arr from "effect/Array" import * as Option from "effect/Option" +import type * as ParseResult from "effect/ParseResult" import * as Predicate from "effect/Predicate" import * as Record from "effect/Record" +import type * as Schema from "effect/Schema" +import * as AST from "effect/SchemaAST" /** * @category model @@ -312,7 +312,8 @@ const getRefinementInnerTransformation = (ast: AST.Refinement): AST.AST | undefi } } -const isParseJsonTransformation = (ast: AST.AST): boolean => ast.annotations[AST.TypeAnnotationId] === ParseJsonTypeId +const isParseJsonTransformation = (ast: AST.AST): boolean => + ast.annotations[AST.SchemaIdAnnotationId] === AST.ParseJsonSchemaId const isOverrideAnnotation = (jsonSchema: JsonSchema): boolean => { return ("type" in jsonSchema) || ("oneOf" in jsonSchema) || ("anyOf" in jsonSchema) || ("const" in jsonSchema) || @@ -352,7 +353,7 @@ const go = ( } return handler } - const surrogate = getSurrogateAnnotation(ast) + const surrogate = AST.getSurrogateAnnotation(ast) if (Option.isSome(surrogate)) { return { ...(ast._tag === "Transformation" ? getJsonSchemaAnnotations(ast.to) : {}), @@ -361,7 +362,7 @@ const go = ( } } if (handleIdentifier && !AST.isTransformation(ast) && !AST.isRefinement(ast)) { - const identifier = getJSONIdentifier(ast) + const identifier = AST.getJSONIdentifier(ast) if (Option.isSome(identifier)) { const id = identifier.value const out = { $ref: get$ref(id) } @@ -603,7 +604,7 @@ const go = ( } } case "Suspend": { - const identifier = Option.orElse(getJSONIdentifier(ast), () => getJSONIdentifier(ast.f())) + const identifier = Option.orElse(AST.getJSONIdentifier(ast), () => AST.getJSONIdentifier(ast.f())) if (Option.isNone(identifier)) { throw new Error(getJSONSchemaMissingIdentifierAnnotationErrorMessage(path, ast)) } @@ -703,12 +704,3 @@ const formatPath = (path: ParseResult.Path): string => const isNonEmpty = (x: ParseResult.SingleOrNonEmpty): x is Arr.NonEmptyReadonlyArray => Array.isArray(x) const formatPropertyKey = (name: PropertyKey): string => typeof name === "string" ? JSON.stringify(name) : String(name) - -const ParseJsonTypeId: unique symbol = Symbol.for("@effect/schema/TypeId/ParseJson") -const SurrogateAnnotationId = Symbol.for("@effect/schema/annotation/Surrogate") -const JSONIdentifierAnnotationId = Symbol.for("@effect/schema/annotation/JSONIdentifier") - -const getSurrogateAnnotation = AST.getAnnotation(SurrogateAnnotationId) -const getJSONIdentifierAnnotation = AST.getAnnotation(JSONIdentifierAnnotationId) -const getJSONIdentifier = (annotated: AST.Annotated) => - Option.orElse(getJSONIdentifierAnnotation(annotated), () => AST.getIdentifierAnnotation(annotated)) diff --git a/packages/platform/src/Transferable.ts b/packages/platform/src/Transferable.ts index 13f4d31466..12fd445b78 100644 --- a/packages/platform/src/Transferable.ts +++ b/packages/platform/src/Transferable.ts @@ -1,12 +1,12 @@ /** * @since 1.0.0 */ -import * as ParseResult from "@effect/schema/ParseResult" -import * as Schema from "@effect/schema/Schema" import * as Context from "effect/Context" import * as Effect from "effect/Effect" import { dual } from "effect/Function" import * as Option from "effect/Option" +import * as ParseResult from "effect/ParseResult" +import * as Schema from "effect/Schema" /** * @since 1.0.0 diff --git a/packages/platform/src/UrlParams.ts b/packages/platform/src/UrlParams.ts index 0777ecaaf1..df69cb0966 100644 --- a/packages/platform/src/UrlParams.ts +++ b/packages/platform/src/UrlParams.ts @@ -1,14 +1,14 @@ /** * @since 1.0.0 */ -import type { ParseOptions } from "@effect/schema/AST" -import type * as ParseResult from "@effect/schema/ParseResult" -import * as Schema from "@effect/schema/Schema" import * as Arr from "effect/Array" import type * as Effect from "effect/Effect" import * as Either from "effect/Either" import { dual } from "effect/Function" import * as Option from "effect/Option" +import type * as ParseResult from "effect/ParseResult" +import * as Schema from "effect/Schema" +import type { ParseOptions } from "effect/SchemaAST" /** * @since 1.0.0 diff --git a/packages/platform/src/Worker.ts b/packages/platform/src/Worker.ts index 683bc751dc..1e2cc0e76d 100644 --- a/packages/platform/src/Worker.ts +++ b/packages/platform/src/Worker.ts @@ -1,16 +1,15 @@ /** * @since 1.0.0 */ -import type * as ParseResult from "@effect/schema/ParseResult" -import type * as Schema from "@effect/schema/Schema" -import type * as Serializable from "@effect/schema/Serializable" import type * as Context from "effect/Context" import type * as Deferred from "effect/Deferred" import type * as Duration from "effect/Duration" import type * as Effect from "effect/Effect" import type { LazyArg } from "effect/Function" import type * as Layer from "effect/Layer" +import type * as ParseResult from "effect/ParseResult" import type * as Pool from "effect/Pool" +import type * as Schema from "effect/Schema" import type * as Scope from "effect/Scope" import type * as Stream from "effect/Stream" import * as internal from "./internal/worker.js" @@ -260,12 +259,12 @@ export interface SerializedWorker { readonly id: number readonly execute: ( message: Req - ) => Req extends Serializable.WithResult + ) => Req extends Schema.WithResult ? Stream.Stream : never readonly executeEffect: ( message: Req - ) => Req extends Serializable.WithResult + ) => Req extends Schema.WithResult ? Effect.Effect : never } @@ -295,17 +294,17 @@ export interface SerializedWorkerPool { readonly backing: Pool.Pool, WorkerError> readonly broadcast: ( message: Req - ) => Req extends Serializable.WithResult + ) => Req extends Schema.WithResult ? Effect.Effect : never readonly execute: ( message: Req - ) => Req extends Serializable.WithResult + ) => Req extends Schema.WithResult ? Stream.Stream : never readonly executeEffect: ( message: Req - ) => Req extends Serializable.WithResult + ) => Req extends Schema.WithResult ? Effect.Effect : never } diff --git a/packages/platform/src/WorkerError.ts b/packages/platform/src/WorkerError.ts index f30822301e..79c4497898 100644 --- a/packages/platform/src/WorkerError.ts +++ b/packages/platform/src/WorkerError.ts @@ -1,9 +1,9 @@ /** * @since 1.0.0 */ -import * as Schema from "@effect/schema/Schema" import type * as Cause from "effect/Cause" import * as Predicate from "effect/Predicate" +import * as Schema from "effect/Schema" import * as internal from "./internal/workerError.js" /** diff --git a/packages/platform/src/WorkerRunner.ts b/packages/platform/src/WorkerRunner.ts index 07ebf0e70a..ae52085a58 100644 --- a/packages/platform/src/WorkerRunner.ts +++ b/packages/platform/src/WorkerRunner.ts @@ -1,11 +1,10 @@ /** * @since 1.0.0 */ -import type * as Schema from "@effect/schema/Schema" -import type * as Serializable from "@effect/schema/Serializable" import type * as Context from "effect/Context" import type * as Effect from "effect/Effect" import type * as Layer from "effect/Layer" +import type * as Schema from "effect/Schema" import type * as Scope from "effect/Scope" import type * as Stream from "effect/Stream" import * as internal from "./internal/workerRunner.js" @@ -128,7 +127,7 @@ export declare namespace SerializedRunner { readonly [K in A["_tag"]]: Extract< A, { readonly _tag: K } - > extends Serializable.SerializableWithResult< + > extends Schema.SerializableWithResult< infer S, infer _SI, infer _SR, diff --git a/packages/platform/src/internal/httpBody.ts b/packages/platform/src/internal/httpBody.ts index 4f43140a2a..4096469b6b 100644 --- a/packages/platform/src/internal/httpBody.ts +++ b/packages/platform/src/internal/httpBody.ts @@ -1,9 +1,9 @@ -import type { ParseOptions } from "@effect/schema/AST" -import * as Schema from "@effect/schema/Schema" import * as Data from "effect/Data" import * as Effect from "effect/Effect" import { identity } from "effect/Function" import * as Inspectable from "effect/Inspectable" +import * as Schema from "effect/Schema" +import type { ParseOptions } from "effect/SchemaAST" import * as Stream_ from "effect/Stream" import type * as PlatformError from "../Error.js" import * as FileSystem from "../FileSystem.js" diff --git a/packages/platform/src/internal/httpClientRequest.ts b/packages/platform/src/internal/httpClientRequest.ts index 7f5aa36565..8d57094805 100644 --- a/packages/platform/src/internal/httpClientRequest.ts +++ b/packages/platform/src/internal/httpClientRequest.ts @@ -1,11 +1,11 @@ -import type { ParseOptions } from "@effect/schema/AST" -import type * as Schema from "@effect/schema/Schema" import * as Effect from "effect/Effect" import { dual } from "effect/Function" import * as Inspectable from "effect/Inspectable" import * as Option from "effect/Option" import { pipeArguments } from "effect/Pipeable" import * as Redacted from "effect/Redacted" +import type * as Schema from "effect/Schema" +import type { ParseOptions } from "effect/SchemaAST" import type * as Stream from "effect/Stream" import type * as PlatformError from "../Error.js" import type * as FileSystem from "../FileSystem.js" diff --git a/packages/platform/src/internal/httpClientResponse.ts b/packages/platform/src/internal/httpClientResponse.ts index 540ffd90e6..d5a902a778 100644 --- a/packages/platform/src/internal/httpClientResponse.ts +++ b/packages/platform/src/internal/httpClientResponse.ts @@ -1,10 +1,10 @@ -import type { ParseOptions } from "@effect/schema/AST" -import type * as ParseResult from "@effect/schema/ParseResult" -import * as Schema from "@effect/schema/Schema" import * as Effect from "effect/Effect" import { dual } from "effect/Function" import * as Inspectable from "effect/Inspectable" import * as Option from "effect/Option" +import type * as ParseResult from "effect/ParseResult" +import * as Schema from "effect/Schema" +import type { ParseOptions } from "effect/SchemaAST" import * as Stream from "effect/Stream" import type { Unify } from "effect/Unify" import * as Cookies from "../Cookies.js" diff --git a/packages/platform/src/internal/httpRouter.ts b/packages/platform/src/internal/httpRouter.ts index dd8954bb32..9d53fec2c9 100644 --- a/packages/platform/src/internal/httpRouter.ts +++ b/packages/platform/src/internal/httpRouter.ts @@ -1,5 +1,3 @@ -import type { ParseOptions } from "@effect/schema/AST" -import * as Schema from "@effect/schema/Schema" import type * as Cause from "effect/Cause" import * as Chunk from "effect/Chunk" import * as Context from "effect/Context" @@ -12,6 +10,8 @@ import * as Inspectable from "effect/Inspectable" import * as Layer from "effect/Layer" import * as Option from "effect/Option" import * as Predicate from "effect/Predicate" +import * as Schema from "effect/Schema" +import type { ParseOptions } from "effect/SchemaAST" import * as Tracer from "effect/Tracer" import type { Mutable } from "effect/Types" import * as FindMyWay from "find-my-way-ts" diff --git a/packages/platform/src/internal/httpServerRequest.ts b/packages/platform/src/internal/httpServerRequest.ts index 78e25531c1..56880eac11 100644 --- a/packages/platform/src/internal/httpServerRequest.ts +++ b/packages/platform/src/internal/httpServerRequest.ts @@ -1,12 +1,12 @@ -import type { ParseOptions } from "@effect/schema/AST" -import type * as ParseResult from "@effect/schema/ParseResult" -import * as Schema from "@effect/schema/Schema" import * as Channel from "effect/Channel" import * as Context from "effect/Context" import * as Effect from "effect/Effect" import * as Inspectable from "effect/Inspectable" import * as Option from "effect/Option" +import type * as ParseResult from "effect/ParseResult" import type { ReadonlyRecord } from "effect/Record" +import * as Schema from "effect/Schema" +import type { ParseOptions } from "effect/SchemaAST" import type * as Scope from "effect/Scope" import * as Stream from "effect/Stream" import * as Cookies from "../Cookies.js" diff --git a/packages/platform/src/internal/httpServerResponse.ts b/packages/platform/src/internal/httpServerResponse.ts index 6648e66555..dc1a46601f 100644 --- a/packages/platform/src/internal/httpServerResponse.ts +++ b/packages/platform/src/internal/httpServerResponse.ts @@ -1,11 +1,11 @@ -import type { ParseOptions } from "@effect/schema/AST" -import type * as Schema from "@effect/schema/Schema" import * as Context from "effect/Context" import * as Effect from "effect/Effect" import * as Effectable from "effect/Effectable" import { dual } from "effect/Function" import * as Inspectable from "effect/Inspectable" import * as Runtime from "effect/Runtime" +import type * as Schema from "effect/Schema" +import type { ParseOptions } from "effect/SchemaAST" import * as Stream from "effect/Stream" import * as Cookies from "../Cookies.js" import type * as PlatformError from "../Error.js" diff --git a/packages/platform/src/internal/keyValueStore.ts b/packages/platform/src/internal/keyValueStore.ts index 244e43fc79..76f1ae29c4 100644 --- a/packages/platform/src/internal/keyValueStore.ts +++ b/packages/platform/src/internal/keyValueStore.ts @@ -1,4 +1,3 @@ -import * as Schema from "@effect/schema/Schema" import * as Context from "effect/Context" import * as Effect from "effect/Effect" import * as Either from "effect/Either" @@ -7,6 +6,7 @@ import type { LazyArg } from "effect/Function" import { dual, identity, pipe } from "effect/Function" import * as Layer from "effect/Layer" import * as Option from "effect/Option" +import * as Schema from "effect/Schema" import * as PlatformError from "../Error.js" import * as FileSystem from "../FileSystem.js" import type * as KeyValueStore from "../KeyValueStore.js" diff --git a/packages/platform/src/internal/multipart.ts b/packages/platform/src/internal/multipart.ts index 127a2bba15..4c64926460 100644 --- a/packages/platform/src/internal/multipart.ts +++ b/packages/platform/src/internal/multipart.ts @@ -1,6 +1,3 @@ -import type { ParseOptions } from "@effect/schema/AST" -import type * as ParseResult from "@effect/schema/ParseResult" -import * as Schema from "@effect/schema/Schema" import * as Cause from "effect/Cause" import * as Channel from "effect/Channel" import * as Chunk from "effect/Chunk" @@ -10,8 +7,11 @@ import { dual, flow, pipe } from "effect/Function" import { globalValue } from "effect/GlobalValue" import * as Inspectable from "effect/Inspectable" import * as Option from "effect/Option" +import type * as ParseResult from "effect/ParseResult" import * as Predicate from "effect/Predicate" import * as Queue from "effect/Queue" +import * as Schema from "effect/Schema" +import type { ParseOptions } from "effect/SchemaAST" import type * as Scope from "effect/Scope" import type * as AsyncInput from "effect/SingleProducerAsyncInput" import * as Stream from "effect/Stream" diff --git a/packages/platform/src/internal/worker.ts b/packages/platform/src/internal/worker.ts index 2e89e2d80c..0718404793 100644 --- a/packages/platform/src/internal/worker.ts +++ b/packages/platform/src/internal/worker.ts @@ -1,5 +1,3 @@ -import * as Schema from "@effect/schema/Schema" -import * as Serializable from "@effect/schema/Serializable" import * as Channel from "effect/Channel" import * as Context from "effect/Context" import * as Deferred from "effect/Deferred" @@ -13,6 +11,7 @@ import * as Mailbox from "effect/Mailbox" import * as Option from "effect/Option" import * as Pool from "effect/Pool" import * as Schedule from "effect/Schedule" +import * as Schema from "effect/Schema" import * as Scope from "effect/Scope" import * as Stream from "effect/Stream" import * as Tracer from "effect/Tracer" @@ -298,14 +297,14 @@ export const makeSerialized = < ...options as any, encode(message) { return Effect.mapError( - Serializable.serialize(message as any), + Schema.serialize(message as any), (cause) => new WorkerError({ reason: "encode", cause }) ) } }) const execute = (message: Req) => { - const parseSuccess = Schema.decode(Serializable.successSchema(message as any)) - const parseFailure = Schema.decode(Serializable.failureSchema(message as any)) + const parseSuccess = Schema.decode(Schema.successSchema(message as any)) + const parseFailure = Schema.decode(Schema.failureSchema(message as any)) return pipe( backing.execute(message), Stream.catchAll((error) => Effect.flatMap(parseFailure(error), Effect.fail)), @@ -313,8 +312,8 @@ export const makeSerialized = < ) } const executeEffect = (message: Req) => { - const parseSuccess = Schema.decode(Serializable.successSchema(message as any)) - const parseFailure = Schema.decode(Serializable.failureSchema(message as any)) + const parseSuccess = Schema.decode(Schema.successSchema(message as any)) + const parseFailure = Schema.decode(Schema.failureSchema(message as any)) return Effect.matchEffect(backing.executeEffect(message), { onFailure: (error) => Effect.flatMap(parseFailure(error), Effect.fail), onSuccess: parseSuccess diff --git a/packages/platform/src/internal/workerRunner.ts b/packages/platform/src/internal/workerRunner.ts index 8ab9aa57cc..9a5f4158a0 100644 --- a/packages/platform/src/internal/workerRunner.ts +++ b/packages/platform/src/internal/workerRunner.ts @@ -1,5 +1,3 @@ -import * as Schema from "@effect/schema/Schema" -import * as Serializable from "@effect/schema/Serializable" import * as Cause from "effect/Cause" import * as Chunk from "effect/Chunk" import * as Context from "effect/Context" @@ -9,6 +7,7 @@ import * as Fiber from "effect/Fiber" import { pipe } from "effect/Function" import * as Layer from "effect/Layer" import * as Schedule from "effect/Schedule" +import * as Schema from "effect/Schema" import type * as Scope from "effect/Scope" import * as Stream from "effect/Stream" import * as Transferable from "../Transferable.js" @@ -189,13 +188,13 @@ export const makeSerialized = < }, encodeError(request, message) { return Effect.mapError( - Serializable.serializeFailure(request as any, message), + Schema.serializeFailure(request as any, message), (cause) => new WorkerError({ reason: "encode", cause }) ) }, encodeOutput(request, message) { return Effect.catchAllCause( - Serializable.serializeSuccess(request as any, message), + Schema.serializeSuccess(request as any, message), (cause) => new WorkerError({ reason: "encode", cause }) ) } diff --git a/packages/platform/test/HttpClient.test.ts b/packages/platform/test/HttpClient.test.ts index a27fa7afa4..3f0ac85494 100644 --- a/packages/platform/test/HttpClient.test.ts +++ b/packages/platform/test/HttpClient.test.ts @@ -6,13 +6,13 @@ import { HttpClientResponse, UrlParams } from "@effect/platform" -import * as Schema from "@effect/schema/Schema" import { assert, describe, expect, it } from "@effect/vitest" import { Either, Ref, Struct } from "effect" import * as Context from "effect/Context" import * as Effect from "effect/Effect" import * as Layer from "effect/Layer" import * as Logger from "effect/Logger" +import * as Schema from "effect/Schema" import * as Stream from "effect/Stream" const Todo = Schema.Struct({ diff --git a/packages/platform/test/KeyValueStore.test.ts b/packages/platform/test/KeyValueStore.test.ts index 8e66a2bce2..9ba1f9fd15 100644 --- a/packages/platform/test/KeyValueStore.test.ts +++ b/packages/platform/test/KeyValueStore.test.ts @@ -1,9 +1,9 @@ import * as KeyValueStore from "@effect/platform/KeyValueStore" -import * as Schema from "@effect/schema/Schema" import * as Effect from "effect/Effect" import { identity } from "effect/Function" import * as Layer from "effect/Layer" import * as Option from "effect/Option" +import * as Schema from "effect/Schema" import { afterEach, describe, expect, it } from "vitest" export const testLayer = (layer: Layer.Layer) => { diff --git a/packages/platform/test/OpenApiJsonSchema.test.ts b/packages/platform/test/OpenApiJsonSchema.test.ts index e40bac81f5..be83d847a9 100644 --- a/packages/platform/test/OpenApiJsonSchema.test.ts +++ b/packages/platform/test/OpenApiJsonSchema.test.ts @@ -1,7 +1,7 @@ import * as JsonSchema from "@effect/platform/OpenApiJsonSchema" -import * as A from "@effect/schema/Arbitrary" -import * as Schema from "@effect/schema/Schema" import AjvNonEsm from "ajv/dist/2019.js" +import * as A from "effect/Arbitrary" +import * as Schema from "effect/Schema" import * as fc from "fast-check" import { describe, expect, it } from "vitest" @@ -102,10 +102,10 @@ schema (SymbolKeyword): symbol` it("a unique symbol should raise an error", () => { expectError( - Schema.UniqueSymbolFromSelf(Symbol.for("@effect/schema/test/a")), + Schema.UniqueSymbolFromSelf(Symbol.for("effect/Schema/test/a")), `Missing annotation details: Generating a JSON Schema for this schema requires a "jsonSchema" annotation -schema (UniqueSymbol): Symbol(@effect/schema/test/a)` +schema (UniqueSymbol): Symbol(effect/Schema/test/a)` ) }) @@ -736,11 +736,11 @@ schema (Declaration): DateFromSelf` }) it("should raise an error if there is a property named with a symbol", () => { - const a = Symbol.for("@effect/schema/test/a") + const a = Symbol.for("effect/Schema/test/a") expectError( Schema.Struct({ [a]: Schema.String }), `Unsupported key -details: Cannot encode Symbol(@effect/schema/test/a) key to JSON Schema` +details: Cannot encode Symbol(effect/Schema/test/a) key to JSON Schema` ) }) diff --git a/packages/platform/test/Transferable.test.ts b/packages/platform/test/Transferable.test.ts index b2e0246ff7..f0bd531736 100644 --- a/packages/platform/test/Transferable.test.ts +++ b/packages/platform/test/Transferable.test.ts @@ -1,6 +1,5 @@ import * as Transferable from "@effect/platform/Transferable" -import { Schema } from "@effect/schema" -import { Effect } from "effect" +import { Effect, Schema } from "effect" import { assert, describe, test } from "vitest" describe("Transferable", () => { diff --git a/packages/platform/tsconfig.build.json b/packages/platform/tsconfig.build.json index 17ad78f02e..058393b854 100644 --- a/packages/platform/tsconfig.build.json +++ b/packages/platform/tsconfig.build.json @@ -1,9 +1,6 @@ { "extends": "./tsconfig.src.json", - "references": [ - { "path": "../effect/tsconfig.build.json" }, - { "path": "../schema/tsconfig.build.json" } - ], + "references": [{ "path": "../effect/tsconfig.build.json" }], "compilerOptions": { "tsBuildInfoFile": ".tsbuildinfo/build.tsbuildinfo", "outDir": "build/esm", diff --git a/packages/platform/tsconfig.src.json b/packages/platform/tsconfig.src.json index 8f1a1eb77f..34700059ad 100644 --- a/packages/platform/tsconfig.src.json +++ b/packages/platform/tsconfig.src.json @@ -1,10 +1,7 @@ { "extends": "../../tsconfig.base.json", "include": ["src"], - "references": [ - { "path": "../effect" }, - { "path": "../schema" } - ], + "references": [{ "path": "../effect" }], "compilerOptions": { "tsBuildInfoFile": ".tsbuildinfo/src.tsbuildinfo", "rootDir": "src", diff --git a/packages/platform/tsconfig.test.json b/packages/platform/tsconfig.test.json index 9c3d8ff20c..3724ddc14c 100644 --- a/packages/platform/tsconfig.test.json +++ b/packages/platform/tsconfig.test.json @@ -4,7 +4,6 @@ "references": [ { "path": "tsconfig.src.json" }, { "path": "../effect" }, - { "path": "../schema" }, { "path": "../vitest" } ], "compilerOptions": { diff --git a/packages/rpc-http/examples/schema.ts b/packages/rpc-http/examples/schema.ts index 246817bb79..a454ae6b77 100644 --- a/packages/rpc-http/examples/schema.ts +++ b/packages/rpc-http/examples/schema.ts @@ -1,6 +1,6 @@ import * as Rpc from "@effect/rpc/Rpc" -import * as S from "@effect/schema/Schema" import { pipe } from "effect/Function" +import * as S from "effect/Schema" export const UserId = pipe(S.Number, S.int(), S.brand("UserId")) export type UserId = S.Schema.Type diff --git a/packages/rpc-http/package.json b/packages/rpc-http/package.json index 32c5dd87bf..255e6a9972 100644 --- a/packages/rpc-http/package.json +++ b/packages/rpc-http/package.json @@ -44,12 +44,10 @@ "devDependencies": { "@effect/platform": "workspace:^", "@effect/platform-node": "workspace:^", - "@effect/schema": "workspace:^", "effect": "workspace:^" }, "peerDependencies": { "@effect/platform": "workspace:^", - "@effect/schema": "workspace:^", "effect": "workspace:^" } } diff --git a/packages/rpc-http/src/HttpRpcResolver.ts b/packages/rpc-http/src/HttpRpcResolver.ts index 5fea8629a8..a39af97235 100644 --- a/packages/rpc-http/src/HttpRpcResolver.ts +++ b/packages/rpc-http/src/HttpRpcResolver.ts @@ -7,11 +7,11 @@ import * as ClientRequest from "@effect/platform/HttpClientRequest" import type * as Rpc from "@effect/rpc/Rpc" import * as Resolver from "@effect/rpc/RpcResolver" import type * as Router from "@effect/rpc/RpcRouter" -import type * as Serializable from "@effect/schema/Serializable" import * as Chunk from "effect/Chunk" import * as Effect from "effect/Effect" import type * as RequestResolver from "effect/RequestResolver" import * as Schedule from "effect/Schedule" +import type * as Schema from "effect/Schema" import * as Stream from "effect/Stream" /** @@ -22,7 +22,7 @@ export const make = >( client: Client.HttpClient ): RequestResolver.RequestResolver< Rpc.Request>, - Serializable.SerializableWithResult.Context> + Schema.SerializableWithResult.Context> > => Resolver.make((requests) => client.post("", { @@ -46,7 +46,7 @@ export const make = >( */ export const makeClient = >( baseUrl: string -): Serializable.SerializableWithResult.Context> extends never ? Effect.Effect< +): Schema.SerializableWithResult.Context> extends never ? Effect.Effect< Resolver.Client< RequestResolver.RequestResolver< Rpc.Request> diff --git a/packages/rpc-http/src/HttpRpcResolverNoStream.ts b/packages/rpc-http/src/HttpRpcResolverNoStream.ts index 6850d52810..321429eb31 100644 --- a/packages/rpc-http/src/HttpRpcResolverNoStream.ts +++ b/packages/rpc-http/src/HttpRpcResolverNoStream.ts @@ -8,10 +8,10 @@ import type * as Rpc from "@effect/rpc/Rpc" import * as Resolver from "@effect/rpc/RpcResolver" import * as ResolverNoStream from "@effect/rpc/RpcResolverNoStream" import type * as Router from "@effect/rpc/RpcRouter" -import type * as Serializable from "@effect/schema/Serializable" import * as Effect from "effect/Effect" import type * as RequestResolver from "effect/RequestResolver" import * as Schedule from "effect/Schedule" +import type * as Schema from "effect/Schema" /** * @category constructors @@ -21,7 +21,7 @@ export const make = >( client: Client.HttpClient ): RequestResolver.RequestResolver< Rpc.Request>, - Serializable.SerializableWithResult.Context> + Schema.SerializableWithResult.Context> > => ResolverNoStream.make((requests) => client.post("", { @@ -38,7 +38,7 @@ export const make = >( */ export const makeClient = >( baseUrl: string -): Serializable.SerializableWithResult.Context> extends never ? Effect.Effect< +): Schema.SerializableWithResult.Context> extends never ? Effect.Effect< Resolver.Client< RequestResolver.RequestResolver< Rpc.Request> diff --git a/packages/rpc-http/src/HttpRpcRouterNoStream.ts b/packages/rpc-http/src/HttpRpcRouterNoStream.ts index eee7606500..401255035a 100644 --- a/packages/rpc-http/src/HttpRpcRouterNoStream.ts +++ b/packages/rpc-http/src/HttpRpcRouterNoStream.ts @@ -6,9 +6,9 @@ import type * as ServerError from "@effect/platform/HttpServerError" import * as ServerRequest from "@effect/platform/HttpServerRequest" import * as ServerResponse from "@effect/platform/HttpServerResponse" import * as Router from "@effect/rpc/RpcRouter" -import type { ParseError } from "@effect/schema/ParseResult" import * as Effect from "effect/Effect" import { dual } from "effect/Function" +import type { ParseError } from "effect/ParseResult" /** * @since 1.0.0 diff --git a/packages/rpc-http/tsconfig.build.json b/packages/rpc-http/tsconfig.build.json index 0042d5c8c0..e32ea6e718 100644 --- a/packages/rpc-http/tsconfig.build.json +++ b/packages/rpc-http/tsconfig.build.json @@ -2,7 +2,6 @@ "extends": "./tsconfig.src.json", "references": [ { "path": "../effect/tsconfig.build.json" }, - { "path": "../schema/tsconfig.build.json" }, { "path": "../rpc/tsconfig.build.json" }, { "path": "../platform/tsconfig.build.json" } ], diff --git a/packages/rpc-http/tsconfig.examples.json b/packages/rpc-http/tsconfig.examples.json index 55e0c61ba2..149a8d1ae5 100644 --- a/packages/rpc-http/tsconfig.examples.json +++ b/packages/rpc-http/tsconfig.examples.json @@ -4,7 +4,6 @@ "references": [ { "path": "tsconfig.src.json" }, { "path": "../effect" }, - { "path": "../schema" }, { "path": "../rpc" }, { "path": "../platform" }, { "path": "../platform-node" } diff --git a/packages/rpc-http/tsconfig.src.json b/packages/rpc-http/tsconfig.src.json index bde274fd69..bfec71fa85 100644 --- a/packages/rpc-http/tsconfig.src.json +++ b/packages/rpc-http/tsconfig.src.json @@ -3,7 +3,6 @@ "include": ["src"], "references": [ { "path": "../effect" }, - { "path": "../schema" }, { "path": "../rpc" }, { "path": "../platform" } ], diff --git a/packages/rpc-http/tsconfig.test.json b/packages/rpc-http/tsconfig.test.json index 4616200ac8..8ad3bae32d 100644 --- a/packages/rpc-http/tsconfig.test.json +++ b/packages/rpc-http/tsconfig.test.json @@ -4,7 +4,6 @@ "references": [ { "path": "tsconfig.src.json" }, { "path": "../effect" }, - { "path": "../schema" }, { "path": "../rpc" }, { "path": "../platform" }, { "path": "../platform-node" } diff --git a/packages/rpc/README.md b/packages/rpc/README.md index 36dce4ae80..7cee42b456 100644 --- a/packages/rpc/README.md +++ b/packages/rpc/README.md @@ -6,7 +6,7 @@ The `@effect/rpc` library facilitates the development of remote procedure call ( ## Declaring Requests -The `TaggedRequest` API in the `@effect/schema` library is designed to facilitate the creation of structured requests that can serialize function signatures involving input arguments, successful outcomes, and potential failures. Essentially, it's a tool for defining a serializable function that can be reliably transported across different systems or network layers. +The `TaggedRequest` API in the `effect/Schema` module is designed to facilitate the creation of structured requests that can serialize function signatures involving input arguments, successful outcomes, and potential failures. Essentially, it's a tool for defining a serializable function that can be reliably transported across different systems or network layers. Here’s a simplified explanation: @@ -32,7 +32,7 @@ sequenceDiagram ```ts filename="request.ts" // request.ts -import { Schema } from "@effect/schema" +import { Schema } from "effect" // Define a user with an ID and name export class User extends Schema.Class("User")({ @@ -209,7 +209,7 @@ Effect.runPromise(program).then(console.log) ```ts filename="request.ts" // request.ts import * as Rpc from "@effect/rpc/Rpc" -import { Schema } from "@effect/schema" +import { Schema } from "effect" export class Counts extends Rpc.StreamRequest()("Counts", { failure: Schema.Never, // Indicates that no errors are expected diff --git a/packages/rpc/package.json b/packages/rpc/package.json index 3f95216b50..7fc139ae08 100644 --- a/packages/rpc/package.json +++ b/packages/rpc/package.json @@ -40,12 +40,10 @@ }, "devDependencies": { "@effect/platform": "workspace:^", - "@effect/schema": "workspace:^", "effect": "workspace:^" }, "peerDependencies": { "@effect/platform": "workspace:^", - "@effect/schema": "workspace:^", "effect": "workspace:^" } } diff --git a/packages/rpc/src/Rpc.ts b/packages/rpc/src/Rpc.ts index 36ffbb4ad4..8e096e793b 100644 --- a/packages/rpc/src/Rpc.ts +++ b/packages/rpc/src/Rpc.ts @@ -2,20 +2,19 @@ * @since 1.0.0 */ import * as Headers from "@effect/platform/Headers" -import type * as ParseResult from "@effect/schema/ParseResult" -import * as Schema from "@effect/schema/Schema" -import type * as Serializable from "@effect/schema/Serializable" import type * as Context from "effect/Context" import * as Effect from "effect/Effect" import * as FiberRef from "effect/FiberRef" import { dual, pipe } from "effect/Function" import { globalValue } from "effect/GlobalValue" +import type * as ParseResult from "effect/ParseResult" import { type Pipeable, pipeArguments } from "effect/Pipeable" import * as Predicate from "effect/Predicate" import type * as PrimaryKey from "effect/PrimaryKey" import type * as Record from "effect/Record" import type * as EffectRequest from "effect/Request" import type * as RequestResolver from "effect/RequestResolver" +import * as Schema from "effect/Schema" import type { Scope } from "effect/Scope" import * as Stream from "effect/Stream" import type * as Types from "effect/Types" @@ -69,8 +68,8 @@ export interface RpcStream extends Rpc. readonly handler: ( request: Req ) => Stream.Stream< - Req extends Serializable.WithResult ? A : never, - Req extends Serializable.WithResult ? E : never, + Req extends Schema.WithResult ? A : never, + Req extends Schema.WithResult ? E : never, R > } @@ -95,7 +94,7 @@ export declare namespace Rpc { * @category models */ export type Context> = A extends Rpc - ? R | Serializable.SerializableWithResult.Context + ? R | Schema.SerializableWithResult.Context : never /** @@ -117,7 +116,7 @@ export declare namespace Rpc { * @category models */ export type ResultUndecoded = A extends - Serializable.WithResult + Schema.WithResult ? StreamRequestTypeId extends keyof A ? Stream.Stream : Effect.Effect : never @@ -157,9 +156,7 @@ export type StreamRequestTypeId = typeof StreamRequestTypeId * @category schemas */ export interface StreamRequest - extends - EffectRequest.Request>, - Serializable.SerializableWithResult + extends EffectRequest.Request>, Schema.SerializableWithResult { readonly [StreamRequestTypeId]: StreamRequestTypeId readonly _tag: Tag @@ -234,8 +231,8 @@ export const stream = ( handler: ( request: Req ) => Stream.Stream< - Req extends Serializable.WithResult ? A : never, - Req extends Serializable.WithResult ? E : never, + Req extends Schema.WithResult ? A : never, + Req extends Schema.WithResult ? E : never, R > ): Rpc => ({ @@ -258,12 +255,12 @@ export interface Request extends EffectRequest.Request.Error >, PrimaryKey.PrimaryKey, - Serializable.WithResult< - Serializable.WithResult.Context, - Schema.Schema.Encoded, - Schema.Schema.Type, - Schema.Schema.Encoded, - Schema.Schema.Type + Schema.WithResult< + Schema.WithResult.Context, + Schema.Schema.Encoded, + Schema.Schema.Type, + Schema.Schema.Encoded, + Schema.Schema.Type > { readonly request: A diff --git a/packages/rpc/src/RpcResolver.ts b/packages/rpc/src/RpcResolver.ts index 3c38c8e6a5..fabb0cf829 100644 --- a/packages/rpc/src/RpcResolver.ts +++ b/packages/rpc/src/RpcResolver.ts @@ -2,16 +2,15 @@ * @since 1.0.0 */ import * as Headers from "@effect/platform/Headers" -import type { ParseError } from "@effect/schema/ParseResult" -import * as Schema from "@effect/schema/Schema" -import * as Serializable from "@effect/schema/Serializable" import * as Arr from "effect/Array" import * as Cause from "effect/Cause" import * as Effect from "effect/Effect" import * as Exit from "effect/Exit" import { dual, pipe } from "effect/Function" +import type { ParseError } from "effect/ParseResult" import * as Request from "effect/Request" import * as RequestResolver from "effect/RequestResolver" +import * as Schema from "effect/Schema" import * as Stream from "effect/Stream" import { StreamRequestTypeId, withRequestTag } from "./internal/rpc.js" import * as Rpc from "./Rpc.js" @@ -26,10 +25,10 @@ export const make = ( ) => >(): RequestResolver.RequestResolver< Rpc.Request>, - Serializable.SerializableWithResult.Context> | HR + Schema.SerializableWithResult.Context> | HR > => { - const getDecode = withRequestTag((req) => Schema.decodeUnknown(Serializable.exitSchema(req))) - const getDecodeChunk = withRequestTag((req) => Schema.decodeUnknown(Schema.Chunk(Serializable.exitSchema(req)))) + const getDecode = withRequestTag((req) => Schema.decodeUnknown(Schema.exitSchema(req))) + const getDecodeChunk = withRequestTag((req) => Schema.decodeUnknown(Schema.Chunk(Schema.exitSchema(req)))) return RequestResolver.makeBatched( (requests: Arr.NonEmptyArray>) => { @@ -41,7 +40,7 @@ export const make = ( const processEffects = pipe( Effect.forEach(effectRequests, (_) => Effect.map( - Serializable.serialize(_.request), + Schema.serialize(_.request), (request) => ({ ..._, request }) )), Effect.flatMap((payload) => @@ -73,7 +72,7 @@ export const make = ( Effect.forEach(streamRequests, (request) => { const decode = getDecodeChunk(request.request) const stream = pipe( - Serializable.serialize(request.request), + Schema.serialize(request.request), Effect.map((_) => ({ ...request, request: _ })), Effect.map((payload) => pipe( diff --git a/packages/rpc/src/RpcResolverNoStream.ts b/packages/rpc/src/RpcResolverNoStream.ts index 286d6cf131..908f480c92 100644 --- a/packages/rpc/src/RpcResolverNoStream.ts +++ b/packages/rpc/src/RpcResolverNoStream.ts @@ -1,8 +1,6 @@ /** * @since 1.0.0 */ -import * as Schema from "@effect/schema/Schema" -import * as Serializable from "@effect/schema/Serializable" import type { NonEmptyArray } from "effect/Array" import * as Channel from "effect/Channel" import * as Chunk from "effect/Chunk" @@ -11,6 +9,7 @@ import * as Exit from "effect/Exit" import { pipe } from "effect/Function" import * as Request from "effect/Request" import * as RequestResolver from "effect/RequestResolver" +import * as Schema from "effect/Schema" import * as Stream from "effect/Stream" import { StreamRequestTypeId, withRequestTag } from "./internal/rpc.js" import type * as Rpc from "./Rpc.js" @@ -25,16 +24,16 @@ export const make = ( ) => >(): RequestResolver.RequestResolver< Rpc.Request>, - Serializable.SerializableWithResult.Context> | HR + Schema.SerializableWithResult.Context> | HR > => { - const getDecode = withRequestTag((req) => Schema.decodeUnknown(Serializable.exitSchema(req))) - const getDecodeChunk = withRequestTag((req) => Schema.decodeUnknown(Schema.Chunk(Serializable.exitSchema(req)))) + const getDecode = withRequestTag((req) => Schema.decodeUnknown(Schema.exitSchema(req))) + const getDecodeChunk = withRequestTag((req) => Schema.decodeUnknown(Schema.Chunk(Schema.exitSchema(req)))) return RequestResolver.makeBatched((requests: NonEmptyArray>) => pipe( Effect.forEach(requests, (_) => Effect.map( - Serializable.serialize(_.request), + Schema.serialize(_.request), (request) => ({ ..._, request }) )), Effect.flatMap(handler), diff --git a/packages/rpc/src/RpcRouter.ts b/packages/rpc/src/RpcRouter.ts index 38d4474c08..727d09d445 100644 --- a/packages/rpc/src/RpcRouter.ts +++ b/packages/rpc/src/RpcRouter.ts @@ -1,9 +1,6 @@ /** * @since 1.0.0 */ -import type { ParseError } from "@effect/schema/ParseResult" -import * as Schema from "@effect/schema/Schema" -import * as Serializable from "@effect/schema/Serializable" import * as Cause from "effect/Cause" import * as Channel from "effect/Channel" import * as Chunk from "effect/Chunk" @@ -12,8 +9,10 @@ import * as Effect from "effect/Effect" import * as Exit from "effect/Exit" import { dual, pipe } from "effect/Function" import * as Mailbox from "effect/Mailbox" +import type { ParseError } from "effect/ParseResult" import { type Pipeable, pipeArguments } from "effect/Pipeable" import * as Predicate from "effect/Predicate" +import * as Schema from "effect/Schema" import * as Stream from "effect/Stream" import { StreamRequestTypeId, withRequestTag } from "./internal/rpc.js" import * as Rpc from "./Rpc.js" @@ -55,7 +54,7 @@ export declare namespace RpcRouter { * @category models */ export type Context> = A extends RpcRouter - ? R | Serializable.SerializableWithResult.Context + ? R | Schema.SerializableWithResult.Context : never /** @@ -63,7 +62,7 @@ export declare namespace RpcRouter { * @category models */ export type ContextRaw> = A extends RpcRouter - ? R | Serializable.Serializable.Context + ? R | Schema.Serializable.Context : never /** @@ -206,8 +205,8 @@ export const toHandler: { ) const schemaArray = Schema.Array(Rpc.RequestSchema(schema)) const decode = Schema.decodeUnknown(schemaArray) - const getEncode = withRequestTag((req) => Schema.encode(Serializable.exitSchema(req))) - const getEncodeChunk = withRequestTag((req) => Schema.encode(Schema.Chunk(Serializable.exitSchema(req)))) + const getEncode = withRequestTag((req) => Schema.encode(Schema.exitSchema(req))) + const getEncodeChunk = withRequestTag((req) => Schema.encode(Schema.Chunk(Schema.exitSchema(req)))) return (u: unknown): Stream.Stream> => pipe( @@ -316,8 +315,8 @@ export const toHandlerNoStream: { ) const schemaArray = Schema.Array(Rpc.RequestSchema(schema)) const decode = Schema.decodeUnknown(schemaArray) - const getEncode = withRequestTag((req) => Schema.encode(Serializable.exitSchema(req))) - const getEncodeChunk = withRequestTag((req) => Schema.encode(Schema.Chunk(Serializable.exitSchema(req)))) + const getEncode = withRequestTag((req) => Schema.encode(Schema.exitSchema(req))) + const getEncodeChunk = withRequestTag((req) => Schema.encode(Schema.Chunk(Schema.exitSchema(req)))) return (u: unknown): Effect.Effect, ParseError, RpcRouter.Context> => Effect.flatMap( @@ -408,8 +407,8 @@ export const toHandlerRaw = >(router: R) => { */ export const toHandlerUndecoded = >(router: R) => { const handler = toHandlerRaw(router) - const getEncode = withRequestTag((req) => Schema.encode(Serializable.successSchema(req))) - const getEncodeChunk = withRequestTag((req) => Schema.encode(Schema.ChunkFromSelf(Serializable.successSchema(req)))) + const getEncode = withRequestTag((req) => Schema.encode(Schema.successSchema(req))) + const getEncodeChunk = withRequestTag((req) => Schema.encode(Schema.ChunkFromSelf(Schema.successSchema(req)))) return >(request: Req): Rpc.Rpc.ResultUndecoded> => { const result = handler(request) if (Effect.isEffect(result)) { diff --git a/packages/rpc/src/internal/rpc.ts b/packages/rpc/src/internal/rpc.ts index 89d5cdd18d..79e5467f6b 100644 --- a/packages/rpc/src/internal/rpc.ts +++ b/packages/rpc/src/internal/rpc.ts @@ -1,16 +1,15 @@ import type * as Headers from "@effect/platform/Headers" -import * as Schema from "@effect/schema/Schema" -import * as Serializable from "@effect/schema/Serializable" import * as Equal from "effect/Equal" import * as Hash from "effect/Hash" import * as PrimaryKey from "effect/PrimaryKey" import * as Request from "effect/Request" +import * as Schema from "effect/Schema" import type * as Rpc from "../Rpc.js" /** @internal */ export const withRequestTag = ( f: ( - request: Serializable.SerializableWithResult + request: Schema.SerializableWithResult ) => A ) => { const cache = new Map() @@ -46,11 +45,11 @@ export const makeRequest = ( ...options, [Request.RequestTypeId]: undefined as any, [PrimaryKey.symbol]: () => `${options.request._tag}:${hash}`, - [Serializable.symbolResult]: { + [Schema.symbolWithResult]: { success: isStream ? Schema.Never - : Serializable.successSchema(options.request as any), - failure: isStream ? Schema.Never : Serializable.failureSchema(options.request as any) + : Schema.successSchema(options.request as any), + failure: isStream ? Schema.Never : Schema.failureSchema(options.request as any) }, [Equal.symbol](that: Rpc.Request) { return Equal.equals(options.request, that.request) diff --git a/packages/rpc/test/Router.test.ts b/packages/rpc/test/Router.test.ts index 8bc0354000..efd3dde82f 100644 --- a/packages/rpc/test/Router.test.ts +++ b/packages/rpc/test/Router.test.ts @@ -1,12 +1,11 @@ import { RpcResolver, RpcResolverNoStream, RpcRouter } from "@effect/rpc" import * as Rpc from "@effect/rpc/Rpc" -import { Schema } from "@effect/schema" -import * as S from "@effect/schema/Schema" import * as Array from "effect/Array" import * as Chunk from "effect/Chunk" import * as Context from "effect/Context" import * as Effect from "effect/Effect" import { flow, pipe } from "effect/Function" +import * as Schema from "effect/Schema" import * as Stream from "effect/Stream" import { assert, describe, expect, it, test } from "vitest" @@ -15,20 +14,20 @@ interface Name { } const Name = Context.GenericTag("Name") -class SomeError extends S.TaggedError()("SomeError", { - message: S.String +class SomeError extends Schema.TaggedError()("SomeError", { + message: Schema.String }) {} -class Post extends S.Class("Post")({ - id: S.Number, - body: S.String +class Post extends Schema.Class("Post")({ + id: Schema.Number, + body: Schema.String }) {} -class CreatePost extends S.TaggedRequest()("CreatePost", { - failure: S.Never, +class CreatePost extends Schema.TaggedRequest()("CreatePost", { + failure: Schema.Never, success: Post, payload: { - body: S.String + body: Schema.String } }) {} @@ -36,68 +35,72 @@ const posts = RpcRouter.make( Rpc.effect(CreatePost, ({ body }) => Effect.succeed(new Post({ id: 1, body }))) ) -class Greet extends S.TaggedRequest()("Greet", { - failure: S.Never, - success: S.String, +class Greet extends Schema.TaggedRequest()("Greet", { + failure: Schema.Never, + success: Schema.String, payload: { - name: S.String + name: Schema.String } }) {} -class Fail extends S.TaggedRequest()("Fail", { +class Fail extends Schema.TaggedRequest()("Fail", { failure: SomeError, - success: S.Void, + success: Schema.Void, payload: { - name: S.String + name: Schema.String } }) {} class FailNoInput - extends S.TaggedRequest()("FailNoInput", { failure: SomeError, success: S.Void, payload: {} }) + extends Schema.TaggedRequest()("FailNoInput", { failure: SomeError, success: Schema.Void, payload: {} }) {} -class EncodeInput extends S.TaggedRequest()("EncodeInput", { - failure: S.Never, - success: S.Date, +class EncodeInput extends Schema.TaggedRequest()("EncodeInput", { + failure: Schema.Never, + success: Schema.Date, payload: { - date: S.Date + date: Schema.Date } }) {} -class EncodeDate extends S.TaggedRequest()("EncodeDate", { +class EncodeDate extends Schema.TaggedRequest()("EncodeDate", { failure: SomeError, - success: S.Date, + success: Schema.Date, payload: { - date: S.String + date: Schema.String } }) {} -class Refined extends S.TaggedRequest()("Refined", { - failure: S.Never, - success: S.Number, +class Refined extends Schema.TaggedRequest()("Refined", { + failure: Schema.Never, + success: Schema.Number, payload: { - number: pipe(S.Number, S.int(), S.greaterThan(10)) + number: pipe(Schema.Number, Schema.int(), Schema.greaterThan(10)) } }) {} -class SpanName extends S.TaggedRequest()("SpanName", { failure: S.Never, success: S.String, payload: {} }) {} +class SpanName + extends Schema.TaggedRequest()("SpanName", { failure: Schema.Never, success: Schema.String, payload: {} }) +{} -class GetName extends S.TaggedRequest()("GetName", { failure: S.Never, success: S.String, payload: {} }) {} +class GetName + extends Schema.TaggedRequest()("GetName", { failure: Schema.Never, success: Schema.String, payload: {} }) +{} -class EchoHeaders extends S.TaggedRequest()("EchoHeaders", { - failure: S.Never, - success: S.Record({ key: S.String, value: S.Union(S.String, S.Undefined) }), +class EchoHeaders extends Schema.TaggedRequest()("EchoHeaders", { + failure: Schema.Never, + success: Schema.Record({ key: Schema.String, value: Schema.Union(Schema.String, Schema.Undefined) }), payload: {} }) {} class Counts extends Rpc.StreamRequest()( "Counts", - { failure: S.Never, success: S.Number, payload: {} } + { failure: Schema.Never, success: Schema.Number, payload: {} } ) {} class FailStream extends Rpc.StreamRequest()( "FailStream", - { failure: SomeError, success: S.Number, payload: {} } + { failure: SomeError, success: Schema.Number, payload: {} } ) {} const router = RpcRouter.make( @@ -126,7 +129,7 @@ const router = RpcRouter.make( Stream.tap((_) => Effect.sleep(10)) )), Rpc.effect(EchoHeaders, () => - Rpc.schemaHeaders(S.Struct({ + Rpc.schemaHeaders(Schema.Struct({ foo: Schema.String, baz: Schema.optional(Schema.String) })).pipe(Effect.orDie)), @@ -153,7 +156,7 @@ const handlerArray = (u: ReadonlyArray) => Effect.map(flow( Array.fromIterable, Array.map(([, response]) => response), - Array.filter((_): _ is S.ExitEncoded => Array.isArray(_) === false) + Array.filter((_): _ is Schema.ExitEncoded => Array.isArray(_) === false) )) ) const handlerEffectArray = (u: ReadonlyArray) => diff --git a/packages/rpc/tsconfig.build.json b/packages/rpc/tsconfig.build.json index 94e5fb0383..472aa658e6 100644 --- a/packages/rpc/tsconfig.build.json +++ b/packages/rpc/tsconfig.build.json @@ -2,8 +2,7 @@ "extends": "./tsconfig.src.json", "references": [ { "path": "../effect/tsconfig.build.json" }, - { "path": "../platform/tsconfig.build.json" }, - { "path": "../schema/tsconfig.build.json" } + { "path": "../platform/tsconfig.build.json" } ], "compilerOptions": { "tsBuildInfoFile": ".tsbuildinfo/build.tsbuildinfo", diff --git a/packages/rpc/tsconfig.examples.json b/packages/rpc/tsconfig.examples.json index 718637d3f2..b52b121594 100644 --- a/packages/rpc/tsconfig.examples.json +++ b/packages/rpc/tsconfig.examples.json @@ -4,8 +4,7 @@ "references": [ { "path": "tsconfig.src.json" }, { "path": "../effect" }, - { "path": "../platform" }, - { "path": "../schema" } + { "path": "../platform" } ], "compilerOptions": { "tsBuildInfoFile": ".tsbuildinfo/examples.tsbuildinfo", diff --git a/packages/rpc/tsconfig.src.json b/packages/rpc/tsconfig.src.json index fe0ac8a681..a1ad892129 100644 --- a/packages/rpc/tsconfig.src.json +++ b/packages/rpc/tsconfig.src.json @@ -1,11 +1,7 @@ { "extends": "../../tsconfig.base.json", "include": ["src"], - "references": [ - { "path": "../effect" }, - { "path": "../platform" }, - { "path": "../schema" } - ], + "references": [{ "path": "../effect" }, { "path": "../platform" }], "compilerOptions": { "tsBuildInfoFile": ".tsbuildinfo/src.tsbuildinfo", "rootDir": "src", diff --git a/packages/rpc/tsconfig.test.json b/packages/rpc/tsconfig.test.json index 380524224f..8939416ac7 100644 --- a/packages/rpc/tsconfig.test.json +++ b/packages/rpc/tsconfig.test.json @@ -4,8 +4,7 @@ "references": [ { "path": "tsconfig.src.json" }, { "path": "../effect" }, - { "path": "../platform" }, - { "path": "../schema" } + { "path": "../platform" } ], "compilerOptions": { "tsBuildInfoFile": ".tsbuildinfo/test.tsbuildinfo", diff --git a/packages/schema/LICENSE b/packages/schema/LICENSE deleted file mode 100644 index be1f5c14c7..0000000000 --- a/packages/schema/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2023 Effectful Technologies Inc - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/packages/schema/README.md b/packages/schema/README.md deleted file mode 100644 index 232abe3184..0000000000 --- a/packages/schema/README.md +++ /dev/null @@ -1,271 +0,0 @@ -# Introduction - -Welcome to the documentation for `@effect/schema`, **a library for defining and using schemas** to validate and transform data in TypeScript. - -`@effect/schema` allows you to define a `Schema` that provides a blueprint for describing the structure and data types of your data. Once defined, you can leverage this schema to perform a range of operations, including: - -| Operation | Description | -| --------------- | -------------------------------------------------------------------------------------------------------------- | -| Decoding | Transforming data from an input type `Encoded` to an output type `Type`. | -| Encoding | Converting data from an output type `Type` back to an input type `Encoded`. | -| Asserting | Verifying that a value adheres to the schema's output type `Type`. | -| Arbitraries | Generate arbitraries for [fast-check](https://github.com/dubzzz/fast-check) testing. | -| JSON Schemas | Create JSON Schemas based on defined schemas. | -| Equivalence | Create [Equivalences](https://effect-ts.github.io/effect/schema/Equivalence.ts.html) based on defined schemas. | -| Pretty printing | Support pretty printing for data structures. | - -# Requirements - -- TypeScript **5.0** or newer -- The `strict` flag enabled in your `tsconfig.json` file -- The `exactOptionalPropertyTypes` flag enabled in your `tsconfig.json` file - ```json - { - // ... - "compilerOptions": { - // ... - "strict": true, - "exactOptionalPropertyTypes": true - } - } - ``` -- Additionally, make sure to install the following packages, as they are peer dependencies. Note that some package managers might not install peer dependencies by default, so you need to install them manually: - - `effect` package (peer dependency) - - [fast-check](https://github.com/dubzzz/fast-check) package (peer dependency) - -# Documentation - -- [Website Docs](https://effect.website/docs/guides/schema) -- [API Reference](https://effect-ts.github.io/effect/docs/schema) -- Comparisons - - [zod (v3)](https://github.com/Effect-TS/effect/blob/main/packages/schema/comparisons.md#zod-v3) - -# Getting started - -To install the **beta** version: - -```bash -npm install @effect/schema -``` - -Additionally, make sure to install the `effect` package, as it's peer dependencies. Note that some package managers might not install peer dependencies by default, so you need to install them manually. - -Once you have installed the library, you can import the necessary types and functions from the `@effect/schema/Schema` module. - -**Example** (Namespace Import) - -```ts -import * as Schema from "@effect/schema/Schema" -``` - -**Example** (Named Import) - -```ts -import { Schema } from "@effect/schema" -``` - -# Technical overview - -A schema is a description of a data structure that can be used to generate various artifacts from a single declaration. - -From a technical point of view a schema is just a typed wrapper of an `AST` value: - -```ts -interface Schema { - readonly ast: AST -} -``` - -The `AST` type represents a tiny portion of the TypeScript AST, roughly speaking the part describing ADTs (algebraic data types), -i.e. products (like structs and tuples) and unions, plus a custom transformation node. - -This means that you can define your own schema constructors / combinators as long as you are able to manipulate the `AST` value accordingly, let's see an example. - -Say we want to define a `pair` schema constructor, which takes a `Schema` as input and returns a `Schema` as output. - -First of all we need to define the signature of `pair` - -```ts -import type { Schema } from "@effect/schema" - -declare const pair: ( - schema: Schema.Schema -) => Schema.Schema -``` - -Then we can implement the body using the APIs exported by the `@effect/schema/AST` module: - -```ts -import { AST, Schema } from "@effect/schema" - -const pair = ( - schema: Schema.Schema -): Schema.Schema => { - const element = new AST.OptionalType( - schema.ast, // <= the element type - false // <= is optional? - ) - const tuple = new AST.TupleType( - [element, element], // <= elements definitions - [], // <= rest element - true // <= is readonly? - ) - return Schema.make(tuple) // <= wrap the AST value in a Schema -} -``` - -This example demonstrates the use of the low-level APIs of the `AST` module, however, the same result can be achieved more easily and conveniently by using the high-level APIs provided by the `Schema` module. - -```ts -import { Schema } from "@effect/schema" - -const pair = ( - schema: Schema.Schema -): Schema.Schema => - Schema.Tuple(schema, schema) -``` - -# FAQ - -## Is it Possible to Extend Functionality Beyond Built-in APIs? - -If your needs aren't addressed by the existing built-in APIs, you have the option to craft your own API using the built-in APIs as a foundation. If these still don't suffice, you can delve into the lower-level APIs provided by the `@effect/schema/AST` module. - -To develop a robust custom API, you need to address two primary challenges: - -1. **Type-level challenge**: Can you define the TypeScript signature for your API? -2. **Runtime-level challenge**: Can you implement your API at runtime using either the `Schema` or `AST` module APIs? - -Let's explore a practical example: "Is it possible to make all fields of a struct nullable?" - -**Defining the API Signature in TypeScript** - -First, let's determine if we can define the API's TypeScript signature: - -```ts -import { Schema } from "@effect/schema" - -declare const nullableFields: < - Fields extends { readonly [x: string]: Schema.Schema.Any } ->( - schema: Schema.Struct -) => Schema.Struct<{ [K in keyof Fields]: Schema.NullOr }> - -// Example use - -/* -const schema: Schema.Struct<{ - name: Schema.NullOr; - age: Schema.NullOr; -}> -*/ -const schema = nullableFields( - Schema.Struct({ - name: Schema.String, - age: Schema.Number - }) -) -``` - -You can preliminarily define the signature of `nullableFields` using TypeScript's `declare` keyword, allowing you to immediately test its validity (at the type-level, initially). The example above confirms that the API behaves as expected by inspecting a schema that utilizes this new API. - -```ts -const schema: Schema.Struct<{ - name: Schema.NullOr - age: Schema.NullOr -}> -``` - -**Implementing the API at Runtime** - -```ts -import { Schema } from "@effect/schema" -import { Record } from "effect" - -const nullableFields = < - Fields extends { readonly [x: string]: Schema.Schema.Any } ->( - schema: Schema.Struct -): Schema.Struct<{ [K in keyof Fields]: Schema.NullOr }> => { - return Schema.Struct( - Record.map(schema.fields, (schema) => Schema.NullOr(schema)) as any as { - [K in keyof Fields]: Schema.NullOr - } - ) -} - -const schema = nullableFields( - Schema.Struct({ - name: Schema.String, - age: Schema.Number - }) -) - -console.log(Schema.decodeUnknownSync(schema)({ name: "a", age: null })) -/* -Output: -{ name: 'a', age: null } -*/ -``` - -# Credits - -This library was inspired by the following projects: - -- [io-ts](https://github.com/gcanti/io-ts) -- [zod](https://github.com/colinhacks/zod) -- [zio-schema](https://github.com/zio/zio-schema) - -# License - -By contributing to this project, you agree that your contributions will be licensed under the project's [MIT License](./LICENSE). - -# Contributing Guidelines - -Thank you for considering contributing to our project! Here are some guidelines to help you get started: - -## Reporting Bugs - -If you have found a bug, please open an issue on our [issue tracker](https://github.com/Effect-TS/effect/issues) and provide as much detail as possible. This should include: - -- A clear and concise description of the problem -- Steps to reproduce the problem -- The expected behavior -- The actual behavior -- Any relevant error messages or logs - -## Suggesting Enhancements - -If you have an idea for an enhancement or a new feature, please open an issue on our [issue tracker](https://github.com/Effect-TS/effect/issues) and provide as much detail as possible. This should include: - -- A clear and concise description of the enhancement or feature -- Any potential benefits or use cases -- Any potential drawbacks or trade-offs - -## Pull Requests - -We welcome contributions via pull requests! Here are some guidelines to help you get started: - -1. Fork the repository and clone it to your local machine. -2. Create a new branch for your changes: `git checkout -b my-new-feature` -3. Ensure you have the required dependencies installed by running: `pnpm install` (assuming pnpm version `8.x`). -4. Make your desired changes and, if applicable, include tests to validate your modifications. -5. Run the following commands to ensure the integrity of your changes: - - `pnpm check`: Verify that the code compiles. - - `pnpm test`: Execute the tests. - - `pnpm circular`: Confirm there are no circular imports. - - `pnpm lint`: Check for code style adherence (if you happen to encounter any errors during this process, you can add the `--fix` option to automatically fix some of these style issues). - - `pnpm dtslint`: Run type-level tests. - - `pnpm docgen`: Update the automatically generated documentation. -6. Create a changeset for your changes: before committing your changes, create a changeset to document the modifications. This helps in tracking and communicating the changes effectively. To create a changeset, run the following command: `pnpm changeset`. -7. Commit your changes: after creating the changeset, commit your changes with a descriptive commit message: `git commit -am 'Add some feature'`. -8. Push your changes to your fork: `git push origin my-new-feature`. -9. Open a pull request against our `main` branch. - -### Pull Request Guidelines - -- Please make sure your changes are consistent with the project's existing style and conventions. -- Please write clear commit messages and include a summary of your changes in the pull request description. -- Please make sure all tests pass and add new tests as necessary. -- If your change requires documentation, please update the relevant documentation. -- Please be patient! We will do our best to review your pull request as soon as possible. diff --git a/packages/schema/docgen.json b/packages/schema/docgen.json deleted file mode 100644 index af59e3a42f..0000000000 --- a/packages/schema/docgen.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "$schema": "../../node_modules/@effect/docgen/schema.json", - "exclude": [ - "src/internal/**/*.ts" - ], - "examplesCompilerOptions": { - "noEmit": true, - "strict": true, - "skipLibCheck": true, - "moduleResolution": "Bundler", - "module": "ES2022", - "target": "ES2022", - "lib": [ - "ES2022", - "DOM" - ], - "paths": { - "effect": [ - "../../../effect/src/index.js" - ], - "effect/*": [ - "../../../effect/src/*.js" - ] - } - } -} diff --git a/packages/schema/dtslint/tsconfig.json b/packages/schema/dtslint/tsconfig.json deleted file mode 100644 index 6b2c70900f..0000000000 --- a/packages/schema/dtslint/tsconfig.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "../../../tsconfig.base.json", - "include": ["."], - "compilerOptions": { - "incremental": false, - "composite": false, - "noUnusedLocals": false - } -} diff --git a/packages/schema/package.json b/packages/schema/package.json deleted file mode 100644 index 290c01fe3f..0000000000 --- a/packages/schema/package.json +++ /dev/null @@ -1,60 +0,0 @@ -{ - "name": "@effect/schema", - "version": "0.75.5", - "type": "module", - "license": "MIT", - "description": "Modeling the schema of data structures as first-class values", - "homepage": "https://effect.website", - "repository": { - "type": "git", - "url": "https://github.com/Effect-TS/effect.git", - "directory": "packages/schema" - }, - "bugs": { - "url": "https://github.com/Effect-TS/effect/issues" - }, - "tags": [ - "typescript", - "algebraic-data-types", - "functional-programming", - "validation", - "schema" - ], - "keywords": [ - "typescript", - "algebraic-data-types", - "functional-programming", - "validation", - "schema" - ], - "publishConfig": { - "access": "public", - "directory": "dist", - "provenance": true - }, - "scripts": { - "codegen": "build-utils prepare-v2", - "build": "pnpm build-esm && pnpm build-annotate && pnpm build-cjs && build-utils pack-v2", - "build-esm": "tsc -b tsconfig.build.json", - "build-cjs": "babel build/esm --plugins @babel/transform-export-namespace-from --plugins @babel/transform-modules-commonjs --out-dir build/cjs --source-maps", - "build-annotate": "babel build/esm --plugins annotate-pure-calls --out-dir build/esm --source-maps", - "dtslint": "dtslint dtslint", - "check": "tsc -b tsconfig.json", - "test": "vitest", - "coverage": "vitest --coverage", - "circular": "madge --extensions ts --circular --no-color --no-spinner src" - }, - "dependencies": { - "fast-check": "^3.21.0" - }, - "peerDependencies": { - "effect": "workspace:^" - }, - "devDependencies": { - "ajv": "^8.17.1", - "effect": "workspace:^", - "fast-check": "workspace:^", - "tinybench": "^2.9.0", - "zod": "^3.23.5" - } -} diff --git a/packages/schema/serializable.md b/packages/schema/serializable.md deleted file mode 100644 index b71af084f1..0000000000 --- a/packages/schema/serializable.md +++ /dev/null @@ -1,355 +0,0 @@ -# Serializable - -The `Serializable` module enables objects to have self-contained schema(s) for serialization. This functionality is particularly beneficial in scenarios where objects need to be consistently serialized and deserialized across various runtime environments or sent over network communications. - -## Serializable trait - -The `Serializable` trait equips objects with the capability to define their serialization logic explicitly. - -```ts -interface Serializable { - readonly [symbol]: Schema.Schema -} -``` - -**Example: Implementing the Serializable Trait** - -```ts -import { Schema, Serializable } from "@effect/schema" -import { Effect } from "effect" - -class Person { - constructor( - readonly id: number, - readonly name: string, - readonly createdAt: Date - ) {} - - // Define the schema for serialization - static FromEncoded = Schema.transform( - Schema.Struct({ - id: Schema.Number, - name: Schema.String, - createdAt: Schema.Date - }), - Schema.instanceOf(Person), - { - decode: ({ createdAt, id, name }) => new Person(id, name, createdAt), - encode: ({ createdAt, id, name }) => ({ id, name, createdAt }) - } - ) - - // Implementing the Serializable trait using the static schema - get [Serializable.symbol]() { - return Person.FromEncoded - } -} - -const person = new Person(1, "John", new Date(0)) - -// Example serialization -const serialized = Effect.runSync(Serializable.serialize(person)) -console.log(serialized) -// { id: 1, name: 'John', createdAt: '1970-01-01T00:00:00.000Z' } - -// Deserialization -const deserialized = Schema.decodeUnknownSync(Person.FromEncoded)(serialized) -console.log(deserialized) -// Person { id: 1, name: 'John', createdAt: 1970-01-01T00:00:00.000Z } - -// Deserialization using an instance: -// if you have access to a Person instance you can use `Serializable.deserialize` to deserialize -const deserializedUsingAnInstance = Effect.runSync( - Serializable.deserialize(person, serialized) -) -console.log(deserializedUsingAnInstance) -// Person { id: 1, name: 'John', createdAt: 1970-01-01T00:00:00.000Z } -``` - -## Streamlining Code with Schema.Class - -While the above example provides a comprehensive view of serialization processes, using the `Schema.Class` API can significantly reduce boilerplate and simplify class modeling. - -```ts -import { Schema, Serializable } from "@effect/schema" -import { Effect } from "effect" - -class Person extends Schema.Class("Person")({ - id: Schema.Number, - name: Schema.String, - createdAt: Schema.Date -}) { - get [Serializable.symbol]() { - return Person - } -} - -const person = new Person({ id: 1, name: "John", createdAt: new Date(0) }) - -const serialized = Effect.runSync(Serializable.serialize(person)) -console.log(serialized) -// { id: 1, name: 'John', createdAt: '1970-01-01T00:00:00.000Z' } - -const deserialized = Schema.decodeUnknownSync(Person)(serialized) -console.log(deserialized) -// Person { id: 1, name: 'John', createdAt: 1970-01-01T00:00:00.000Z } - -const deserializedUsingAnInstance = Effect.runSync( - Serializable.deserialize(person, serialized) -) -console.log(deserializedUsingAnInstance) -// Person { id: 1, name: 'John', createdAt: 1970-01-01T00:00:00.000Z } -``` - -## WithResult trait - -The `WithResult` trait is designed to encapsulate the outcome of an operation, distinguishing between success and failure cases. Each case is associated with a schema that defines the structure and types of the success or failure data. - -```ts -interface WithResult< - Success, - SuccessEncoded, - Failure, - FailureEncoded, - ResultR -> { - readonly [symbolResult]: { - readonly success: Schema.Schema - readonly failure: Schema.Schema - } -} -``` - -## SerializableWithResult trait - -The `SerializableWithResult` trait is specifically designed to model remote procedures that require serialization of their input and output, managing both successful and failed outcomes. - -This trait combines functionality from both the `Serializable` and `WithResult` traits to handle data serialization and the bifurcation of operation results into success or failure categories. - -**Definition** - -```ts -interface SerializableWithResult< - A, - I, - R, - Success, - SuccessEncoded, - Failure, - FailureEncoded, - ResultR -> extends Serializable, - WithResult {} -``` - -**Components** - -- **Payload (`A, I, R`)**: The payload is described using the `Serializable` trait, which includes the type of the payload (`A`), its serialized form (`I`), and any relevant runtime context (`R`). -- **Success Case (`Success, SuccessEncoded, ResultR`)**: Defined by `Schema`, this outlines the structure and type of the data upon a successful operation, along with its serialized form. -- **Failure Case (`Failure, FailureEncoded, ResultR`)**: This is analogous to the Success Case but caters to scenarios where the operation fails. It is described by `Schema`. - -**Workflow** - -1. **Initialization**: Begin with data of type `A`. -2. **Serialization**: Convert this data into its serialized format `I`. -3. **Transmission**: Send this serialized data over the network. -4. **Reception and Deserialization**: Upon receiving, convert the data back from type `I` to `A`. -5. **Processing**: The deserialized data is then processed to determine the outcome as either success (`Success`) or failure (`Failure`). -6. **Result Serialization**: Depending on the outcome, serialize the result into `Exit`. -7. **Response Transmission**: Send the serialized outcome back over the network. -8. **Final Deserialization**: Deserialize the received outcome back into `Exit` for final use. - -```mermaid -sequenceDiagram - Sender->>SenderBound: encodes A to I - SenderBound-->>ReceiverBound: send I - ReceiverBound->>Receiver: decodes I to A - Receiver->>ReceiverBound: encodes Exit
to Exit - ReceiverBound-->>SenderBound: send back
Exit - SenderBound->>Sender: decodes Exit
to Exit -``` - -**Example** - -```ts -import type { ParseResult } from "@effect/schema" -import { Schema, Serializable } from "@effect/schema" -import { Effect, Exit } from "effect" - -class Person extends Schema.Class("Person")({ - id: Schema.Number, - name: Schema.String, - createdAt: Schema.Date -}) { - get [Serializable.symbol]() { - return Person - } -} - -class GetPersonById { - constructor(readonly id: number) {} - - static FromEncoded = Schema.transform( - Schema.Number, - Schema.instanceOf(GetPersonById), - { - decode: (id) => new GetPersonById(id), - encode: ({ id }) => id - } - ) - - get [Serializable.symbol]() { - return GetPersonById.FromEncoded - } - - get [Serializable.symbolResult]() { - return { - success: Person, - failure: Schema.String - } - } -} - -function handleGetPersonById( - serializedReq: typeof GetPersonById.FromEncoded.Encoded -) { - return Effect.gen(function* () { - const req = yield* Schema.decodeUnknown(GetPersonById.FromEncoded)( - serializedReq - ) - return yield* Serializable.serializeExit( - req, - req.id === 0 - ? Exit.fail("User not found") - : Exit.succeed( - new Person({ id: req.id, name: "John", createdAt: new Date() }) - ) - ) - }) -} - -const roundtrip = ( - req: GetPersonById -): Effect.Effect, ParseResult.ParseError> => - Effect.gen(function* () { - const serializedReq = yield* Serializable.serialize(req) - const exit = yield* handleGetPersonById(serializedReq) - return yield* Serializable.deserializeExit(req, exit) - }) - -console.log(Effect.runSync(roundtrip(new GetPersonById(1)))) -/* -Output: -{ - _id: 'Exit', - _tag: 'Success', - value: Person { id: 1, name: 'John', createdAt: 2024-07-02T17:40:59.666Z } -} -*/ - -console.log(Effect.runSync(roundtrip(new GetPersonById(0)))) -/* -Output: -{ - _id: 'Exit', - _tag: 'Failure', - cause: { _id: 'Cause', _tag: 'Fail', failure: 'User not found' } -} -*/ -``` - -## Streamlining Code with Schema.TaggedRequest - -While the previous example effectively demonstrates the mechanisms involved, it does require a significant amount of boilerplate code. To streamline development, the `Schema.TaggedRequest` API is specifically designed to reduce complexity and increase readability. - -```ts -import type { ParseResult } from "@effect/schema" -import { Schema, Serializable } from "@effect/schema" -import { Effect, Exit } from "effect" - -// Define a simple person class using Schema.Class for ease of serialization -class Person extends Schema.Class("Person")({ - id: Schema.Number, - name: Schema.String, - createdAt: Schema.Date -}) {} - -// Represents a serializable function: `(payload: { readonly id: number }) => Exit` -class GetPersonById extends Schema.TaggedRequest()( - "GetPersonById", - { - payload: { id: Schema.Number }, // Define the schema for the payload, - success: Person, // Schema for successful outcome - failure: Schema.String // Schema for failure outcome - } -) {} - -// Function to handle the GetPersonById request and process the response -function handleGetPersonById(serializedReq: typeof GetPersonById.Encoded) { - return Effect.gen(function* () { - const req = yield* Schema.decodeUnknown(GetPersonById)(serializedReq) - return yield* Serializable.serializeExit( - req, - req.id === 0 - ? Exit.fail("User not found") - : Exit.succeed( - new Person({ id: req.id, name: "John", createdAt: new Date() }) - ) - ) - }) -} - -// Simulates a roundtrip serialization and deserialization process -const roundtrip = ( - req: GetPersonById -): Effect.Effect, ParseResult.ParseError> => - Effect.gen(function* () { - const serializedReq = yield* Serializable.serialize(req) - const exit = yield* handleGetPersonById(serializedReq) - return yield* Serializable.deserializeExit(req, exit) - }) - -// Example outputs from invoking the roundtrip function -console.log(Effect.runSync(roundtrip(new GetPersonById({ id: 1 })))) -/* -Output: -{ - _id: 'Exit', - _tag: 'Success', - value: Person { id: 1, name: 'John', createdAt: 2024-07-02T17:40:59.666Z } -} -*/ - -console.log(Effect.runSync(roundtrip(new GetPersonById({ id: 0 })))) -/* -Output: -{ - _id: 'Exit', - _tag: 'Failure', - cause: { _id: 'Cause', _tag: 'Fail', failure: 'User not found' } -} -*/ -``` - -## Communication and Serialization with Schema and Serializable Traits - -This section outlines a streamlined client-server interaction using the `Serializable` and `WithResult` traits from the `@effect/schema` library to manage serialization and processing of data objects across network communications. - -**Client-Side Operations:** - -1. **Initialization**: Start with an object of type `A`, which implements `Serializable.SerializableWithResult`. -2. **Serialization**: Serialize the object `A` using `Serializable.serialize`, which employs the schema retrieved from the `Serializable` interface tied to `A`. -3. **Transmission**: Send the serialized data of type `I` to the server and wait for a response. - -**Server-Side Operations:** - -1. **Reception**: Receive the serialized data `I`. -2. **Deserialization**: Convert the serialized data `I` back into an object of type `A` using a predefined union schema `Schema
`. -3. **Processing**: Handle the message of type `A` to derive an outcome as `Exit`. -4. **Result Serialization**: Serialize the result `Exit` to `Exit` utilizing the schema obtained from `A`'s `WithResult` interface. -5. **Response**: Send the serialized response `Exit` back to the client. - -**Client-Side Response Handling:** - -1. **Reception**: Receive the response `Exit`. -2. **Final Deserialization**: Convert `Exit` back to `Exit` using the original object `A` and the schema from the `WithResult` interface. diff --git a/packages/schema/src/ArrayFormatter.ts b/packages/schema/src/ArrayFormatter.ts deleted file mode 100644 index 7c5dfbe783..0000000000 --- a/packages/schema/src/ArrayFormatter.ts +++ /dev/null @@ -1,82 +0,0 @@ -/** - * @since 0.67.0 - */ - -import * as array_ from "effect/Array" -import * as Effect from "effect/Effect" -import * as util_ from "./internal/util.js" -import type * as ParseResult from "./ParseResult.js" -import * as TreeFormatter from "./TreeFormatter.js" - -/** - * @category model - * @since 0.67.0 - */ -export interface Issue { - readonly _tag: ParseResult.ParseIssue["_tag"] - readonly path: ReadonlyArray - readonly message: string -} - -/** - * @category formatting - * @since 0.67.0 - */ -export const formatIssue = (issue: ParseResult.ParseIssue): Effect.Effect> => go(issue) - -/** - * @category formatting - * @since 0.67.0 - */ -export const formatIssueSync = (issue: ParseResult.ParseIssue): Array => Effect.runSync(formatIssue(issue)) - -/** - * @category formatting - * @since 0.67.0 - */ -export const formatError = (error: ParseResult.ParseError): Effect.Effect> => formatIssue(error.issue) - -/** - * @category formatting - * @since 0.67.0 - */ -export const formatErrorSync = (error: ParseResult.ParseError): Array => formatIssueSync(error.issue) - -const succeed = (issue: Issue) => Effect.succeed([issue]) - -const getArray = ( - issue: ParseResult.ParseIssue, - path: ReadonlyArray, - onFailure: () => Effect.Effect> -) => - Effect.matchEffect(TreeFormatter.getMessage(issue), { - onFailure, - onSuccess: (message) => succeed({ _tag: issue._tag, path, message }) - }) - -const go = ( - e: ParseResult.ParseIssue | ParseResult.Pointer, - path: ReadonlyArray = [] -): Effect.Effect> => { - const _tag = e._tag - switch (_tag) { - case "Type": - return Effect.map(TreeFormatter.formatTypeMessage(e), (message) => [{ _tag, path, message }]) - case "Forbidden": - return succeed({ _tag, path, message: TreeFormatter.formatForbiddenMessage(e) }) - case "Unexpected": - return succeed({ _tag, path, message: TreeFormatter.formatUnexpectedMessage(e) }) - case "Missing": - return Effect.map(TreeFormatter.formatMissingMessage(e), (message) => [{ _tag, path, message }]) - case "Pointer": - return go(e.issue, path.concat(e.path)) - case "Composite": - return getArray(e, path, () => - util_.isNonEmpty(e.issues) - ? Effect.map(Effect.forEach(e.issues, (issue) => go(issue, path)), array_.flatten) - : go(e.issues, path)) - case "Refinement": - case "Transformation": - return getArray(e, path, () => go(e.issue, path)) - } -} diff --git a/packages/schema/src/Equivalence.ts b/packages/schema/src/Equivalence.ts deleted file mode 100644 index 750752e6aa..0000000000 --- a/packages/schema/src/Equivalence.ts +++ /dev/null @@ -1,222 +0,0 @@ -/** - * @since 0.67.0 - */ - -import * as Arr from "effect/Array" -import * as Equal from "effect/Equal" -import * as Equivalence from "effect/Equivalence" -import * as Option from "effect/Option" -import * as AST from "./AST.js" -import * as errors_ from "./internal/errors.js" -import * as util_ from "./internal/util.js" -import * as ParseResult from "./ParseResult.js" -import type * as Schema from "./Schema.js" - -/** - * @category hooks - * @since 0.67.0 - */ -export const EquivalenceHookId: unique symbol = Symbol.for("@effect/schema/EquivalenceHookId") - -/** - * @category hooks - * @since 0.67.0 - */ -export type EquivalenceHookId = typeof EquivalenceHookId - -/** - * @category annotations - * @since 0.67.0 - */ -export const equivalence = - (handler: (...args: ReadonlyArray>) => Equivalence.Equivalence) => - (self: Schema.Schema): Schema.Schema => self.annotations({ [EquivalenceHookId]: handler }) - -/** - * @category Equivalence - * @since 0.67.0 - */ -export const make = (schema: Schema.Schema): Equivalence.Equivalence => go(schema.ast, []) - -const getHook = AST.getAnnotation< - (...args: ReadonlyArray>) => Equivalence.Equivalence ->( - EquivalenceHookId -) - -const go = (ast: AST.AST, path: ReadonlyArray): Equivalence.Equivalence => { - const hook = getHook(ast) - if (Option.isSome(hook)) { - switch (ast._tag) { - case "Declaration": - return hook.value(...ast.typeParameters.map((tp) => go(tp, path))) - case "Refinement": - return hook.value(go(ast.from, path)) - default: - return hook.value() - } - } - switch (ast._tag) { - case "NeverKeyword": - throw new Error(errors_.getEquivalenceUnsupportedErrorMessage(ast, path)) - case "Transformation": - return go(ast.to, path) - case "Declaration": - case "Literal": - case "StringKeyword": - case "TemplateLiteral": - case "UniqueSymbol": - case "SymbolKeyword": - case "UnknownKeyword": - case "AnyKeyword": - case "NumberKeyword": - case "BooleanKeyword": - case "BigIntKeyword": - case "UndefinedKeyword": - case "VoidKeyword": - case "Enums": - case "ObjectKeyword": - return Equal.equals - case "Refinement": - return go(ast.from, path) - case "Suspend": { - const get = util_.memoizeThunk(() => go(ast.f(), path)) - return (a, b) => get()(a, b) - } - case "TupleType": { - const elements = ast.elements.map((element, i) => go(element.type, path.concat(i))) - const rest = ast.rest.map((annotatedAST) => go(annotatedAST.type, path)) - return Equivalence.make((a, b) => { - const len = a.length - if (len !== b.length) { - return false - } - // --------------------------------------------- - // handle elements - // --------------------------------------------- - let i = 0 - for (; i < Math.min(len, ast.elements.length); i++) { - if (!elements[i](a[i], b[i])) { - return false - } - } - // --------------------------------------------- - // handle rest element - // --------------------------------------------- - if (Arr.isNonEmptyReadonlyArray(rest)) { - const [head, ...tail] = rest - for (; i < len - tail.length; i++) { - if (!head(a[i], b[i])) { - return false - } - } - // --------------------------------------------- - // handle post rest elements - // --------------------------------------------- - for (let j = 0; j < tail.length; j++) { - i += j - if (!tail[j](a[i], b[i])) { - return false - } - } - } - return true - }) - } - case "TypeLiteral": { - if (ast.propertySignatures.length === 0 && ast.indexSignatures.length === 0) { - return Equal.equals - } - const propertySignatures = ast.propertySignatures.map((ps) => go(ps.type, path.concat(ps.name))) - const indexSignatures = ast.indexSignatures.map((is) => go(is.type, path)) - return Equivalence.make((a, b) => { - const aStringKeys = Object.keys(a) - const aSymbolKeys = Object.getOwnPropertySymbols(a) - // --------------------------------------------- - // handle property signatures - // --------------------------------------------- - for (let i = 0; i < propertySignatures.length; i++) { - const ps = ast.propertySignatures[i] - const name = ps.name - const aHas = Object.prototype.hasOwnProperty.call(a, name) - const bHas = Object.prototype.hasOwnProperty.call(b, name) - if (ps.isOptional) { - if (aHas !== bHas) { - return false - } - } - if (aHas && bHas && !propertySignatures[i](a[name], b[name])) { - return false - } - } - // --------------------------------------------- - // handle index signatures - // --------------------------------------------- - let bSymbolKeys: Array | undefined - let bStringKeys: Array | undefined - for (let i = 0; i < indexSignatures.length; i++) { - const is = ast.indexSignatures[i] - const base = AST.getParameterBase(is.parameter) - const isSymbol = AST.isSymbolKeyword(base) - if (isSymbol) { - bSymbolKeys = bSymbolKeys || Object.getOwnPropertySymbols(b) - if (aSymbolKeys.length !== bSymbolKeys.length) { - return false - } - } else { - bStringKeys = bStringKeys || Object.keys(b) - if (aStringKeys.length !== bStringKeys.length) { - return false - } - } - const aKeys = isSymbol ? aSymbolKeys : aStringKeys - for (let j = 0; j < aKeys.length; j++) { - const key = aKeys[j] - if ( - !Object.prototype.hasOwnProperty.call(b, key) || !indexSignatures[i](a[key], b[key]) - ) { - return false - } - } - } - return true - }) - } - case "Union": { - const searchTree = ParseResult.getSearchTree(ast.types, true) - const ownKeys = util_.ownKeys(searchTree.keys) - const len = ownKeys.length - return Equivalence.make((a, b) => { - let candidates: Array = [] - if (len > 0 && isRecordOrArray(a)) { - for (let i = 0; i < len; i++) { - const name = ownKeys[i] - const buckets = searchTree.keys[name].buckets - if (Object.prototype.hasOwnProperty.call(a, name)) { - const literal = String(a[name]) - if (Object.prototype.hasOwnProperty.call(buckets, literal)) { - candidates = candidates.concat(buckets[literal]) - } - } - } - } - if (searchTree.otherwise.length > 0) { - candidates = candidates.concat(searchTree.otherwise) - } - const tuples = candidates.map((ast) => [go(ast, path), ParseResult.is({ ast } as any)] as const) - for (let i = 0; i < tuples.length; i++) { - const [equivalence, is] = tuples[i] - if (is(a) && is(b)) { - if (equivalence(a, b)) { - return true - } - } - } - return false - }) - } - } -} - -const isRecordOrArray = (input: unknown): input is { [x: PropertyKey]: unknown } => - typeof input === "object" && input !== null diff --git a/packages/schema/src/Serializable.ts b/packages/schema/src/Serializable.ts deleted file mode 100644 index fecaaa3b2c..0000000000 --- a/packages/schema/src/Serializable.ts +++ /dev/null @@ -1,385 +0,0 @@ -/** - * @since 0.67.0 - */ -import type * as Effect from "effect/Effect" -import type * as Exit from "effect/Exit" -import { dual } from "effect/Function" -import { globalValue } from "effect/GlobalValue" -import * as serializable_ from "./internal/serializable.js" -import type * as ParseResult from "./ParseResult.js" -import * as Schema from "./Schema.js" - -// --------------------------------------------- -// Serializable -// --------------------------------------------- - -/** - * @since 0.67.0 - * @category symbol - */ -export const symbol: unique symbol = serializable_.symbol as any - -/** - * The `Serializable` trait allows objects to define their own schema for - * serialization. - * - * @since 0.67.0 - * @category model - */ -export interface Serializable { - readonly [symbol]: Schema.Schema -} - -/** - * @since 0.67.0 - * @category model - */ -export declare namespace Serializable { - /** - * @since 0.68.15 - */ - export type Type = T extends Serializable ? A : never - /** - * @since 0.68.15 - */ - export type Encoded = T extends Serializable ? I : never - /** - * @since 0.67.0 - */ - export type Context = T extends Serializable ? R : never - /** - * @since 0.69.0 - */ - export type Any = Serializable - /** - * @since 0.69.0 - */ - export type All = - | Any - | Serializable - | Serializable - | Serializable -} - -/** - * @since 0.69.0 - */ -export const asSerializable = ( - serializable: S -): Serializable, Serializable.Encoded, Serializable.Context> => serializable as any - -/** - * @since 0.67.0 - * @category accessor - */ -export const selfSchema = (self: Serializable): Schema.Schema => self[symbol] - -/** - * @since 0.67.0 - * @category encoding - */ -export const serialize = (self: Serializable): Effect.Effect => - Schema.encodeUnknown(self[symbol])(self) - -/** - * @since 0.67.0 - * @category decoding - */ -export const deserialize: { - (value: unknown): (self: Serializable) => Effect.Effect - (self: Serializable, value: unknown): Effect.Effect -} = dual( - 2, - (self: Serializable, value: unknown): Effect.Effect => - Schema.decodeUnknown(self[symbol])(value) -) - -// --------------------------------------------- -// WithResult -// --------------------------------------------- - -/** - * @since 0.67.0 - * @category symbol - */ -export const symbolResult: unique symbol = serializable_.symbolResult as any - -/** - * The `WithResult` trait is designed to encapsulate the outcome of an - * operation, distinguishing between success and failure cases. Each case is - * associated with a schema that defines the structure and types of the success - * or failure data. - * - * @since 0.67.0 - * @category model - */ -export interface WithResult { - readonly [symbolResult]: { - readonly success: Schema.Schema - readonly failure: Schema.Schema - } -} - -/** - * @since 0.67.0 - * @category model - */ -export declare namespace WithResult { - /** - * @since 0.68.16 - */ - export type Success = T extends WithResult ? _A : never - /** - * @since 0.69.0 - */ - export type SuccessEncoded = T extends WithResult ? _I : never - /** - * @since 0.69.0 - */ - export type Failure = T extends WithResult ? _E : never - /** - * @since 0.69.0 - */ - export type FailureEncoded = T extends WithResult ? _EI : never - - /** - * @since 0.67.0 - */ - export type Context = T extends WithResult ? R : never - /** - * @since 0.69.0 - */ - export type Any = WithResult - /** - * @since 0.69.0 - */ - export type All = - | Any - | WithResult -} - -/** - * @since 0.69.0 - */ -export const asWithResult = ( - withExit: WR -): WithResult< - WithResult.Success, - WithResult.SuccessEncoded, - WithResult.Failure, - WithResult.FailureEncoded, - WithResult.Context -> => withExit as any - -/** - * @since 0.67.0 - * @category accessor - */ -export const failureSchema = (self: WithResult): Schema.Schema => - self[symbolResult].failure - -/** - * @since 0.67.0 - * @category accessor - */ -export const successSchema = (self: WithResult): Schema.Schema => - self[symbolResult].success - -const exitSchemaCache = globalValue( - "@effect/schema/Serializable/exitSchemaCache", - () => new WeakMap>() -) - -/** - * @since 0.67.0 - * @category accessor - */ -export const exitSchema = (self: WithResult): Schema.Schema< - Exit.Exit, - Schema.ExitEncoded, - R -> => { - const proto = Object.getPrototypeOf(self) - if (!(symbolResult in proto)) { - return Schema.Exit({ - failure: failureSchema(self), - success: successSchema(self), - defect: Schema.Defect - }) - } - let schema = exitSchemaCache.get(proto) - if (schema === undefined) { - schema = Schema.Exit({ - failure: failureSchema(self), - success: successSchema(self), - defect: Schema.Defect - }) - exitSchemaCache.set(proto, schema) - } - return schema -} - -/** - * @since 0.67.0 - * @category encoding - */ -export const serializeFailure: { - (value: FA): ( - self: WithResult - ) => Effect.Effect - (self: WithResult, value: FA): Effect.Effect -} = dual( - 2, - (self: WithResult, value: FA): Effect.Effect => - Schema.encode(self[symbolResult].failure)(value) -) - -/** - * @since 0.67.0 - * @category decoding - */ -export const deserializeFailure: { - ( - value: unknown - ): (self: WithResult) => Effect.Effect - (self: WithResult, value: unknown): Effect.Effect -} = dual( - 2, - ( - self: WithResult, - value: unknown - ): Effect.Effect => Schema.decodeUnknown(self[symbolResult].failure)(value) -) - -/** - * @since 0.67.0 - * @category encoding - */ -export const serializeSuccess: { - (value: SA): ( - self: WithResult - ) => Effect.Effect - (self: WithResult, value: SA): Effect.Effect -} = dual( - 2, - (self: WithResult, value: SA): Effect.Effect => - Schema.encode(self[symbolResult].success)(value) -) - -/** - * @since 0.67.0 - * @category decoding - */ -export const deserializeSuccess: { - (value: unknown): ( - self: WithResult - ) => Effect.Effect - (self: WithResult, value: unknown): Effect.Effect -} = dual( - 2, - ( - self: WithResult, - value: unknown - ): Effect.Effect => Schema.decodeUnknown(self[symbolResult].success)(value) -) - -/** - * @since 0.67.0 - * @category encoding - */ -export const serializeExit: { - (value: Exit.Exit): ( - self: WithResult - ) => Effect.Effect, ParseResult.ParseError, R> - ( - self: WithResult, - value: Exit.Exit - ): Effect.Effect, ParseResult.ParseError, R> -} = dual(2, ( - self: WithResult, - value: Exit.Exit -): Effect.Effect, ParseResult.ParseError, R> => - Schema.encode(exitSchema(self))(value)) - -/** - * @since 0.67.0 - * @category decoding - */ -export const deserializeExit: { - (value: unknown): ( - self: WithResult - ) => Effect.Effect, ParseResult.ParseError, R> - ( - self: WithResult, - value: unknown - ): Effect.Effect, ParseResult.ParseError, R> -} = dual(2, ( - self: WithResult, - value: unknown -): Effect.Effect, ParseResult.ParseError, R> => Schema.decodeUnknown(exitSchema(self))(value)) - -// --------------------------------------------- -// SerializableWithResult -// --------------------------------------------- - -/** - * The `SerializableWithResult` trait is specifically designed to model remote - * procedures that require serialization of their input and output, managing - * both successful and failed outcomes. - * - * This trait combines functionality from both the `Serializable` and `WithResult` - * traits to handle data serialization and the bifurcation of operation results - * into success or failure categories. - * - * @since 0.67.0 - * @category model - */ -export interface SerializableWithResult< - A, - I, - R, - Success, - SuccessEncoded, - Failure, - FailureEncoded, - ResultR -> extends Serializable, WithResult {} - -/** - * @since 0.67.0 - * @category model - */ -export declare namespace SerializableWithResult { - /** - * @since 0.69.0 - */ - export type Context