This commit is contained in:
@@ -1,54 +0,0 @@
|
|||||||
import { z } from "zod"
|
|
||||||
import { Class, ClassType } from "../util"
|
|
||||||
|
|
||||||
|
|
||||||
export type SchemableClass<
|
|
||||||
SchemaT extends z.ZodRawShape,
|
|
||||||
SchemaUnknownKeys extends z.UnknownKeysParam,
|
|
||||||
SchemaCatchall extends z.ZodTypeAny,
|
|
||||||
|
|
||||||
Values extends {},
|
|
||||||
DefaultValues extends Partial<Values>,
|
|
||||||
|
|
||||||
Type extends ClassType = "AbstractClass"
|
|
||||||
> = (
|
|
||||||
Class<
|
|
||||||
Type,
|
|
||||||
|
|
||||||
{
|
|
||||||
readonly schema: z.ZodObject<
|
|
||||||
SchemaT,
|
|
||||||
SchemaUnknownKeys,
|
|
||||||
SchemaCatchall,
|
|
||||||
Values,
|
|
||||||
Values
|
|
||||||
>
|
|
||||||
|
|
||||||
readonly defaultValues: DefaultValues
|
|
||||||
} & Values,
|
|
||||||
|
|
||||||
Parameters<(values: Values) => never>
|
|
||||||
> & {
|
|
||||||
readonly schema: z.ZodObject<
|
|
||||||
SchemaT,
|
|
||||||
SchemaUnknownKeys,
|
|
||||||
SchemaCatchall,
|
|
||||||
Values,
|
|
||||||
Values
|
|
||||||
>
|
|
||||||
|
|
||||||
readonly defaultValues: DefaultValues
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
export type SchemableClassInput<
|
|
||||||
Values extends {},
|
|
||||||
DefaultValues extends Partial<Values>,
|
|
||||||
> = {
|
|
||||||
[Key in Exclude<keyof Values, keyof DefaultValues>]: Values[Key]
|
|
||||||
} & {
|
|
||||||
[Key in keyof DefaultValues]?: Key extends keyof Values
|
|
||||||
? Values[Key]
|
|
||||||
: never
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
import { Opaque } from "type-fest"
|
|
||||||
|
|
||||||
|
|
||||||
export type DefinedDefaultValuesTag = "@thilawyn/schemable-class/DefinedDefaultValues"
|
|
||||||
|
|
||||||
export function defineDefaultValues<T>(values: T) {
|
|
||||||
return values as Opaque<T, DefinedDefaultValuesTag>
|
|
||||||
}
|
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
import { AbstractClass, Class as ConcreteClass, Opaque } from "type-fest"
|
|
||||||
import { z } from "zod"
|
|
||||||
import { DefinedDefaultValuesTag, SchemableClass } from "."
|
|
||||||
import { StaticMembers } from "../util"
|
|
||||||
|
|
||||||
|
|
||||||
export function extendSchemableClass<
|
|
||||||
C extends SchemableClass<
|
|
||||||
ExtendSchemaT,
|
|
||||||
ExtendSchemaUnknownKeys,
|
|
||||||
ExtendSchemaCatchall,
|
|
||||||
ExtendSchemaValues,
|
|
||||||
ExtendDefaultValues
|
|
||||||
>,
|
|
||||||
|
|
||||||
ExtendSchemaT extends z.ZodRawShape,
|
|
||||||
ExtendSchemaUnknownKeys extends z.UnknownKeysParam,
|
|
||||||
ExtendSchemaCatchall extends z.ZodTypeAny,
|
|
||||||
ExtendSchemaValues extends {},
|
|
||||||
ExtendDefaultValues extends Partial<ExtendSchemaValues>,
|
|
||||||
|
|
||||||
SchemaT extends z.ZodRawShape,
|
|
||||||
SchemaUnknownKeys extends z.UnknownKeysParam,
|
|
||||||
SchemaCatchall extends z.ZodTypeAny,
|
|
||||||
SchemaValues extends ExtendSchemaValues,
|
|
||||||
|
|
||||||
DefaultValues extends Partial<SchemaValues>,
|
|
||||||
>(
|
|
||||||
extend: C | SchemableClass<
|
|
||||||
ExtendSchemaT,
|
|
||||||
ExtendSchemaUnknownKeys,
|
|
||||||
ExtendSchemaCatchall,
|
|
||||||
ExtendSchemaValues,
|
|
||||||
ExtendDefaultValues
|
|
||||||
>,
|
|
||||||
|
|
||||||
props: {
|
|
||||||
schema: (props: {
|
|
||||||
schema: z.ZodObject<
|
|
||||||
ExtendSchemaT,
|
|
||||||
ExtendSchemaUnknownKeys,
|
|
||||||
ExtendSchemaCatchall,
|
|
||||||
ExtendSchemaValues,
|
|
||||||
ExtendSchemaValues
|
|
||||||
>
|
|
||||||
|
|
||||||
shape: ExtendSchemaT
|
|
||||||
}) => z.ZodObject<
|
|
||||||
SchemaT,
|
|
||||||
SchemaUnknownKeys,
|
|
||||||
SchemaCatchall,
|
|
||||||
SchemaValues,
|
|
||||||
SchemaValues
|
|
||||||
>
|
|
||||||
|
|
||||||
defaultValues: (defaultValues: ExtendDefaultValues) => Opaque<DefaultValues, DefinedDefaultValuesTag>
|
|
||||||
},
|
|
||||||
) {
|
|
||||||
type Class<T, Arguments extends unknown[]> = (
|
|
||||||
C extends ConcreteClass<any>
|
|
||||||
? ConcreteClass<T, Arguments>
|
|
||||||
: AbstractClass<T, Arguments>
|
|
||||||
)
|
|
||||||
|
|
||||||
const schema = props.schema({
|
|
||||||
schema: extend.schema,
|
|
||||||
shape: extend.schema.shape,
|
|
||||||
})
|
|
||||||
const defaultValues = props.defaultValues(extend.defaultValues)
|
|
||||||
|
|
||||||
return class extends extend {
|
|
||||||
static readonly schema = schema
|
|
||||||
readonly schema = schema
|
|
||||||
|
|
||||||
static readonly defaultValues = defaultValues
|
|
||||||
readonly defaultValues = defaultValues
|
|
||||||
} as unknown as (
|
|
||||||
Class<
|
|
||||||
Omit<InstanceType<C>, "schema" | "defaultValues" | keyof ExtendSchemaValues> &
|
|
||||||
{
|
|
||||||
readonly schema: z.ZodObject<SchemaT, SchemaUnknownKeys, SchemaCatchall, SchemaValues, SchemaValues>,
|
|
||||||
readonly defaultValues: DefaultValues,
|
|
||||||
} &
|
|
||||||
SchemaValues,
|
|
||||||
|
|
||||||
Parameters<(values: SchemaValues) => void>
|
|
||||||
> &
|
|
||||||
|
|
||||||
Omit<StaticMembers<C>, "schema" | "defaultValues"> &
|
|
||||||
{
|
|
||||||
readonly schema: z.ZodObject<SchemaT, SchemaUnknownKeys, SchemaCatchall, SchemaValues, SchemaValues>,
|
|
||||||
readonly defaultValues: DefaultValues,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
export * from "./SchemableClass"
|
|
||||||
export * from "./defineDefaultValues"
|
|
||||||
export * from "./extendSchemableClass"
|
|
||||||
export * from "./makeSchemableClass"
|
|
||||||
export * from "./newSchemable"
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
import { Effect } from "effect"
|
|
||||||
import { JsonifiableObject } from "type-fest/source/jsonifiable"
|
|
||||||
import { z } from "zod"
|
|
||||||
import { SchemableClass } from ".."
|
|
||||||
import { Class, ClassType } from "../../util"
|
|
||||||
|
|
||||||
|
|
||||||
export type JsonifiableSchemableClass<
|
|
||||||
SchemaT extends z.ZodRawShape,
|
|
||||||
SchemaUnknownKeys extends z.UnknownKeysParam,
|
|
||||||
SchemaCatchall extends z.ZodTypeAny,
|
|
||||||
|
|
||||||
Values extends {},
|
|
||||||
DefaultValues extends Partial<Values>,
|
|
||||||
|
|
||||||
JsonifySchemaT extends z.ZodRawShape,
|
|
||||||
JsonifySchemaUnknownKeys extends z.UnknownKeysParam,
|
|
||||||
JsonifySchemaCatchall extends z.ZodTypeAny,
|
|
||||||
|
|
||||||
DejsonifySchemaT extends z.ZodRawShape,
|
|
||||||
DejsonifySchemaUnknownKeys extends z.UnknownKeysParam,
|
|
||||||
DejsonifySchemaCatchall extends z.ZodTypeAny,
|
|
||||||
|
|
||||||
JsonifiedValues extends JsonifiableObject,
|
|
||||||
|
|
||||||
Type extends ClassType = "AbstractClass"
|
|
||||||
> = (
|
|
||||||
SchemableClass<
|
|
||||||
SchemaT,
|
|
||||||
SchemaUnknownKeys,
|
|
||||||
SchemaCatchall,
|
|
||||||
Values,
|
|
||||||
DefaultValues,
|
|
||||||
Type
|
|
||||||
> &
|
|
||||||
|
|
||||||
Class<
|
|
||||||
Type,
|
|
||||||
|
|
||||||
{
|
|
||||||
readonly jsonifySchema: z.ZodObject<
|
|
||||||
JsonifySchemaT,
|
|
||||||
JsonifySchemaUnknownKeys,
|
|
||||||
JsonifySchemaCatchall,
|
|
||||||
JsonifiedValues,
|
|
||||||
Values
|
|
||||||
>
|
|
||||||
|
|
||||||
readonly dejsonifySchema: z.ZodObject<
|
|
||||||
DejsonifySchemaT,
|
|
||||||
DejsonifySchemaUnknownKeys,
|
|
||||||
DejsonifySchemaCatchall,
|
|
||||||
Values,
|
|
||||||
JsonifiedValues
|
|
||||||
>
|
|
||||||
|
|
||||||
jsonify(): JsonifiedValues
|
|
||||||
jsonifyPromise(): Promise<JsonifiedValues>
|
|
||||||
jsonifyEffect(): Effect.Effect<never, z.ZodError<Values>, JsonifiedValues>
|
|
||||||
},
|
|
||||||
|
|
||||||
any[]
|
|
||||||
> & {
|
|
||||||
readonly jsonifySchema: z.ZodObject<
|
|
||||||
JsonifySchemaT,
|
|
||||||
JsonifySchemaUnknownKeys,
|
|
||||||
JsonifySchemaCatchall,
|
|
||||||
JsonifiedValues,
|
|
||||||
Values
|
|
||||||
>
|
|
||||||
|
|
||||||
readonly dejsonifySchema: z.ZodObject<
|
|
||||||
DejsonifySchemaT,
|
|
||||||
DejsonifySchemaUnknownKeys,
|
|
||||||
DejsonifySchemaCatchall,
|
|
||||||
Values,
|
|
||||||
JsonifiedValues
|
|
||||||
>
|
|
||||||
}
|
|
||||||
)
|
|
||||||
@@ -1,213 +0,0 @@
|
|||||||
import { Effect, pipe } from "effect"
|
|
||||||
import { JsonifiableObject } from "type-fest/source/jsonifiable"
|
|
||||||
import { z } from "zod"
|
|
||||||
import { JsonifiableSchemableClass } from "."
|
|
||||||
import { parseZodTypeEffect } from "../../util"
|
|
||||||
|
|
||||||
|
|
||||||
export function dejsonifySchemable<
|
|
||||||
C extends JsonifiableSchemableClass<
|
|
||||||
SchemaT,
|
|
||||||
SchemaUnknownKeys,
|
|
||||||
SchemaCatchall,
|
|
||||||
|
|
||||||
Values,
|
|
||||||
DefaultValues,
|
|
||||||
|
|
||||||
JsonifySchemaT,
|
|
||||||
JsonifySchemaUnknownKeys,
|
|
||||||
JsonifySchemaCatchall,
|
|
||||||
|
|
||||||
DejsonifySchemaT,
|
|
||||||
DejsonifySchemaUnknownKeys,
|
|
||||||
DejsonifySchemaCatchall,
|
|
||||||
|
|
||||||
JsonifiedValues,
|
|
||||||
|
|
||||||
"Class"
|
|
||||||
>,
|
|
||||||
|
|
||||||
SchemaT extends z.ZodRawShape,
|
|
||||||
SchemaUnknownKeys extends z.UnknownKeysParam,
|
|
||||||
SchemaCatchall extends z.ZodTypeAny,
|
|
||||||
|
|
||||||
Values extends {},
|
|
||||||
DefaultValues extends Partial<Values>,
|
|
||||||
|
|
||||||
JsonifySchemaT extends z.ZodRawShape,
|
|
||||||
JsonifySchemaUnknownKeys extends z.UnknownKeysParam,
|
|
||||||
JsonifySchemaCatchall extends z.ZodTypeAny,
|
|
||||||
|
|
||||||
DejsonifySchemaT extends z.ZodRawShape,
|
|
||||||
DejsonifySchemaUnknownKeys extends z.UnknownKeysParam,
|
|
||||||
DejsonifySchemaCatchall extends z.ZodTypeAny,
|
|
||||||
|
|
||||||
JsonifiedValues extends JsonifiableObject,
|
|
||||||
>(
|
|
||||||
class_: C | JsonifiableSchemableClass<
|
|
||||||
SchemaT,
|
|
||||||
SchemaUnknownKeys,
|
|
||||||
SchemaCatchall,
|
|
||||||
|
|
||||||
Values,
|
|
||||||
DefaultValues,
|
|
||||||
|
|
||||||
JsonifySchemaT,
|
|
||||||
JsonifySchemaUnknownKeys,
|
|
||||||
JsonifySchemaCatchall,
|
|
||||||
|
|
||||||
DejsonifySchemaT,
|
|
||||||
DejsonifySchemaUnknownKeys,
|
|
||||||
DejsonifySchemaCatchall,
|
|
||||||
|
|
||||||
JsonifiedValues,
|
|
||||||
|
|
||||||
"Class"
|
|
||||||
>,
|
|
||||||
|
|
||||||
values: JsonifiedValues,
|
|
||||||
params?: Partial<z.ParseParams>,
|
|
||||||
) {
|
|
||||||
return new class_(
|
|
||||||
class_.dejsonifySchema.parse(values, params)
|
|
||||||
) as InstanceType<C>
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export async function dejsonifySchemablePromise<
|
|
||||||
C extends JsonifiableSchemableClass<
|
|
||||||
SchemaT,
|
|
||||||
SchemaUnknownKeys,
|
|
||||||
SchemaCatchall,
|
|
||||||
|
|
||||||
Values,
|
|
||||||
DefaultValues,
|
|
||||||
|
|
||||||
JsonifySchemaT,
|
|
||||||
JsonifySchemaUnknownKeys,
|
|
||||||
JsonifySchemaCatchall,
|
|
||||||
|
|
||||||
DejsonifySchemaT,
|
|
||||||
DejsonifySchemaUnknownKeys,
|
|
||||||
DejsonifySchemaCatchall,
|
|
||||||
|
|
||||||
JsonifiedValues,
|
|
||||||
|
|
||||||
"Class"
|
|
||||||
>,
|
|
||||||
|
|
||||||
SchemaT extends z.ZodRawShape,
|
|
||||||
SchemaUnknownKeys extends z.UnknownKeysParam,
|
|
||||||
SchemaCatchall extends z.ZodTypeAny,
|
|
||||||
|
|
||||||
Values extends {},
|
|
||||||
DefaultValues extends Partial<Values>,
|
|
||||||
|
|
||||||
JsonifySchemaT extends z.ZodRawShape,
|
|
||||||
JsonifySchemaUnknownKeys extends z.UnknownKeysParam,
|
|
||||||
JsonifySchemaCatchall extends z.ZodTypeAny,
|
|
||||||
|
|
||||||
DejsonifySchemaT extends z.ZodRawShape,
|
|
||||||
DejsonifySchemaUnknownKeys extends z.UnknownKeysParam,
|
|
||||||
DejsonifySchemaCatchall extends z.ZodTypeAny,
|
|
||||||
|
|
||||||
JsonifiedValues extends JsonifiableObject,
|
|
||||||
>(
|
|
||||||
class_: C | JsonifiableSchemableClass<
|
|
||||||
SchemaT,
|
|
||||||
SchemaUnknownKeys,
|
|
||||||
SchemaCatchall,
|
|
||||||
|
|
||||||
Values,
|
|
||||||
DefaultValues,
|
|
||||||
|
|
||||||
JsonifySchemaT,
|
|
||||||
JsonifySchemaUnknownKeys,
|
|
||||||
JsonifySchemaCatchall,
|
|
||||||
|
|
||||||
DejsonifySchemaT,
|
|
||||||
DejsonifySchemaUnknownKeys,
|
|
||||||
DejsonifySchemaCatchall,
|
|
||||||
|
|
||||||
JsonifiedValues,
|
|
||||||
|
|
||||||
"Class"
|
|
||||||
>,
|
|
||||||
|
|
||||||
values: JsonifiedValues,
|
|
||||||
params?: Partial<z.ParseParams>,
|
|
||||||
) {
|
|
||||||
return new class_(
|
|
||||||
await class_.dejsonifySchema.parseAsync(values, params)
|
|
||||||
) as InstanceType<C>
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export function dejsonifySchemableEffect<
|
|
||||||
C extends JsonifiableSchemableClass<
|
|
||||||
SchemaT,
|
|
||||||
SchemaUnknownKeys,
|
|
||||||
SchemaCatchall,
|
|
||||||
|
|
||||||
Values,
|
|
||||||
DefaultValues,
|
|
||||||
|
|
||||||
JsonifySchemaT,
|
|
||||||
JsonifySchemaUnknownKeys,
|
|
||||||
JsonifySchemaCatchall,
|
|
||||||
|
|
||||||
DejsonifySchemaT,
|
|
||||||
DejsonifySchemaUnknownKeys,
|
|
||||||
DejsonifySchemaCatchall,
|
|
||||||
|
|
||||||
JsonifiedValues,
|
|
||||||
|
|
||||||
"Class"
|
|
||||||
>,
|
|
||||||
|
|
||||||
SchemaT extends z.ZodRawShape,
|
|
||||||
SchemaUnknownKeys extends z.UnknownKeysParam,
|
|
||||||
SchemaCatchall extends z.ZodTypeAny,
|
|
||||||
|
|
||||||
Values extends {},
|
|
||||||
DefaultValues extends Partial<Values>,
|
|
||||||
|
|
||||||
JsonifySchemaT extends z.ZodRawShape,
|
|
||||||
JsonifySchemaUnknownKeys extends z.UnknownKeysParam,
|
|
||||||
JsonifySchemaCatchall extends z.ZodTypeAny,
|
|
||||||
|
|
||||||
DejsonifySchemaT extends z.ZodRawShape,
|
|
||||||
DejsonifySchemaUnknownKeys extends z.UnknownKeysParam,
|
|
||||||
DejsonifySchemaCatchall extends z.ZodTypeAny,
|
|
||||||
|
|
||||||
JsonifiedValues extends JsonifiableObject,
|
|
||||||
>(
|
|
||||||
class_: C | JsonifiableSchemableClass<
|
|
||||||
SchemaT,
|
|
||||||
SchemaUnknownKeys,
|
|
||||||
SchemaCatchall,
|
|
||||||
|
|
||||||
Values,
|
|
||||||
DefaultValues,
|
|
||||||
|
|
||||||
JsonifySchemaT,
|
|
||||||
JsonifySchemaUnknownKeys,
|
|
||||||
JsonifySchemaCatchall,
|
|
||||||
|
|
||||||
DejsonifySchemaT,
|
|
||||||
DejsonifySchemaUnknownKeys,
|
|
||||||
DejsonifySchemaCatchall,
|
|
||||||
|
|
||||||
JsonifiedValues,
|
|
||||||
|
|
||||||
"Class"
|
|
||||||
>,
|
|
||||||
|
|
||||||
values: JsonifiedValues,
|
|
||||||
params?: Partial<z.ParseParams>,
|
|
||||||
) {
|
|
||||||
return pipe(
|
|
||||||
parseZodTypeEffect(class_.dejsonifySchema, values, params),
|
|
||||||
Effect.map(values => new class_(values) as InstanceType<C>),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
export * from "./JsonifiableSchemableClass"
|
|
||||||
export * from "./dejsonifySchemable"
|
|
||||||
export * from "./makeJsonifiableSchemableClass"
|
|
||||||
export * from "./schema"
|
|
||||||
@@ -1,134 +0,0 @@
|
|||||||
import { Effect } from "effect"
|
|
||||||
import { AbstractClass, Class as ConcreteClass } from "type-fest"
|
|
||||||
import { JsonifiableObject } from "type-fest/source/jsonifiable"
|
|
||||||
import { z } from "zod"
|
|
||||||
import { SchemableClass } from ".."
|
|
||||||
import { StaticMembers, parseZodTypeEffect } from "../../util"
|
|
||||||
|
|
||||||
|
|
||||||
export function makeJsonifiableSchemableClass<
|
|
||||||
C extends SchemableClass<
|
|
||||||
SchemaT,
|
|
||||||
SchemaUnknownKeys,
|
|
||||||
SchemaCatchall,
|
|
||||||
Values,
|
|
||||||
DefaultValues
|
|
||||||
>,
|
|
||||||
|
|
||||||
SchemaT extends z.ZodRawShape,
|
|
||||||
SchemaUnknownKeys extends z.UnknownKeysParam,
|
|
||||||
SchemaCatchall extends z.ZodTypeAny,
|
|
||||||
|
|
||||||
Values extends {},
|
|
||||||
DefaultValues extends Partial<Values>,
|
|
||||||
|
|
||||||
JsonifySchemaT extends z.ZodRawShape,
|
|
||||||
JsonifySchemaUnknownKeys extends z.UnknownKeysParam,
|
|
||||||
JsonifySchemaCatchall extends z.ZodTypeAny,
|
|
||||||
|
|
||||||
DejsonifySchemaT extends z.ZodRawShape,
|
|
||||||
DejsonifySchemaUnknownKeys extends z.UnknownKeysParam,
|
|
||||||
DejsonifySchemaCatchall extends z.ZodTypeAny,
|
|
||||||
|
|
||||||
JsonifiedValues extends JsonifiableObject,
|
|
||||||
>(
|
|
||||||
extend: C | SchemableClass<
|
|
||||||
SchemaT,
|
|
||||||
SchemaUnknownKeys,
|
|
||||||
SchemaCatchall,
|
|
||||||
Values,
|
|
||||||
DefaultValues
|
|
||||||
>,
|
|
||||||
|
|
||||||
props: {
|
|
||||||
jsonifySchema: (props: {
|
|
||||||
schema: z.ZodObject<
|
|
||||||
SchemaT,
|
|
||||||
SchemaUnknownKeys,
|
|
||||||
SchemaCatchall,
|
|
||||||
Values,
|
|
||||||
Values
|
|
||||||
>
|
|
||||||
|
|
||||||
shape: SchemaT
|
|
||||||
}) => z.ZodObject<
|
|
||||||
JsonifySchemaT,
|
|
||||||
JsonifySchemaUnknownKeys,
|
|
||||||
JsonifySchemaCatchall,
|
|
||||||
JsonifiedValues,
|
|
||||||
Values
|
|
||||||
>
|
|
||||||
|
|
||||||
dejsonifySchema: (props: {
|
|
||||||
schema: z.ZodObject<
|
|
||||||
SchemaT,
|
|
||||||
SchemaUnknownKeys,
|
|
||||||
SchemaCatchall,
|
|
||||||
Values,
|
|
||||||
Values
|
|
||||||
>
|
|
||||||
|
|
||||||
shape: SchemaT
|
|
||||||
}) => z.ZodObject<
|
|
||||||
DejsonifySchemaT,
|
|
||||||
DejsonifySchemaUnknownKeys,
|
|
||||||
DejsonifySchemaCatchall,
|
|
||||||
Values,
|
|
||||||
JsonifiedValues
|
|
||||||
>
|
|
||||||
},
|
|
||||||
) {
|
|
||||||
type Class<T, Arguments extends unknown[]> = (
|
|
||||||
C extends ConcreteClass<any>
|
|
||||||
? ConcreteClass<T, Arguments>
|
|
||||||
: AbstractClass<T, Arguments>
|
|
||||||
)
|
|
||||||
|
|
||||||
const jsonifySchema = props.jsonifySchema({
|
|
||||||
schema: extend.schema,
|
|
||||||
shape: extend.schema.shape,
|
|
||||||
})
|
|
||||||
|
|
||||||
const dejsonifySchema = props.dejsonifySchema({
|
|
||||||
schema: extend.schema,
|
|
||||||
shape: extend.schema.shape,
|
|
||||||
})
|
|
||||||
|
|
||||||
return class extends extend {
|
|
||||||
static readonly jsonifySchema = jsonifySchema
|
|
||||||
readonly jsonifySchema = jsonifySchema
|
|
||||||
|
|
||||||
static readonly dejsonifySchema = dejsonifySchema
|
|
||||||
readonly dejsonifySchema = dejsonifySchema
|
|
||||||
|
|
||||||
jsonify() {
|
|
||||||
return this.jsonifySchema.parse(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
jsonifyPromise() {
|
|
||||||
return this.jsonifySchema.parseAsync(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
jsonifyEffect() {
|
|
||||||
return parseZodTypeEffect(this.jsonifySchema, this)
|
|
||||||
}
|
|
||||||
} as unknown as (
|
|
||||||
Class<
|
|
||||||
InstanceType<C> & {
|
|
||||||
readonly jsonifySchema: z.ZodObject<JsonifySchemaT, JsonifySchemaUnknownKeys, JsonifySchemaCatchall, JsonifiedValues, Values>,
|
|
||||||
readonly dejsonifySchema: z.ZodObject<DejsonifySchemaT, DejsonifySchemaUnknownKeys, DejsonifySchemaCatchall, Values, JsonifiedValues>,
|
|
||||||
|
|
||||||
jsonify(): JsonifiedValues
|
|
||||||
jsonifyPromise(): Promise<JsonifiedValues>
|
|
||||||
jsonifyEffect(): Effect.Effect<never, z.ZodError<Values>, JsonifiedValues>
|
|
||||||
},
|
|
||||||
|
|
||||||
ConstructorParameters<C>
|
|
||||||
> &
|
|
||||||
|
|
||||||
StaticMembers<C> & {
|
|
||||||
readonly jsonifySchema: z.ZodObject<JsonifySchemaT, JsonifySchemaUnknownKeys, JsonifySchemaCatchall, JsonifiedValues, Values>,
|
|
||||||
readonly dejsonifySchema: z.ZodObject<DejsonifySchemaT, DejsonifySchemaUnknownKeys, DejsonifySchemaCatchall, Values, JsonifiedValues>,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
import { Opaque } from "type-fest"
|
|
||||||
import { z } from "zod"
|
|
||||||
import { identity } from "../../../util"
|
|
||||||
|
|
||||||
|
|
||||||
export type JsonifiedBigInt = Opaque<string, "@thilawyn/schemable-class/JsonifiedBigInt">
|
|
||||||
|
|
||||||
|
|
||||||
export function jsonifyBigIntSchema<S extends z.ZodBigInt>(schema: S) {
|
|
||||||
return schema.transform(v => v.toString() as JsonifiedBigInt)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function dejsonifyBigIntSchema<S extends z.ZodBigInt>(schema: S) {
|
|
||||||
return z
|
|
||||||
.custom<JsonifiedBigInt>(identity)
|
|
||||||
.pipe(z
|
|
||||||
.string()
|
|
||||||
.transform(v => {
|
|
||||||
try {
|
|
||||||
return BigInt(v)
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.pipe(schema)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
import { Opaque } from "type-fest"
|
|
||||||
import { z } from "zod"
|
|
||||||
import { identity } from "../../../util"
|
|
||||||
|
|
||||||
|
|
||||||
export type JsonifiedDate = Opaque<string, "@thilawyn/schemable-class/JsonifiedDate">
|
|
||||||
|
|
||||||
|
|
||||||
export function jsonifyDateSchema<S extends z.ZodDate>(schema: S) {
|
|
||||||
return schema.transform(v => v.toString() as JsonifiedDate)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function dejsonifyDateSchema<S extends z.ZodDate>(schema: S) {
|
|
||||||
return z
|
|
||||||
.custom<JsonifiedDate>(identity)
|
|
||||||
.pipe(z
|
|
||||||
.string()
|
|
||||||
.transform(v => {
|
|
||||||
try {
|
|
||||||
return new Date(v)
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.pipe(schema)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
import { Decimal } from "decimal.js"
|
|
||||||
import { Opaque } from "type-fest"
|
|
||||||
import { z } from "zod"
|
|
||||||
import { identity } from "../../../util"
|
|
||||||
|
|
||||||
|
|
||||||
export type JsonifiedDecimal = Opaque<string, "@thilawyn/schemable-class/JsonifiedDecimal">
|
|
||||||
|
|
||||||
|
|
||||||
export function jsonifyDecimalSchema<
|
|
||||||
S extends z.ZodType<Decimal, z.ZodTypeDef, Decimal>
|
|
||||||
>(schema: S) {
|
|
||||||
return schema.transform(v => v.toJSON() as JsonifiedDecimal)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function dejsonifyDecimalSchema<
|
|
||||||
S extends z.ZodType<Decimal, z.ZodTypeDef, Decimal>
|
|
||||||
>(schema: S) {
|
|
||||||
return z
|
|
||||||
.custom<JsonifiedDecimal>(identity)
|
|
||||||
.pipe(z
|
|
||||||
.string()
|
|
||||||
.transform(v => {
|
|
||||||
try {
|
|
||||||
return new Decimal(v)
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.pipe(schema)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
export * from "./bigint"
|
|
||||||
export * from "./date"
|
|
||||||
export * from "./decimal"
|
|
||||||
export * from "./schemable"
|
|
||||||
@@ -1,139 +0,0 @@
|
|||||||
import { JsonifiableObject } from "type-fest/source/jsonifiable"
|
|
||||||
import { z } from "zod"
|
|
||||||
import { JsonifiableSchemableClass } from ".."
|
|
||||||
|
|
||||||
|
|
||||||
export function jsonifySchemableSchema<
|
|
||||||
C extends JsonifiableSchemableClass<
|
|
||||||
SchemaT,
|
|
||||||
SchemaUnknownKeys,
|
|
||||||
SchemaCatchall,
|
|
||||||
|
|
||||||
Values,
|
|
||||||
DefaultValues,
|
|
||||||
|
|
||||||
JsonifySchemaT,
|
|
||||||
JsonifySchemaUnknownKeys,
|
|
||||||
JsonifySchemaCatchall,
|
|
||||||
|
|
||||||
DejsonifySchemaT,
|
|
||||||
DejsonifySchemaUnknownKeys,
|
|
||||||
DejsonifySchemaCatchall,
|
|
||||||
|
|
||||||
JsonifiedValues,
|
|
||||||
|
|
||||||
"Class"
|
|
||||||
>,
|
|
||||||
|
|
||||||
SchemaT extends z.ZodRawShape,
|
|
||||||
SchemaUnknownKeys extends z.UnknownKeysParam,
|
|
||||||
SchemaCatchall extends z.ZodTypeAny,
|
|
||||||
|
|
||||||
Values extends {},
|
|
||||||
DefaultValues extends Partial<Values>,
|
|
||||||
|
|
||||||
JsonifySchemaT extends z.ZodRawShape,
|
|
||||||
JsonifySchemaUnknownKeys extends z.UnknownKeysParam,
|
|
||||||
JsonifySchemaCatchall extends z.ZodTypeAny,
|
|
||||||
|
|
||||||
DejsonifySchemaT extends z.ZodRawShape,
|
|
||||||
DejsonifySchemaUnknownKeys extends z.UnknownKeysParam,
|
|
||||||
DejsonifySchemaCatchall extends z.ZodTypeAny,
|
|
||||||
|
|
||||||
JsonifiedValues extends JsonifiableObject,
|
|
||||||
|
|
||||||
S extends z.ZodType<InstanceType<C>, z.ZodTypeDef, InstanceType<C>>,
|
|
||||||
>(
|
|
||||||
class_: C | JsonifiableSchemableClass<
|
|
||||||
SchemaT,
|
|
||||||
SchemaUnknownKeys,
|
|
||||||
SchemaCatchall,
|
|
||||||
|
|
||||||
Values,
|
|
||||||
DefaultValues,
|
|
||||||
|
|
||||||
JsonifySchemaT,
|
|
||||||
JsonifySchemaUnknownKeys,
|
|
||||||
JsonifySchemaCatchall,
|
|
||||||
|
|
||||||
DejsonifySchemaT,
|
|
||||||
DejsonifySchemaUnknownKeys,
|
|
||||||
DejsonifySchemaCatchall,
|
|
||||||
|
|
||||||
JsonifiedValues,
|
|
||||||
|
|
||||||
"Class"
|
|
||||||
>,
|
|
||||||
|
|
||||||
schema: S,
|
|
||||||
) {
|
|
||||||
return schema.pipe(class_.jsonifySchema)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export function dejsonifySchemableSchema<
|
|
||||||
C extends JsonifiableSchemableClass<
|
|
||||||
SchemaT,
|
|
||||||
SchemaUnknownKeys,
|
|
||||||
SchemaCatchall,
|
|
||||||
|
|
||||||
Values,
|
|
||||||
DefaultValues,
|
|
||||||
|
|
||||||
JsonifySchemaT,
|
|
||||||
JsonifySchemaUnknownKeys,
|
|
||||||
JsonifySchemaCatchall,
|
|
||||||
|
|
||||||
DejsonifySchemaT,
|
|
||||||
DejsonifySchemaUnknownKeys,
|
|
||||||
DejsonifySchemaCatchall,
|
|
||||||
|
|
||||||
JsonifiedValues,
|
|
||||||
|
|
||||||
"Class"
|
|
||||||
>,
|
|
||||||
|
|
||||||
SchemaT extends z.ZodRawShape,
|
|
||||||
SchemaUnknownKeys extends z.UnknownKeysParam,
|
|
||||||
SchemaCatchall extends z.ZodTypeAny,
|
|
||||||
|
|
||||||
Values extends {},
|
|
||||||
DefaultValues extends Partial<Values>,
|
|
||||||
|
|
||||||
JsonifySchemaT extends z.ZodRawShape,
|
|
||||||
JsonifySchemaUnknownKeys extends z.UnknownKeysParam,
|
|
||||||
JsonifySchemaCatchall extends z.ZodTypeAny,
|
|
||||||
|
|
||||||
DejsonifySchemaT extends z.ZodRawShape,
|
|
||||||
DejsonifySchemaUnknownKeys extends z.UnknownKeysParam,
|
|
||||||
DejsonifySchemaCatchall extends z.ZodTypeAny,
|
|
||||||
|
|
||||||
JsonifiedValues extends JsonifiableObject,
|
|
||||||
|
|
||||||
S extends z.ZodType<InstanceType<C>, z.ZodTypeDef, InstanceType<C>>,
|
|
||||||
>(
|
|
||||||
class_: C | JsonifiableSchemableClass<
|
|
||||||
SchemaT,
|
|
||||||
SchemaUnknownKeys,
|
|
||||||
SchemaCatchall,
|
|
||||||
|
|
||||||
Values,
|
|
||||||
DefaultValues,
|
|
||||||
|
|
||||||
JsonifySchemaT,
|
|
||||||
JsonifySchemaUnknownKeys,
|
|
||||||
JsonifySchemaCatchall,
|
|
||||||
|
|
||||||
DejsonifySchemaT,
|
|
||||||
DejsonifySchemaUnknownKeys,
|
|
||||||
DejsonifySchemaCatchall,
|
|
||||||
|
|
||||||
JsonifiedValues,
|
|
||||||
|
|
||||||
"Class"
|
|
||||||
>,
|
|
||||||
|
|
||||||
schema: S,
|
|
||||||
) {
|
|
||||||
return class_.dejsonifySchema.transform(v => new class_(v)).pipe(schema)
|
|
||||||
}
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
import { AbstractClass, Class as ConcreteClass, Opaque } from "type-fest"
|
|
||||||
import { z } from "zod"
|
|
||||||
import { DefinedDefaultValuesTag } from "."
|
|
||||||
import { StaticMembers } from "../util"
|
|
||||||
|
|
||||||
|
|
||||||
export function makeSchemableClassFrom<
|
|
||||||
C extends AbstractClass<{
|
|
||||||
schema?: never
|
|
||||||
defaultValues?: never
|
|
||||||
}, []> & {
|
|
||||||
schema?: never
|
|
||||||
defaultValues?: never
|
|
||||||
},
|
|
||||||
|
|
||||||
SchemaT extends z.ZodRawShape,
|
|
||||||
SchemaUnknownKeys extends z.UnknownKeysParam,
|
|
||||||
SchemaCatchall extends z.ZodTypeAny,
|
|
||||||
|
|
||||||
Values extends {},
|
|
||||||
DefaultValues extends Partial<Values>,
|
|
||||||
>(
|
|
||||||
extend: C,
|
|
||||||
|
|
||||||
{ schema, defaultValues }: {
|
|
||||||
schema: z.ZodObject<SchemaT, SchemaUnknownKeys, SchemaCatchall, Values, Values>
|
|
||||||
defaultValues: Opaque<DefaultValues, DefinedDefaultValuesTag>
|
|
||||||
},
|
|
||||||
) {
|
|
||||||
type Class<T, Arguments extends unknown[]> = (
|
|
||||||
C extends ConcreteClass<any>
|
|
||||||
? ConcreteClass<T, Arguments>
|
|
||||||
: AbstractClass<T, Arguments>
|
|
||||||
)
|
|
||||||
|
|
||||||
return class extends (extend as unknown as ConcreteClass<any, []>) {
|
|
||||||
static readonly schema = schema
|
|
||||||
readonly schema = schema
|
|
||||||
|
|
||||||
static readonly defaultValues = defaultValues
|
|
||||||
readonly defaultValues = defaultValues
|
|
||||||
|
|
||||||
constructor(values: Values) {
|
|
||||||
super()
|
|
||||||
Object.assign(this, values)
|
|
||||||
}
|
|
||||||
} as unknown as (
|
|
||||||
Class<
|
|
||||||
InstanceType<C> &
|
|
||||||
{
|
|
||||||
readonly schema: z.ZodObject<SchemaT, SchemaUnknownKeys, SchemaCatchall, Values, Values>,
|
|
||||||
readonly defaultValues: DefaultValues,
|
|
||||||
} &
|
|
||||||
Values,
|
|
||||||
|
|
||||||
Parameters<(values: Values) => void>
|
|
||||||
> &
|
|
||||||
|
|
||||||
StaticMembers<C> &
|
|
||||||
{
|
|
||||||
readonly schema: z.ZodObject<SchemaT, SchemaUnknownKeys, SchemaCatchall, Values, Values>,
|
|
||||||
readonly defaultValues: DefaultValues,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export function makeSchemableClass<
|
|
||||||
SchemaT extends z.ZodRawShape,
|
|
||||||
SchemaUnknownKeys extends z.UnknownKeysParam,
|
|
||||||
SchemaCatchall extends z.ZodTypeAny,
|
|
||||||
|
|
||||||
Values extends {},
|
|
||||||
DefaultValues extends Partial<Values>,
|
|
||||||
>(
|
|
||||||
props: {
|
|
||||||
schema: z.ZodObject<SchemaT, SchemaUnknownKeys, SchemaCatchall, Values, Values>
|
|
||||||
defaultValues: Opaque<DefaultValues, DefinedDefaultValuesTag>
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
return makeSchemableClassFrom(Object, props)
|
|
||||||
}
|
|
||||||
@@ -1,127 +0,0 @@
|
|||||||
import { Effect, pipe } from "effect"
|
|
||||||
import { HasRequiredKeys } from "type-fest"
|
|
||||||
import { z } from "zod"
|
|
||||||
import { SchemableClass, SchemableClassInput } from "."
|
|
||||||
import { parseZodTypeEffect } from "../util"
|
|
||||||
|
|
||||||
|
|
||||||
type ParamsArgs = [] | [params: Partial<z.ParseParams>]
|
|
||||||
|
|
||||||
type NewSchemableArgs<Input extends object> =
|
|
||||||
HasRequiredKeys<Input> extends true
|
|
||||||
? [values: Input, ...args: ParamsArgs]
|
|
||||||
: [] | [values: Input, ...args: ParamsArgs]
|
|
||||||
|
|
||||||
|
|
||||||
export function newSchemable<
|
|
||||||
C extends SchemableClass<
|
|
||||||
SchemaT,
|
|
||||||
SchemaUnknownKeys,
|
|
||||||
SchemaCatchall,
|
|
||||||
Values,
|
|
||||||
DefaultValues,
|
|
||||||
"Class"
|
|
||||||
>,
|
|
||||||
|
|
||||||
SchemaT extends z.ZodRawShape,
|
|
||||||
SchemaUnknownKeys extends z.UnknownKeysParam,
|
|
||||||
SchemaCatchall extends z.ZodTypeAny,
|
|
||||||
|
|
||||||
Values extends {},
|
|
||||||
DefaultValues extends Partial<Values>,
|
|
||||||
>(
|
|
||||||
class_: C | SchemableClass<
|
|
||||||
SchemaT,
|
|
||||||
SchemaUnknownKeys,
|
|
||||||
SchemaCatchall,
|
|
||||||
Values,
|
|
||||||
DefaultValues,
|
|
||||||
"Class"
|
|
||||||
>,
|
|
||||||
|
|
||||||
...[values, params]: NewSchemableArgs<
|
|
||||||
SchemableClassInput<Values, DefaultValues>
|
|
||||||
>
|
|
||||||
) {
|
|
||||||
return new class_(
|
|
||||||
class_.schema.parse({ ...class_.defaultValues, ...values }, params)
|
|
||||||
) as InstanceType<C>
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export async function newSchemablePromise<
|
|
||||||
C extends SchemableClass<
|
|
||||||
SchemaT,
|
|
||||||
SchemaUnknownKeys,
|
|
||||||
SchemaCatchall,
|
|
||||||
Values,
|
|
||||||
DefaultValues,
|
|
||||||
"Class"
|
|
||||||
>,
|
|
||||||
|
|
||||||
SchemaT extends z.ZodRawShape,
|
|
||||||
SchemaUnknownKeys extends z.UnknownKeysParam,
|
|
||||||
SchemaCatchall extends z.ZodTypeAny,
|
|
||||||
|
|
||||||
Values extends {},
|
|
||||||
DefaultValues extends Partial<Values>,
|
|
||||||
>(
|
|
||||||
class_: C | SchemableClass<
|
|
||||||
SchemaT,
|
|
||||||
SchemaUnknownKeys,
|
|
||||||
SchemaCatchall,
|
|
||||||
Values,
|
|
||||||
DefaultValues,
|
|
||||||
"Class"
|
|
||||||
>,
|
|
||||||
|
|
||||||
...[values, params]: NewSchemableArgs<
|
|
||||||
SchemableClassInput<Values, DefaultValues>
|
|
||||||
>
|
|
||||||
) {
|
|
||||||
return new class_(
|
|
||||||
await class_.schema.parseAsync({ ...class_.defaultValues, ...values }, params)
|
|
||||||
) as InstanceType<C>
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export function newSchemableEffect<
|
|
||||||
C extends SchemableClass<
|
|
||||||
SchemaT,
|
|
||||||
SchemaUnknownKeys,
|
|
||||||
SchemaCatchall,
|
|
||||||
Values,
|
|
||||||
DefaultValues,
|
|
||||||
"Class"
|
|
||||||
>,
|
|
||||||
|
|
||||||
SchemaT extends z.ZodRawShape,
|
|
||||||
SchemaUnknownKeys extends z.UnknownKeysParam,
|
|
||||||
SchemaCatchall extends z.ZodTypeAny,
|
|
||||||
|
|
||||||
Values extends {},
|
|
||||||
DefaultValues extends Partial<Values>,
|
|
||||||
>(
|
|
||||||
class_: C | SchemableClass<
|
|
||||||
SchemaT,
|
|
||||||
SchemaUnknownKeys,
|
|
||||||
SchemaCatchall,
|
|
||||||
Values,
|
|
||||||
DefaultValues,
|
|
||||||
"Class"
|
|
||||||
>,
|
|
||||||
|
|
||||||
...[values, params]: NewSchemableArgs<
|
|
||||||
SchemableClassInput<Values, DefaultValues>
|
|
||||||
>
|
|
||||||
) {
|
|
||||||
return pipe(
|
|
||||||
parseZodTypeEffect(
|
|
||||||
class_.schema,
|
|
||||||
{ ...class_.defaultValues, ...values },
|
|
||||||
params,
|
|
||||||
),
|
|
||||||
|
|
||||||
Effect.map(values => new class_(values) as InstanceType<C>),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
export * from "./makeSchemableClassObservable"
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
import { mapValues } from "lodash-es"
|
|
||||||
import { makeObservable, observable } from "mobx"
|
|
||||||
import { AbstractConstructor } from "type-fest"
|
|
||||||
import { z } from "zod"
|
|
||||||
import { SchemableClass } from ".."
|
|
||||||
|
|
||||||
|
|
||||||
export function makeSchemableClassObservable<
|
|
||||||
C extends SchemableClass<SchemaT, SchemaUnknownKeys, SchemaCatchall, Values, DefaultValues>,
|
|
||||||
|
|
||||||
SchemaT extends z.ZodRawShape,
|
|
||||||
SchemaUnknownKeys extends z.UnknownKeysParam,
|
|
||||||
SchemaCatchall extends z.ZodTypeAny,
|
|
||||||
|
|
||||||
Values extends {},
|
|
||||||
DefaultValues extends Partial<Values>,
|
|
||||||
>(
|
|
||||||
extend: C | SchemableClass<SchemaT, SchemaUnknownKeys, SchemaCatchall, Values, DefaultValues>
|
|
||||||
) {
|
|
||||||
return class extends (extend as AbstractConstructor<any>) {
|
|
||||||
constructor(...args: any[]) {
|
|
||||||
super(...args)
|
|
||||||
|
|
||||||
makeObservable(this,
|
|
||||||
mapValues(this.schema.shape, () => observable)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} as unknown as C
|
|
||||||
}
|
|
||||||
@@ -35,7 +35,7 @@ class User extends exp.extends implements Implements<typeof exp> {}
|
|||||||
User.defaultValues
|
User.defaultValues
|
||||||
const inst = User.create({ id: 1n, name: "" })
|
const inst = User.create({ id: 1n, name: "" })
|
||||||
console.log(inst)
|
console.log(inst)
|
||||||
const jsonifiedUser = inst.jsonify()
|
const jsonifiedUser = await inst.jsonifyPromise()
|
||||||
|
|
||||||
|
|
||||||
class SubTest extends User.extend({
|
class SubTest extends User.extend({
|
||||||
|
|||||||
Reference in New Issue
Block a user