0.1.0 (#1)
All checks were successful
continuous-integration/drone/push Build is passing

Co-authored-by: Julien Valverdé <julien.valverde@mailo.com>
Reviewed-on: https://git.jvalver.de/Thilawyn/schemable-class/pulls/1
This commit was merged in pull request #1.
This commit is contained in:
Julien Valverdé
2024-01-05 00:39:32 +01:00
parent 8365820639
commit 0817f85f5d
24 changed files with 905 additions and 3 deletions

View File

@@ -0,0 +1,66 @@
import { Effect } from "effect"
import { Class } from "type-fest"
import { JsonifiableObject } from "type-fest/source/jsonifiable"
import { z } from "zod"
import { SchemableClassConstructorParams, SchemableConfig } from ".."
export type JsonifiableSchemableConfig<
$SchemableConfig extends SchemableConfig = SchemableConfig,
JsonifiedValues extends JsonifiableObject = {},
JsonifySchemaT extends z.ZodRawShape = z.ZodRawShape,
JsonifySchemaUnknownKeys extends z.UnknownKeysParam = z.UnknownKeysParam,
JsonifySchemaCatchall extends z.ZodTypeAny = z.ZodTypeAny,
DejsonifySchemaT extends z.ZodRawShape = z.ZodRawShape,
DejsonifySchemaUnknownKeys extends z.UnknownKeysParam = z.UnknownKeysParam,
DejsonifySchemaCatchall extends z.ZodTypeAny = z.ZodTypeAny,
> = {
readonly $schemableConfig: $SchemableConfig
readonly jsonifiedValues: JsonifiedValues
readonly jsonifySchema: z.ZodObject<
JsonifySchemaT,
JsonifySchemaUnknownKeys,
JsonifySchemaCatchall,
JsonifiedValues,
$SchemableConfig["values"]
>
readonly dejsonifySchema: z.ZodObject<
DejsonifySchemaT,
DejsonifySchemaUnknownKeys,
DejsonifySchemaCatchall,
$SchemableConfig["values"],
JsonifiedValues
>
}
export type JsonifiableSchemableClass<
$Config extends JsonifiableSchemableConfig
> = (
Class<
JsonifiableSchemableObject<$Config>,
SchemableClassConstructorParams<$Config["$schemableConfig"]>
> & {
readonly $jsonifiableSchemableConfig: $Config
readonly jsonifySchema: $Config["jsonifySchema"]
readonly dejsonifySchema: $Config["dejsonifySchema"]
}
)
export type JsonifiableSchemableObject<
$Config extends JsonifiableSchemableConfig
> = {
readonly $jsonifiableSchemableConfig: $Config
readonly jsonifySchema: $Config["jsonifySchema"]
readonly dejsonifySchema: $Config["dejsonifySchema"]
jsonify(): $Config["jsonifiedValues"]
jsonifyPromise(): Promise<$Config["jsonifiedValues"]>
jsonifyEffect(): Effect.Effect<never, z.ZodError<$Config["$schemableConfig"]["values"]>, $Config["jsonifiedValues"]>
}

View File

@@ -0,0 +1,47 @@
import { Effect, pipe } from "effect"
import { z } from "zod"
import { JsonifiableSchemableClass, JsonifiableSchemableConfig } from "."
import { parseZodTypeEffect } from "../util"
export const dejsonifySchemable = <
C extends JsonifiableSchemableClass<$Config>,
$Config extends JsonifiableSchemableConfig,
>(
class_: C | JsonifiableSchemableClass<$Config>,
values: $Config["jsonifiedValues"],
params?: Partial<z.ParseParams>,
) =>
new class_(class_.dejsonifySchema.parse(values, params)) as InstanceType<C>
export const dejsonifySchemablePromise = async <
C extends JsonifiableSchemableClass<$Config>,
$Config extends JsonifiableSchemableConfig,
>(
class_: C | JsonifiableSchemableClass<$Config>,
values: $Config["jsonifiedValues"],
params?: Partial<z.ParseParams>,
) =>
new class_(await class_.dejsonifySchema.parseAsync(values, params)) as InstanceType<C>
export const dejsonifySchemableEffect = <
C extends JsonifiableSchemableClass<$Config>,
$Config extends JsonifiableSchemableConfig,
>(
class_: C | JsonifiableSchemableClass<$Config>,
values: $Config["jsonifiedValues"],
params?: Partial<z.ParseParams>,
) => pipe(
parseZodTypeEffect<
z.output<typeof class_.dejsonifySchema>,
z.input<typeof class_.dejsonifySchema>
>(
class_.dejsonifySchema,
values,
params,
),
Effect.map(values => new class_(values) as InstanceType<C>),
)

4
src/jsonifiable/index.ts Normal file
View File

@@ -0,0 +1,4 @@
export * from "./JsonifiableSchemableClass"
export * from "./dejsonifySchemable"
export * from "./makeJsonifiableSchemableClass"
export * from "./schema"

View File

@@ -0,0 +1,98 @@
import { Class } from "type-fest"
import { JsonifiableObject } from "type-fest/source/jsonifiable"
import { z } from "zod"
import { JsonifiableSchemableClass, JsonifiableSchemableConfig, JsonifiableSchemableObject } from "."
import { SchemableClass, SchemableConfig } from ".."
import { StaticMembers, parseZodTypeEffect } from "../util"
export function makeJsonifiableSchemableClass<
C extends SchemableClass<$SchemableConfig>,
$SchemableConfig extends SchemableConfig,
JsonifiedValues extends JsonifiableObject,
JsonifySchemaT extends z.ZodRawShape,
JsonifySchemaUnknownKeys extends z.UnknownKeysParam,
JsonifySchemaCatchall extends z.ZodTypeAny,
DejsonifySchemaT extends z.ZodRawShape,
DejsonifySchemaUnknownKeys extends z.UnknownKeysParam,
DejsonifySchemaCatchall extends z.ZodTypeAny,
>(
class_: C | SchemableClass<$SchemableConfig>,
props: {
jsonifySchema: (props: {
schema: $SchemableConfig["schema"]
s: $SchemableConfig["schema"]["shape"]
}) => z.ZodObject<
JsonifySchemaT,
JsonifySchemaUnknownKeys,
JsonifySchemaCatchall,
JsonifiedValues,
$SchemableConfig["values"]
>
dejsonifySchema: (props: {
schema: $SchemableConfig["schema"]
s: $SchemableConfig["schema"]["shape"]
}) => z.ZodObject<
DejsonifySchemaT,
DejsonifySchemaUnknownKeys,
DejsonifySchemaCatchall,
$SchemableConfig["values"],
JsonifiedValues
>
},
) {
const jsonifySchema = props.jsonifySchema({
schema: class_.schema,
s: class_.schema.shape,
})
const dejsonifySchema = props.dejsonifySchema({
schema: class_.schema,
s: class_.schema.shape,
})
const $jsonifiableSchemableConfig = {
$schemableConfig: class_.$schemableConfig,
jsonifiedValues: undefined as unknown as JsonifiedValues,
jsonifySchema: undefined as unknown as typeof jsonifySchema,
dejsonifySchema: undefined as unknown as typeof dejsonifySchema,
} as const satisfies JsonifiableSchemableConfig
const jsonifiableClass = class JsonifiableSchemableObject extends class_ {
static readonly $jsonifiableSchemableConfig = $jsonifiableSchemableConfig
static readonly jsonifySchema = jsonifySchema
static readonly dejsonifySchema = dejsonifySchema
readonly $jsonifiableSchemableConfig = $jsonifiableSchemableConfig
readonly jsonifySchema = jsonifySchema
readonly dejsonifySchema = dejsonifySchema
jsonify() {
return this.jsonifySchema.parse(this)
}
jsonifyPromise() {
return this.jsonifySchema.parseAsync(this)
}
jsonifyEffect() {
return parseZodTypeEffect(this.jsonifySchema, this)
}
} satisfies JsonifiableSchemableClass<typeof $jsonifiableSchemableConfig>
return jsonifiableClass as unknown as (
Class<
InstanceType<C> & JsonifiableSchemableObject<typeof $jsonifiableSchemableConfig>,
ConstructorParameters<C>
> &
StaticMembers<C> &
StaticMembers<JsonifiableSchemableClass<typeof $jsonifiableSchemableConfig>>
)
}

View File

@@ -0,0 +1,18 @@
import { z } from "zod"
export const jsonifyBigIntSchema = <S extends z.ZodBigInt>(schema: S) =>
schema.transform(v => v.toString())
export const dejsonifyBigIntSchema = <S extends z.ZodBigInt>(schema: S) =>
z
.string()
.transform(v => {
try {
return BigInt(v)
}
catch (e) {
return v
}
})
.pipe(schema)

View File

@@ -0,0 +1,18 @@
import { z } from "zod"
export const jsonifyDateSchema = <S extends z.ZodDate>(schema: S) =>
schema.transform(v => v.toString())
export const dejsonifyDateSchema = <S extends z.ZodDate>(schema: S) =>
z
.string()
.transform(v => {
try {
return new Date(v)
}
catch (e) {
return v
}
})
.pipe(schema)

View File

@@ -0,0 +1,19 @@
import { Decimal } from "decimal.js"
import { z } from "zod"
export const jsonifyDecimalSchema = <S extends z.ZodType<Decimal, z.ZodTypeDef, Decimal>>(schema: S) =>
schema.transform(v => v.toJSON())
export const dejsonifyDecimalSchema = <S extends z.ZodType<Decimal, z.ZodTypeDef, Decimal>>(schema: S) =>
z
.string()
.transform(v => {
try {
return new Decimal(v)
}
catch (e) {
return v
}
})
.pipe(schema)

View File

@@ -0,0 +1,4 @@
export * from "./bigint"
export * from "./date"
export * from "./decimal"
export * from "./schemable"

View File

@@ -0,0 +1,25 @@
import { z } from "zod"
import { JsonifiableSchemableClass, JsonifiableSchemableConfig } from ".."
// TODO: try to find a way to get rid of the 'class_' arg
export const jsonifySchemableSchema = <
C extends JsonifiableSchemableClass<$Config>,
$Config extends JsonifiableSchemableConfig,
S extends z.ZodType<InstanceType<C>, z.ZodTypeDef, InstanceType<C>>,
>(
class_: C | JsonifiableSchemableClass<$Config>,
schema: S,
) =>
schema.pipe(class_.jsonifySchema)
// TODO: try to find a way to get rid of the 'class_' arg
export const dejsonifySchemableSchema = <
C extends JsonifiableSchemableClass<$Config>,
$Config extends JsonifiableSchemableConfig,
S extends z.ZodType<InstanceType<C>, z.ZodTypeDef, InstanceType<C>>,
>(
class_: C | JsonifiableSchemableClass<$Config>,
schema: S,
) =>
class_.dejsonifySchema.transform(v => new class_(v)).pipe(schema)