From 24d4ab6e462370c55853193af5c1a35b12da0236 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Wed, 4 Sep 2024 00:33:45 +0200 Subject: [PATCH] 0.1.15 (#16) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Julien Valverdé Reviewed-on: https://git.valverde.cloud/Thilawyn/thilalib/pulls/16 --- bun.lockb | Bin 70373 -> 104113 bytes package.json | 26 +++- src/Layers/PrismaStudioRoute.ts | 44 ++++++ src/Schema/Email.ts | 12 ++ src/Schema/MobX/ObservableClass.ts | 28 ++-- src/Schema/TanStackForm/index.ts | 1 + .../TanStackForm/makeSchemaFormValidator.ts | 138 ++++++++++++++++++ src/Schema/index.ts | 1 + src/Schema/toJsonifiable.ts | 2 +- src/tests.ts | 20 ++- tsup.config.ts | 1 + 11 files changed, 247 insertions(+), 26 deletions(-) create mode 100644 src/Layers/PrismaStudioRoute.ts create mode 100644 src/Schema/Email.ts create mode 100644 src/Schema/TanStackForm/index.ts create mode 100644 src/Schema/TanStackForm/makeSchemaFormValidator.ts diff --git a/bun.lockb b/bun.lockb index 5ff5c9a648528a222a0007fb5dbe75919f55bb12..22706bc996ac2568b292fd7a9aaeffed48e21e27 100755 GIT binary patch delta 30944 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 delta 10156 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 +// readonly httpPort?: Config.Config +// readonly schemaPath?: Config.Config +// readonly schemaText?: Config.Config +// } = {}) => +// Layer.effectDiscard(Effect.acquireRelease( +// Effect.gen(function*() { +// const prisma = yield* PrismaClient +// const app = yield* ExpressApp + +// const port = yield* httpPort + +// const server = new StudioServer({ +// port, +// schemaPath: yield* schemaPath, +// schemaText: yield* schemaText, +// versions: { prisma: prisma.Prisma.prismaVersion.client }, +// }) + +// app.use(yield* httpRoot, proxy(`http://localhost:${ port }`)) + +// yield* Effect.promise(() => server.start()) +// return server +// }), + +// server => Effect.sync(() => server.stop()), +// )) + + +// export const PrismaStudioRouteLive = Layer.empty +// export const PrismaStudioRouteDebug = PrismaStudioRoute() diff --git a/src/Schema/Email.ts b/src/Schema/Email.ts new file mode 100644 index 0000000..7762efd --- /dev/null +++ b/src/Schema/Email.ts @@ -0,0 +1,12 @@ +import { Schema } from "@effect/schema" + + +export const Email = Schema.pattern( + /^(?!\.)(?!.*\.\.)([A-Z0-9_+-.]*)[A-Z0-9_+-]@([A-Z0-9][A-Z0-9-]*\.)+[A-Z]{2,}$/i, + + { + identifier: "Email", + title: "email", + message: () => "Not an email address", + }, +) diff --git a/src/Schema/MobX/ObservableClass.ts b/src/Schema/MobX/ObservableClass.ts index 3be882a..61243c7 100644 --- a/src/Schema/MobX/ObservableClass.ts +++ b/src/Schema/MobX/ObservableClass.ts @@ -8,19 +8,19 @@ interface ObservableClassSelf { readonly fields: { readonly [K in keyof Schema.Struct.Fields]: Schema.Struct.Fields[K] } } -export const ObservableClass = ( - self: Self, - options?: Omit, -) => - class Observable extends self { - declare ["constructor"]: typeof Observable +interface ObservableClassOptions extends Omit {} - constructor(...args: any[]) { - super(...args) +export const ObservableClass = (options?: ObservableClassOptions) => + (self: Self) => + class Observable extends self { + declare ["constructor"]: typeof Observable - makeObservable(this, - mapValues(this.constructor.fields, () => observable), - options, - ) - } - } as Self + constructor(...args: any[]) { + super(...args) + + makeObservable(this, + mapValues(this.constructor.fields, () => observable), + options, + ) + } + } as Self diff --git a/src/Schema/TanStackForm/index.ts b/src/Schema/TanStackForm/index.ts new file mode 100644 index 0000000..ee81f8e --- /dev/null +++ b/src/Schema/TanStackForm/index.ts @@ -0,0 +1 @@ +export * from "./makeSchemaFormValidator" diff --git a/src/Schema/TanStackForm/makeSchemaFormValidator.ts b/src/Schema/TanStackForm/makeSchemaFormValidator.ts new file mode 100644 index 0000000..0e87f91 --- /dev/null +++ b/src/Schema/TanStackForm/makeSchemaFormValidator.ts @@ -0,0 +1,138 @@ +import { ArrayFormatter, Schema } from "@effect/schema" +import type { ParseOptions } from "@effect/schema/AST" +import type { DeepKeys, DeepValue, FieldApi, FormApi, FormValidationError, ValidationError, Validator } from "@tanstack/form-core" +import { Array, Effect, Either, flow, Layer, ManagedRuntime, pipe } from "effect" +import { mapValues } from "remeda" + + +export const makeSchemaFormValidator = ( + schema: Schema.Schema, + options?: ParseOptions, +) => { + const decodeEither = Schema.decodeEither(schema, options) + + return < + TFormData extends I, + TFormValidator extends Validator | undefined, + >(props: { + value: TFormData + formApi: FormApi + }): FormValidationError => + decodeEither(props.value).pipe(result => + Either.isLeft(result) + ? { + form: "Please check the fields", + fields: issuesToFieldsRecord(ArrayFormatter.formatErrorSync(result.left), props.formApi) as any, + } + : null + ) +} + +export const makeSchemaAsyncFormValidator = ( + schema: Schema.Schema, + options?: ParseOptions, +) => { + const runtime = ManagedRuntime.make(Layer.empty) + const decode = Schema.decode(schema, options) + + return < + TFormData extends I, + TFormValidator extends Validator | undefined, + >(props: { + value: TFormData + formApi: FormApi + signal: AbortSignal + }): Promise> => + decode(props.value).pipe( + Effect.matchEffect({ + onSuccess: () => Effect.succeed(null), + + onFailure: e => ArrayFormatter.formatError(e).pipe( + Effect.map(issues => ({ + form: "Please check the fields", + fields: issuesToFieldsRecord(issues, props.formApi) as any, + })) + ), + }), + + prgm => runtime.runPromise(prgm, { signal: props.signal }), + ) +} + +/** + * TODO: handle nested array fields + */ +const issuesToFieldsRecord = < + TFormData, + TFormValidator extends Validator | undefined = undefined, +>( + issues: readonly ArrayFormatter.Issue[], + _formApi: FormApi, +) => pipe(issues, + Array.groupBy(issue => issue.path.join(".")), + + mapValues(flow( + Array.map(issue => issue.message), + Array.join("\n"), + )), +) + + +export const makeSchemaFieldValidator = ( + schema: Schema.Schema, + options?: ParseOptions, +) => { + const decodeEither = Schema.decodeEither(schema, options) + + return < + TParentData, + TName extends DeepKeys, + TFieldValidator extends Validator, unknown> | undefined, + TFormValidator extends Validator | undefined, + TData extends I & DeepValue, + >(props: { + value: TData + fieldApi: FieldApi + }): ValidationError => + decodeEither(props.value).pipe(result => + Either.isLeft(result) + ? ArrayFormatter.formatErrorSync(result.left) + .map(issue => issue.message) + .join("\n") + : null + ) +} + +export const makeSchemaAsyncFieldValidator = ( + schema: Schema.Schema, + options?: ParseOptions, +) => { + const runtime = ManagedRuntime.make(Layer.empty) + const decode = Schema.decode(schema, options) + + return < + TParentData, + TName extends DeepKeys, + TFieldValidator extends Validator, unknown> | undefined, + TFormValidator extends Validator | undefined, + TData extends I & DeepValue, + >(props: { + value: TData + fieldApi: FieldApi + signal: AbortSignal + }): Promise => + decode(props.value).pipe( + Effect.matchEffect({ + onSuccess: () => Effect.succeed(null), + + onFailure: e => ArrayFormatter.formatError(e).pipe( + Effect.map(flow( + Array.map(issue => issue.message), + Array.join("\n"), + )) + ), + }), + + prgm => runtime.runPromise(prgm, { signal: props.signal }), + ) +} diff --git a/src/Schema/index.ts b/src/Schema/index.ts index b047a9e..a66cc17 100644 --- a/src/Schema/index.ts +++ b/src/Schema/index.ts @@ -1,5 +1,6 @@ export * from "./Class" export * from "./DateTime" +export * from "./Email" export * from "./encodedAsPrismaJsonValue" export * from "./Kind" export * as MobX from "./MobX" diff --git a/src/Schema/toJsonifiable.ts b/src/Schema/toJsonifiable.ts index 0112b3e..c7b0a4f 100644 --- a/src/Schema/toJsonifiable.ts +++ b/src/Schema/toJsonifiable.ts @@ -10,4 +10,4 @@ export const toJsonifiable = < jsonifiableSchema: Schema.Schema ) => (decodedSchema: Schema.Schema) => - Schema.compose(jsonifiableSchema, decodedSchema) + Schema.compose(jsonifiableSchema, decodedSchema, { strict: true }) diff --git a/src/tests.ts b/src/tests.ts index f1adbc7..de20458 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -1,5 +1,5 @@ import { Schema as S } from "@effect/schema" -import { reaction, runInAction } from "mobx" +import { computed, makeObservable, reaction, runInAction } from "mobx" import type { Simplify } from "type-fest" import { MutableTaggedClass, toJsonifiable } from "./Schema" import { ObservableClass } from "./Schema/MobX" @@ -18,12 +18,24 @@ type TestB = { type Merged = Simplify> -class User extends MutableTaggedClass()("User", { + +const UserSchema = MutableTaggedClass()("User", { id: S.BigIntFromSelf, role: S.Union(S.Literal("BasicUser"), S.Literal("Admin")), }).pipe( - ObservableClass -) {} + ObservableClass() +) + +class User extends UserSchema { + constructor(...args: ConstructorParameters) { + super(...args) + makeObservable(this, { idAsString: computed }) + } + + get idAsString() { + return this.id.toString() + } +} const JsonifiableUser = User.pipe( toJsonifiable(S.Struct({ diff --git a/tsup.config.ts b/tsup.config.ts index 2327cf8..3ea8c21 100644 --- a/tsup.config.ts +++ b/tsup.config.ts @@ -7,6 +7,7 @@ export default defineConfig({ "./src/Layers/index.ts", "./src/Schema/index.ts", "./src/Schema/MobX/index.ts", + "./src/Schema/TanStackForm/index.ts", "./src/Types/index.ts", ], format: ["esm", "cjs"],