https://github.com/figureland/versioned-schema
Create versioned schemas for distributed applications
https://github.com/figureland/versioned-schema
distributed effect-ts schema typescript valibot versioned-schema
Last synced: 3 months ago
JSON representation
Create versioned schemas for distributed applications
- Host: GitHub
- URL: https://github.com/figureland/versioned-schema
- Owner: figureland
- License: mit
- Created: 2025-02-21T11:58:41.000Z (11 months ago)
- Default Branch: main
- Last Pushed: 2025-04-06T22:35:20.000Z (9 months ago)
- Last Synced: 2025-05-11T20:55:34.073Z (8 months ago)
- Topics: distributed, effect-ts, schema, typescript, valibot, versioned-schema
- Language: TypeScript
- Homepage:
- Size: 236 KB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
[](https://github.com/figureland/versioned-schema/actions/workflows/ci.yml)
[](https://img.shields.io/npm/v/@figureland/versioned-schema?color=40bd5c)
# versioned-schema
A tiny tool which allows you to create basic versioned schemas, using [valibot](https://valibot.dev/). This is handy when designing distributed apps and data structures.
This library can also be used with [effect/Schema](https://effect.website/docs/schema/introduction/).
## Explainer
Let's make up a scenario where we have a basic data structure in our app. We want to update it by adding a new field called `description`. And then later on, And later on, we decide to change the type of field `description` to be an array of strings.
In this scenario, we might end up with different versions of our data structure that can clash.
```ts
type Example = {
id: string
createdAt: number
name: string
}
type Example2 = {
id: string
createdAt: number
name: string
description: string
}
type Example3 = {
id: string
createdAt: number
name: string
description: string[]
}
```
We want our app to be able to support different versions of this data structure. So we might end up with something like this:
```ts
type Example =
| {
id: string
createdAt: number
name: string
version: '1'
}
| {
id: string
createdAt: number
name: string
description: string
version: '2'
}
| {
id: string
createdAt: number
name: string
description: string[]
version: '3'
}
```
These different versions can introduce a lot of complexity. This is not a new problem, and there are a lot of different approaches that tend to be application-specific.
This library provides some basic helpers to make it easier to work with that schema in your app.
### Create a versioned schema
```ts
import { number, string, array } from 'valibot'
import { createVersionedSchema } from '@figureland/versioned-schema'
const exampleSchema = createVersionedSchema({
// Base schema - shared across all versions
base: {
id: string(),
createdAt: number()
},
// Version-specific schemas
versions: {
'1': {
name: string()
},
'2': {
name: string(),
description: string()
},
'3': {
name: string(),
description: array(string())
}
}
})
const { schema, versions, parse, validate, isVersion } = exampleSchema
```
### Infer the type of a schema
```ts
import type { InferOutput } from 'valibot'
type Example = InferOutput
```
### List available schema versions
```ts
// List available schema versions
console.log(exampleSchema.versions)
// ['1', '2', '3']
```
### Parse data
```ts
// Parse data
const v1Data = {
id: '123',
createdAt: Date.now(),
name: 'Example V1',
version: '1'
}
console.log(exampleSchema.parse(v1Data))
// { id: '123', createdAt: 1234567890, name: 'Example V1', version: '1' }
const v2Data = {
id: '456',
createdAt: Date.now(),
name: 'Example V2',
description: 'Version 2 has a description',
version: '2'
}
console.log(exampleSchema.parse(v2Data))
// { id: '456', createdAt: 1234567890, name: 'Example V2', description: '...', version: '2' }
```
### Validate unknown data
```ts
// Check if data matches any version of your schema (type-safe)
console.log(exampleSchema.validate(v1Data)) // true
console.log(exampleSchema.validate({ version: '1' })) // false (missing required fields)
// Check if data is a specific version of your schema (type-safe)
console.log(exampleSchema.isVersion('1', v1Data)) // true
console.log(exampleSchema.isVersion('2', v1Data)) // false
```
### Use with effect/Schema
```ts
import { Schema } from 'effect'
import { createVersionedSchema } from '@figureland/versioned-schema/effect'
const exampleSchema = createVersionedSchema({
base: {
id: Schema.String,
createdAt: Schema.Number
}
})
```
### Use with zod
```ts
import { createVersionedSchema } from '@figureland/versioned-schema/zod'
const exampleSchema = createVersionedSchema({
base: {
id: z.string(),
createdAt: z.number()
},
versions: {
'1': {
name: z.string()
}
}
})
```
## Scripts
### Install
```bash
bun install
```
### Test
```bash
bun test
```
### Build
```bash
bun run build
```