Skip to content

[WIP]: schema generator #192

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 46 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
3a6c087
feat(registry): adds `ValueSet` module, safe globals
ahrjarrett Apr 8, 2025
b7ffef0
feat(root): adds README template to workspace generator
ahrjarrett Apr 8, 2025
bcf4b10
fix(build): uses node:path to import README template
ahrjarrett Apr 8, 2025
dfd660e
feat(build): apply package header when generating readme
ahrjarrett Apr 8, 2025
f347998
fix(build): updates README template to use `pkgHeader` variable
ahrjarrett Apr 8, 2025
1843df3
fix(root): schema coverage
ahrjarrett Apr 8, 2025
85d3563
init(generator): initialize package
ahrjarrett Apr 8, 2025
72217ac
feat(generator): adds tiny parser combinator library
ahrjarrett Apr 8, 2025
963f9af
feat(generator): schema generator is working
ahrjarrett Apr 9, 2025
dc4d5dd
chore: commits changeset
ahrjarrett Apr 9, 2025
9d7793c
fix build
ahrjarrett Apr 9, 2025
7c8ee73
feat(generator): generates unary schemas
ahrjarrett Apr 9, 2025
bde57db
feat(generator): adds object generator
ahrjarrett Apr 9, 2025
d5b6fc3
feat(generator): splits out tuple.core
ahrjarrett Apr 9, 2025
da6c16e
feat(generator): adds generator for union schemas
ahrjarrett Apr 9, 2025
9ad9a87
feat(generator): generates intersect schemas
ahrjarrett Apr 10, 2025
54ce7b1
fix(generator): gets the types right for `.toJsonSchema` and `.toString`
ahrjarrett Apr 10, 2025
0ae7adb
feat(generator): adds integer schema
ahrjarrett Apr 10, 2025
ad344c8
feat(generator): adds the following schemas
ahrjarrett Apr 10, 2025
040c553
feat(generator): adds the following generated schemas
ahrjarrett Apr 10, 2025
a9227c5
test(generator): tests that all the schemas build
ahrjarrett Apr 10, 2025
66735db
cli partially implemented
ahrjarrett Apr 11, 2025
06ccba6
init(schema-core): breaks `@traversable/schema` into separate `@trave…
ahrjarrett Apr 12, 2025
bae9a48
sure
ahrjarrett Apr 12, 2025
04d7666
build(generator): runs cli from package.json
ahrjarrett Apr 12, 2025
3ca3de1
chore(generator): commits generated file
ahrjarrett Apr 12, 2025
80c1809
fix(built): dangling comma
ahrjarrett Apr 12, 2025
8bc7099
feat(schema): generating from core :tada:
ahrjarrett Apr 13, 2025
2aff99e
feat(schema): generating 'equals' extensions
ahrjarrett Apr 13, 2025
7cdf5aa
feat(schema): generates all targets
ahrjarrett Apr 13, 2025
303ab80
feat(generator): generators generate
ahrjarrett Apr 13, 2025
b99bbab
feat(generator): fully generating w/o type errors
ahrjarrett Apr 13, 2025
3f78ef7
fix(generator): fixes self-reference problem in generated schemas
ahrjarrett Apr 13, 2025
53fed17
includes some iffy changes to object type (makes type homomorphic, bu…
ahrjarrett Apr 14, 2025
a7f2fe5
reboot working
ahrjarrett Apr 14, 2025
2642e9b
feat(jit): jitless with formatting
ahrjarrett Apr 16, 2025
d747501
fix(jit): formatting oversight
ahrjarrett Apr 16, 2025
21c023c
feat(jit): finished testing
ahrjarrett Apr 16, 2025
bdefc57
refactor(jit): inline some functions, remove dead code
ahrjarrett Apr 17, 2025
a8bc572
fix(jit): fixes broken import, auto-gen changes
ahrjarrett Apr 17, 2025
2563923
init(arbitrary): initializes new package `@traversable/schema-arbitrary`
ahrjarrett Apr 17, 2025
87e89e8
Merge branch 'main' into schema-generator
ahrjarrett Apr 21, 2025
15869ad
feat(build): adds `bench:types` script
ahrjarrett Apr 21, 2025
6aa1a9d
feat(schema): builds schemas from core + plugins
ahrjarrett Apr 21, 2025
03ef95d
test(core): adds typelevel benchmark samples
ahrjarrett Apr 21, 2025
265ef05
fix(schema): fixes build
ahrjarrett Apr 24, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
9 changes: 9 additions & 0 deletions .changeset/eager-brooms-carry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
"@traversable/schema-to-json-schema": patch
"@traversable/derive-validators": patch
"@traversable/schema-generator": patch
"@traversable/registry": patch
"@traversable/schema": patch
---

feat(generator): adds a shadcn-like schema generator feature
40 changes: 0 additions & 40 deletions .changeset/great-ghosts-fix.md

This file was deleted.

71 changes: 44 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,18 @@
</p>

<div align="center">
<img alt="NPM Version" src="https://img.shields.io/npm/v/%40traversable%2Fschema?style=flat-square&logo=npm&label=npm&color=blue">
<img alt="NPM Version" src="https://img.shields.io/npm/v/%40traversable%2Fschema-core?style=flat-square&logo=npm&label=npm&color=blue">
&nbsp;
<img alt="TypeScript" src="https://img.shields.io/badge/TypeScript-5.5%2B-blue?style=flat-square&logo=TypeScript&logoColor=4a9cf6">
&nbsp;
<img alt="Static Badge" src="https://img.shields.io/badge/license-MIT-a094a2?style=flat-square">
&nbsp;
<img alt="npm" src="https://img.shields.io/npm/dt/@traversable/schema?style=flat-square">
<img alt="npm" src="https://img.shields.io/npm/dt/@traversable/schema-core?style=flat-square">
&nbsp;
</div>

<div align="center">
<img alt="npm bundle size (scoped)" src="https://img.shields.io/bundlephobia/minzip/%40traversable/schema?style=flat-square&label=size">
<img alt="npm bundle size (scoped)" src="https://img.shields.io/bundlephobia/minzip/%40traversable/schema-core?style=flat-square&label=size">
&nbsp;
<img alt="Static Badge" src="https://img.shields.io/badge/ESM-supported-2d9574?style=flat-square&logo=JavaScript">
&nbsp;
Expand All @@ -34,14 +34,14 @@
<span>&nbsp;&nbsp;•&nbsp;&nbsp;</span>
<a href="https://tsplay.dev/w2y29W" target="_blank">TypeScript Playground</a>
<span>&nbsp;&nbsp;•&nbsp;&nbsp;</span>
<a href="https://www.npmjs.com/package/@traversable/schema" target="_blank">npm</a>
<a href="https://www.npmjs.com/package/@traversable/schema-core" target="_blank">npm</a>
<br />
</div>
<br />

<br />

`@traversable/schema` exploits a TypeScript feature called
`@traversable/schema-core` exploits a TypeScript feature called
[inferred type predicates](https://devblogs.microsoft.com/typescript/announcing-typescript-5-5/#inferred-type-predicates)
to do what libaries like `zod` do, without the additional runtime overhead or abstraction.

Expand All @@ -55,14 +55,14 @@ to do what libaries like `zod` do, without the additional runtime overhead or ab
## Requirements

The only hard requirement is [TypeScript 5.5](https://devblogs.microsoft.com/typescript/announcing-typescript-5-5/).
Since the core primitive that `@traversable/schema` is built on top of is
Since the core primitive that `@traversable/schema-core` is built on top of is
[inferred type predicates](https://devblogs.microsoft.com/typescript/announcing-typescript-5-5/#inferred-type-predicates),
we do not have plans to backport to previous versions.

## Quick start

```typescript
import { t } from '@traversable/schema'
import { t } from '@traversable/schema-core'

declare let ex_01: unknown

Expand Down Expand Up @@ -90,7 +90,7 @@ if (schema_01(ex_01)) {

## Features

`@traversable/schema` is modular by schema (like valibot), but takes it a step further by making its feature set opt-in by default.
`@traversable/schema-core` is modular by schema (like valibot), but takes it a step further by making its feature set opt-in by default.

The ability to add features like this is a knock-on effect of traversable's extensible core.

Expand All @@ -104,14 +104,14 @@ which no other schema library currently does (although please file an issue if t
This is possible because the traversable schemas are themselves just type predicates with a few additional properties
that allow them to also be used for reflection.

- **Instructions:** To use this feature, define a predicate inline and `@traversable/schema` will figure out the rest.
- **Instructions:** To use this feature, define a predicate inline and `@traversable/schema-core` will figure out the rest.

#### Example

You can play with this example in the <a href="https://tsplay.dev/WkJD2m" target="_blank">TypeScript Playground</a>.

```typescript
import { t } from '@traversable/schema'
import { t } from '@traversable/schema-core'

export let Classes = t.object({
promise: (v) => v instanceof Promise,
Expand Down Expand Up @@ -195,7 +195,7 @@ type Shorthand = t.typeof<typeof Shorthand>
Play with this example in the [TypeScript playground](https://tsplay.dev/NaBEPm).

```typescript
import { t } from '@traversable/schema'
import { t } from '@traversable/schema-core'
import '@traversable/derive-validators/install'
// ↑↑ importing `@traversable/derive-validators/install` adds `.validate` to all schemas

Expand Down Expand Up @@ -241,7 +241,7 @@ keys are printed at runtime might differ from the order they appear on the type-
Play with this example in the [TypeScript playground](https://tsplay.dev/W49jew)

```typescript
import { t } from '@traversable/schema'
import { t } from '@traversable/schema-core'
import '@traversable/schema-to-string/install'
// ↑↑ importing `@traversable/schema-to-string/install` adds the upgraded `.toString` method on all schemas

Expand Down Expand Up @@ -284,7 +284,7 @@ Play with this example in the [TypeScript playground](https://tsplay.dev/NB98Vw)
```typescript
import * as vi from 'vitest'

import { t } from '@traversable/schema'
import { t } from '@traversable/schema-core'
import '@traversable/schema-to-json-schema/install'
// ↑↑ importing `@traversable/schema-to-json-schema/install` adds `.toJsonSchema` on all schemas

Expand Down Expand Up @@ -348,22 +348,21 @@ vi.assertType<{

### Codec (`.pipe`, `.extend`, `.parse`, `.decode` & `.encode`)

- **Instructions:** to install the `.codec` method on all schemas, all you need to do is import `@traversable/derive-codec`.
- To create a covariant codec (similar to zod's `.transform`), use `.codec.pipe`
- To create a contravariant codec (similar to zod's `.preprocess`), use `.codec.extend` (WIP)
- **Instructions:** to install the `.pipe` and `.extend` methods on all schemas, simply `@traversable/derive-codec/install`.
- To create a covariant codec (similar to zod's `.transform`), use `.pipe`
- To create a contravariant codec (similar to zod's `.preprocess`), use `.extend` (WIP)

#### Example

Play with this example in the [TypeScript playground](https://tsplay.dev/mbbv3m).

```typescript
import { t } from '@traversable/schema'
import { t } from '@traversable/schema-core'
import '@traversable/derive-codec/install'
// ↑↑ importing `@traversable/derive-codec/install` adds `.codec` on all schemas
// ↑↑ importing `@traversable/derive-codec/install` adds `.pipe` and `.extend` on all schemas

let User = t
.object({ name: t.optional(t.string), createdAt: t.string })
.codec // <-- notice we're pulling off the `.codec` property
.pipe((user) => ({ ...user, createdAt: new Date(user.createdAt) }))
.unpipe((user) => ({ ...user, createdAt: user.createdAt.toISOString() }))

Expand All @@ -384,24 +383,42 @@ let toAPI = User.encode(fromAPI)
flowchart TD
registry(registry)
json(json) -.-> registry(registry)
schema(schema) -.-> registry(registry)
schema-core(schema-core) -.-> registry(registry)
derive-codec(derive-codec) -.-> registry(registry)
derive-codec(derive-codec) -.-> schema(schema)
derive-codec(derive-codec) -.-> schema-core(schema-core)
derive-equals(derive-equals) -.-> json(json)
derive-equals(derive-equals) -.-> registry(registry)
derive-equals(derive-equals) -.-> schema(schema)
derive-equals(derive-equals) -.-> schema-core(schema-core)
derive-validators(derive-validators) -.-> json(json)
derive-validators(derive-validators) -.-> registry(registry)
derive-validators(derive-validators) -.-> schema(schema)
derive-validators(derive-validators) -.-> schema-core(schema-core)
schema-arbitrary(schema-arbitrary) -.-> registry(registry)
schema-arbitrary(schema-arbitrary) -.-> schema-core(schema-core)
schema-jit-compiler(schema-jit-compiler) -.-> registry(registry)
schema-jit-compiler(schema-jit-compiler) -.-> schema-core(schema-core)
schema-seed(schema-seed) -.-> json(json)
schema-seed(schema-seed) -.-> registry(registry)
schema-seed(schema-seed) -.-> schema(schema)
schema-seed(schema-seed) -.-> schema-core(schema-core)
schema-to-json-schema(schema-to-json-schema) -.-> registry(registry)
schema-to-json-schema(schema-to-json-schema) -.-> schema(schema)
schema-to-json-schema(schema-to-json-schema) -.-> schema-core(schema-core)
schema-to-string(schema-to-string) -.-> registry(registry)
schema-to-string(schema-to-string) -.-> schema(schema)
schema-to-string(schema-to-string) -.-> schema-core(schema-core)
schema-valibot-adapter(schema-valibot-adapter) -.-> json(json)
schema-valibot-adapter(schema-valibot-adapter) -.-> registry(registry)
schema-zod-adapter(schema-zod-adapter) -.-> json(json)
schema-zod-adapter(schema-zod-adapter) -.depends on.-> registry(registry)
schema-zod-adapter(schema-zod-adapter) -.-> registry(registry)
schema-generator(schema-generator) -.-> derive-validators(derive-validators)
schema-generator(schema-generator) -.-> derive-equals(derive-equals)
schema-generator(schema-generator) -.-> registry(registry)
schema-generator(schema-generator) -.-> schema-core(schema-core)
schema-generator(schema-generator) -.-> schema-to-json-schema(schema-to-json-schema)
schema-generator(schema-generator) -.-> schema-to-string(schema-to-string)
schema(schema) -.-> derive-codec(derive-codec)
schema(schema) -.-> derive-equals(derive-equals)
schema(schema) -.-> derive-validators(derive-validators)
schema(schema) -.-> registry(registry)
schema(schema) -.-> schema-core(schema-core)
schema(schema) -.-> schema-generator(schema-generator)
schema(schema) -.-> schema-to-json-schema(schema-to-json-schema)
schema(schema) -.depends on.-> schema-to-string(schema-to-string)
```
38 changes: 38 additions & 0 deletions bin/assets/_README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<br>
<h1 align="center">ᯓ𝘁𝗿𝗮𝘃𝗲𝗿𝘀𝗮𝗯𝗹𝗲/<%= pkgHeader =></h1>
<br>

<p align="center">
TODO: write me
</p>

<div align="center">
<img alt="NPM Version" src="https://img.shields.io/npm/v/%40traversable%2F<%= pkgName =>?style=flat-square&logo=npm&label=npm&color=blue">
&nbsp;
<img alt="TypeScript" src="https://img.shields.io/badge/TypeScript-5.5%2B-blue?style=flat-square&logo=TypeScript&logoColor=4a9cf6">
&nbsp;
<img alt="Static Badge" src="https://img.shields.io/badge/license-MIT-a094a2?style=flat-square">
&nbsp;
<img alt="npm" src="https://img.shields.io/npm/dt/@traversable/<%= pkgName =>?style=flat-square">
&nbsp;
</div>

<div align="center">
<img alt="npm bundle size (scoped)" src="https://img.shields.io/bundlephobia/minzip/%40traversable/<%= pkgName =>?style=flat-square&label=size">
&nbsp;
<img alt="Static Badge" src="https://img.shields.io/badge/ESM-supported-2d9574?style=flat-square&logo=JavaScript">
&nbsp;
<img alt="Static Badge" src="https://img.shields.io/badge/CJS-supported-2d9574?style=flat-square&logo=Node.JS">
&nbsp;
</div>

<div align="center">
<a href="https://stackblitz.com/edit/traversable?file=src%2Fsandbox.tsx" target="_blank">Demo (StackBlitz)</a>
<span>&nbsp;&nbsp;•&nbsp;&nbsp;</span>
<a href="https://tsplay.dev/w2y29W" target="_blank">TypeScript Playground</a>
<span>&nbsp;&nbsp;•&nbsp;&nbsp;</span>
<a href="https://www.npmjs.com/package/@traversable/<%= pkgName =>" target="_blank">npm</a>
<br>
</div>
<br>
<br>
9 changes: 9 additions & 0 deletions bin/assets/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,10 @@
import * as fs from 'node:fs'
import * as path from 'node:path'

const PATH = {
README: path.join(path.resolve(), 'bin', 'assets', '_README.md')
} as const

export { default as template } from "./_package.json"

export let getReadmeTemplate = () => fs.readFileSync(PATH.README).toString('utf8')
Loading