{"id":25746221,"url":"https://github.com/figureland/versioned-schema","last_synced_at":"2026-02-25T19:02:31.912Z","repository":{"id":278741270,"uuid":"936621982","full_name":"figureland/versioned-schema","owner":"figureland","description":"Create versioned schemas for distributed applications","archived":false,"fork":false,"pushed_at":"2025-04-06T22:35:20.000Z","size":242,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-05-11T20:55:34.073Z","etag":null,"topics":["distributed","effect-ts","schema","typescript","valibot","versioned-schema"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/figureland.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-02-21T11:58:41.000Z","updated_at":"2025-04-06T22:35:22.000Z","dependencies_parsed_at":"2025-03-31T12:26:15.649Z","dependency_job_id":"37ff4a92-d92d-4b83-a8b5-b993d5b7db18","html_url":"https://github.com/figureland/versioned-schema","commit_stats":null,"previous_names":["figureland/versioned-schema"],"tags_count":14,"template":false,"template_full_name":"figureland/base-bun","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/figureland%2Fversioned-schema","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/figureland%2Fversioned-schema/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/figureland%2Fversioned-schema/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/figureland%2Fversioned-schema/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/figureland","download_url":"https://codeload.github.com/figureland/versioned-schema/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253632989,"owners_count":21939387,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["distributed","effect-ts","schema","typescript","valibot","versioned-schema"],"created_at":"2025-02-26T11:30:19.295Z","updated_at":"2025-10-25T19:49:06.793Z","avatar_url":"https://github.com/figureland.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![CI](https://github.com/figureland/versioned-schema/actions/workflows/ci.yml/badge.svg)](https://github.com/figureland/versioned-schema/actions/workflows/ci.yml)\n[![NPM](https://img.shields.io/npm/v/@figureland/versioned-schema?color=40bd5c)](https://img.shields.io/npm/v/@figureland/versioned-schema?color=40bd5c)\n\n# versioned-schema\n\nA 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.\n\nThis library can also be used with [effect/Schema](https://effect.website/docs/schema/introduction/).\n\n## Explainer\n\nLet'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.\n\nIn this scenario, we might end up with different versions of our data structure that can clash.\n\n```ts\ntype Example = {\n  id: string\n  createdAt: number\n  name: string\n}\n\ntype Example2 = {\n  id: string\n  createdAt: number\n  name: string\n  description: string\n}\n\ntype Example3 = {\n  id: string\n  createdAt: number\n  name: string\n  description: string[]\n}\n```\n\nWe want our app to be able to support different versions of this data structure. So we might end up with something like this:\n\n```ts\ntype Example =\n  | {\n      id: string\n      createdAt: number\n      name: string\n      version: '1'\n    }\n  | {\n      id: string\n      createdAt: number\n      name: string\n      description: string\n      version: '2'\n    }\n  | {\n      id: string\n      createdAt: number\n      name: string\n      description: string[]\n      version: '3'\n    }\n```\n\nThese 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.\n\nThis library provides some basic helpers to make it easier to work with that schema in your app.\n\n### Create a versioned schema\n\n```ts\nimport { number, string, array } from 'valibot'\nimport { createVersionedSchema } from '@figureland/versioned-schema'\n\nconst exampleSchema = createVersionedSchema({\n  // Base schema - shared across all versions\n  base: {\n    id: string(),\n    createdAt: number()\n  },\n  // Version-specific schemas\n  versions: {\n    '1': {\n      name: string()\n    },\n    '2': {\n      name: string(),\n      description: string()\n    },\n    '3': {\n      name: string(),\n      description: array(string())\n    }\n  }\n})\n\nconst { schema, versions, parse, validate, isVersion } = exampleSchema\n```\n\n### Infer the type of a schema\n\n```ts\nimport type { InferOutput } from 'valibot'\n\ntype Example = InferOutput\u003ctypeof exampleSchema.schema\u003e\n```\n\n### List available schema versions\n\n```ts\n// List available schema versions\nconsole.log(exampleSchema.versions)\n// ['1', '2', '3']\n```\n\n### Parse data\n\n```ts\n// Parse data\nconst v1Data = {\n  id: '123',\n  createdAt: Date.now(),\n  name: 'Example V1',\n  version: '1'\n}\nconsole.log(exampleSchema.parse(v1Data))\n// { id: '123', createdAt: 1234567890, name: 'Example V1', version: '1' }\n\nconst v2Data = {\n  id: '456',\n  createdAt: Date.now(),\n  name: 'Example V2',\n  description: 'Version 2 has a description',\n  version: '2'\n}\nconsole.log(exampleSchema.parse(v2Data))\n// { id: '456', createdAt: 1234567890, name: 'Example V2', description: '...', version: '2' }\n```\n\n### Validate unknown data\n\n```ts\n// Check if data matches any version of your schema (type-safe)\nconsole.log(exampleSchema.validate(v1Data)) // true\nconsole.log(exampleSchema.validate({ version: '1' })) // false (missing required fields)\n\n// Check if data is a specific version of your schema (type-safe)\nconsole.log(exampleSchema.isVersion('1', v1Data)) // true\nconsole.log(exampleSchema.isVersion('2', v1Data)) // false\n```\n\n### Use with effect/Schema\n\n```ts\nimport { Schema } from 'effect'\nimport { createVersionedSchema } from '@figureland/versioned-schema/effect'\nconst exampleSchema = createVersionedSchema({\n  base: {\n    id: Schema.String,\n    createdAt: Schema.Number\n  }\n})\n```\n\n### Use with zod\n\n```ts\nimport { createVersionedSchema } from '@figureland/versioned-schema/zod'\n\nconst exampleSchema = createVersionedSchema({\n  base: {\n    id: z.string(),\n    createdAt: z.number()\n  },\n  versions: {\n    '1': {\n      name: z.string()\n    }\n  }\n})\n```\n\n## Scripts\n\n### Install\n\n```bash\nbun install\n```\n\n### Test\n\n```bash\nbun test\n```\n\n### Build\n\n```bash\nbun run build\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffigureland%2Fversioned-schema","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffigureland%2Fversioned-schema","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffigureland%2Fversioned-schema/lists"}