From ab2ee2d3619d12c669bdc6af209746b473a0e2df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Sat, 30 Dec 2023 01:07:23 +0100 Subject: [PATCH 01/24] Initial files --- .drone.jsonnet | 110 ++++++++++++++++++++++ .gitignore | 1 - package.json | 43 +++++++++ rollup.config.js | 30 ++++++ src/index.ts | 195 +++++++++++++++++++++++++++++++++++++++ src/legacy/tests.ts | 74 +++++++++++++++ src/legacy/trait.ts | 126 +++++++++++++++++++++++++ src/legacy/util/class.ts | 109 ++++++++++++++++++++++ src/tests.ts | 70 ++++++++++++++ tsconfig.json | 24 +++++ 10 files changed, 781 insertions(+), 1 deletion(-) create mode 100644 .drone.jsonnet create mode 100644 package.json create mode 100644 rollup.config.js create mode 100644 src/index.ts create mode 100644 src/legacy/tests.ts create mode 100644 src/legacy/trait.ts create mode 100644 src/legacy/util/class.ts create mode 100644 src/tests.ts create mode 100644 tsconfig.json diff --git a/.drone.jsonnet b/.drone.jsonnet new file mode 100644 index 0000000..fefec26 --- /dev/null +++ b/.drone.jsonnet @@ -0,0 +1,110 @@ +local bun_image = "oven/bun:1"; +local node_image = "node:20"; + + +local install_step = { + name: "install", + image: bun_image, + commands: ["bun install --frozen-lockfile"], +}; + +local lint_step = { + name: "lint", + image: bun_image, + commands: ["bun lint:tsc"], +}; + +local build_step = { + name: "build", + image: bun_image, + commands: ["bun run build"], +}; + +local pack_step = { + name: "pack", + image: node_image, + commands: ["npm pack --dry-run"], +}; + +local publish_step = { + name: "publish", + image: node_image, + + environment: { + NPM_TOKEN: { from_secret: "npm_token" } + }, + + commands: [ + "npm set @thilawyn:registry https://git.jvalver.de/api/packages/thilawyn/npm/", + "npm config set -- //git.jvalver.de/api/packages/thilawyn/npm/:_authToken $NPM_TOKEN", + "npm publish", + ], +}; + + +[ + // Lint the whole project when not in master, not in a PR nor on a tag + { + kind: "pipeline", + type: "docker", + name: "lint", + + trigger: { + ref: { + exclude: [ + "refs/heads/master", + "refs/pull/**", + "refs/tags/**", + ] + } + }, + + steps: [ + install_step, + lint_step, + ], + }, + + // Build the package without publishing for pull requests + { + kind: "pipeline", + type: "docker", + name: "build", + + trigger: { + ref: { + include: ["refs/pull/**"] + } + }, + + steps: [ + install_step, + lint_step, + build_step, + pack_step, + ], + }, + + // Build and publish the package for master and tags + { + kind: "pipeline", + type: "docker", + name: "build-publish", + + trigger: { + ref: { + include: [ + "refs/heads/master", + "refs/tags/**", + ] + } + }, + + steps: [ + install_step, + lint_step, + build_step, + publish_step, + ], + }, +] diff --git a/.gitignore b/.gitignore index ceaea36..745264f 100644 --- a/.gitignore +++ b/.gitignore @@ -129,4 +129,3 @@ dist .yarn/build-state.yml .yarn/install-state.gz .pnp.* - diff --git a/package.json b/package.json new file mode 100644 index 0000000..e2d658f --- /dev/null +++ b/package.json @@ -0,0 +1,43 @@ +{ + "name": "@thilawyn/schemable-classes", + "version": "20231230.0.0", + "type": "module", + "publishConfig": { + "registry": "https://git.jvalver.de/api/packages/thilawyn/npm/" + }, + "files": [ + "./dist" + ], + "exports": { + ".": { + "import": { + "types": "./dist/lib.d.mts", + "default": "./dist/lib.mjs" + }, + "require": { + "types": "./dist/lib.d.cts", + "default": "./dist/lib.cjs" + } + } + }, + "scripts": { + "build": "rollup -c", + "lint:tsc": "tsc --noEmit", + "clean:cache": "rm -f tsconfig.tsbuildinfo", + "clean:dist": "rm -rf dist", + "clean:node": "rm -rf node_modules" + }, + "dependencies": { + "type-fest": "^4.9.0" + }, + "devDependencies": { + "bun-types": "latest", + "npm-check-updates": "^16.14.12", + "npm-sort": "^0.0.4", + "rollup": "^4.9.1", + "rollup-plugin-cleanup": "^3.2.1", + "rollup-plugin-ts": "^3.4.5", + "tsx": "^4.7.0", + "typescript": "^5.3.3" + } +} diff --git a/rollup.config.js b/rollup.config.js new file mode 100644 index 0000000..da6b231 --- /dev/null +++ b/rollup.config.js @@ -0,0 +1,30 @@ +import { defineConfig } from "rollup" +import cleanup from "rollup-plugin-cleanup" +import ts from "rollup-plugin-ts" +import pkg from "./package.json" assert { type: "json" } + + +export default defineConfig({ + input: "src/index.ts", + + output: [ + { + file: pkg.exports["."].import.default, + format: "esm", + }, + + { + file: pkg.exports["."].require.default, + format: "cjs", + }, + ], + + plugins: [ + ts(), + + cleanup({ + comments: "jsdoc", + extensions: ["ts"], + }), + ], +}) diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..8351eca --- /dev/null +++ b/src/index.ts @@ -0,0 +1,195 @@ +import { AbstractClass, AbstractConstructor, Opaque, UnionToIntersection } from "type-fest" + + +/** + * Represents the static members of a class. + * @template C - The class type. + */ +export type StaticMembers = { + [Key in keyof C as Key extends "prototype" ? never : Key]: C[Key] +} + + +/** + * Represents a trait that can be applied to a class. + * @template C - The abstract class type. + */ +export type Trait< + C extends AbstractClass +> = Opaque< + TraitApplier, + "thilatrait/Trait" +> + +/** + * Represents the function signature for applying a trait to a parent class. + * @template C - The abstract class type. + */ +export type TraitApplier< + C extends AbstractClass +> = + (Parent: AbstractConstructor) => C + +/** + * Unwraps the type of the class from a given trait. + * @template T - The trait type. + */ +export type UnwrapTraitC = + T extends Trait + ? C + : never + + +/** + * Creates a trait using the provided trait applier function. + * @template C - The abstract class type. + * @param applier - The trait applier function. + * @returns A trait. + * @example + * Creates a trait: + * ```ts + * const Permissible = trait(Parent => { + * abstract class Permissible extends Parent { + * static readonly defaultPermissions: string[] = [] + * permissions: string[] = [] + * + * // Constructor is optional + * // If you wish to use it, make sure it takes any[] as an args array and passes it to the super call. This is necessary for inheritance to work properly. + * // Trait constructors cannot have typed arguments of their own, they only serve to run logic during object instantiation. + * constructor(...args: any[]) { + * super(...args) + * } + * } + * + * return Permissible + * }) + * ``` + * Creates a generic trait: + * ```ts + * const Identifiable = () => + * trait(Parent => { + * abstract class Identifiable extends Parent { + * abstract readonly id: ID + * + * equals(el: Identifiable) { + * return this.id === el.id + * } + * + * // Optional + * constructor(...args: any[]) { + * super(...args) + * } + * } + * + * return Identifiable + * }) + * ``` + * Creates a subtrait: + * ```ts + * const ImplementsIdentifiable = (defaultID: ID) => + * trait(Parent => { + * abstract class ImplementsIdentifiable extends extendsAndExpresses( + * Parent, + * [Identifiable()], + * ) { + * id: ID = defaultID + * + * // Optional + * constructor(...args: any[]) { + * super(...args) + * } + * } + * + * return ImplementsIdentifiable + * }) + * ``` + */ +export function trait< + C extends AbstractClass +>( + applier: TraitApplier +) { + return applier as Trait +} + + +/** + * Extends a class with the given traits and expresses their combined functionality. + * @template C - The abstract class type. + * @template Traits - An array of traits. + * @param extend - The class to extend. + * @param traits - An array of traits to apply. + * @returns A new class type expressing the combined functionality of the base class and traits. + * @example + * Extends a superclass and applies traits: + * ```ts + * class User extends extendsAndExpresses(Entity, [Identifiable(), Permissible]) { + * readonly id: bigint + * + * constructor(id: bigint) { + * super() + * this.id = id + * } + * } + * ``` + */ +export function extendsAndExpresses< + C extends AbstractClass, + Traits extends readonly Trait[], +>( + extend: C, + traits: Traits, +) { + return traits.reduce( + (previous, trait) => trait(previous), + extend, + ) as ( + AbstractClass< + InstanceType & + UnionToIntersection< + InstanceType< + UnwrapTraitC< + Traits[number] + > + > + >, + + ConstructorParameters + > & + + StaticMembers & + StaticMembers< + UnionToIntersection< + UnwrapTraitC< + Traits[number] + > + > + > + ) +} + +/** + * Expresses the combined functionality of multiple traits. + * @template Traits - An array of trait. + * @param traits - An array of trait to apply. + * @returns A new class type expressing the combined functionality of the traits. + * @example + * Applies traits to a class: + * ```ts + * class User extends expresses(Identifiable(), Permissible) { + * readonly id: bigint + * + * constructor(id: bigint) { + * super() + * this.id = id + * } + * } + * ``` + */ +export function expresses< + Traits extends readonly Trait[], +>( + ...traits: Traits +) { + return extendsAndExpresses(Object, traits) +} diff --git a/src/legacy/tests.ts b/src/legacy/tests.ts new file mode 100644 index 0000000..e86528d --- /dev/null +++ b/src/legacy/tests.ts @@ -0,0 +1,74 @@ +import { AbstractClass } from "type-fest" +import { expresses } from "./trait" + + +function inspectClass(class_: AbstractClass) { + Object.getOwnPropertyNames(class_).forEach(name => { + console.log( + "[static]", + name, + Object.getOwnPropertyDescriptor(class_, name) + ) + }) + + Object.getOwnPropertyNames(class_.prototype).forEach(name => { + console.log( + "[prototype]", + name, + Object.getOwnPropertyDescriptor(class_.prototype, name) + ) + }) +} + + +abstract class Identified { + abstract id: ID + + equals(el: Identified) { + return this.id === el.id + } + + // initializer() { + // console.log("Identified initializer") + // } +} + +class ImplementsIdentifiable extends Identified { + id!: ID +} + + +abstract class Permissible { + static readonly defaultPermissions: string[] = [] + permissions: string[] = [] + // permissions!: string[] + + constructor() { + console.log("Permissible constructor") + } + + initializer() { + console.log("Permissible initializer") + this.permissions = [] + } +} + + +class User extends expresses( + Identified as typeof Identified, + // Identified, + Permissible, +) { + readonly id: bigint + + constructor(id: bigint) { + super() + this.id = id + } +} + +const user1 = new User(BigInt(1)) +const user2 = new User(BigInt(2)) + +console.log(user1) +console.log(user1.equals(user2)) diff --git a/src/legacy/trait.ts b/src/legacy/trait.ts new file mode 100644 index 0000000..10cc87b --- /dev/null +++ b/src/legacy/trait.ts @@ -0,0 +1,126 @@ +import { AbstractClass, Class, UnionToIntersection } from "type-fest" +import { StaticMembers, copyProperties, getInheritanceHierarchy } from "./util/class" + + +/** + * Represents a trait that can be used to define common behavior + * for classes and abstract classes. + * @typeParam T - The type of the trait. + */ +export type Trait = + AbstractClass + + +/** + * Creates a link class that expresses the given traits. + * @param traits - An array of traits to be expressed by the link class. + * @returns A dynamically created class that expresses the given traits. + * @typeParam Traits - An array of traits that the link class expresses. + */ +export function expresses< + Traits extends readonly Trait[] +>( + ...traits: Traits +) { + return makeLinkClass(traits) +} + + +/** + * Creates a link class that extends a base class and expresses the given traits. + * @param extend - The base class or abstract class to extend. + * @param traits - An array of traits to be expressed by the link class. + * @returns A dynamically created class that extends the given base class and expresses the given traits. + * @typeParam C - The type of the base class to extend. + * @typeParam Traits - An array of traits that the link class expresses. + */ +export function extendsAndExpresses< + C extends Class + | AbstractClass, + Traits extends readonly Trait[], +>( + extend: C, + ...traits: Traits +) { + return makeLinkClass(traits, extend) +} + + +/** + * Creates a link class that expresses the given traits and optionally extends a base class. + * @param traits - An array of traits to be expressed by the link class. + * @param extend - The base class or abstract class to extend (optional). + * @returns A dynamically created class that expresses the given traits and extends the base class. + * @typeParam Traits - An array of traits that the link class expresses. + * @typeParam C - The type of the base class to extend (optional). + */ +export function makeLinkClass< + Traits extends readonly Trait[], + C extends Class + | AbstractClass + | undefined = undefined, +>( + traits: Traits, + extend?: C, +) { + const class_ = extend + ? class extends extend { + constructor(...args: any[]) { + super(...args) + + traits.forEach(trait => { + trait.prototype.initializer?.call(this) + }) + } + } + : class { + constructor() { + traits.forEach(trait => { + trait.prototype.initializer?.call(this) + }) + } + } + + traits.forEach(trait => { + getInheritanceHierarchy(trait).forEach(current => { + copyProperties( + current, + class_, + ["name", "length"], + ["constructor"], + ) + }) + }) + + return class_ as unknown as ( + (C extends Class | AbstractClass + ? ( + AbstractClass< + InstanceType & + UnionToIntersection< + InstanceType< + Traits[number] + > + >, + + ConstructorParameters + > & + + StaticMembers + ) + : Trait< + UnionToIntersection< + InstanceType< + Traits[number] + > + > + > + ) & + + StaticMembers< + UnionToIntersection< + Traits[number] + > + > + ) +} diff --git a/src/legacy/util/class.ts b/src/legacy/util/class.ts new file mode 100644 index 0000000..518c960 --- /dev/null +++ b/src/legacy/util/class.ts @@ -0,0 +1,109 @@ +import { AbstractClass } from "type-fest" + + +/** + * Represents the static members of a class. + * + * @template C - The type of the class for which static members are extracted. + * @typeparam The static members of the class. + */ +export type StaticMembers = Pick + + +/** + * Flattens the inheritance hierarchy of a given class by copying all properties + * from its superclass chain into a single object. + * + * @template C - The type of the class to be flattened, extending AbstractClass. + * @param C - The class to be flattened. + * @returns A new class with properties flattened from the entire inheritance hierarchy. + */ +export function flattenClass< + C extends AbstractClass +>(class_: C) { + const flattenedClass = class {} as unknown as C + + getInheritanceHierarchy(class_).forEach(current => { + copyProperties(current, flattenedClass) + }) + + copyProperty(class_, flattenedClass, "name") + copyProperty(class_.prototype, flattenedClass.prototype, "constructor") + + return flattenedClass +} + + +/** + * Retrieves the inheritance hierarchy of a given class, including itself. + * + * @param class_ - The class for which the inheritance hierarchy is retrieved. + * @returns An array representing the inheritance hierarchy, ordered from the furthest in the hierarchy to `class_` itself. + */ +export function getInheritanceHierarchy( + class_: AbstractClass +): AbstractClass[] { + const parent = Object.getPrototypeOf(class_) + + return isClass(parent) + ? [...getInheritanceHierarchy(parent), class_] + : [class_] +} + + +/** + * Checks if a given element appears to be a class based on its string representation. + * + * @param el - The element to check for being a class. + * @returns `true` if the element is likely a class; otherwise, `false`. + */ +export function isClass(el: { toString: () => string }) { + return Boolean(el.toString().match(/^class(?: [.\S]+)?(?: extends [.\S]+)? {[\s\S]*}$/)) +} + + +/** + * Copies properties from one class to another, including static and prototype properties. + * + * @param from - The source class to copy properties from. + * @param to - The destination class to copy properties to. + */ +export function copyProperties( + from: AbstractClass, + to: AbstractClass, + ignoreKeys: string[] = [], + ignorePrototypeKeys: string[] = [], +) { + Object.getOwnPropertyNames(from).forEach(name => { + if (name === "prototype" + || ignoreKeys.find(v => v === name) + ) + return + + // console.log(from, to, name, Object.getOwnPropertyDescriptor(from, name)) + + copyProperty(from, to, name) + }) + + Object.getOwnPropertyNames(from.prototype).forEach(name => { + if (ignorePrototypeKeys.find(v => v === name)) + return + + // console.log(from, to, name, Object.getOwnPropertyDescriptor(from, name)) + + copyProperty(from.prototype, to.prototype, name) + }) +} + + +export function copyProperty( + from: unknown, + to: unknown, + name: string, +) { + Object.defineProperty( + to, + name, + Object.getOwnPropertyDescriptor(from, name) || Object.create(null), + ) +} diff --git a/src/tests.ts b/src/tests.ts new file mode 100644 index 0000000..bb49d1f --- /dev/null +++ b/src/tests.ts @@ -0,0 +1,70 @@ +import { expresses, extendsAndExpresses, trait } from "." + + +const Identifiable = () => + trait(Parent => { + abstract class Identifiable extends Parent { + abstract readonly id: ID + + equals(el: Identifiable) { + return this.id === el.id + } + + constructor(...args: any[]) { + super(...args) + console.log("Identified constructor") + } + } + + return Identifiable + }) + +const ImplementsIdentifiable = (defaultID: ID) => + trait(Parent => { + abstract class ImplementsIdentifiable extends extendsAndExpresses( + Parent, + [Identifiable()], + ) { + id: ID = defaultID + + constructor(...args: any[]) { + super(...args) + console.log("ImplementsIdentifiable constructor") + } + } + + return ImplementsIdentifiable + }) + + +const Permissible = trait(Parent => { + abstract class Permissible extends Parent { + static readonly defaultPermissions: string[] = [] + permissions: string[] = [] + + constructor(...args: any[]) { + super(...args) + console.log("Permissible constructor") + } + } + + return Permissible +}) + + +const UserProto = expresses( + // Identifiable(), + ImplementsIdentifiable(0n), + Permissible, +) + +class User extends UserProto { + constructor(id: bigint) { + super() + this.id = id + } +} + +const user1 = new User(1n) +console.log(user1) +console.log(user1.equals(user1)) diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..5470793 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "lib": ["ESNext"], + "module": "esnext", + "target": "esnext", + "moduleResolution": "bundler", + "moduleDetection": "force", + // "allowImportingTsExtensions": true, + // "noEmit": true, + "declaration": true, + "composite": true, + "strict": true, + "downlevelIteration": true, + "skipLibCheck": true, + "jsx": "react-jsx", + "allowSyntheticDefaultImports": true, + "forceConsistentCasingInFileNames": true, + "allowJs": true, + "types": [ + "bun-types" + ] + }, + "include": ["src"] +} -- 2.49.1 From 60daa8ec3aabb135394255dc32bb56e4c59a28d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Sat, 30 Dec 2023 01:59:45 +0100 Subject: [PATCH 02/24] Util file --- bun.lockb | Bin 0 -> 150218 bytes package.json | 6 +- src/index.ts | 195 --------------------------------------- src/legacy/tests.ts | 74 --------------- src/legacy/trait.ts | 126 ------------------------- src/legacy/util/class.ts | 109 ---------------------- src/tests.ts | 70 -------------- src/util.ts | 73 +++++++++++++++ 8 files changed, 78 insertions(+), 575 deletions(-) create mode 100755 bun.lockb delete mode 100644 src/legacy/tests.ts delete mode 100644 src/legacy/trait.ts delete mode 100644 src/legacy/util/class.ts delete mode 100644 src/tests.ts create mode 100644 src/util.ts diff --git a/bun.lockb b/bun.lockb new file mode 100755 index 0000000000000000000000000000000000000000..692b0f6e2e5e15465484758c10d9eb64860dd447 GIT binary patch literal 150218 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 z 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 SK@xTWM=(+BbFKe{|NI|?ozG+d literal 0 HcmV?d00001 diff --git a/package.json b/package.json index e2d658f..4f0ff3b 100644 --- a/package.json +++ b/package.json @@ -28,9 +28,13 @@ "clean:node": "rm -rf node_modules" }, "dependencies": { - "type-fest": "^4.9.0" + "effect": "^2.0.0-next.62", + "lodash-es": "^4.17.21", + "type-fest": "^4.9.0", + "zod": "^3.22.4" }, "devDependencies": { + "@types/lodash-es": "^4.17.12", "bun-types": "latest", "npm-check-updates": "^16.14.12", "npm-sort": "^0.0.4", diff --git a/src/index.ts b/src/index.ts index 8351eca..e69de29 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,195 +0,0 @@ -import { AbstractClass, AbstractConstructor, Opaque, UnionToIntersection } from "type-fest" - - -/** - * Represents the static members of a class. - * @template C - The class type. - */ -export type StaticMembers = { - [Key in keyof C as Key extends "prototype" ? never : Key]: C[Key] -} - - -/** - * Represents a trait that can be applied to a class. - * @template C - The abstract class type. - */ -export type Trait< - C extends AbstractClass -> = Opaque< - TraitApplier, - "thilatrait/Trait" -> - -/** - * Represents the function signature for applying a trait to a parent class. - * @template C - The abstract class type. - */ -export type TraitApplier< - C extends AbstractClass -> = - (Parent: AbstractConstructor) => C - -/** - * Unwraps the type of the class from a given trait. - * @template T - The trait type. - */ -export type UnwrapTraitC = - T extends Trait - ? C - : never - - -/** - * Creates a trait using the provided trait applier function. - * @template C - The abstract class type. - * @param applier - The trait applier function. - * @returns A trait. - * @example - * Creates a trait: - * ```ts - * const Permissible = trait(Parent => { - * abstract class Permissible extends Parent { - * static readonly defaultPermissions: string[] = [] - * permissions: string[] = [] - * - * // Constructor is optional - * // If you wish to use it, make sure it takes any[] as an args array and passes it to the super call. This is necessary for inheritance to work properly. - * // Trait constructors cannot have typed arguments of their own, they only serve to run logic during object instantiation. - * constructor(...args: any[]) { - * super(...args) - * } - * } - * - * return Permissible - * }) - * ``` - * Creates a generic trait: - * ```ts - * const Identifiable = () => - * trait(Parent => { - * abstract class Identifiable extends Parent { - * abstract readonly id: ID - * - * equals(el: Identifiable) { - * return this.id === el.id - * } - * - * // Optional - * constructor(...args: any[]) { - * super(...args) - * } - * } - * - * return Identifiable - * }) - * ``` - * Creates a subtrait: - * ```ts - * const ImplementsIdentifiable = (defaultID: ID) => - * trait(Parent => { - * abstract class ImplementsIdentifiable extends extendsAndExpresses( - * Parent, - * [Identifiable()], - * ) { - * id: ID = defaultID - * - * // Optional - * constructor(...args: any[]) { - * super(...args) - * } - * } - * - * return ImplementsIdentifiable - * }) - * ``` - */ -export function trait< - C extends AbstractClass ->( - applier: TraitApplier -) { - return applier as Trait -} - - -/** - * Extends a class with the given traits and expresses their combined functionality. - * @template C - The abstract class type. - * @template Traits - An array of traits. - * @param extend - The class to extend. - * @param traits - An array of traits to apply. - * @returns A new class type expressing the combined functionality of the base class and traits. - * @example - * Extends a superclass and applies traits: - * ```ts - * class User extends extendsAndExpresses(Entity, [Identifiable(), Permissible]) { - * readonly id: bigint - * - * constructor(id: bigint) { - * super() - * this.id = id - * } - * } - * ``` - */ -export function extendsAndExpresses< - C extends AbstractClass, - Traits extends readonly Trait[], ->( - extend: C, - traits: Traits, -) { - return traits.reduce( - (previous, trait) => trait(previous), - extend, - ) as ( - AbstractClass< - InstanceType & - UnionToIntersection< - InstanceType< - UnwrapTraitC< - Traits[number] - > - > - >, - - ConstructorParameters - > & - - StaticMembers & - StaticMembers< - UnionToIntersection< - UnwrapTraitC< - Traits[number] - > - > - > - ) -} - -/** - * Expresses the combined functionality of multiple traits. - * @template Traits - An array of trait. - * @param traits - An array of trait to apply. - * @returns A new class type expressing the combined functionality of the traits. - * @example - * Applies traits to a class: - * ```ts - * class User extends expresses(Identifiable(), Permissible) { - * readonly id: bigint - * - * constructor(id: bigint) { - * super() - * this.id = id - * } - * } - * ``` - */ -export function expresses< - Traits extends readonly Trait[], ->( - ...traits: Traits -) { - return extendsAndExpresses(Object, traits) -} diff --git a/src/legacy/tests.ts b/src/legacy/tests.ts deleted file mode 100644 index e86528d..0000000 --- a/src/legacy/tests.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { AbstractClass } from "type-fest" -import { expresses } from "./trait" - - -function inspectClass(class_: AbstractClass) { - Object.getOwnPropertyNames(class_).forEach(name => { - console.log( - "[static]", - name, - Object.getOwnPropertyDescriptor(class_, name) - ) - }) - - Object.getOwnPropertyNames(class_.prototype).forEach(name => { - console.log( - "[prototype]", - name, - Object.getOwnPropertyDescriptor(class_.prototype, name) - ) - }) -} - - -abstract class Identified { - abstract id: ID - - equals(el: Identified) { - return this.id === el.id - } - - // initializer() { - // console.log("Identified initializer") - // } -} - -class ImplementsIdentifiable extends Identified { - id!: ID -} - - -abstract class Permissible { - static readonly defaultPermissions: string[] = [] - permissions: string[] = [] - // permissions!: string[] - - constructor() { - console.log("Permissible constructor") - } - - initializer() { - console.log("Permissible initializer") - this.permissions = [] - } -} - - -class User extends expresses( - Identified as typeof Identified, - // Identified, - Permissible, -) { - readonly id: bigint - - constructor(id: bigint) { - super() - this.id = id - } -} - -const user1 = new User(BigInt(1)) -const user2 = new User(BigInt(2)) - -console.log(user1) -console.log(user1.equals(user2)) diff --git a/src/legacy/trait.ts b/src/legacy/trait.ts deleted file mode 100644 index 10cc87b..0000000 --- a/src/legacy/trait.ts +++ /dev/null @@ -1,126 +0,0 @@ -import { AbstractClass, Class, UnionToIntersection } from "type-fest" -import { StaticMembers, copyProperties, getInheritanceHierarchy } from "./util/class" - - -/** - * Represents a trait that can be used to define common behavior - * for classes and abstract classes. - * @typeParam T - The type of the trait. - */ -export type Trait = - AbstractClass - - -/** - * Creates a link class that expresses the given traits. - * @param traits - An array of traits to be expressed by the link class. - * @returns A dynamically created class that expresses the given traits. - * @typeParam Traits - An array of traits that the link class expresses. - */ -export function expresses< - Traits extends readonly Trait[] ->( - ...traits: Traits -) { - return makeLinkClass(traits) -} - - -/** - * Creates a link class that extends a base class and expresses the given traits. - * @param extend - The base class or abstract class to extend. - * @param traits - An array of traits to be expressed by the link class. - * @returns A dynamically created class that extends the given base class and expresses the given traits. - * @typeParam C - The type of the base class to extend. - * @typeParam Traits - An array of traits that the link class expresses. - */ -export function extendsAndExpresses< - C extends Class - | AbstractClass, - Traits extends readonly Trait[], ->( - extend: C, - ...traits: Traits -) { - return makeLinkClass(traits, extend) -} - - -/** - * Creates a link class that expresses the given traits and optionally extends a base class. - * @param traits - An array of traits to be expressed by the link class. - * @param extend - The base class or abstract class to extend (optional). - * @returns A dynamically created class that expresses the given traits and extends the base class. - * @typeParam Traits - An array of traits that the link class expresses. - * @typeParam C - The type of the base class to extend (optional). - */ -export function makeLinkClass< - Traits extends readonly Trait[], - C extends Class - | AbstractClass - | undefined = undefined, ->( - traits: Traits, - extend?: C, -) { - const class_ = extend - ? class extends extend { - constructor(...args: any[]) { - super(...args) - - traits.forEach(trait => { - trait.prototype.initializer?.call(this) - }) - } - } - : class { - constructor() { - traits.forEach(trait => { - trait.prototype.initializer?.call(this) - }) - } - } - - traits.forEach(trait => { - getInheritanceHierarchy(trait).forEach(current => { - copyProperties( - current, - class_, - ["name", "length"], - ["constructor"], - ) - }) - }) - - return class_ as unknown as ( - (C extends Class | AbstractClass - ? ( - AbstractClass< - InstanceType & - UnionToIntersection< - InstanceType< - Traits[number] - > - >, - - ConstructorParameters - > & - - StaticMembers - ) - : Trait< - UnionToIntersection< - InstanceType< - Traits[number] - > - > - > - ) & - - StaticMembers< - UnionToIntersection< - Traits[number] - > - > - ) -} diff --git a/src/legacy/util/class.ts b/src/legacy/util/class.ts deleted file mode 100644 index 518c960..0000000 --- a/src/legacy/util/class.ts +++ /dev/null @@ -1,109 +0,0 @@ -import { AbstractClass } from "type-fest" - - -/** - * Represents the static members of a class. - * - * @template C - The type of the class for which static members are extracted. - * @typeparam The static members of the class. - */ -export type StaticMembers = Pick - - -/** - * Flattens the inheritance hierarchy of a given class by copying all properties - * from its superclass chain into a single object. - * - * @template C - The type of the class to be flattened, extending AbstractClass. - * @param C - The class to be flattened. - * @returns A new class with properties flattened from the entire inheritance hierarchy. - */ -export function flattenClass< - C extends AbstractClass ->(class_: C) { - const flattenedClass = class {} as unknown as C - - getInheritanceHierarchy(class_).forEach(current => { - copyProperties(current, flattenedClass) - }) - - copyProperty(class_, flattenedClass, "name") - copyProperty(class_.prototype, flattenedClass.prototype, "constructor") - - return flattenedClass -} - - -/** - * Retrieves the inheritance hierarchy of a given class, including itself. - * - * @param class_ - The class for which the inheritance hierarchy is retrieved. - * @returns An array representing the inheritance hierarchy, ordered from the furthest in the hierarchy to `class_` itself. - */ -export function getInheritanceHierarchy( - class_: AbstractClass -): AbstractClass[] { - const parent = Object.getPrototypeOf(class_) - - return isClass(parent) - ? [...getInheritanceHierarchy(parent), class_] - : [class_] -} - - -/** - * Checks if a given element appears to be a class based on its string representation. - * - * @param el - The element to check for being a class. - * @returns `true` if the element is likely a class; otherwise, `false`. - */ -export function isClass(el: { toString: () => string }) { - return Boolean(el.toString().match(/^class(?: [.\S]+)?(?: extends [.\S]+)? {[\s\S]*}$/)) -} - - -/** - * Copies properties from one class to another, including static and prototype properties. - * - * @param from - The source class to copy properties from. - * @param to - The destination class to copy properties to. - */ -export function copyProperties( - from: AbstractClass, - to: AbstractClass, - ignoreKeys: string[] = [], - ignorePrototypeKeys: string[] = [], -) { - Object.getOwnPropertyNames(from).forEach(name => { - if (name === "prototype" - || ignoreKeys.find(v => v === name) - ) - return - - // console.log(from, to, name, Object.getOwnPropertyDescriptor(from, name)) - - copyProperty(from, to, name) - }) - - Object.getOwnPropertyNames(from.prototype).forEach(name => { - if (ignorePrototypeKeys.find(v => v === name)) - return - - // console.log(from, to, name, Object.getOwnPropertyDescriptor(from, name)) - - copyProperty(from.prototype, to.prototype, name) - }) -} - - -export function copyProperty( - from: unknown, - to: unknown, - name: string, -) { - Object.defineProperty( - to, - name, - Object.getOwnPropertyDescriptor(from, name) || Object.create(null), - ) -} diff --git a/src/tests.ts b/src/tests.ts deleted file mode 100644 index bb49d1f..0000000 --- a/src/tests.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { expresses, extendsAndExpresses, trait } from "." - - -const Identifiable = () => - trait(Parent => { - abstract class Identifiable extends Parent { - abstract readonly id: ID - - equals(el: Identifiable) { - return this.id === el.id - } - - constructor(...args: any[]) { - super(...args) - console.log("Identified constructor") - } - } - - return Identifiable - }) - -const ImplementsIdentifiable = (defaultID: ID) => - trait(Parent => { - abstract class ImplementsIdentifiable extends extendsAndExpresses( - Parent, - [Identifiable()], - ) { - id: ID = defaultID - - constructor(...args: any[]) { - super(...args) - console.log("ImplementsIdentifiable constructor") - } - } - - return ImplementsIdentifiable - }) - - -const Permissible = trait(Parent => { - abstract class Permissible extends Parent { - static readonly defaultPermissions: string[] = [] - permissions: string[] = [] - - constructor(...args: any[]) { - super(...args) - console.log("Permissible constructor") - } - } - - return Permissible -}) - - -const UserProto = expresses( - // Identifiable(), - ImplementsIdentifiable(0n), - Permissible, -) - -class User extends UserProto { - constructor(id: bigint) { - super() - this.id = id - } -} - -const user1 = new User(1n) -console.log(user1) -console.log(user1.equals(user1)) diff --git a/src/util.ts b/src/util.ts new file mode 100644 index 0000000..7ab75c7 --- /dev/null +++ b/src/util.ts @@ -0,0 +1,73 @@ +import { Effect, pipe } from "effect" +import { mapValues } from "lodash-es" +import { z } from "zod" + + +/** + * Removes default values from a ZodObject schema and returns a new schema. + * + * @param schema - The ZodObject schema to process. + * @returns A new ZodObject schema with default values removed. + */ +export const zodObjectRemoveDefaults = < + T extends z.ZodRawShape, + UnknownKeys extends z.UnknownKeysParam, + Catchall extends z.ZodTypeAny, + Output extends {}, + Input extends {}, +>( + schema: z.ZodObject< + T, + UnknownKeys, + Catchall, + Output, + Input + > +) => + schema.extend(zodShapeRemoveDefaults(schema.shape)) + +/** + * Removes default values from a ZodObject shape and returns a new shape. + * + * @param shape - The ZodObject shape to process. + * @returns A new shape with default values removed. + */ +export const zodShapeRemoveDefaults = < + Shape extends z.ZodRawShape +>( + shape: Shape +): { + [K in keyof Shape]: + Shape[K] extends z.ZodDefault + ? T + : Shape[K] +} => + mapValues(shape, el => + el instanceof z.ZodDefault + ? el.removeDefault() + : el + ) + + +/** + * Parses a value using a ZodType schema wrapped in an Effect monad. + * + * @param schema - The ZodType schema to use for parsing. + * @param args - The arguments to pass to the `safeParseAsync` method of the schema. + * @returns An Effect monad representing the parsing result. + */ +export const parseZodTypeEffect = < + Output, + Input, +>( + schema: z.ZodType, + ...args: Parameters +) => pipe( + Effect.promise(() => schema.safeParseAsync(...args)), + + Effect.flatMap(response => + response.success + ? Effect.succeed(response.data) + : Effect.fail(response.error) + ), +) -- 2.49.1 From 54de41cf97d4da290a01412c83d92f6af3908d43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Sat, 30 Dec 2023 03:32:36 +0100 Subject: [PATCH 03/24] makeSchemaClass --- bun.lockb | Bin 150218 -> 150232 bytes src/index.ts | 1 + src/makeSchemaClass.ts | 48 +++++++++++++++++++++++++++++++++++++++++ src/tests.ts | 14 ++++++++++++ src/util.ts | 9 ++++++++ 5 files changed, 72 insertions(+) create mode 100644 src/makeSchemaClass.ts create mode 100644 src/tests.ts diff --git a/bun.lockb b/bun.lockb index 692b0f6e2e5e15465484758c10d9eb64860dd447..c02ea2e3fb71feee257f82c5cd59dd9893eb69c1 100755 GIT binary patch delta 12943 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 + { + schema: schemaWithDefaultValues + }: { + schema: z.ZodObject< + SchemaWithDefaultValuesT, + SchemaWithDefaultValuesUnknownKeys, + SchemaWithDefaultValuesCatchall, + SchemaWithDefaultValuesOutput, + SchemaWithDefaultValuesInput + > + } +) { + + const schema = zodObjectRemoveDefaults(schemaWithDefaultValues) + + class SchemaObject { + static readonly schema = schema + static readonly schemaWithDefaultValues = schemaWithDefaultValues + + readonly schema = schema + readonly schemaWithDefaultValues = schemaWithDefaultValues + + constructor(data: z.output) { + Object.assign(this, data) + } + } + + return SchemaObject as ( + Class< + SchemaObject & z.output, + ConstructorParameters + > & + StaticMembers + ) + +} diff --git a/src/tests.ts b/src/tests.ts new file mode 100644 index 0000000..1c2b569 --- /dev/null +++ b/src/tests.ts @@ -0,0 +1,14 @@ +import { z } from "zod" +import { makeSchemaClass } from "./makeSchemaClass" + + +const UserSchema = z.object({ + /** User ID */ + id: z.bigint().default(-1n) +}) + + +const UserSchemaObject = makeSchemaClass({ schema: UserSchema }) + +const user = new UserSchemaObject({ id: 1n }) +user.id diff --git a/src/util.ts b/src/util.ts index 7ab75c7..2cf7b08 100644 --- a/src/util.ts +++ b/src/util.ts @@ -3,6 +3,15 @@ import { mapValues } from "lodash-es" import { z } from "zod" +/** + * Represents the static members of a class. + * @template C - The class type. + */ +export type StaticMembers = { + [Key in keyof C as Key extends "prototype" ? never : Key]: C[Key] +} + + /** * Removes default values from a ZodObject schema and returns a new schema. * -- 2.49.1 From caa8f9d2be4367158987157975e042913c0f0aa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Sat, 30 Dec 2023 23:19:12 +0100 Subject: [PATCH 04/24] SchemaClass --- src/SchemaClass.ts | 86 ++++++++++++++++++++++++++++++++++++++++++ src/index.ts | 1 + src/makeSchemaClass.ts | 10 ++--- src/tests.ts | 6 ++- 4 files changed, 96 insertions(+), 7 deletions(-) create mode 100644 src/SchemaClass.ts diff --git a/src/SchemaClass.ts b/src/SchemaClass.ts new file mode 100644 index 0000000..478adf4 --- /dev/null +++ b/src/SchemaClass.ts @@ -0,0 +1,86 @@ +import { Class } from "type-fest" +import { z } from "zod" + + +export type SchemaClass< + Values extends {} = {}, + Input extends {} = {}, + + SchemaT extends z.ZodRawShape = z.ZodRawShape, + SchemaUnknownKeys extends z.UnknownKeysParam = z.UnknownKeysParam, + SchemaCatchall extends z.ZodTypeAny = z.ZodTypeAny, + + SchemaWithDefaultValuesT extends z.ZodRawShape = z.ZodRawShape, + SchemaWithDefaultValuesUnknownKeys extends z.UnknownKeysParam = z.UnknownKeysParam, + SchemaWithDefaultValuesCatchall extends z.ZodTypeAny = z.ZodTypeAny, +> = ( + Class< + SchemaObject< + Values, + Input, + + SchemaT, + SchemaUnknownKeys, + SchemaCatchall, + + SchemaWithDefaultValuesT, + SchemaWithDefaultValuesUnknownKeys, + SchemaWithDefaultValuesCatchall + >, + + SchemaClassConstructorParams + > & { + readonly schema: z.ZodObject< + SchemaT, + SchemaUnknownKeys, + SchemaCatchall, + Values, + Values + > + + readonly schemaWithDefaultValues: z.ZodObject< + SchemaWithDefaultValuesT, + SchemaWithDefaultValuesUnknownKeys, + SchemaWithDefaultValuesCatchall, + Values, + Input + > + } +) + +export type SchemaClassConstructorParams< + Values extends {} = {} +> = ( + Parameters< + (data: Values) => void + > +) + +export type SchemaObject< + Values extends {} = {}, + Input extends {} = {}, + + SchemaT extends z.ZodRawShape = z.ZodRawShape, + SchemaUnknownKeys extends z.UnknownKeysParam = z.UnknownKeysParam, + SchemaCatchall extends z.ZodTypeAny = z.ZodTypeAny, + + SchemaWithDefaultValuesT extends z.ZodRawShape = z.ZodRawShape, + SchemaWithDefaultValuesUnknownKeys extends z.UnknownKeysParam = z.UnknownKeysParam, + SchemaWithDefaultValuesCatchall extends z.ZodTypeAny = z.ZodTypeAny, +> = { + readonly schema: z.ZodObject< + SchemaT, + SchemaUnknownKeys, + SchemaCatchall, + Values, + Values + > + + readonly schemaWithDefaultValues: z.ZodObject< + SchemaWithDefaultValuesT, + SchemaWithDefaultValuesUnknownKeys, + SchemaWithDefaultValuesCatchall, + Values, + Input + > +} & Values diff --git a/src/index.ts b/src/index.ts index 8038132..9877e90 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1 +1,2 @@ +export * from "./SchemaClass" export * from "./makeSchemaClass" diff --git a/src/makeSchemaClass.ts b/src/makeSchemaClass.ts index caf104a..e14a3fa 100644 --- a/src/makeSchemaClass.ts +++ b/src/makeSchemaClass.ts @@ -25,7 +25,7 @@ export function makeSchemaClass< const schema = zodObjectRemoveDefaults(schemaWithDefaultValues) - class SchemaObject { + const class_ = class { static readonly schema = schema static readonly schemaWithDefaultValues = schemaWithDefaultValues @@ -37,12 +37,12 @@ export function makeSchemaClass< } } - return SchemaObject as ( + return class_ as ( Class< - SchemaObject & z.output, - ConstructorParameters + InstanceType & z.output, + ConstructorParameters > & - StaticMembers + StaticMembers ) } diff --git a/src/tests.ts b/src/tests.ts index 1c2b569..5b7ee67 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -10,5 +10,7 @@ const UserSchema = z.object({ const UserSchemaObject = makeSchemaClass({ schema: UserSchema }) -const user = new UserSchemaObject({ id: 1n }) -user.id +class User extends UserSchemaObject {} + +const user = new User({ id: 1n }) +user.schema -- 2.49.1 From 5704fd817dc27a00975e239c3b02fd0d53a632ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Sat, 30 Dec 2023 23:51:03 +0100 Subject: [PATCH 05/24] SchemaClass comments --- src/SchemaClass.ts | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/SchemaClass.ts b/src/SchemaClass.ts index 478adf4..f009d1f 100644 --- a/src/SchemaClass.ts +++ b/src/SchemaClass.ts @@ -2,6 +2,18 @@ import { Class } from "type-fest" import { z } from "zod" +/** + * Represents a schema class with generic parameters for defining validation schemas. + * + * @template Values - The type of values expected by the schema. + * @template Input - The type of input data expected by the schema. + * @template SchemaT - The type of the raw shape of the schema. + * @template SchemaUnknownKeys - The type of unknown keys parameter for the schema. + * @template SchemaCatchall - The type of catchall parameter for the schema. + * @template SchemaWithDefaultValuesT - The type of the raw shape for default values schema. + * @template SchemaWithDefaultValuesUnknownKeys - The type of unknown keys parameter for default values schema. + * @template SchemaWithDefaultValuesCatchall - The type of catchall parameter for default values schema. + */ export type SchemaClass< Values extends {} = {}, Input extends {} = {}, @@ -48,6 +60,11 @@ export type SchemaClass< } ) +/** + * Represents the constructor parameters for a schema class. + * + * @template Values - The type of values expected by the schema. + */ export type SchemaClassConstructorParams< Values extends {} = {} > = ( @@ -56,6 +73,18 @@ export type SchemaClassConstructorParams< > ) +/** + * Represents a schema object with generic parameters for defining validation schemas. + * + * @template Values - The type of values expected by the schema. + * @template Input - The type of input data expected by the schema. + * @template SchemaT - The type of the raw shape of the schema. + * @template SchemaUnknownKeys - The type of unknown keys parameter for the schema. + * @template SchemaCatchall - The type of catchall parameter for the schema. + * @template SchemaWithDefaultValuesT - The type of the raw shape for default values schema. + * @template SchemaWithDefaultValuesUnknownKeys - The type of unknown keys parameter for default values schema. + * @template SchemaWithDefaultValuesCatchall - The type of catchall parameter for default values schema. + */ export type SchemaObject< Values extends {} = {}, Input extends {} = {}, -- 2.49.1 From 737cb781e6982a67cf74a17f838b1541bb16049a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Sun, 31 Dec 2023 00:37:30 +0100 Subject: [PATCH 06/24] SchemaClass work --- src/SchemaClass.ts | 141 +++++++++++++++++++-------------------------- 1 file changed, 58 insertions(+), 83 deletions(-) diff --git a/src/SchemaClass.ts b/src/SchemaClass.ts index f009d1f..962f622 100644 --- a/src/SchemaClass.ts +++ b/src/SchemaClass.ts @@ -3,89 +3,17 @@ import { z } from "zod" /** - * Represents a schema class with generic parameters for defining validation schemas. - * - * @template Values - The type of values expected by the schema. - * @template Input - The type of input data expected by the schema. - * @template SchemaT - The type of the raw shape of the schema. - * @template SchemaUnknownKeys - The type of unknown keys parameter for the schema. - * @template SchemaCatchall - The type of catchall parameter for the schema. - * @template SchemaWithDefaultValuesT - The type of the raw shape for default values schema. - * @template SchemaWithDefaultValuesUnknownKeys - The type of unknown keys parameter for default values schema. - * @template SchemaWithDefaultValuesCatchall - The type of catchall parameter for default values schema. + * Configuration for creating a schemable object with validation schemas. + * @template Values - The type representing the expected values. + * @template Input - The type representing the input values. + * @template SchemaT - The type representing the base validation schema. + * @template SchemaUnknownKeys - The type representing the unknown keys behavior in the base validation schema. + * @template SchemaCatchall - The type representing the catchall behavior in the base validation schema. + * @template SchemaWithDefaultValuesT - The type representing the validation schema with default values. + * @template SchemaWithDefaultValuesUnknownKeys - The type representing the unknown keys behavior in the validation schema with default values. + * @template SchemaWithDefaultValuesCatchall - The type representing the catchall behavior in the validation schema with default values. */ -export type SchemaClass< - Values extends {} = {}, - Input extends {} = {}, - - SchemaT extends z.ZodRawShape = z.ZodRawShape, - SchemaUnknownKeys extends z.UnknownKeysParam = z.UnknownKeysParam, - SchemaCatchall extends z.ZodTypeAny = z.ZodTypeAny, - - SchemaWithDefaultValuesT extends z.ZodRawShape = z.ZodRawShape, - SchemaWithDefaultValuesUnknownKeys extends z.UnknownKeysParam = z.UnknownKeysParam, - SchemaWithDefaultValuesCatchall extends z.ZodTypeAny = z.ZodTypeAny, -> = ( - Class< - SchemaObject< - Values, - Input, - - SchemaT, - SchemaUnknownKeys, - SchemaCatchall, - - SchemaWithDefaultValuesT, - SchemaWithDefaultValuesUnknownKeys, - SchemaWithDefaultValuesCatchall - >, - - SchemaClassConstructorParams - > & { - readonly schema: z.ZodObject< - SchemaT, - SchemaUnknownKeys, - SchemaCatchall, - Values, - Values - > - - readonly schemaWithDefaultValues: z.ZodObject< - SchemaWithDefaultValuesT, - SchemaWithDefaultValuesUnknownKeys, - SchemaWithDefaultValuesCatchall, - Values, - Input - > - } -) - -/** - * Represents the constructor parameters for a schema class. - * - * @template Values - The type of values expected by the schema. - */ -export type SchemaClassConstructorParams< - Values extends {} = {} -> = ( - Parameters< - (data: Values) => void - > -) - -/** - * Represents a schema object with generic parameters for defining validation schemas. - * - * @template Values - The type of values expected by the schema. - * @template Input - The type of input data expected by the schema. - * @template SchemaT - The type of the raw shape of the schema. - * @template SchemaUnknownKeys - The type of unknown keys parameter for the schema. - * @template SchemaCatchall - The type of catchall parameter for the schema. - * @template SchemaWithDefaultValuesT - The type of the raw shape for default values schema. - * @template SchemaWithDefaultValuesUnknownKeys - The type of unknown keys parameter for default values schema. - * @template SchemaWithDefaultValuesCatchall - The type of catchall parameter for default values schema. - */ -export type SchemaObject< +export type SchemableConfig< Values extends {} = {}, Input extends {} = {}, @@ -97,6 +25,9 @@ export type SchemaObject< SchemaWithDefaultValuesUnknownKeys extends z.UnknownKeysParam = z.UnknownKeysParam, SchemaWithDefaultValuesCatchall extends z.ZodTypeAny = z.ZodTypeAny, > = { + readonly values: Values + readonly input: Input + readonly schema: z.ZodObject< SchemaT, SchemaUnknownKeys, @@ -112,4 +43,48 @@ export type SchemaObject< Values, Input > -} & Values +} + + +/** + * Represents a class with validation schemas. + * @template $Config - The configuration type for the schemable object. + */ +export type SchemaClass< + $Config extends SchemableConfig +> = ( + Class< + SchemaObject<$Config>, + SchemaClassConstructorParams<$Config> + > & { + readonly $schemableConfig: $Config + readonly schema: $Config["schema"] + readonly schemaWithDefaultValues: $Config["schemaWithDefaultValues"] + } +) + +/** + * Represents the constructor parameters for the schemable object class. + * @template $Config - The configuration type for the schemable object. + */ +export type SchemaClassConstructorParams< + $Config extends SchemableConfig +> = ( + Parameters< + (data: $Config["values"]) => void + > +) + +/** + * Represents an object with validation schemas. + * @template $Config - The configuration type for the schemable object. + */ +export type SchemaObject< + $Config extends SchemableConfig +> = ( + { + readonly $schemableConfig: $Config + readonly schema: $Config["schema"] + readonly schemaWithDefaultValues: $Config["schemaWithDefaultValues"] + } & $Config["values"] +) -- 2.49.1 From 9552a7f709b561868478a20bb4675b580fd19e7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Sun, 31 Dec 2023 00:48:02 +0100 Subject: [PATCH 07/24] SchemaClass -> SchemableClass --- src/{SchemaClass.ts => SchemableClass.ts} | 10 +++++----- src/newSchemable.ts | 17 +++++++++++++++++ 2 files changed, 22 insertions(+), 5 deletions(-) rename src/{SchemaClass.ts => SchemableClass.ts} (94%) create mode 100644 src/newSchemable.ts diff --git a/src/SchemaClass.ts b/src/SchemableClass.ts similarity index 94% rename from src/SchemaClass.ts rename to src/SchemableClass.ts index 962f622..f85216c 100644 --- a/src/SchemaClass.ts +++ b/src/SchemableClass.ts @@ -50,12 +50,12 @@ export type SchemableConfig< * Represents a class with validation schemas. * @template $Config - The configuration type for the schemable object. */ -export type SchemaClass< +export type SchemableClass< $Config extends SchemableConfig > = ( Class< - SchemaObject<$Config>, - SchemaClassConstructorParams<$Config> + SchemableObject<$Config>, + SchemableClassConstructorParams<$Config> > & { readonly $schemableConfig: $Config readonly schema: $Config["schema"] @@ -67,7 +67,7 @@ export type SchemaClass< * Represents the constructor parameters for the schemable object class. * @template $Config - The configuration type for the schemable object. */ -export type SchemaClassConstructorParams< +export type SchemableClassConstructorParams< $Config extends SchemableConfig > = ( Parameters< @@ -79,7 +79,7 @@ export type SchemaClassConstructorParams< * Represents an object with validation schemas. * @template $Config - The configuration type for the schemable object. */ -export type SchemaObject< +export type SchemableObject< $Config extends SchemableConfig > = ( { diff --git a/src/newSchemable.ts b/src/newSchemable.ts new file mode 100644 index 0000000..26482a6 --- /dev/null +++ b/src/newSchemable.ts @@ -0,0 +1,17 @@ +type ParamsArgs = [] | [Partial] + +type NewEntityArgs = + HasRequiredKeys extends true + ? [Input, ...ParamsArgs] + : [] | [Input, ...ParamsArgs] + + +export const newEntity = < + $Config extends EntityConfig, + Static extends EntityClassStatic<$Config>, + T extends Entity<$Config>, +>( + class_: EntityClass<$Config, Static, T>, + ...[values, params]: NewEntityArgs<$Config["input"]> +) => + new class_(class_.schemaWithDefaultValues.parse(values || {}, params)) -- 2.49.1 From d0b5018ad5684ec312237f24dfba5586a87f1fbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Sun, 31 Dec 2023 00:48:42 +0100 Subject: [PATCH 08/24] Fix --- src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index 9877e90..379ba4d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,2 +1,2 @@ -export * from "./SchemaClass" +export * from "./SchemableClass" export * from "./makeSchemaClass" -- 2.49.1 From fcacd8566daaa06bfbaeac4ee16a0545d2756e64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Sun, 31 Dec 2023 01:19:31 +0100 Subject: [PATCH 09/24] makeSchemableClass refactoring --- src/index.ts | 2 +- ...keSchemaClass.ts => makeSchemableClass.ts} | 31 ++++++++++--------- src/newSchemable.ts | 14 ++++++--- src/tests.ts | 9 +++--- 4 files changed, 31 insertions(+), 25 deletions(-) rename src/{makeSchemaClass.ts => makeSchemableClass.ts} (59%) diff --git a/src/index.ts b/src/index.ts index 379ba4d..a850a00 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,2 +1,2 @@ export * from "./SchemableClass" -export * from "./makeSchemaClass" +export * from "./makeSchemableClass" diff --git a/src/makeSchemaClass.ts b/src/makeSchemableClass.ts similarity index 59% rename from src/makeSchemaClass.ts rename to src/makeSchemableClass.ts index e14a3fa..f0fd976 100644 --- a/src/makeSchemaClass.ts +++ b/src/makeSchemableClass.ts @@ -1,9 +1,9 @@ -import { Class } from "type-fest" import { z } from "zod" -import { StaticMembers, zodObjectRemoveDefaults } from "./util" +import { SchemableClass, SchemableConfig } from "." +import { zodObjectRemoveDefaults } from "./util" -export function makeSchemaClass< +export function makeSchemableClass< SchemaWithDefaultValuesT extends z.ZodRawShape, SchemaWithDefaultValuesUnknownKeys extends z.UnknownKeysParam, SchemaWithDefaultValuesCatchall extends z.ZodTypeAny, @@ -25,24 +25,25 @@ export function makeSchemaClass< const schema = zodObjectRemoveDefaults(schemaWithDefaultValues) - const class_ = class { - static readonly schema = schema + const $schemableConfig = { + values: {} as z.output, + input: {} as z.input, + schema, + schemaWithDefaultValues, + } as const satisfies SchemableConfig + + return class { + static readonly $schemableConfig = $schemableConfig + static readonly schema = schema static readonly schemaWithDefaultValues = schemaWithDefaultValues - readonly schema = schema + readonly $schemableConfig = $schemableConfig + readonly schema = schema readonly schemaWithDefaultValues = schemaWithDefaultValues constructor(data: z.output) { Object.assign(this, data) } - } - - return class_ as ( - Class< - InstanceType & z.output, - ConstructorParameters - > & - StaticMembers - ) + } as SchemableClass } diff --git a/src/newSchemable.ts b/src/newSchemable.ts index 26482a6..873d667 100644 --- a/src/newSchemable.ts +++ b/src/newSchemable.ts @@ -1,3 +1,8 @@ +import { HasRequiredKeys } from "type-fest" +import { z } from "zod" +import { SchemableClass, SchemableConfig } from "." + + type ParamsArgs = [] | [Partial] type NewEntityArgs = @@ -6,12 +11,11 @@ type NewEntityArgs = : [] | [Input, ...ParamsArgs] -export const newEntity = < - $Config extends EntityConfig, - Static extends EntityClassStatic<$Config>, - T extends Entity<$Config>, +export const newSchemable = < + C extends SchemableClass<$Config>, + $Config extends SchemableConfig, >( - class_: EntityClass<$Config, Static, T>, + class_: C | SchemableClass<$Config>, ...[values, params]: NewEntityArgs<$Config["input"]> ) => new class_(class_.schemaWithDefaultValues.parse(values || {}, params)) diff --git a/src/tests.ts b/src/tests.ts index 5b7ee67..29278e0 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -1,5 +1,6 @@ import { z } from "zod" -import { makeSchemaClass } from "./makeSchemaClass" +import { makeSchemableClass } from "." +import { newSchemable } from "./newSchemable" const UserSchema = z.object({ @@ -8,9 +9,9 @@ const UserSchema = z.object({ }) -const UserSchemaObject = makeSchemaClass({ schema: UserSchema }) +const UserSchemaObject = makeSchemableClass({ schema: UserSchema }) class User extends UserSchemaObject {} -const user = new User({ id: 1n }) -user.schema +const user1 = new User({ id: 1n }) +const user2 = newSchemable(User) -- 2.49.1 From a8e2fe74745731757c111b133c5145d2734093aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Sun, 31 Dec 2023 01:32:59 +0100 Subject: [PATCH 10/24] newSchemable work --- src/index.ts | 1 + src/newSchemable.ts | 36 +++++++++++++++++++++++++++++++++--- src/tests.ts | 3 +-- 3 files changed, 35 insertions(+), 5 deletions(-) diff --git a/src/index.ts b/src/index.ts index a850a00..17d8b56 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,2 +1,3 @@ export * from "./SchemableClass" export * from "./makeSchemableClass" +export * from "./newSchemable" diff --git a/src/newSchemable.ts b/src/newSchemable.ts index 873d667..955d0f3 100644 --- a/src/newSchemable.ts +++ b/src/newSchemable.ts @@ -1,11 +1,13 @@ +import { Effect, pipe } from "effect" import { HasRequiredKeys } from "type-fest" import { z } from "zod" import { SchemableClass, SchemableConfig } from "." +import { parseZodTypeEffect } from "./util" type ParamsArgs = [] | [Partial] -type NewEntityArgs = +type NewSchemableArgs = HasRequiredKeys extends true ? [Input, ...ParamsArgs] : [] | [Input, ...ParamsArgs] @@ -16,6 +18,34 @@ export const newSchemable = < $Config extends SchemableConfig, >( class_: C | SchemableClass<$Config>, - ...[values, params]: NewEntityArgs<$Config["input"]> + ...[values, params]: NewSchemableArgs<$Config["input"]> ) => - new class_(class_.schemaWithDefaultValues.parse(values || {}, params)) + new class_(class_.schemaWithDefaultValues.parse(values || {}, params)) as InstanceType + +export const newSchemablePromise = async < + C extends SchemableClass<$Config>, + $Config extends SchemableConfig, +>( + class_: C | SchemableClass<$Config>, + ...[values, params]: NewSchemableArgs<$Config["input"]> +) => + new class_(await class_.schemaWithDefaultValues.parseAsync(values || {}, params)) as InstanceType + +export const newSchemableEffect = < + C extends SchemableClass<$Config>, + $Config extends SchemableConfig, +>( + class_: C | SchemableClass<$Config>, + ...[values, params]: NewSchemableArgs<$Config["input"]> +) => pipe( + parseZodTypeEffect< + z.output, + z.input + >( + class_.schemaWithDefaultValues, + values || {}, + params, + ), + + Effect.map(values => new class_(values) as InstanceType), +) diff --git a/src/tests.ts b/src/tests.ts index 29278e0..2dc332c 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -1,6 +1,5 @@ import { z } from "zod" -import { makeSchemableClass } from "." -import { newSchemable } from "./newSchemable" +import { makeSchemableClass, newSchemable } from "." const UserSchema = z.object({ -- 2.49.1 From 680c3d86178e728d6a9029e86e623a20627f467c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Sun, 31 Dec 2023 01:45:40 +0100 Subject: [PATCH 11/24] makeSchemableClass work --- src/makeSchemableClass.ts | 2 +- src/tests.ts | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/makeSchemableClass.ts b/src/makeSchemableClass.ts index f0fd976..d7c35dc 100644 --- a/src/makeSchemableClass.ts +++ b/src/makeSchemableClass.ts @@ -32,7 +32,7 @@ export function makeSchemableClass< schemaWithDefaultValues, } as const satisfies SchemableConfig - return class { + return class SchemableObject { static readonly $schemableConfig = $schemableConfig static readonly schema = schema static readonly schemaWithDefaultValues = schemaWithDefaultValues diff --git a/src/tests.ts b/src/tests.ts index 2dc332c..0d17ecb 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -13,4 +13,7 @@ const UserSchemaObject = makeSchemableClass({ schema: UserSchema }) class User extends UserSchemaObject {} const user1 = new User({ id: 1n }) -const user2 = newSchemable(User) +const user2 = newSchemable(User, { id: 2n }) + +console.log(user1) +console.log(user2) -- 2.49.1 From d0e0962535276c905226f06c086808db195cb002 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Sun, 31 Dec 2023 02:29:47 +0100 Subject: [PATCH 12/24] JsonifiableSchemable --- .npmrc | 1 + bun.lockb | Bin 150232 -> 150672 bytes bunfig.toml | 2 ++ package.json | 1 + src/JsonifiableSchemable.ts | 11 +++++++++++ 5 files changed, 15 insertions(+) create mode 100644 .npmrc create mode 100644 bunfig.toml create mode 100644 src/JsonifiableSchemable.ts diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..93f962e --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +@thilawyn:registry=https://git.jvalver.de/api/packages/thilawyn/npm/ diff --git a/bun.lockb b/bun.lockb index c02ea2e3fb71feee257f82c5cd59dd9893eb69c1..281a69c7a3f18ae14172e8a50d6bc897860689d4 100755 GIT binary patch delta 27402 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 a^^rM4#t+D#AKBUISr4bL5BW^(&iOxELg)4X delta 26808 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 HVE+FC4!JWy diff --git a/bunfig.toml b/bunfig.toml new file mode 100644 index 0000000..bb40fbe --- /dev/null +++ b/bunfig.toml @@ -0,0 +1,2 @@ +[install.scopes] +"@thilawyn" = "https://git.jvalver.de/api/packages/thilawyn/npm/" diff --git a/package.json b/package.json index 4f0ff3b..09e5a88 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "clean:node": "rm -rf node_modules" }, "dependencies": { + "@thilawyn/thilatrait": "^20231230.0.0", "effect": "^2.0.0-next.62", "lodash-es": "^4.17.21", "type-fest": "^4.9.0", diff --git a/src/JsonifiableSchemable.ts b/src/JsonifiableSchemable.ts new file mode 100644 index 0000000..d64e34e --- /dev/null +++ b/src/JsonifiableSchemable.ts @@ -0,0 +1,11 @@ +import { trait } from "@thilawyn/thilatrait" + + +export const JsonifiableSchemable = () => + trait(Parent => { + abstract class JsonifiableSchemable extends Parent { + + } + + return JsonifiableSchemable + }) -- 2.49.1 From cc518efc1f9fb80796107a28c0178e321d09298b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Sun, 31 Dec 2023 02:31:34 +0100 Subject: [PATCH 13/24] Regenerated lockfile --- bun.lockb | Bin 150672 -> 150685 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/bun.lockb b/bun.lockb index 281a69c7a3f18ae14172e8a50d6bc897860689d4..159acb9422a2937552a3906922876d80474b0283 100755 GIT binary patch delta 12846 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 Gss9fRAa_Op delta 12849 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 Date: Sun, 31 Dec 2023 03:15:06 +0100 Subject: [PATCH 14/24] makeJsonifiableSchemableClass --- src/JsonifiableSchemable.ts | 11 ----- src/makeJsonifiableSchemableClass.ts | 62 ++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 11 deletions(-) delete mode 100644 src/JsonifiableSchemable.ts create mode 100644 src/makeJsonifiableSchemableClass.ts diff --git a/src/JsonifiableSchemable.ts b/src/JsonifiableSchemable.ts deleted file mode 100644 index d64e34e..0000000 --- a/src/JsonifiableSchemable.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { trait } from "@thilawyn/thilatrait" - - -export const JsonifiableSchemable = () => - trait(Parent => { - abstract class JsonifiableSchemable extends Parent { - - } - - return JsonifiableSchemable - }) diff --git a/src/makeJsonifiableSchemableClass.ts b/src/makeJsonifiableSchemableClass.ts new file mode 100644 index 0000000..84a9261 --- /dev/null +++ b/src/makeJsonifiableSchemableClass.ts @@ -0,0 +1,62 @@ +import { JsonifiableObject } from "type-fest/source/jsonifiable" +import { z } from "zod" +import { SchemableClass, SchemableConfig } from "." + + +export function makeJsonifiableSchemableClass< + C extends SchemableClass<$Config>, + $Config 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<$Config>, + + props: { + jsonifySchema: (props: { + schema: $Config["schema"] + s: $Config["schema"]["shape"] + }) => z.ZodObject< + JsonifySchemaT, + JsonifySchemaUnknownKeys, + JsonifySchemaCatchall, + JsonifiedValues, + $Config["values"] + > + + dejsonifySchema: (props: { + schema: $Config["schema"] + s: $Config["schema"]["shape"] + }) => z.ZodObject< + DejsonifySchemaT, + DejsonifySchemaUnknownKeys, + DejsonifySchemaCatchall, + $Config["values"], + JsonifiedValues + > + }, +) { + + const jsonifySchema = props.jsonifySchema({ + schema: class_.schema, + s: class_.schema.shape, + }) + + const dejsonifySchema = props.dejsonifySchema({ + schema: class_.schema, + s: class_.schema.shape, + }) + + + return class JsonifiableSchemableObject { + + } + +} -- 2.49.1 From 92271583cec8cb8d7f42359e2bd3c7c4b1ada2ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Mon, 1 Jan 2024 22:19:50 +0100 Subject: [PATCH 15/24] makeJsonifiableSchemableClass --- src/makeJsonifiableSchemableClass.ts | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/makeJsonifiableSchemableClass.ts b/src/makeJsonifiableSchemableClass.ts index 84a9261..7a053f4 100644 --- a/src/makeJsonifiableSchemableClass.ts +++ b/src/makeJsonifiableSchemableClass.ts @@ -1,6 +1,7 @@ import { JsonifiableObject } from "type-fest/source/jsonifiable" import { z } from "zod" import { SchemableClass, SchemableConfig } from "." +import { parseZodTypeEffect } from "./util" export function makeJsonifiableSchemableClass< @@ -55,8 +56,24 @@ export function makeJsonifiableSchemableClass< }) - return class JsonifiableSchemableObject { + return class JsonifiableSchemableObject extends class_ { + static readonly jsonifySchema = jsonifySchema + static readonly dejsonifySchema = dejsonifySchema + readonly jsonifySchema = jsonifySchema + readonly dejsonifySchema = dejsonifySchema + + jsonify() { + return this.jsonifySchema.parse(this) + } + + jsonifyPromise() { + return this.jsonifySchema.parseAsync(this) + } + + jsonifyEffect() { + return parseZodTypeEffect(this.jsonifySchema, this) + } } } -- 2.49.1 From 00040fb7df8ac7bab47973c4e3673004f5367af0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Mon, 1 Jan 2024 23:14:08 +0100 Subject: [PATCH 16/24] Jsonifiable --- bun.lockb | Bin 150685 -> 151052 bytes package.json | 19 ++++++++++++++---- src/jsonifiable/index.ts | 2 ++ .../makeJsonifiableSchemableClass.ts | 4 ++-- src/jsonifiable/schema/bigint.ts | 18 +++++++++++++++++ src/jsonifiable/schema/date.ts | 18 +++++++++++++++++ src/jsonifiable/schema/decimal.ts | 19 ++++++++++++++++++ src/jsonifiable/schema/index.ts | 3 +++ src/tests.ts | 12 +++++++++-- 9 files changed, 87 insertions(+), 8 deletions(-) create mode 100644 src/jsonifiable/index.ts rename src/{ => jsonifiable}/makeJsonifiableSchemableClass.ts (95%) create mode 100644 src/jsonifiable/schema/bigint.ts create mode 100644 src/jsonifiable/schema/date.ts create mode 100644 src/jsonifiable/schema/decimal.ts create mode 100644 src/jsonifiable/schema/index.ts diff --git a/bun.lockb b/bun.lockb index 159acb9422a2937552a3906922876d80474b0283..74e015cb65608180bb9f472b98d7a2af182d9067 100755 GIT binary patch delta 26068 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 j%OA=(schema: S) => + schema.transform(v => v.toString()) + +export const dejsonifyBigIntSchema = (schema: S) => + z + .string() + .transform(v => { + try { + return BigInt(v) + } + catch (e) { + return v + } + }) + .pipe(schema) diff --git a/src/jsonifiable/schema/date.ts b/src/jsonifiable/schema/date.ts new file mode 100644 index 0000000..b5ac677 --- /dev/null +++ b/src/jsonifiable/schema/date.ts @@ -0,0 +1,18 @@ +import { z } from "zod" + + +export const jsonifyDateSchema = (schema: S) => + schema.transform(v => v.toString()) + +export const dejsonifyDateSchema = (schema: S) => + z + .string() + .transform(v => { + try { + return new Date(v) + } + catch (e) { + return v + } + }) + .pipe(schema) diff --git a/src/jsonifiable/schema/decimal.ts b/src/jsonifiable/schema/decimal.ts new file mode 100644 index 0000000..58c492d --- /dev/null +++ b/src/jsonifiable/schema/decimal.ts @@ -0,0 +1,19 @@ +import { Decimal } from "decimal.js" +import { z } from "zod" + + +export const jsonifyDecimalSchema = >(schema: S) => + schema.transform(v => v.toJSON()) + +export const dejsonifyDecimalSchema = >(schema: S) => + z + .string() + .transform(v => { + try { + return new Decimal(v) + } + catch (e) { + return v + } + }) + .pipe(schema) diff --git a/src/jsonifiable/schema/index.ts b/src/jsonifiable/schema/index.ts new file mode 100644 index 0000000..f4bad9b --- /dev/null +++ b/src/jsonifiable/schema/index.ts @@ -0,0 +1,3 @@ +export * from "./bigint" +export * from "./date" +export * from "./decimal" diff --git a/src/tests.ts b/src/tests.ts index 0d17ecb..ca96997 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -8,9 +8,17 @@ const UserSchema = z.object({ }) -const UserSchemaObject = makeSchemableClass({ schema: UserSchema }) +const UserSchemableObject = makeSchemableClass({ schema: UserSchema }) -class User extends UserSchemaObject {} +// const UserJsonifiableSchemableObject = makeJsonifiableSchemableClass(UserSchemableObject, { +// jsonifySchema: ({ schema, s }) => schema.extend({ +// }), + +// dejsonifySchema: ({ schema, s }) => schema.extend({ +// }), +// }) + +class User extends UserSchemableObject {} const user1 = new User({ id: 1n }) const user2 = newSchemable(User, { id: 2n }) -- 2.49.1 From de6a97e0a6861c2910e98e107e8b2d331726a9db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Tue, 2 Jan 2024 01:50:44 +0100 Subject: [PATCH 17/24] makeJsonifiableSchemableClass --- rollup.config.js | 10 ++- src/jsonifiable/JsonifiableSchemableClass.ts | 61 +++++++++++++++++++ src/jsonifiable/index.ts | 1 + .../makeJsonifiableSchemableClass.ts | 49 ++++++++++----- src/makeSchemableClass.ts | 8 +-- src/tests.ts | 17 +++--- 6 files changed, 119 insertions(+), 27 deletions(-) create mode 100644 src/jsonifiable/JsonifiableSchemableClass.ts diff --git a/rollup.config.js b/rollup.config.js index da6b231..aa4dbe2 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -12,11 +12,19 @@ export default defineConfig({ file: pkg.exports["."].import.default, format: "esm", }, - { file: pkg.exports["."].require.default, format: "cjs", }, + + { + file: pkg.exports["./jsonifiable"].import.default, + format: "esm", + }, + { + file: pkg.exports["./jsonifiable"].require.default, + format: "cjs", + }, ], plugins: [ diff --git a/src/jsonifiable/JsonifiableSchemableClass.ts b/src/jsonifiable/JsonifiableSchemableClass.ts new file mode 100644 index 0000000..41298f7 --- /dev/null +++ b/src/jsonifiable/JsonifiableSchemableClass.ts @@ -0,0 +1,61 @@ +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"] +} diff --git a/src/jsonifiable/index.ts b/src/jsonifiable/index.ts index ae3e8e2..831c7de 100644 --- a/src/jsonifiable/index.ts +++ b/src/jsonifiable/index.ts @@ -1,2 +1,3 @@ +export * from "./JsonifiableSchemableClass" export * from "./makeJsonifiableSchemableClass" export * from "./schema" diff --git a/src/jsonifiable/makeJsonifiableSchemableClass.ts b/src/jsonifiable/makeJsonifiableSchemableClass.ts index 99d0029..332299e 100644 --- a/src/jsonifiable/makeJsonifiableSchemableClass.ts +++ b/src/jsonifiable/makeJsonifiableSchemableClass.ts @@ -1,12 +1,14 @@ +import { Class } from "type-fest" import { JsonifiableObject } from "type-fest/source/jsonifiable" import { z } from "zod" +import { JsonifiableSchemableConfig } from "." import { SchemableClass, SchemableConfig } from ".." -import { parseZodTypeEffect } from "../util" +import { StaticMembers, parseZodTypeEffect } from "../util" export function makeJsonifiableSchemableClass< - C extends SchemableClass<$Config>, - $Config extends SchemableConfig, + C extends SchemableClass<$SchemableConfig>, + $SchemableConfig extends SchemableConfig, JsonifiedValues extends JsonifiableObject, @@ -18,28 +20,28 @@ export function makeJsonifiableSchemableClass< DejsonifySchemaUnknownKeys extends z.UnknownKeysParam, DejsonifySchemaCatchall extends z.ZodTypeAny, >( - class_: C | SchemableClass<$Config>, + class_: C | SchemableClass<$SchemableConfig>, props: { jsonifySchema: (props: { - schema: $Config["schema"] - s: $Config["schema"]["shape"] + schema: $SchemableConfig["schema"] + s: $SchemableConfig["schema"]["shape"] }) => z.ZodObject< JsonifySchemaT, JsonifySchemaUnknownKeys, JsonifySchemaCatchall, JsonifiedValues, - $Config["values"] + $SchemableConfig["values"] > dejsonifySchema: (props: { - schema: $Config["schema"] - s: $Config["schema"]["shape"] + schema: $SchemableConfig["schema"] + s: $SchemableConfig["schema"]["shape"] }) => z.ZodObject< DejsonifySchemaT, DejsonifySchemaUnknownKeys, DejsonifySchemaCatchall, - $Config["values"], + $SchemableConfig["values"], JsonifiedValues > }, @@ -55,13 +57,21 @@ export function makeJsonifiableSchemableClass< 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 - return class JsonifiableSchemableObject extends class_ { - static readonly jsonifySchema = jsonifySchema - static readonly dejsonifySchema = dejsonifySchema + const jsonifiableClass = class JsonifiableSchemableObject extends class_ { + static readonly $jsonifiableSchemableConfig = $jsonifiableSchemableConfig + static readonly jsonifySchema = jsonifySchema + static readonly dejsonifySchema = dejsonifySchema - readonly jsonifySchema = jsonifySchema - readonly dejsonifySchema = dejsonifySchema + readonly $jsonifiableSchemableConfig = $jsonifiableSchemableConfig + readonly jsonifySchema = jsonifySchema + readonly dejsonifySchema = dejsonifySchema jsonify() { return this.jsonifySchema.parse(this) @@ -76,4 +86,13 @@ export function makeJsonifiableSchemableClass< } } + return jsonifiableClass as ( + Class< + InstanceType & InstanceType, + ConstructorParameters + > & + StaticMembers & + StaticMembers + ) + } diff --git a/src/makeSchemableClass.ts b/src/makeSchemableClass.ts index d7c35dc..88bcf72 100644 --- a/src/makeSchemableClass.ts +++ b/src/makeSchemableClass.ts @@ -26,10 +26,10 @@ export function makeSchemableClass< const schema = zodObjectRemoveDefaults(schemaWithDefaultValues) const $schemableConfig = { - values: {} as z.output, - input: {} as z.input, - schema, - schemaWithDefaultValues, + values: undefined as unknown as z.output, + input: undefined as unknown as z.input, + schema: undefined as unknown as typeof schema, + schemaWithDefaultValues: undefined as unknown as typeof schemaWithDefaultValues, } as const satisfies SchemableConfig return class SchemableObject { diff --git a/src/tests.ts b/src/tests.ts index ca96997..b20c473 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -1,5 +1,6 @@ import { z } from "zod" import { makeSchemableClass, newSchemable } from "." +import { dejsonifyBigIntSchema, jsonifyBigIntSchema, makeJsonifiableSchemableClass } from "./jsonifiable" const UserSchema = z.object({ @@ -10,15 +11,17 @@ const UserSchema = z.object({ const UserSchemableObject = makeSchemableClass({ schema: UserSchema }) -// const UserJsonifiableSchemableObject = makeJsonifiableSchemableClass(UserSchemableObject, { -// jsonifySchema: ({ schema, s }) => schema.extend({ -// }), +const UserJsonifiableSchemableObject = makeJsonifiableSchemableClass(UserSchemableObject, { + jsonifySchema: ({ schema, s }) => schema.extend({ + id: jsonifyBigIntSchema(s.id) + }), -// dejsonifySchema: ({ schema, s }) => schema.extend({ -// }), -// }) + dejsonifySchema: ({ schema, s }) => schema.extend({ + id: dejsonifyBigIntSchema(s.id) + }), +}) -class User extends UserSchemableObject {} +class User extends UserJsonifiableSchemableObject {} const user1 = new User({ id: 1n }) const user2 = newSchemable(User, { id: 2n }) -- 2.49.1 From 3c2dc477fdc85470ceb2bb28ca41762877432cd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Tue, 2 Jan 2024 02:43:16 +0100 Subject: [PATCH 18/24] makeJsonifiableSchemableClass --- src/jsonifiable/JsonifiableSchemableClass.ts | 5 +++++ src/jsonifiable/makeJsonifiableSchemableClass.ts | 8 ++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/jsonifiable/JsonifiableSchemableClass.ts b/src/jsonifiable/JsonifiableSchemableClass.ts index 41298f7..c0dc3c0 100644 --- a/src/jsonifiable/JsonifiableSchemableClass.ts +++ b/src/jsonifiable/JsonifiableSchemableClass.ts @@ -1,3 +1,4 @@ +import { Effect } from "effect" import { Class } from "type-fest" import { JsonifiableObject } from "type-fest/source/jsonifiable" import { z } from "zod" @@ -58,4 +59,8 @@ export type JsonifiableSchemableObject< readonly $jsonifiableSchemableConfig: $Config readonly jsonifySchema: $Config["jsonifySchema"] readonly dejsonifySchema: $Config["dejsonifySchema"] + + jsonify(): $Config["jsonifiedValues"] + jsonifyPromise(): Promise<$Config["jsonifiedValues"]> + jsonifyEffect(): Effect.Effect, $Config["jsonifiedValues"]> } diff --git a/src/jsonifiable/makeJsonifiableSchemableClass.ts b/src/jsonifiable/makeJsonifiableSchemableClass.ts index 332299e..ebbdf8a 100644 --- a/src/jsonifiable/makeJsonifiableSchemableClass.ts +++ b/src/jsonifiable/makeJsonifiableSchemableClass.ts @@ -1,7 +1,7 @@ import { Class } from "type-fest" import { JsonifiableObject } from "type-fest/source/jsonifiable" import { z } from "zod" -import { JsonifiableSchemableConfig } from "." +import { JsonifiableSchemableClass, JsonifiableSchemableConfig, JsonifiableSchemableObject } from "." import { SchemableClass, SchemableConfig } from ".." import { StaticMembers, parseZodTypeEffect } from "../util" @@ -84,15 +84,15 @@ export function makeJsonifiableSchemableClass< jsonifyEffect() { return parseZodTypeEffect(this.jsonifySchema, this) } - } + } satisfies JsonifiableSchemableClass return jsonifiableClass as ( Class< - InstanceType & InstanceType, + InstanceType & JsonifiableSchemableObject, ConstructorParameters > & StaticMembers & - StaticMembers + StaticMembers> ) } -- 2.49.1 From 0e9d946696a5c046e5a4562c76c22c15d0d52a21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Tue, 2 Jan 2024 02:54:40 +0100 Subject: [PATCH 19/24] makeJsonifiableSchemableClass fix --- src/jsonifiable/makeJsonifiableSchemableClass.ts | 2 +- src/tests.ts | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/jsonifiable/makeJsonifiableSchemableClass.ts b/src/jsonifiable/makeJsonifiableSchemableClass.ts index ebbdf8a..a956b0b 100644 --- a/src/jsonifiable/makeJsonifiableSchemableClass.ts +++ b/src/jsonifiable/makeJsonifiableSchemableClass.ts @@ -86,7 +86,7 @@ export function makeJsonifiableSchemableClass< } } satisfies JsonifiableSchemableClass - return jsonifiableClass as ( + return jsonifiableClass as unknown as ( Class< InstanceType & JsonifiableSchemableObject, ConstructorParameters diff --git a/src/tests.ts b/src/tests.ts index b20c473..3eddcd5 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -28,3 +28,5 @@ const user2 = newSchemable(User, { id: 2n }) console.log(user1) console.log(user2) + +console.log(await user2.jsonifyPromise()) -- 2.49.1 From 713e679e3558ab61d3dcb55ef627cc9a9de9b277 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Tue, 2 Jan 2024 03:37:09 +0100 Subject: [PATCH 20/24] Schemable JSON helpers --- src/jsonifiable/schema/index.ts | 1 + src/jsonifiable/schema/schemable.ts | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 src/jsonifiable/schema/schemable.ts diff --git a/src/jsonifiable/schema/index.ts b/src/jsonifiable/schema/index.ts index f4bad9b..08ecef8 100644 --- a/src/jsonifiable/schema/index.ts +++ b/src/jsonifiable/schema/index.ts @@ -1,3 +1,4 @@ export * from "./bigint" export * from "./date" export * from "./decimal" +export * from "./schemable" diff --git a/src/jsonifiable/schema/schemable.ts b/src/jsonifiable/schema/schemable.ts new file mode 100644 index 0000000..c6e2a2d --- /dev/null +++ b/src/jsonifiable/schema/schemable.ts @@ -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, z.ZodTypeDef, InstanceType>, +>( + 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, z.ZodTypeDef, InstanceType>, +>( + class_: C | JsonifiableSchemableClass<$Config>, + schema: S, +) => + class_.dejsonifySchema.transform(v => new class_(v)).pipe(schema) -- 2.49.1 From f170714435600902b36028226b66fc59485a45a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Tue, 2 Jan 2024 17:12:44 +0100 Subject: [PATCH 21/24] Tests work --- src/tests.ts | 54 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 42 insertions(+), 12 deletions(-) diff --git a/src/tests.ts b/src/tests.ts index 3eddcd5..39ad805 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -1,17 +1,19 @@ import { z } from "zod" import { makeSchemableClass, newSchemable } from "." -import { dejsonifyBigIntSchema, jsonifyBigIntSchema, makeJsonifiableSchemableClass } from "./jsonifiable" +import { dejsonifyBigIntSchema, dejsonifySchemableSchema, jsonifyBigIntSchema, jsonifySchemableSchema, makeJsonifiableSchemableClass } from "./jsonifiable" -const UserSchema = z.object({ - /** User ID */ - id: z.bigint().default(-1n) +const GroupSchema = z.object({ + /** Group ID */ + id: z.bigint(), + + /** Group name */ + name: z.string(), }) +const GroupSchemableObject = makeSchemableClass({ schema: GroupSchema }) -const UserSchemableObject = makeSchemableClass({ schema: UserSchema }) - -const UserJsonifiableSchemableObject = makeJsonifiableSchemableClass(UserSchemableObject, { +const GroupJsonifiableSchemableObject = makeJsonifiableSchemableClass(GroupSchemableObject, { jsonifySchema: ({ schema, s }) => schema.extend({ id: jsonifyBigIntSchema(s.id) }), @@ -21,12 +23,40 @@ const UserJsonifiableSchemableObject = makeJsonifiableSchemableClass(UserSchemab }), }) +class Group extends GroupJsonifiableSchemableObject {} + + +const UserSchema = z.object({ + /** User ID */ + id: z.bigint(), + + /** Name string */ + name: z.string(), + + /** User group */ + group: z.instanceof(Group), +}) + +const UserSchemableObject = makeSchemableClass({ schema: UserSchema }) + +const UserJsonifiableSchemableObject = makeJsonifiableSchemableClass(UserSchemableObject, { + jsonifySchema: ({ schema, s }) => schema.extend({ + id: jsonifyBigIntSchema(s.id), + group: jsonifySchemableSchema(Group, s.group), + }), + + dejsonifySchema: ({ schema, s }) => schema.extend({ + id: dejsonifyBigIntSchema(s.id), + group: dejsonifySchemableSchema(Group, s.group), + }), +}) + class User extends UserJsonifiableSchemableObject {} -const user1 = new User({ id: 1n }) -const user2 = newSchemable(User, { id: 2n }) -console.log(user1) -console.log(user2) +const group1 = new Group({ id: 1n, name: "Group 1" }) -console.log(await user2.jsonifyPromise()) +const user1 = new User({ id: 1n, name: "User 1", group: group1 }) +const user2 = newSchemable(User, { id: 2n, name: "User 2", group: group1 }) + +console.log(user2.jsonify()) -- 2.49.1 From fb82d014b7ab9938521502d62e104f65610fda4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Tue, 2 Jan 2024 17:42:19 +0100 Subject: [PATCH 22/24] Working dejsonify --- src/jsonifiable/dejsonifySchemable.ts | 47 +++++++++++++++++++++++++++ src/jsonifiable/index.ts | 1 + src/tests.ts | 6 ++-- 3 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 src/jsonifiable/dejsonifySchemable.ts diff --git a/src/jsonifiable/dejsonifySchemable.ts b/src/jsonifiable/dejsonifySchemable.ts new file mode 100644 index 0000000..35ceafb --- /dev/null +++ b/src/jsonifiable/dejsonifySchemable.ts @@ -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, +) => + new class_(class_.dejsonifySchema.parse(values, params)) as InstanceType + + +export const dejsonifySchemablePromise = async < + C extends JsonifiableSchemableClass<$Config>, + $Config extends JsonifiableSchemableConfig, +>( + class_: C | JsonifiableSchemableClass<$Config>, + values: $Config["jsonifiedValues"], + params?: Partial, +) => + new class_(await class_.dejsonifySchema.parseAsync(values, params)) as InstanceType + + +export const dejsonifySchemableEffect = < + C extends JsonifiableSchemableClass<$Config>, + $Config extends JsonifiableSchemableConfig, +>( + class_: C | JsonifiableSchemableClass<$Config>, + values: $Config["jsonifiedValues"], + params?: Partial, +) => pipe( + parseZodTypeEffect< + z.output, + z.input + >( + class_.dejsonifySchema, + values, + params, + ), + + Effect.map(values => new class_(values) as InstanceType), +) diff --git a/src/jsonifiable/index.ts b/src/jsonifiable/index.ts index 831c7de..74e7d23 100644 --- a/src/jsonifiable/index.ts +++ b/src/jsonifiable/index.ts @@ -1,3 +1,4 @@ export * from "./JsonifiableSchemableClass" +export * from "./dejsonifySchemable" export * from "./makeJsonifiableSchemableClass" export * from "./schema" diff --git a/src/tests.ts b/src/tests.ts index 39ad805..c19daf7 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -1,6 +1,6 @@ import { z } from "zod" import { makeSchemableClass, newSchemable } from "." -import { dejsonifyBigIntSchema, dejsonifySchemableSchema, jsonifyBigIntSchema, jsonifySchemableSchema, makeJsonifiableSchemableClass } from "./jsonifiable" +import { dejsonifyBigIntSchema, dejsonifySchemable, dejsonifySchemableSchema, jsonifyBigIntSchema, jsonifySchemableSchema, makeJsonifiableSchemableClass } from "./jsonifiable" const GroupSchema = z.object({ @@ -59,4 +59,6 @@ const group1 = new Group({ id: 1n, name: "Group 1" }) const user1 = new User({ id: 1n, name: "User 1", group: group1 }) const user2 = newSchemable(User, { id: 2n, name: "User 2", group: group1 }) -console.log(user2.jsonify()) +const jsonifiedUser2 = user2.jsonify() +const dejsonifiedUser2 = dejsonifySchemable(User, jsonifiedUser2) +console.log(dejsonifiedUser2) -- 2.49.1 From 5e5cc8d87ec20eccaf31d7c2e7168e6bea629e56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Fri, 5 Jan 2024 00:04:12 +0100 Subject: [PATCH 23/24] Build system work --- bun.lockb | Bin 151052 -> 154055 bytes package.json | 8 ++++---- rollup.config.js | 38 -------------------------------------- rollup.config.ts | 43 +++++++++++++++++++++++++++++++++++++++++++ src/newSchemable.ts | 26 ++++++++++++++++++++++++++ 5 files changed, 73 insertions(+), 42 deletions(-) delete mode 100644 rollup.config.js create mode 100644 rollup.config.ts diff --git a/bun.lockb b/bun.lockb index 74e015cb65608180bb9f472b98d7a2af182d9067..4e23eb8b4364adf2258b86fdc025f2982746ab68 100755 GIT binary patch delta 28883 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 diff --git a/package.json b/package.json index 414881e..cc31d6b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { - "name": "@thilawyn/schemable-classes", - "version": "20231230.0.0", + "name": "@thilawyn/schemable-class", + "version": "1.0.0", "type": "module", "publishConfig": { "registry": "https://git.jvalver.de/api/packages/thilawyn/npm/" @@ -31,14 +31,13 @@ } }, "scripts": { - "build": "rollup -c", + "build": "rollup -c rollup.config.ts", "lint:tsc": "tsc --noEmit", "clean:cache": "rm -f tsconfig.tsbuildinfo", "clean:dist": "rm -rf dist", "clean:node": "rm -rf node_modules" }, "dependencies": { - "@thilawyn/thilatrait": "^20231230.0.0", "decimal.js": "^10.4.3", "effect": "^2.0.0-next.62", "lodash-es": "^4.17.21", @@ -46,6 +45,7 @@ "zod": "^3.22.4" }, "devDependencies": { + "@rollup/plugin-node-resolve": "^15.2.3", "@types/lodash-es": "^4.17.12", "bun-types": "latest", "npm-check-updates": "^16.14.12", diff --git a/rollup.config.js b/rollup.config.js deleted file mode 100644 index aa4dbe2..0000000 --- a/rollup.config.js +++ /dev/null @@ -1,38 +0,0 @@ -import { defineConfig } from "rollup" -import cleanup from "rollup-plugin-cleanup" -import ts from "rollup-plugin-ts" -import pkg from "./package.json" assert { type: "json" } - - -export default defineConfig({ - input: "src/index.ts", - - output: [ - { - file: pkg.exports["."].import.default, - format: "esm", - }, - { - file: pkg.exports["."].require.default, - format: "cjs", - }, - - { - file: pkg.exports["./jsonifiable"].import.default, - format: "esm", - }, - { - file: pkg.exports["./jsonifiable"].require.default, - format: "cjs", - }, - ], - - plugins: [ - ts(), - - cleanup({ - comments: "jsdoc", - extensions: ["ts"], - }), - ], -}) diff --git a/rollup.config.ts b/rollup.config.ts new file mode 100644 index 0000000..8625946 --- /dev/null +++ b/rollup.config.ts @@ -0,0 +1,43 @@ +import { nodeResolve } from "@rollup/plugin-node-resolve" +import { defineConfig } from "rollup" +import cleanup from "rollup-plugin-cleanup" +import ts from "rollup-plugin-ts" +import pkg from "./package.json" assert { type: "json" } + + +export const createBundleConfig = ( + input: string, + name: keyof typeof pkg.exports, +) => + defineConfig({ + input, + + output: [ + { + file: pkg.exports[name].import.default, + format: "esm", + }, + { + file: pkg.exports[name].require.default, + format: "cjs", + }, + ], + + external: id => !/^[./]/.test(id), + + plugins: [ + nodeResolve(), + ts(), + + cleanup({ + comments: "jsdoc", + extensions: ["ts"], + }), + ], + }) + + +export default [ + createBundleConfig("src/index.ts", "."), + createBundleConfig("src/jsonifiable/index.ts", "./jsonifiable"), +] diff --git a/src/newSchemable.ts b/src/newSchemable.ts index 955d0f3..da0be36 100644 --- a/src/newSchemable.ts +++ b/src/newSchemable.ts @@ -13,6 +13,14 @@ type NewSchemableArgs = : [] | [Input, ...ParamsArgs] +/** + * Creates a new instance of a SchemableClass with default values. + * + * @param class_ - The SchemableClass. + * @param values - The values to be parsed and used to create the instance. + * @param params - Optional parameters for parsing. + * @returns A new instance of the specified SchemableClass. + */ export const newSchemable = < C extends SchemableClass<$Config>, $Config extends SchemableConfig, @@ -22,6 +30,15 @@ export const newSchemable = < ) => new class_(class_.schemaWithDefaultValues.parse(values || {}, params)) as InstanceType + +/** + * Creates a new instance of a SchemableClass with default values asynchronously. + * + * @param class_ - The SchemableClass. + * @param values - The values to be parsed and used to create the instance. + * @param params - Optional parameters for parsing. + * @returns A Promise resolving to a new instance of the specified SchemableClass. + */ export const newSchemablePromise = async < C extends SchemableClass<$Config>, $Config extends SchemableConfig, @@ -31,6 +48,15 @@ export const newSchemablePromise = async < ) => new class_(await class_.schemaWithDefaultValues.parseAsync(values || {}, params)) as InstanceType + +/** + * Creates a new instance of a SchemableClass with default values as an Effect. + * + * @param class_ - The SchemableClass. + * @param values - The values to be parsed and used to create the instance. + * @param params - Optional parameters for parsing. + * @returns An Effect producing a new instance of the specified SchemableClass. + */ export const newSchemableEffect = < C extends SchemableClass<$Config>, $Config extends SchemableConfig, -- 2.49.1 From 3b2bcbf77f52cb2c4a4ccfcaf2e7d582cc6263db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Fri, 5 Jan 2024 00:24:45 +0100 Subject: [PATCH 24/24] Version change --- README.md | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b731fa9..adb9b58 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,3 @@ -# schemable-classes +# schemable-class -Create TypeScript classes out of Zod schemas \ No newline at end of file +Create TypeScript classes out of Zod schemas diff --git a/package.json b/package.json index cc31d6b..547eb5f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@thilawyn/schemable-class", - "version": "1.0.0", + "version": "0.1.0", "type": "module", "publishConfig": { "registry": "https://git.jvalver.de/api/packages/thilawyn/npm/" -- 2.49.1