Skip to content

Commit

Permalink
feat: add ParseError path formatter
Browse files Browse the repository at this point in the history
  • Loading branch information
0x706b committed Jun 15, 2024
1 parent db39697 commit 8fd543d
Show file tree
Hide file tree
Showing 47 changed files with 1,617 additions and 1,155 deletions.
8 changes: 8 additions & 0 deletions .changeset/dirty-hounds-mix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"@fncts/schema": patch
"@fncts/base": patch
"@fncts/http": patch
"@fncts/io": patch
---

feat(schema): add ParseError path formatter
7 changes: 7 additions & 0 deletions packages/base/src/collection/Iterable/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,13 @@ export function toIterable<A>(self: Iterable<A>): Iterable<A> {
return self;
}

/**
* @tsplus getter fncts.Iterable toArray
*/
export function toArray<A>(self: Iterable<A>): Array<A> {
return Array.from(self);
}

/**
* @tsplus pipeable fncts.Iterable flatMap
*/
Expand Down
2 changes: 2 additions & 0 deletions packages/base/src/collection/compat.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
/* eslint-disable simple-import-sort/exports */
// codegen:start { preset: type-barrel, include: ./compat/*.ts }
export type {} from "./compat/Set.js";
export type {} from "./compat/Map.js";
export type {} from "./compat/Array.js";
// codegen:end
3 changes: 3 additions & 0 deletions packages/base/src/collection/compat/Map.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// codegen:start { preset: barrel, include: ./Map/*.ts }
export * from "./Map/definition.js";
// codegen:end
6 changes: 6 additions & 0 deletions packages/base/src/collection/compat/Map/definition.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
declare global {
/**
* @tsplus type fncts.Map
*/
interface Map<K, V> {}
}
3 changes: 3 additions & 0 deletions packages/base/src/collection/compat/Set.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// codegen:start { preset: barrel, include: ./Set/*.ts }
export * from "./Set/definition.js";
// codegen:end
6 changes: 6 additions & 0 deletions packages/base/src/collection/compat/Set/definition.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
declare global {
/**
* @tsplus type fncts.Set
*/
interface Set<T> {}
}
23 changes: 23 additions & 0 deletions packages/base/src/data/Eq/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,26 @@ export function contramap<A, B>(f: (b: B) => A) {
return Eq({ equals: (b2) => (b1) => self.equals(f(b2))(f(b1)) });
};
}

/**
* @tsplus static fncts.EqOps all
*/
export function all<A>(collection: Iterable<Eq<A>>): Eq<ReadonlyArray<A>> {
return Eq({
equals: (y) => (x) => {
const len = Math.min(x.length, y.length);

let collectionLength = 0;
for (const eq of collection) {
if (collectionLength >= len) {
break;
}
if (!eq.equals(y[collectionLength]!)(x[collectionLength]!)) {
return false;
}
collectionLength++;
}
return true;
},
});
}
35 changes: 35 additions & 0 deletions packages/base/src/data/Ord/api.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,38 @@
/**
* @tsplus static fncts.OrdOps all
*/
export function all<A>(collection: Iterable<Ord<A>>): Ord<ReadonlyArray<A>> {
return Ord<ReadonlyArray<A>>({
...Eq.all(collection),
compare: (y) => (x) => {
const len = Math.min(x.length, y.length);
let collectionLength = 0;
for (const O of collection) {
if (collectionLength >= len) {
break;
}

const o = O.compare(y[collectionLength]!)(x[collectionLength]!);

if (o !== Ordering.EQ) {
return o;
}
collectionLength++;
}
return Ordering.EQ;
},
});
}

/**
* @tsplus static fncts.OrdOps tuple
*/
export function tuple<T extends ReadonlyArray<Ord<any>>>(
...elements: T
): Ord<Readonly<{ [I in keyof T]: [T[I]] extends [Ord<infer A>] ? A : never }>> {
return Ord.all(elements) as any;
}

/* eslint-disable simple-import-sort/exports */
// codegen:start { preset: barrel, include: api/*.ts }
export * from "./api/min.js";
Expand Down
9 changes: 9 additions & 0 deletions packages/base/src/util/predicates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,15 @@ export function isPlain(value: unknown): value is object {
return isObject(value) && value.constructor === Object;
}

/**
* @tsplus pipeable global hasProperty
*/
export function hasProperty<P extends PropertyKey>(property: P) {
return (self: unknown): self is { [K in P]: unknown } => {
return isObject(self) && property in self;
};
}

export function isInstanceOf<C extends Constructor<A>, A>(type: C): (value: unknown) => value is A {
return (value): value is A => value instanceof type;
}
Expand Down
2 changes: 1 addition & 1 deletion packages/http/src/BodyError.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export class JsonError extends BodyError {

export class SchemaError extends BodyError {
readonly _tag = BodyErrorTag.SchemaError;
constructor(readonly error: ParseFailure) {
constructor(readonly error: ParseError) {
super();
}
}
Expand Down
6 changes: 3 additions & 3 deletions packages/http/src/IncomingMessage/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,21 @@ import type { IncomingMessage } from "./definition.js";
*/
export function schemaBodyJson<A>(schema: Schema<A>) {
const decode = schema.decode;
return <E>(self: IncomingMessage<E>): IO<never, E | ParseFailure, A> => self.json.flatMap(decode);
return <E>(self: IncomingMessage<E>): IO<never, E | ParseError, A> => self.json.flatMap(decode);
}

/**
* @tsplus pipeable fncts.http.IncomingMessage schemaBodyUrlParams
*/
export function schemaBodyUrlParams<A>(schema: Schema<A>) {
const decode = schema.decode;
return <E>(self: IncomingMessage<E>): IO<never, E | ParseFailure, A> => self.urlParamsBody.flatMap(decode);
return <E>(self: IncomingMessage<E>): IO<never, E | ParseError, A> => self.urlParamsBody.flatMap(decode);
}

/**
* @tsplus pipeable fncts.http.IncomingMessage schemaHeaders
*/
export function schemaHeaders<A>(schema: Schema<A>) {
const decode = schema.decode;
return <E>(self: IncomingMessage<E>): IO<never, E | ParseFailure, A> => decode(self.headers);
return <E>(self: IncomingMessage<E>): IO<never, E | ParseError, A> => decode(self.headers);
}
6 changes: 3 additions & 3 deletions packages/http/src/Route/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const searchParams = IO.service(RouteContext.Tag).map((routeContext) => r
/**
* @tsplus static fncts.http.RouteContextOps schemaParams
*/
export function schemaParams<A>(schema: Schema<A>): IO<RouteContext, ParseFailure, A> {
export function schemaParams<A>(schema: Schema<A>): IO<RouteContext, ParseError, A> {
const decode = schema.decode;
return IO.service(RouteContext.Tag).flatMap((routeContext) =>
decode({ ...routeContext.params, ...routeContext.searchParams }),
Expand All @@ -27,15 +27,15 @@ export function schemaParams<A>(schema: Schema<A>): IO<RouteContext, ParseFailur
/**
* @tsplus static fncts.http.RouteContextOps schemaPathParams
*/
export function schemaPathParams<A>(schema: Schema<A>): IO<RouteContext, ParseFailure, A> {
export function schemaPathParams<A>(schema: Schema<A>): IO<RouteContext, ParseError, A> {
const decode = schema.decode;
return params.flatMap(decode);
}

/**
* @tsplus static fncts.http.RouteContextOps schemaSearchParams
*/
export function schemaSearchParams<A>(schema: Schema<A>): IO<RouteContext, ParseFailure, A> {
export function schemaSearchParams<A>(schema: Schema<A>): IO<RouteContext, ParseError, A> {
const decode = schema.decode;
return searchParams.flatMap(decode);
}
Expand Down
42 changes: 21 additions & 21 deletions packages/io/src/IO/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ export function async<R, E, A>(
__tsplusTrace?: string,
): IO<R, E, A> {
const io = new IOPrimitive(IOTag.Async) as any;
io.i0 = register;
io.i1 = () => blockingOn;
io.i0 = register;
io.i1 = () => blockingOn;
io.trace = __tsplusTrace;
return io;
}
Expand Down Expand Up @@ -316,8 +316,8 @@ export function checkInterruptible<R, E, A>(
export function flatMap<A, R1, E1, B>(f: (a: A) => IO<R1, E1, B>, __tsplusTrace?: string) {
return <R, E>(ma: IO<R, E, A>): IO<R | R1, E | E1, B> => {
const io = new IOPrimitive(IOTag.OnSuccess) as any;
io.i0 = ma;
io.i1 = f;
io.i0 = ma;
io.i1 = f;
io.trace = __tsplusTrace;

return io;
Expand Down Expand Up @@ -365,8 +365,8 @@ export function condIO<R, R1, E, A>(

/**
* Returns a lazily constructed effect, whose construction may itself require
* effects. The effect must not throw any exceptions. When no environment is required (i.e., when R == unknown)
* it is conceptually equivalent to `flatten(succeedWith(io))`. If you wonder if the effect throws exceptions,
* effects. The effect must not throw any exceptions. When no environment is required (i.e., when R == never)
* it is conceptually equivalent to `flatten(succeed(io))`. If you wonder if the effect throws exceptions,
* do not use this method, use `IO.deferTryCatch`.
*
* @tsplus static fncts.io.IOOps defer
Expand All @@ -377,7 +377,7 @@ export function defer<R = never, E = never, A = never>(io: Lazy<IO<R, E, A>>, __

/**
* Returns a lazily constructed effect, whose construction may itself require effects.
* When no environment is required (i.e., when R == unknown) it is conceptually equivalent to `flatten(try(io))`.
* When no environment is required (i.e., when R == never) it is conceptually equivalent to `flatten(tryCatch(io))`.
*
* @tsplus static fncts.io.IOOps deferTry
*/
Expand All @@ -398,7 +398,7 @@ export function deferTry<R = never, E = never, A = never>(
* Returns a lazily constructed effect, whose construction may itself require effects,
* translating any thrown exceptions into typed failed effects and mapping the error.
*
* When no environment is required (i.e., when R == unknown) it is conceptually equivalent to `flatten(effect(io))`.
* When no environment is required (i.e., when R == never) it is conceptually equivalent to `flatten(try(io))`.
*
* @tsplus static IOOps deferTryCatch
*/
Expand Down Expand Up @@ -469,7 +469,7 @@ export function failNow<E>(e: E, __tsplusTrace?: string): FIO<E, never> {
*/
export function refailCause<E>(cause: Cause<E>, __tsplusTrace?: string): FIO<E, never> {
const io = new IOPrimitive(IOTag.Fail) as any;
io.i0 = () => cause;
io.i0 = () => cause;
io.trace = __tsplusTrace;
return io;
}
Expand All @@ -481,7 +481,7 @@ export function refailCause<E>(cause: Cause<E>, __tsplusTrace?: string): FIO<E,
*/
export function failCauseNow<E>(cause: Cause<E>, __tsplusTrace?: string): FIO<E, never> {
const io = new IOPrimitive(IOTag.Fail) as any;
io.i0 = () => cause;
io.i0 = () => cause;
io.trace = __tsplusTrace;
return io;
}
Expand Down Expand Up @@ -1249,9 +1249,9 @@ export function matchCauseIO<E, A, R1, E1, A1, R2, E2, A2>(
) {
return <R>(self: IO<R, E, A>): IO<R | R1 | R2, E1 | E2, A1 | A2> => {
const io = new IOPrimitive(IOTag.OnSuccessAndFailure) as any;
io.i0 = self;
io.i1 = onFailure;
io.i2 = onSuccess;
io.i0 = self;
io.i1 = onFailure;
io.i2 = onSuccess;
io.trace = __tsplusTrace;
return io;
};
Expand Down Expand Up @@ -1695,22 +1695,22 @@ export function sequenceIterableDiscard<R, E, A>(as: Iterable<IO<R, E, A>>, __ts
*/
export function succeedNow<A>(value: A, __tsplusTrace?: string): IO<never, never, A> {
const io = new IOPrimitive(IOTag.SucceedNow) as any;
io.i0 = value;
io.i0 = value;
io.trace = __tsplusTrace;
return io;
}

/**
* Imports a total synchronous effect into a pure `IO` value.
* The effect must not throw any exceptions. If you wonder if the effect
* throws exceptions, then do not use this method, use `IO.try`
* throws exceptions, then do not use this method, use `IO.tryCatch`
*
* @tsplus static fncts.io.IOOps succeed
* @tsplus static fncts.io.IOOps __call
*/
export function succeed<A>(effect: Lazy<A>, __tsplusTrace?: string): UIO<A> {
const io = new IOPrimitive(IOTag.Sync) as any;
io.i0 = effect;
io.i0 = effect;
io.trace = __tsplusTrace;
return io;
}
Expand All @@ -1723,7 +1723,7 @@ export function summarized<R1, E1, B, C>(summary: IO<R1, E1, B>, f: (start: B, e
return gen(function* (_) {
const start = yield* _(summary);
const value = yield* _(ma);
const end = yield* _(summary);
const end = yield* _(summary);
return tuple(f(start, end), value);
});
};
Expand Down Expand Up @@ -1964,7 +1964,7 @@ export function withFiberRuntime<R, E, A>(
__tsplusTrace?: string,
): IO<R, E, A> {
const io = new IOPrimitive(IOTag.Stateful) as any;
io.i0 = onState;
io.i0 = onState;
io.trace = __tsplusTrace;
return io;
}
Expand All @@ -1974,7 +1974,7 @@ export function withFiberRuntime<R, E, A>(
*/
export function updateRuntimeFlags(patch: RuntimeFlags.Patch, __tsplusTrace?: string): IO<never, never, void> {
const io = new IOPrimitive(IOTag.UpdateRuntimeFlags) as any;
io.i0 = patch;
io.i0 = patch;
io.trace = __tsplusTrace;
return io;
}
Expand Down Expand Up @@ -2051,8 +2051,8 @@ export function gen<T extends GenIO<any, any, any>, A>(
): IO<_R<T>, _E<T>, A> {
return IO.defer(() => {
const iterator = f(adapter as any);
const state = iterator.next();
const run = (state: IteratorYieldResult<T> | IteratorReturnResult<A>): IO<any, any, A> => {
const state = iterator.next();
const run = (state: IteratorYieldResult<T> | IteratorReturnResult<A>): IO<any, any, A> => {
if (state.done) {
return IO.succeed(state.value);
}
Expand Down
Loading

0 comments on commit 8fd543d

Please sign in to comment.