['_type'] | {} | null | undefined): u is T {
if (!(u instanceof globalThis.Map)) return false
else {
diff --git a/examples/sandbox/src/lib/namespace.ts b/examples/sandbox/src/lib/namespace.ts
index a627dd4c..8e779d2c 100644
--- a/examples/sandbox/src/lib/namespace.ts
+++ b/examples/sandbox/src/lib/namespace.ts
@@ -1,5 +1,5 @@
-export * from '@traversable/schema/namespace'
-export { getConfig } from '@traversable/schema'
+export * from '@traversable/schema-core/namespace'
+export { getConfig } from '@traversable/schema-core'
export type {
F,
diff --git a/examples/sandbox/src/lib/prototype.ts b/examples/sandbox/src/lib/prototype.ts
index 11b75ada..6f43173d 100644
--- a/examples/sandbox/src/lib/prototype.ts
+++ b/examples/sandbox/src/lib/prototype.ts
@@ -1,8 +1,8 @@
-import { t } from '@traversable/schema'
+import { t } from '@traversable/schema-core'
export function parse(this: S, u: unknown) {
if (this(u)) return u
else throw Error('invalid input')
}
-export const prototype = { parse }
+export const bindParse = { parse }
diff --git a/examples/sandbox/src/lib/react.ts b/examples/sandbox/src/lib/react.ts
index 16e344fc..8618b235 100644
--- a/examples/sandbox/src/lib/react.ts
+++ b/examples/sandbox/src/lib/react.ts
@@ -1,5 +1,5 @@
import type * as React from 'react'
-import { t } from '@traversable/schema'
+import { t } from '@traversable/schema-core'
export interface Key extends t.union<[t.null, t.string]> { }
export const Key = t.union(t.null, t.string) satisfies Key
@@ -18,7 +18,7 @@ export function ElementSchema(propsSch
props: t.object
key: Key
}>
-export function ElementSchema(propsSchema: { [x: string]: t.Schema } = {}) {
+export function ElementSchema
(propsSchema: P = {} as never) {
return t.object({
type: t.any,
props: t.object(propsSchema),
diff --git a/examples/sandbox/src/lib/set.ts b/examples/sandbox/src/lib/set.ts
index 2106dc6e..94aea2c0 100644
--- a/examples/sandbox/src/lib/set.ts
+++ b/examples/sandbox/src/lib/set.ts
@@ -1,5 +1,5 @@
import * as T from '@traversable/registry'
-import { t } from '@traversable/schema'
+import { t } from '@traversable/schema-core'
import type {
ValidationError,
ValidationFn,
@@ -40,7 +40,7 @@ export namespace set {
export function def(x: S): set {
type T = Set
- const predicate = t.isPredicate(x) ? x : (_?: any) => true
+ const predicate = T._isPredicate(x) ? x : (_?: any) => true
function SetSchema(u: unknown): u is T {
if (!(u instanceof globalThis.Set)) return false
else {
diff --git a/examples/sandbox/src/lib/shared.ts b/examples/sandbox/src/lib/shared.ts
index 3d658d3a..eb4daf74 100644
--- a/examples/sandbox/src/lib/shared.ts
+++ b/examples/sandbox/src/lib/shared.ts
@@ -1,7 +1,7 @@
import type { HKT } from '@traversable/registry'
import { NS, URI as URI_, symbol as symbol_ } from '@traversable/registry'
import { has } from '@traversable/registry'
-import { t } from '@traversable/schema'
+import { t } from '@traversable/schema-core'
import type { set } from './set'
import type { map } from './map'
diff --git a/examples/sandbox/src/lib/toHtml.tsx b/examples/sandbox/src/lib/toHtml.tsx
index 1794002d..64546cff 100644
--- a/examples/sandbox/src/lib/toHtml.tsx
+++ b/examples/sandbox/src/lib/toHtml.tsx
@@ -1,7 +1,7 @@
import * as React from 'react'
import type * as T from '@traversable/registry'
import { fn, parseKey } from '@traversable/registry'
-import { t } from '@traversable/schema'
+import { t } from '@traversable/schema-core'
import { Json } from '@traversable/json'
import * as isReact from './react'
diff --git a/examples/sandbox/src/sandbox.tsx b/examples/sandbox/src/sandbox.tsx
index cc90c307..a9c3f94b 100644
--- a/examples/sandbox/src/sandbox.tsx
+++ b/examples/sandbox/src/sandbox.tsx
@@ -1,15 +1,15 @@
import { t } from './lib'
// to view the inferred type predicates demo, see './demo/inferredTypePredicates.ts'
import './demo/inferredTypePredicates'
-// to view the '.toString' demo, check your browser console + see './demo/toString.ts'
+// to view the '.toString' demo, see './demo/toString.ts' + check your browser console
import './demo/toString'
-// to view the '.toJsonSchema' demo, check your browser console + see './demo/toJsonSchema.ts'
+// to view the '.toJsonSchema' demo, see './demo/toJsonSchema.ts' + check your browser console
import './demo/toJsonSchema'
-// to view the '.validate' demo, check your browser console + see './demo/validate.ts'
+// to view the '.validate' demo, see './demo/validate.ts' + check your browser console
import './demo/validate'
-// to view the '.pipe' and '.extend' demo, check your browser console + see './demo/codec.ts'
+// to view the '.pipe' and '.extend' demo, see './demo/codec.ts' + check your browser console
import './demo/codec'
-// to see how to extend traversable schemas in userland, check your browser console + see './demo/userlandExtensions.ts'
+// to see how to extend traversable schemas in userland, see './demo/userlandExtensions.ts' + check your browser console
import './demo/userlandExtensions'
// to see how traversable schemas support reflection + custom interpreters, run this example with 'pnpm dev'
import { HardcodedSchemaExamples, RandomlyGeneratedSchemas } from './demo/advanced'
diff --git a/examples/sandbox/tsconfig.app.json b/examples/sandbox/tsconfig.app.json
index d962aa70..0b205611 100644
--- a/examples/sandbox/tsconfig.app.json
+++ b/examples/sandbox/tsconfig.app.json
@@ -32,8 +32,8 @@
"@traversable/json/*": ["../../packages/json/src/*"],
"@traversable/registry": ["../../packages/registry/src"],
"@traversable/registry/*": ["../../packages/registry/src/*"],
- "@traversable/schema": ["../../packages/schema/src"],
- "@traversable/schema/*": ["../../packages/schema/src/*"],
+ "@traversable/schema-core": ["../../packages/schema-core/src"],
+ "@traversable/schema-core/*": ["../../packages/schema-core/src/*"],
"@traversable/schema-seed": ["../../packages/schema-seed/src"],
"@traversable/schema-seed/*": ["../../packages/schema-seed/src/*"],
"@traversable/schema-to-json-schema": ["../../packages/schema-to-json-schema/src"],
diff --git a/examples/sandbox/vite.config.ts b/examples/sandbox/vite.config.ts
index a38e2595..a1147956 100644
--- a/examples/sandbox/vite.config.ts
+++ b/examples/sandbox/vite.config.ts
@@ -11,7 +11,7 @@ export default defineConfig({
'@traversable/derive-validators': fileURLToPath(new URL('../../packages/derive-validators/src', import.meta.url)),
'@traversable/json': fileURLToPath(new URL('../../packages/json/src', import.meta.url)),
'@traversable/registry': fileURLToPath(new URL('../../packages/registry/src', import.meta.url)),
- '@traversable/schema': fileURLToPath(new URL('../../packages/schema/src', import.meta.url)),
+ '@traversable/schema-core': fileURLToPath(new URL('../../packages/schema-core/src', import.meta.url)),
'@traversable/schema-seed': fileURLToPath(new URL('../../packages/schema-seed/src', import.meta.url)),
'@traversable/schema-to-json-schema': fileURLToPath(new URL('../../packages/schema-to-json-schema/src', import.meta.url)),
'@traversable/schema-to-string': fileURLToPath(new URL('../../packages/schema-to-string/src', import.meta.url)),
diff --git a/package.json b/package.json
index fe4b7943..c11df0eb 100644
--- a/package.json
+++ b/package.json
@@ -3,12 +3,15 @@
"private": true,
"license": "MIT",
"scripts": {
- "bench": "pnpm vitest bench --outputJson benchmarks/benchmark--$(date -Iseconds).json",
+ "bench": "pnpm bench:types && pnpm bench:runtime",
+ "bench:runtime": "./bin/bench.ts run",
+ "bench:types": "./bin/bench.ts prepareTypes && ./bin/bench.ts runTypes && ./bin/bench.ts cleanupTypes",
"boot": "pnpm install && pnpm reboot",
- "build": "pnpm build:root && pnpm run build:pre && pnpm --recursive --parallel run build && pnpm build:post",
+ "build": "pnpm build:root && pnpm run build:pre && pnpm --recursive --parallel run build && pnpm build:post && pnpm build:dist && cd packages/schema && pnpm build:schemas",
+ "build:docs": "pnpm dlx tsx ./bin/docs.ts",
"build:pre": "pnpm dlx tsx ./bin/bump.ts",
"build:pkgs": "pnpm --filter \"@traversable/*\" run \"/^build:.*/\"",
- "build:root": "tsc -b tsconfig.build.json && pnpm run docs",
+ "build:root": "tsc -b tsconfig.build.json && pnpm run build:docs",
"build:post": "pnpm circular",
"build:dist": "pnpm dlx tsx ./bin/pack.ts",
"changes": "changeset add",
@@ -21,43 +24,39 @@
"clean:build": "pnpm -r --stream --parallel run clean:build",
"clean:deps": "pnpm -r --stream --parallel run clean:deps && rm -rf node_modules",
"clean:generated": "pnpm -r --stream --parallel run clean:generated",
+ "cli": "./packages/schema-generator/src/cli.ts",
"describe": "pnpm run \"/^describe:.*/\"",
"describe:project": "./bin/describe.ts",
"dev": "pnpm --filter \"@traversable/sandbox\" run \"dev\"",
- "docs": "pnpm dlx tsx ./bin/docs.ts",
"reboot": "./bin/reboot.ts",
- "test": "vitest run -- --skipTypes && tsc -b tsconfig.json",
+ "test": "vitest run -- --skipTypes --exclude packages/**/test/e2e* && tsc -b tsconfig.json",
+ "test_": "vitest run -- --skipTypes && tsc -b tsconfig.json",
"test:cov": "pnpm vitest run --coverage",
- "test:watch": "pnpm vitest --coverage",
+ "test:e2e": "pnpm vitest run --coverage",
+ "test:watch": "pnpm vitest run -- --exclude packages/schema-generator/test/e2e.test.ts",
"test:watch:no-cov": "pnpm vitest",
"workspace:new": "./bin/workspace-create.ts",
"workspace:rm": "./bin/workspace-cleanup.ts"
},
"devDependencies": {
- "@ark/attest": "^0.44.8",
- "@babel/cli": "^7.25.9",
- "@babel/core": "^7.26.0",
- "@babel/plugin-transform-export-namespace-from": "^7.25.9",
- "@babel/plugin-transform-modules-commonjs": "^7.25.9",
- "@changesets/changelog-github": "^0.5.0",
- "@changesets/cli": "^2.27.9",
- "@fast-check/vitest": "^0.2.0",
- "@types/madge": "^5.0.3",
- "@types/node": "^22.9.0",
- "@vitest/coverage-v8": "3.1.1",
- "@vitest/ui": "3.1.1",
- "babel-plugin-annotate-pure-calls": "^0.4.0",
- "fast-check": "^4.0.1",
- "madge": "^8.0.0",
- "tinybench": "^3.0.4",
- "typescript": "5.8.2",
- "vitest": "^3.0.4"
- },
- "overrides": {
- "typescript": "5.8.2"
- },
- "resolutions": {
- "typescript": "5.8.2"
+ "@ark/attest": "catalog:",
+ "@babel/cli": "catalog:",
+ "@babel/core": "catalog:",
+ "@babel/plugin-transform-export-namespace-from": "catalog:",
+ "@babel/plugin-transform-modules-commonjs": "catalog:",
+ "@changesets/changelog-github": "catalog:",
+ "@changesets/cli": "catalog:",
+ "@fast-check/vitest": "catalog:",
+ "@types/madge": "catalog:",
+ "@types/node": "catalog:",
+ "@vitest/coverage-v8": "catalog:",
+ "@vitest/ui": "catalog:",
+ "babel-plugin-annotate-pure-calls": "catalog:",
+ "fast-check": "catalog:",
+ "madge": "catalog:",
+ "tinybench": "catalog:",
+ "typescript": "catalog:",
+ "vitest": "catalog:"
},
"packageManager": "pnpm@10.2.1"
}
diff --git a/packages/derive-codec/package.json b/packages/derive-codec/package.json
index f44676d5..dba79328 100644
--- a/packages/derive-codec/package.json
+++ b/packages/derive-codec/package.json
@@ -48,19 +48,19 @@
},
"peerDependencies": {
"@traversable/registry": "workspace:^",
- "@traversable/schema": "workspace:^"
+ "@traversable/schema-core": "workspace:^"
},
"peerDependenciesMeta": {
"@traversable/registry": {
"optional": false
},
- "@traversable/schema": {
+ "@traversable/schema-core": {
"optional": false
}
},
"devDependencies": {
"@traversable/registry": "workspace:^",
- "@traversable/schema": "workspace:^",
+ "@traversable/schema-core": "workspace:^",
"@traversable/schema-seed": "workspace:^"
}
}
diff --git a/packages/derive-codec/src/__generated__/__manifest__.ts b/packages/derive-codec/src/__generated__/__manifest__.ts
index c7c375f5..1426835d 100644
--- a/packages/derive-codec/src/__generated__/__manifest__.ts
+++ b/packages/derive-codec/src/__generated__/__manifest__.ts
@@ -42,19 +42,19 @@ export default {
},
"peerDependencies": {
"@traversable/registry": "workspace:^",
- "@traversable/schema": "workspace:^"
+ "@traversable/schema-core": "workspace:^"
},
"peerDependenciesMeta": {
"@traversable/registry": {
"optional": false
},
- "@traversable/schema": {
+ "@traversable/schema-core": {
"optional": false
}
},
"devDependencies": {
"@traversable/registry": "workspace:^",
- "@traversable/schema": "workspace:^",
+ "@traversable/schema-core": "workspace:^",
"@traversable/schema-seed": "workspace:^"
}
} as const
\ No newline at end of file
diff --git a/packages/derive-codec/src/bind.ts b/packages/derive-codec/src/bind.ts
deleted file mode 100644
index 3e74fb89..00000000
--- a/packages/derive-codec/src/bind.ts
+++ /dev/null
@@ -1,77 +0,0 @@
-import type { Parameters } from '@traversable/registry'
-
-import {
- t,
- t_never,
- t_unknown,
- t_any,
- t_void,
- t_null,
- t_undefined,
- t_symbol,
- t_boolean,
- t_integer,
- t_bigint,
- t_number,
- t_string,
- t_eq,
- t_optional,
- t_array,
- t_record,
- t_union,
- t_intersect,
- t_tuple,
- t_object,
- // t_of,
- // def,
-} from '@traversable/schema'
-import { pipe } from './codec.js'
-
-const Object_assign = globalThis.Object.assign
-
-const def = {
- never: t.never.def,
- any: t.any.def,
- unknown: t.unknown.def,
- void: t.void.def,
- null: t.null.def,
- undefined: t.undefined.def,
- symbol: t.symbol.def,
- boolean: t.boolean.def,
- integer: t.integer.def,
- bigint: t.bigint.def,
- number: t.number.def,
- string: t.string.def,
- eq: t.eq.def,
- optional: t.optional.def,
- array: t.array.def,
- record: t.record.def,
- union: t.union.def,
- intersect: t.intersect.def,
- tuple: t.tuple.def,
- object: t.object.def,
- of: t.of.def,
-}
-
-export function bind() {
- void Object_assign(t_never, pipe(t.never));
- void Object_assign(t_unknown, pipe(t.unknown));
- void Object_assign(t_any, pipe(t.any));
- void Object_assign(t_void, pipe(t.void));
- void Object_assign(t_null, pipe(t.null));
- void Object_assign(t_undefined, pipe(t.undefined));
- void Object_assign(t_boolean, pipe(t.boolean));
- void Object_assign(t_symbol, pipe(t.symbol));
- void Object_assign(t_integer, pipe(t.integer));
- void Object_assign(t_bigint, pipe(t.bigint));
- void Object_assign(t_number, pipe(t.number));
- void Object_assign(t_string, pipe(t.string));
- void ((t_eq.def as any) = (...args: Parameters) => pipe(def.eq(...args)));
- void ((t_optional.def as any) = (...args: Parameters) => pipe(def.optional(...args)));
- void ((t_record.def as any) = (...args: Parameters) => pipe(def.record(...args)));
- void ((t_array.def as any) = (...args: Parameters) => pipe(def.array(...args)));
- void ((t_union.def as any) = (...args: Parameters) => pipe(def.union(...args)));
- void ((t_intersect.def as any) = (...args: Parameters) => pipe(def.intersect(...args)));
- void ((t_tuple.def as any) = (...args: Parameters) => pipe(def.tuple(...args)));
- void ((t_object.def as any) = (...args: Parameters) => pipe(def.object(...args)));
-}
diff --git a/packages/derive-codec/src/codec.ts b/packages/derive-codec/src/codec.ts
index c7cf4378..b1a4ba54 100644
--- a/packages/derive-codec/src/codec.ts
+++ b/packages/derive-codec/src/codec.ts
@@ -1,4 +1,5 @@
-import type { t } from '@traversable/schema'
+import type { Unknown } from '@traversable/registry'
+import type { t } from '@traversable/schema-core'
/** @internal */
interface Pipelines {
@@ -8,19 +9,31 @@ interface Pipelines {
}
export const Invariant = {
- DecodeError: (u: unknown) => globalThis.Error('DecodeError: could not decode invalid input, got: \n\r' + JSON.stringify(u, null, 2))
+ DecodeError: (u: unknown) =>
+ Error('DecodeError: could not decode invalid input, got: \n\r' + JSON.stringify(u, null, 2))
} as const
export interface Pipe { unpipe(mapBack: (b: B) => T): Codec }
-
export interface Extend { unextend(mapBack: (s: S) => B): Codec }
+export interface BindCodec {
+ pipe(map: (src: T['_type' & keyof T]) => B):
+ Pipe
+ extend(premap: (b: B) => T['_type' & keyof T]):
+ Extend
+}
+
+export let bindCodec = {
+ pipe(this: S, mapfn: (src: S['_type']) => B) { return Codec.new(this).pipe(mapfn) },
+ extend(this: S, mapfn: (src: S['_type']) => B) { return Codec.new(this).extend(mapfn) },
+} satisfies BindCodec
+
export class Codec {
static new
- : (schema: S) => S & { codec: Codec }
- = (schema) => { const codec = new Codec(schema); Object.defineProperty(schema, 'codec', { value: codec, writable: true }); return schema as never }
+ : (schema: S) => Codec
+ = (schema) => new Codec(schema)
- parse(u: S | {} | null | undefined): T | Error {
+ parse(u: S | Unknown): T | Error {
if (typeof this.schema === 'function' && this.schema(u) === false)
return Invariant.DecodeError(u)
else return this.decode(u as S)
@@ -29,7 +42,8 @@ export class Codec {
decode(source: S): T
decode(source: S) {
this._.$ = source
- for (let ix = 0, len = this._.to.length; ix < len; ix++) {
+ let len = this._.to.length
+ for (let ix = 0; ix < len; ix++) {
const f = this._.to[ix]
this._.$ = f(this._.$)
}
@@ -39,7 +53,8 @@ export class Codec {
encode(target: T): S
encode(target: T) {
this._.$ = target
- for (let ix = this._.from.length; ix-- !== 0;) {
+ let len = this._.from.length
+ for (let ix = len; ix-- !== 0;) {
const f = this._.from[ix]
this._.$ = f(this._.$)
}
@@ -68,21 +83,8 @@ export class Codec {
}
}
- private constructor(
+ constructor(
public schema: A,
private _: Pipelines = { from: [], to: [], $: void 0 }
) { }
}
-
-export interface pipe {
- codec: {
- pipe(map: (src: T['_type' & keyof T]) => B):
- Pipe
- extend(premap: (b: B) => T['_type' & keyof T]):
- Extend
- }
-}
-
-export function pipe(schema: S): pipe {
- return Codec.new(schema)
-}
diff --git a/packages/derive-codec/src/exports.ts b/packages/derive-codec/src/exports.ts
index ff1a5fff..705f9570 100644
--- a/packages/derive-codec/src/exports.ts
+++ b/packages/derive-codec/src/exports.ts
@@ -5,5 +5,4 @@ export type {
} from './codec.js'
export {
Codec,
- pipe,
} from './codec.js'
diff --git a/packages/derive-codec/src/install.ts b/packages/derive-codec/src/install.ts
index 8dd38fac..97f04836 100644
--- a/packages/derive-codec/src/install.ts
+++ b/packages/derive-codec/src/install.ts
@@ -1,30 +1,58 @@
-import type { t } from '@traversable/schema'
-import type { pipe } from './codec.js'
+import { Object_assign } from '@traversable/registry'
+import { t } from '@traversable/schema-core'
-import { bind } from './bind.js'
-// SIDE-EFFECT
-void bind()
+import type { BindCodec } from './codec.js'
+import { bindCodec } from './codec.js'
-declare module '@traversable/schema' {
- interface t_LowerBound extends pipe> { }
- interface t_never extends pipe { }
- interface t_unknown extends pipe { }
- interface t_void extends pipe { }
- interface t_any extends pipe { }
- interface t_null extends pipe { }
- interface t_undefined extends pipe { }
- interface t_symbol extends pipe { }
- interface t_boolean extends pipe { }
- interface t_integer extends pipe { }
- interface t_bigint extends pipe { }
- interface t_number extends pipe { }
- interface t_string extends pipe { }
- interface t_eq extends pipe> { }
- interface t_optional extends pipe> { }
- interface t_array extends pipe> { }
- interface t_record extends pipe> { }
- interface t_union extends pipe> { }
- interface t_intersect extends pipe> { }
- interface t_tuple extends pipe> { }
- interface t_object extends pipe> { }
+declare module '@traversable/schema-core' {
+ interface t_LowerBound extends BindCodec> { }
+ // interface t_never extends BindCodec { }
+ interface t_unknown extends BindCodec { }
+ interface t_void extends BindCodec { }
+ interface t_any extends BindCodec { }
+ interface t_null extends BindCodec { }
+ interface t_undefined extends BindCodec { }
+ interface t_symbol extends BindCodec { }
+ interface t_boolean extends BindCodec { }
+ interface t_integer extends BindCodec { }
+ interface t_bigint extends BindCodec { }
+ interface t_number extends BindCodec { }
+ interface t_string extends BindCodec { }
+ interface t_eq extends BindCodec> { }
+ interface t_optional extends BindCodec> { }
+ interface t_array extends BindCodec> { }
+ interface t_record extends BindCodec> { }
+ interface t_union extends BindCodec> { }
+ interface t_intersect extends BindCodec> { }
+ interface t_tuple extends BindCodec> { }
+ interface t_object extends BindCodec> { }
+}
+
+/////////////////
+/// INSTALL ///
+void bind() ///
+/// INSTALL ///
+/////////////////
+
+export function bind() {
+ Object_assign(t.never, bindCodec)
+ Object_assign(t.unknown, bindCodec)
+ Object_assign(t.any, bindCodec)
+ Object_assign(t.void, bindCodec)
+ Object_assign(t.null, bindCodec)
+ Object_assign(t.undefined, bindCodec)
+ Object_assign(t.boolean, bindCodec)
+ Object_assign(t.symbol, bindCodec)
+ Object_assign(t.integer, bindCodec)
+ Object_assign(t.bigint, bindCodec)
+ Object_assign(t.number, bindCodec)
+ Object_assign(t.string, bindCodec)
+ Object_assign(t.eq.userDefinitions, bindCodec)
+ Object_assign(t.optional.userDefinitions, bindCodec)
+ Object_assign(t.array.userDefinitions, bindCodec)
+ Object_assign(t.record.userDefinitions, bindCodec)
+ Object_assign(t.union.userDefinitions, bindCodec)
+ Object_assign(t.intersect.userDefinitions, bindCodec)
+ Object_assign(t.tuple.userDefinitions, bindCodec)
+ Object_assign(t.object.userDefinitions, bindCodec)
}
diff --git a/packages/derive-codec/test/codec.test.ts b/packages/derive-codec/test/codec.test.ts
index 4f970c59..afd805b1 100644
--- a/packages/derive-codec/test/codec.test.ts
+++ b/packages/derive-codec/test/codec.test.ts
@@ -1,7 +1,7 @@
import * as vi from 'vitest'
import { Codec } from '@traversable/derive-codec'
-import { t } from '@traversable/schema'
+import { t } from '@traversable/schema-core'
vi.describe('〖⛳️〗‹‹‹ ❲@traverable/derive-codec❳', () => {
vi.it('〖⛳️〗› ❲Codec❳', () => {
@@ -35,7 +35,7 @@ vi.describe('〖⛳️〗‹‹‹ ❲@traverable/derive-codec❳', () => {
}] satisfies [any]
const codec_01 = Codec
- .new(ServerUser).codec
+ .new(ServerUser)
.extend(({ data }: { data: ServerUser }) => data)
.unextend((_) => ({ data: _ }))
.extend(([_]: [{ data: ServerUser }]) => _)
@@ -51,4 +51,3 @@ vi.describe('〖⛳️〗‹‹‹ ❲@traverable/derive-codec❳', () => {
vi.assert.deepEqual(codec_01.encode(codec_01.decode(codec_01.encode(codec_01.decode(serverResponse)))), serverResponse)
})
})
-
diff --git a/packages/derive-codec/test/install.test.ts b/packages/derive-codec/test/install.test.ts
index 61b7c7b6..56fd6077 100644
--- a/packages/derive-codec/test/install.test.ts
+++ b/packages/derive-codec/test/install.test.ts
@@ -1,12 +1,41 @@
-import * as vi from 'vitest'
-import { t } from '@traversable/schema'
+import { assert, it, describe, vi } from 'vitest'
-vi.describe('〖⛳️〗‹‹‹ ❲@traversable/derive-codec❳', () => {
- vi.it('〖⛳️〗› ❲pre-install❳', () => vi.assert.isFalse(t.has('codec')(t.string)))
+import { t } from '@traversable/schema-core'
- vi.it('〖⛳️〗› ❲post-install❳', () => {
- import('@traversable/derive-codec/install')
- .then(() => vi.assert.isTrue(t.has('codec')(t.string)))
- .catch((e) => vi.assert.fail(e.message))
+describe('〖⛳️〗‹‹‹ ❲@traversable/derive-codec❳', async () => {
+ it('〖⛳️〗› ❲pre-install❳', async () => {
+ assert.isFalse(t.has('pipe')(t.string))
+ assert.isFalse(t.has('extend')(t.string))
+ })
+
+ it('〖⛳️〗› ❲post-install❳', async () => {
+ assert.isFalse(t.has('pipe')(t.string))
+ assert.isFalse(t.has('extend')(t.string))
+
+ await vi.waitFor(() => import('@traversable/derive-codec/install'))
+
+ assert.isTrue(t.has('pipe')(t.string))
+ assert.isTrue(t.has('extend')(t.string))
+
+ let codec_01 = t.array(t.string)
+ .pipe((ss) => ss.map(Number))
+ .unpipe((xs) => xs.map(String))
+
+ assert.deepEqual(codec_01.decode(['1', '2', '3']), [1, 2, 3])
+ assert.deepEqual(codec_01.encode([1, 2, 3]), ['1', '2', '3'])
+
+ let codec_02 = t.array(t.array(t.integer))
+ .pipe((xss) => xss.map((xs) => xs.map((x) => [x] satisfies [any])))
+ .unpipe((yss) => yss.map((ys) => ys.map(([y]) => y)))
+ .pipe((xss) => xss.map((xs) => xs.map(([x]) => [x - 1] satisfies [any])))
+ .unpipe((yss) => yss.map((ys) => ys.map(([y]) => [y + 1])))
+
+ assert.deepEqual(codec_02.decode(
+ [[0, 1, 2], [3, 4, 5], [6, 7, 8]]
+ ), [[[-1], [0], [1]], [[2], [3], [4]], [[5], [6], [7]]])
+
+ assert.deepEqual(codec_02.encode(
+ [[[-1], [0], [1]], [[2], [3], [4]], [[5], [6], [7]]]
+ ), [[0, 1, 2], [3, 4, 5], [6, 7, 8]])
})
})
diff --git a/packages/derive-codec/tsconfig.build.json b/packages/derive-codec/tsconfig.build.json
index cabdfce7..2972409b 100644
--- a/packages/derive-codec/tsconfig.build.json
+++ b/packages/derive-codec/tsconfig.build.json
@@ -9,6 +9,6 @@
},
"references": [
{ "path": "../registry" },
- { "path": "../schema" }
+ { "path": "../schema-core" }
]
}
diff --git a/packages/derive-codec/tsconfig.src.json b/packages/derive-codec/tsconfig.src.json
index fa90f525..9416bd78 100644
--- a/packages/derive-codec/tsconfig.src.json
+++ b/packages/derive-codec/tsconfig.src.json
@@ -8,7 +8,7 @@
},
"references": [
{ "path": "../registry" },
- { "path": "../schema" }
+ { "path": "../schema-core" }
],
"include": ["src"]
}
diff --git a/packages/derive-codec/tsconfig.test.json b/packages/derive-codec/tsconfig.test.json
index 80aa9583..3ad0d988 100644
--- a/packages/derive-codec/tsconfig.test.json
+++ b/packages/derive-codec/tsconfig.test.json
@@ -9,7 +9,7 @@
"references": [
{ "path": "tsconfig.src.json" },
{ "path": "../registry" },
- { "path": "../schema" },
+ { "path": "../schema-core" },
{ "path": "../schema-seed" }
],
"include": ["test"]
diff --git a/packages/derive-equals/package.json b/packages/derive-equals/package.json
index 070d2f37..342235ff 100644
--- a/packages/derive-equals/package.json
+++ b/packages/derive-equals/package.json
@@ -17,7 +17,8 @@
"@traversable": {
"generateExports": {
"include": [
- "**/*.ts"
+ "**/*.ts",
+ "schemas/*.ts"
]
},
"generateIndex": {
@@ -46,7 +47,7 @@
"peerDependencies": {
"@traversable/json": "workspace:^",
"@traversable/registry": "workspace:^",
- "@traversable/schema": "workspace:^"
+ "@traversable/schema-core": "workspace:^"
},
"peerDependenciesMeta": {
"@traversable/json": {
@@ -55,14 +56,14 @@
"@traversable/registry": {
"optional": false
},
- "@traversable/schema": {
+ "@traversable/schema-core": {
"optional": false
}
},
"devDependencies": {
"@traversable/json": "workspace:^",
"@traversable/registry": "workspace:^",
- "@traversable/schema": "workspace:^",
+ "@traversable/schema-core": "workspace:^",
"@traversable/schema-seed": "workspace:^",
"@traversable/schema-to-string": "workspace:^"
}
diff --git a/packages/derive-equals/src/__generated__/__manifest__.ts b/packages/derive-equals/src/__generated__/__manifest__.ts
index 19d271aa..3ac6d645 100644
--- a/packages/derive-equals/src/__generated__/__manifest__.ts
+++ b/packages/derive-equals/src/__generated__/__manifest__.ts
@@ -16,7 +16,7 @@ export default {
},
"@traversable": {
"generateExports": {
- "include": ["**/*.ts"]
+ "include": ["**/*.ts", "schemas/*.ts"]
},
"generateIndex": {
"include": ["**/*.ts"]
@@ -42,7 +42,7 @@ export default {
"peerDependencies": {
"@traversable/json": "workspace:^",
"@traversable/registry": "workspace:^",
- "@traversable/schema": "workspace:^"
+ "@traversable/schema-core": "workspace:^"
},
"peerDependenciesMeta": {
"@traversable/json": {
@@ -51,14 +51,14 @@ export default {
"@traversable/registry": {
"optional": false
},
- "@traversable/schema": {
+ "@traversable/schema-core": {
"optional": false
}
},
"devDependencies": {
"@traversable/json": "workspace:^",
"@traversable/registry": "workspace:^",
- "@traversable/schema": "workspace:^",
+ "@traversable/schema-core": "workspace:^",
"@traversable/schema-seed": "workspace:^",
"@traversable/schema-to-string": "workspace:^"
}
diff --git a/packages/derive-equals/src/equals.ts b/packages/derive-equals/src/equals.ts
index 2fc46842..646f757e 100644
--- a/packages/derive-equals/src/equals.ts
+++ b/packages/derive-equals/src/equals.ts
@@ -1,7 +1,7 @@
import type { Algebra, Kind } from '@traversable/registry'
import { Equal, fn, URI } from '@traversable/registry'
import type { Json } from '@traversable/json'
-import { t } from '@traversable/schema'
+import { t } from '@traversable/schema-core'
/** @internal */
type FixUnknown = 0 extends T & 1 ? unknown : T
diff --git a/packages/derive-equals/src/install.ts b/packages/derive-equals/src/install.ts
index a4fc0eec..23c2cb55 100644
--- a/packages/derive-equals/src/install.ts
+++ b/packages/derive-equals/src/install.ts
@@ -1,15 +1,20 @@
-import { Equal, has } from '@traversable/registry'
-import { t } from '@traversable/schema'
-
-import * as Eq from './equals.js'
+import {
+ Array_isArray,
+ Equal,
+ Object_assign,
+ Object_hasOwn,
+ Object_is,
+ Object_keys,
+} from '@traversable/registry'
+import { t } from '@traversable/schema-core'
export interface equals {
equals: Equal
}
-declare module '@traversable/schema' {
+declare module '@traversable/schema-core' {
interface t_LowerBound extends equals { }
- interface t_never extends equals { }
+ // interface t_never extends equals { }
interface t_unknown extends equals { }
interface t_void extends equals { }
interface t_any extends equals { }
@@ -31,33 +36,7 @@ declare module '@traversable/schema' {
interface t_object extends equals { }
}
-/** @internal */
-const hasEquals
- : (u: unknown) => u is { equals: Equal }
- = has('equals', (u): u is Equal => typeof u === 'function' && u.length === 2)
-
-/** @internal */
-const getEquals
- : (u: unknown) => Equal
- = (u) => hasEquals(u) ? u.equals : Object_is
-
-/** @internal */
-const Object_assign = globalThis.Object.assign
-
-/** @internal */
-const Object_keys = globalThis.Object.keys
-
-/** @internal */
-const Array_isArray = globalThis.Array.isArray
-
-/** @internal */
-const Object_is = globalThis.Object.is
-
-/** @internal */
-const hasOwn = (u: unknown, k: K): u is Record =>
- !!u && typeof u === 'object' && globalThis.Object.prototype.hasOwnProperty.call(u, k)
-
-export function eqEquals(this: any, x: V, y: V): boolean { return t.eq.def(x)(y) }
+export function eqEquals(this: t.eq, x: V, y: V): boolean { return t.eq.def(x)(y) }
export function optionalEquals(
this: t.optional<{ equals: Equal }>,
@@ -99,19 +78,20 @@ export function recordEquals(
if (len !== rhs.length) return false
for (let ix = len; ix-- !== 0;) {
k = lhs[ix]
- if (!hasOwn(r, k)) return false
+ if (!Object_hasOwn(r, k)) return false
if (!(this.def.equals(l[k], r[k]))) return false
}
len = rhs.length
for (let ix = len; ix-- !== 0;) {
k = rhs[ix]
- if (!hasOwn(l, k)) return false
+ if (!Object_hasOwn(l, k)) return false
if (!(this.def.equals(l[k], r[k]))) return false
}
- return Eq.record(this.def.equals)(l, r)
+ return true
}
-export function unionEquals(this: t.union<{ equals: Equal }[]>,
+export function unionEquals(
+ this: t.union<{ equals: Equal }[]>,
l: unknown,
r: unknown
): boolean {
@@ -141,10 +121,10 @@ export function tupleEquals(
if (Array_isArray(l)) {
if (!Array_isArray(r)) return false
for (let ix = this.def.length; ix-- !== 0;) {
- if (!hasOwn(l, ix) && !hasOwn(r, ix)) continue
- if (hasOwn(l, ix) && !hasOwn(r, ix)) return false
- if (!hasOwn(l, ix) && hasOwn(r, ix)) return false
- if (hasOwn(l, ix) && hasOwn(r, ix)) {
+ if (!Object_hasOwn(l, ix) && !Object_hasOwn(r, ix)) continue
+ if (Object_hasOwn(l, ix) && !Object_hasOwn(r, ix)) return false
+ if (!Object_hasOwn(l, ix) && Object_hasOwn(r, ix)) return false
+ if (Object_hasOwn(l, ix) && Object_hasOwn(r, ix)) {
if (!this.def[ix].equals(l[ix], r[ix])) return false
}
}
@@ -162,8 +142,8 @@ export function objectEquals(
if (!l || typeof l !== 'object' || Array_isArray(l)) return false
if (!r || typeof r !== 'object' || Array_isArray(r)) return false
for (const k in this.def) {
- const lHas = hasOwn(l, k)
- const rHas = hasOwn(r, k)
+ const lHas = Object_hasOwn(l, k)
+ const rHas = Object_hasOwn(r, k)
if (lHas) {
if (!rHas) return false
if (!this.def[k].equals(l[k], r[k])) return false
@@ -183,9 +163,6 @@ void bind() ///
/// INSTALL ///
/////////////////
-
-function stringEquals(l: never, r: never) { return Object_is(l, r) }
-
export function bind() {
Object_assign(t.never, { equals: function neverEquals(l: never, r: never) { return Object_is(l, r) } })
Object_assign(t.unknown, { equals: function unknownEquals(l: never, r: never) { return Object_is(l, r) } })
@@ -198,17 +175,13 @@ export function bind() {
Object_assign(t.integer, { equals: function integerEquals(l: never, r: never) { return Object_is(l, r) } })
Object_assign(t.bigint, { equals: function bigintEquals(l: never, r: never) { return Object_is(l, r) } })
Object_assign(t.number, { equals: function numberEquals(l: never, r: never) { return Object_is(l, r) } })
- Object_assign(t.string, { equals: stringEquals.bind(t.string) })
- Object_assign(t.eq.prototype, { equals: eqEquals })
-
- // let test = arrayEquals.bind(t.array.prototype)
- t.array.prototype.equals = arrayEquals
- t.record.prototype.equals = recordEquals
- // Object_assign(t.array.prototype, { equals: arrayEquals.bind(t.array.prototype) })
- // Object_assign(t.record.prototype, { equals: recordEquals })
- Object_assign(t.optional.prototype, { equals: optionalEquals })
- Object_assign(t.union.prototype, { equals: unionEquals })
- Object_assign(t.intersect.prototype, { equals: intersectEquals })
- Object_assign(t.tuple.prototype, { equals: tupleEquals })
- Object_assign(t.object.prototype, { equals: objectEquals })
+ Object_assign(t.string, { equals: function stringEquals(l: never, r: never) { return Object_is(l, r) } })
+ Object_assign(t.eq.userDefinitions, { equals: eqEquals })
+ Object_assign(t.array.userDefinitions, { equals: arrayEquals })
+ Object_assign(t.record.userDefinitions, { equals: recordEquals })
+ Object_assign(t.optional.userDefinitions, { equals: optionalEquals })
+ Object_assign(t.union.userDefinitions, { equals: unionEquals })
+ Object_assign(t.intersect.userDefinitions, { equals: intersectEquals })
+ Object_assign(t.tuple.userDefinitions, { equals: tupleEquals })
+ Object_assign(t.object.userDefinitions, { equals: objectEquals })
}
diff --git a/packages/derive-equals/src/schemas/any.ts b/packages/derive-equals/src/schemas/any.ts
new file mode 100644
index 00000000..09d8da5f
--- /dev/null
+++ b/packages/derive-equals/src/schemas/any.ts
@@ -0,0 +1,7 @@
+import type { Equal } from "@traversable/registry"
+import { Object_is } from "@traversable/registry"
+
+export type equals = Equal
+export function equals(left: unknown, right: unknown): boolean {
+ return Object_is(left, right)
+}
diff --git a/packages/derive-equals/src/schemas/array.ts b/packages/derive-equals/src/schemas/array.ts
new file mode 100644
index 00000000..aa06a7bf
--- /dev/null
+++ b/packages/derive-equals/src/schemas/array.ts
@@ -0,0 +1,24 @@
+import type { Equal } from '@traversable/registry'
+import { has, Array_isArray, Object_is } from '@traversable/registry'
+import type { t } from '@traversable/schema-core'
+
+export type equals = never | Equal
+
+export function equals(arraySchema: t.array): equals
+export function equals(arraySchema: t.array): equals
+export function equals({ def }: t.array<{ equals: Equal }>): Equal {
+ let equals = has('equals', (x): x is Equal => typeof x === 'function')(def) ? def.equals : Object_is
+ function arrayEquals(l: unknown[], r: unknown[]): boolean {
+ if (Object_is(l, r)) return true
+ if (Array_isArray(l)) {
+ if (!Array_isArray(r)) return false
+ let len = l.length
+ if (len !== r.length) return false
+ for (let ix = len; ix-- !== 0;)
+ if (!equals(l[ix], r[ix])) return false
+ return true
+ } else return false
+ }
+ return arrayEquals
+}
+
diff --git a/packages/derive-equals/src/schemas/bigint.ts b/packages/derive-equals/src/schemas/bigint.ts
new file mode 100644
index 00000000..7c98bbf1
--- /dev/null
+++ b/packages/derive-equals/src/schemas/bigint.ts
@@ -0,0 +1,7 @@
+import type { Equal } from '@traversable/registry'
+import { Object_is } from '@traversable/registry'
+
+export type equals = Equal
+export function equals(left: bigint, right: bigint): boolean {
+ return Object_is(left, right)
+}
diff --git a/packages/derive-equals/src/schemas/boolean.ts b/packages/derive-equals/src/schemas/boolean.ts
new file mode 100644
index 00000000..306bb12b
--- /dev/null
+++ b/packages/derive-equals/src/schemas/boolean.ts
@@ -0,0 +1,7 @@
+import type { Equal } from '@traversable/registry'
+import { Object_is } from '@traversable/registry'
+
+export type equals = Equal
+export function equals(left: boolean, right: boolean): boolean {
+ return Object_is(left, right)
+}
diff --git a/packages/derive-equals/src/schemas/eq.ts b/packages/derive-equals/src/schemas/eq.ts
new file mode 100644
index 00000000..774127f6
--- /dev/null
+++ b/packages/derive-equals/src/schemas/eq.ts
@@ -0,0 +1,11 @@
+import type { Equal } from '@traversable/registry'
+import { laxEquals } from '@traversable/registry'
+import type { t } from '@traversable/schema-core'
+
+export type equals = never | Equal
+export function equals(eqSchema: t.eq): equals
+export function equals(): Equal {
+ return function eqEquals(left: any, right: any) {
+ return laxEquals(left, right)
+ }
+}
diff --git a/packages/derive-equals/src/schemas/integer.ts b/packages/derive-equals/src/schemas/integer.ts
new file mode 100644
index 00000000..29fcd602
--- /dev/null
+++ b/packages/derive-equals/src/schemas/integer.ts
@@ -0,0 +1,7 @@
+import type { Equal } from '@traversable/registry'
+import { SameValueNumber } from '@traversable/registry'
+
+export type equals = Equal
+export function equals(left: number, right: number): boolean {
+ return SameValueNumber(left, right)
+}
diff --git a/packages/derive-equals/src/schemas/intersect.ts b/packages/derive-equals/src/schemas/intersect.ts
new file mode 100644
index 00000000..ce880aa1
--- /dev/null
+++ b/packages/derive-equals/src/schemas/intersect.ts
@@ -0,0 +1,16 @@
+import type { Equal } from '@traversable/registry'
+import { Object_is } from '@traversable/registry'
+import type { t } from '@traversable/schema-core'
+
+export type equals = Equal
+export function equals(intersectSchema: t.intersect<[...S]>): equals
+export function equals(intersectSchema: t.intersect<[...S]>): equals
+export function equals({ def }: t.intersect<{ equals: Equal }[]>): Equal {
+ function intersectEquals(l: unknown, r: unknown): boolean {
+ if (Object_is(l, r)) return true
+ for (let ix = def.length; ix-- !== 0;)
+ if (!def[ix].equals(l, r)) return false
+ return true
+ }
+ return intersectEquals
+}
diff --git a/packages/derive-equals/src/schemas/never.ts b/packages/derive-equals/src/schemas/never.ts
new file mode 100644
index 00000000..3ed89421
--- /dev/null
+++ b/packages/derive-equals/src/schemas/never.ts
@@ -0,0 +1,6 @@
+import type { Equal } from '@traversable/registry'
+
+export type equals = Equal
+export function equals(left: never, right: never): boolean {
+ return false
+}
diff --git a/packages/derive-equals/src/schemas/null.ts b/packages/derive-equals/src/schemas/null.ts
new file mode 100644
index 00000000..12c2f636
--- /dev/null
+++ b/packages/derive-equals/src/schemas/null.ts
@@ -0,0 +1,7 @@
+import type { Equal } from '@traversable/registry'
+import { Object_is } from '@traversable/registry'
+
+export type equals = Equal
+export function equals(left: null, right: null): boolean {
+ return Object_is(left, right)
+}
diff --git a/packages/derive-equals/src/schemas/number.ts b/packages/derive-equals/src/schemas/number.ts
new file mode 100644
index 00000000..29fcd602
--- /dev/null
+++ b/packages/derive-equals/src/schemas/number.ts
@@ -0,0 +1,7 @@
+import type { Equal } from '@traversable/registry'
+import { SameValueNumber } from '@traversable/registry'
+
+export type equals = Equal
+export function equals(left: number, right: number): boolean {
+ return SameValueNumber(left, right)
+}
diff --git a/packages/derive-equals/src/schemas/object.ts b/packages/derive-equals/src/schemas/object.ts
new file mode 100644
index 00000000..ecda0b32
--- /dev/null
+++ b/packages/derive-equals/src/schemas/object.ts
@@ -0,0 +1,55 @@
+import type * as T from '@traversable/registry'
+import { Array_isArray, Object_hasOwn, Object_is } from '@traversable/registry'
+import type { t } from '@traversable/schema-core'
+
+export type equals = never | T.Equal
+export function equals(objectSchema: t.object): equals>
+export function equals(objectSchema: t.object): equals>
+export function equals({ def }: t.object): equals> {
+ function objectEquals(l: { [x: string]: unknown }, r: { [x: string]: unknown }) {
+ if (Object_is(l, r)) return true
+ if (!l || typeof l !== 'object' || Array_isArray(l)) return false
+ if (!r || typeof r !== 'object' || Array_isArray(r)) return false
+ for (const k in def) {
+ const lHas = Object_hasOwn(l, k)
+ const rHas = Object_hasOwn(r, k)
+ if (lHas) {
+ if (!rHas) return false
+ if (!def[k].equals(l[k], r[k])) return false
+ }
+ if (rHas) {
+ if (!lHas) return false
+ if (!def[k].equals(l[k], r[k])) return false
+ }
+ if (!def[k].equals(l[k], r[k])) return false
+ }
+ return true
+ }
+ return objectEquals
+}
+
+// export type equals = never | T.Equal
+// export function equals(objectSchema: t.object): equals>
+// export function equals(objectSchema: t.object): equals>
+// export function equals({ def }: t.object<{ [x: string]: { equals: T.Equal } }>): T.Equal<{ [x: string]: unknown }> {
+// function objectEquals(l: { [x: string]: unknown }, r: { [x: string]: unknown }) {
+// if (Object_is(l, r)) return true
+// if (!l || typeof l !== 'object' || Array_isArray(l)) return false
+// if (!r || typeof r !== 'object' || Array_isArray(r)) return false
+// for (const k in def) {
+// const lHas = Object_hasOwn(l, k)
+// const rHas = Object_hasOwn(r, k)
+// if (lHas) {
+// if (!rHas) return false
+// if (!def[k].equals(l[k], r[k])) return false
+// }
+// if (rHas) {
+// if (!lHas) return false
+// if (!def[k].equals(l[k], r[k])) return false
+// }
+// if (!def[k].equals(l[k], r[k])) return false
+// }
+// return true
+// }
+// return objectEquals
+// }
diff --git a/packages/derive-equals/src/schemas/of.ts b/packages/derive-equals/src/schemas/of.ts
new file mode 100644
index 00000000..38809729
--- /dev/null
+++ b/packages/derive-equals/src/schemas/of.ts
@@ -0,0 +1,6 @@
+import { Equal } from '@traversable/registry'
+
+export type equals = Equal
+export function equals(left: T, right: T): boolean {
+ return Equal.lax(left, right)
+}
diff --git a/packages/derive-equals/src/schemas/optional.ts b/packages/derive-equals/src/schemas/optional.ts
new file mode 100644
index 00000000..25944376
--- /dev/null
+++ b/packages/derive-equals/src/schemas/optional.ts
@@ -0,0 +1,13 @@
+import type { Equal } from '@traversable/registry'
+import { Object_is } from '@traversable/registry'
+import type { t } from '@traversable/schema-core'
+
+export type equals = never | Equal
+export function equals(optionalSchema: t.optional): equals
+export function equals(optionalSchema: t.optional): equals
+export function equals({ def }: t.optional<{ equals: Equal }>): Equal {
+ return function optionalEquals(l: unknown, r: unknown): boolean {
+ if (Object_is(l, r)) return true
+ return def.equals(l, r)
+ }
+}
diff --git a/packages/derive-equals/src/schemas/record.ts b/packages/derive-equals/src/schemas/record.ts
new file mode 100644
index 00000000..07addff1
--- /dev/null
+++ b/packages/derive-equals/src/schemas/record.ts
@@ -0,0 +1,32 @@
+import type { Equal } from '@traversable/registry'
+import { Array_isArray, Object_is, Object_keys, Object_hasOwn } from '@traversable/registry'
+import type { t } from '@traversable/schema-core'
+
+export type equals = never | Equal
+export function equals(recordSchema: t.record): equals
+export function equals(recordSchema: t.record): equals
+export function equals({ def }: t.record<{ equals: Equal }>): Equal> {
+ function recordEquals(l: Record, r: Record): boolean {
+ if (Object_is(l, r)) return true
+ if (!l || typeof l !== 'object' || Array_isArray(l)) return false
+ if (!r || typeof r !== 'object' || Array_isArray(r)) return false
+ const lhs = Object_keys(l)
+ const rhs = Object_keys(r)
+ let len = lhs.length
+ let k: string
+ if (len !== rhs.length) return false
+ for (let ix = len; ix-- !== 0;) {
+ k = lhs[ix]
+ if (!Object_hasOwn(r, k)) return false
+ if (!(def.equals(l[k], r[k]))) return false
+ }
+ len = rhs.length
+ for (let ix = len; ix-- !== 0;) {
+ k = rhs[ix]
+ if (!Object_hasOwn(l, k)) return false
+ if (!(def.equals(l[k], r[k]))) return false
+ }
+ return true
+ }
+ return recordEquals
+}
diff --git a/packages/derive-equals/src/schemas/string.ts b/packages/derive-equals/src/schemas/string.ts
new file mode 100644
index 00000000..b9444108
--- /dev/null
+++ b/packages/derive-equals/src/schemas/string.ts
@@ -0,0 +1,6 @@
+import type { Equal } from '@traversable/registry'
+
+export type equals = Equal
+export function equals(left: string, right: string): boolean {
+ return left === right
+}
diff --git a/packages/derive-equals/src/schemas/symbol.ts b/packages/derive-equals/src/schemas/symbol.ts
new file mode 100644
index 00000000..f3bb7486
--- /dev/null
+++ b/packages/derive-equals/src/schemas/symbol.ts
@@ -0,0 +1,7 @@
+import type { Equal } from '@traversable/registry'
+import { Object_is } from '@traversable/registry'
+
+export type equals = Equal
+export function equals(left: symbol, right: symbol): boolean {
+ return Object_is(left, right)
+}
diff --git a/packages/derive-equals/src/schemas/tuple.ts b/packages/derive-equals/src/schemas/tuple.ts
new file mode 100644
index 00000000..66adadaa
--- /dev/null
+++ b/packages/derive-equals/src/schemas/tuple.ts
@@ -0,0 +1,27 @@
+import type { Equal } from '@traversable/registry'
+import { Array_isArray, Object_hasOwn, Object_is } from '@traversable/registry'
+import type { t } from '@traversable/schema-core'
+
+export type equals = Equal
+
+export function equals(tupleSchema: t.tuple): equals
+export function equals(tupleSchema: t.tuple): equals
+export function equals(tupleSchema: t.tuple) {
+ function tupleEquals(l: typeof tupleSchema['_type'], r: typeof tupleSchema['_type']): boolean {
+ if (Object_is(l, r)) return true
+ if (Array_isArray(l)) {
+ if (!Array_isArray(r)) return false
+ for (let ix = tupleSchema.def.length; ix-- !== 0;) {
+ if (!Object_hasOwn(l, ix) && !Object_hasOwn(r, ix)) continue
+ if (Object_hasOwn(l, ix) && !Object_hasOwn(r, ix)) return false
+ if (!Object_hasOwn(l, ix) && Object_hasOwn(r, ix)) return false
+ if (Object_hasOwn(l, ix) && Object_hasOwn(r, ix)) {
+ if (!tupleSchema.def[ix].equals(l[ix], r[ix])) return false
+ }
+ }
+ return true
+ }
+ return false
+ }
+ return tupleEquals
+}
diff --git a/packages/derive-equals/src/schemas/undefined.ts b/packages/derive-equals/src/schemas/undefined.ts
new file mode 100644
index 00000000..75156d56
--- /dev/null
+++ b/packages/derive-equals/src/schemas/undefined.ts
@@ -0,0 +1,7 @@
+import type { Equal } from '@traversable/registry'
+import { Object_is } from '@traversable/registry'
+
+export type equals = Equal
+export function equals(left: undefined, right: undefined): boolean {
+ return Object_is(left, right)
+}
diff --git a/packages/derive-equals/src/schemas/union.ts b/packages/derive-equals/src/schemas/union.ts
new file mode 100644
index 00000000..c0275e69
--- /dev/null
+++ b/packages/derive-equals/src/schemas/union.ts
@@ -0,0 +1,16 @@
+import type { Equal } from '@traversable/registry'
+import { Object_is } from '@traversable/registry'
+import type { t } from '@traversable/schema-core'
+
+export type equals = Equal
+export function equals(unionSchema: t.union<[...S]>): equals
+export function equals(unionSchema: t.union<[...S]>): equals
+export function equals({ def }: t.union<{ equals: Equal }[]>): Equal {
+ function unionEquals(l: unknown, r: unknown): boolean {
+ if (Object_is(l, r)) return true
+ for (let ix = def.length; ix-- !== 0;)
+ if (def[ix].equals(l, r)) return true
+ return false
+ }
+ return unionEquals
+}
diff --git a/packages/derive-equals/src/schemas/unknown.ts b/packages/derive-equals/src/schemas/unknown.ts
new file mode 100644
index 00000000..ccd2a780
--- /dev/null
+++ b/packages/derive-equals/src/schemas/unknown.ts
@@ -0,0 +1,7 @@
+import type { Equal } from '@traversable/registry'
+import { Object_is } from '@traversable/registry'
+
+export type equals = Equal
+export function equals(left: any, right: any): boolean {
+ return Object_is(left, right)
+}
diff --git a/packages/derive-equals/src/schemas/void.ts b/packages/derive-equals/src/schemas/void.ts
new file mode 100644
index 00000000..d11d89e3
--- /dev/null
+++ b/packages/derive-equals/src/schemas/void.ts
@@ -0,0 +1,7 @@
+import type { Equal } from '@traversable/registry'
+import { Object_is } from '@traversable/registry'
+
+export type equals = Equal
+export function equals(left: void, right: void): boolean {
+ return Object_is(left, right)
+}
diff --git a/packages/derive-equals/test/equals.test.ts b/packages/derive-equals/test/equals.test.ts
index a08e6d89..4a7cf067 100644
--- a/packages/derive-equals/test/equals.test.ts
+++ b/packages/derive-equals/test/equals.test.ts
@@ -4,7 +4,7 @@ import * as NodeJSUtil from 'node:util'
import type { Algebra, Kind } from '@traversable/registry'
import { Equal, fn, omitMethods, URI } from '@traversable/registry'
-import { t } from '@traversable/schema'
+import { t } from '@traversable/schema-core'
import { Seed } from '@traversable/schema-seed'
import { Eq } from '@traversable/derive-equals'
diff --git a/packages/derive-equals/test/install.test.ts b/packages/derive-equals/test/install.test.ts
index 02d25347..1a409bdd 100644
--- a/packages/derive-equals/test/install.test.ts
+++ b/packages/derive-equals/test/install.test.ts
@@ -1,12 +1,33 @@
-import * as vi from 'vitest'
-import { t } from '@traversable/schema'
+import { assert, describe, it, vi } from 'vitest'
+import { t } from '@traversable/schema-core'
-vi.describe('〖⛳️〗‹‹‹ ❲@traversable/derive-equals❳', () => {
- vi.it('〖⛳️〗› ❲pre-install❳', () => vi.assert.isFalse(t.has('equals')(t.string)))
+describe('〖⛳️〗‹‹‹ ❲@traversable/derive-equals❳', async () => {
+ it('〖⛳️〗› ❲pre-install❳', () => assert.isFalse(t.has('equals')(t.string)))
- vi.it('〖⛳️〗› ❲post-install❳', () => {
- import('@traversable/derive-equals/install')
- .then(() => vi.assert.isTrue(t.has('equals')(t.string)))
- .catch((e) => vi.assert.fail(e.message))
+ it('〖⛳️〗› ❲post-install❳', async () => {
+ assert.isFalse(t.has('equals')(t.string))
+ assert.isFalse(t.has('equals')(t.array(t.string)))
+
+ await vi.waitFor(() => import('@traversable/derive-equals/install'))
+
+ assert.isTrue(t.has('equals')(t.string))
+ assert.isTrue(t.has('equals')(t.array(t.string)))
+
+ assert.isTrue(t.string.equals('', ''))
+ assert.isFalse(t.string.equals('a', 'b'))
+
+ assert.isTrue(t.array(t.string).equals([], []))
+ assert.isTrue(t.array(t.string).equals([''], ['']))
+ assert.isFalse(t.array(t.string).equals(['a'], []))
+ assert.isFalse(t.array(t.string).equals(['a'], ['b']))
+
+ assert.isTrue(t.array(t.array(t.string)).equals([], []))
+ assert.isTrue(t.array(t.array(t.string)).equals([[]], [[]]))
+ assert.isTrue(t.array(t.array(t.string)).equals([['a']], [['a']]))
+ assert.isTrue(t.array(t.array(t.string)).equals([[], ['b']], [[], ['b']]))
+
+ assert.isFalse(t.array(t.array(t.string)).equals([[]], [['c']]))
+ assert.isFalse(t.array(t.array(t.string)).equals([['d']], [['e']]))
+ assert.isFalse(t.array(t.array(t.string)).equals([['f']], [['f', 'g']]))
})
})
diff --git a/packages/derive-equals/tsconfig.build.json b/packages/derive-equals/tsconfig.build.json
index 30eb210a..5dac57a7 100644
--- a/packages/derive-equals/tsconfig.build.json
+++ b/packages/derive-equals/tsconfig.build.json
@@ -10,6 +10,6 @@
"references": [
{ "path": "../json" },
{ "path": "../registry" },
- { "path": "../schema" },
+ { "path": "../schema-core" },
]
}
diff --git a/packages/derive-equals/tsconfig.src.json b/packages/derive-equals/tsconfig.src.json
index 0f1e77bf..acd96694 100644
--- a/packages/derive-equals/tsconfig.src.json
+++ b/packages/derive-equals/tsconfig.src.json
@@ -9,7 +9,7 @@
"references": [
{ "path": "../json" },
{ "path": "../registry" },
- { "path": "../schema" },
+ { "path": "../schema-core" },
],
"include": ["src"]
}
diff --git a/packages/derive-equals/tsconfig.test.json b/packages/derive-equals/tsconfig.test.json
index 77da0195..aa484eed 100644
--- a/packages/derive-equals/tsconfig.test.json
+++ b/packages/derive-equals/tsconfig.test.json
@@ -10,7 +10,7 @@
{ "path": "tsconfig.src.json" },
{ "path": "../json" },
{ "path": "../registry" },
- { "path": "../schema" },
+ { "path": "../schema-core" },
{ "path": "../schema-seed" },
{ "path": "../schema-to-string" },
],
diff --git a/packages/derive-validators/package.json b/packages/derive-validators/package.json
index 952cfda2..f8301dac 100644
--- a/packages/derive-validators/package.json
+++ b/packages/derive-validators/package.json
@@ -49,12 +49,12 @@
"peerDependencies": {
"@traversable/json": "workspace:^",
"@traversable/registry": "workspace:^",
- "@traversable/schema": "workspace:^"
+ "@traversable/schema-core": "workspace:^"
},
"devDependencies": {
"@traversable/json": "workspace:^",
"@traversable/registry": "workspace:^",
- "@traversable/schema": "workspace:^",
+ "@traversable/schema-core": "workspace:^",
"@traversable/schema-seed": "workspace:^"
}
}
diff --git a/packages/derive-validators/src/__generated__/__manifest__.ts b/packages/derive-validators/src/__generated__/__manifest__.ts
index e2451c33..05818dcd 100644
--- a/packages/derive-validators/src/__generated__/__manifest__.ts
+++ b/packages/derive-validators/src/__generated__/__manifest__.ts
@@ -43,12 +43,12 @@ export default {
"peerDependencies": {
"@traversable/json": "workspace:^",
"@traversable/registry": "workspace:^",
- "@traversable/schema": "workspace:^"
+ "@traversable/schema-core": "workspace:^"
},
"devDependencies": {
"@traversable/json": "workspace:^",
"@traversable/registry": "workspace:^",
- "@traversable/schema": "workspace:^",
+ "@traversable/schema-core": "workspace:^",
"@traversable/schema-seed": "workspace:^"
}
} as const
\ No newline at end of file
diff --git a/packages/derive-validators/src/errors.ts b/packages/derive-validators/src/errors.ts
index c8738280..4330cccd 100644
--- a/packages/derive-validators/src/errors.ts
+++ b/packages/derive-validators/src/errors.ts
@@ -1,4 +1,4 @@
-import { t } from '@traversable/schema'
+import { t } from '@traversable/schema-core'
export interface ValidationError {
kind: string
@@ -38,7 +38,14 @@ export const ErrorType = {
OutOfBounds: 'OUT_OF_BOUNDS',
} as const satisfies Record
-function error(kind: T, path: (keyof any)[], got: unknown, msg: string | undefined, expected: unknown, schemaPath: (keyof any)[]): {
+function error