{"id":15012973,"url":"https://github.com/lucasavila00/beff","last_synced_at":"2026-05-03T12:09:23.468Z","repository":{"id":193779593,"uuid":"683896092","full_name":"lucasavila00/beff","owner":"lucasavila00","description":"Efficient validators from Typescript types generated by a blazing fast compiler","archived":false,"fork":false,"pushed_at":"2026-04-29T01:07:51.000Z","size":12592,"stargazers_count":6,"open_issues_count":5,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-04-29T03:51:38.950Z","etag":null,"topics":["jsonschema","parser","typescript","validator"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lucasavila00.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":null,"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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2023-08-28T02:32:08.000Z","updated_at":"2026-04-29T01:07:37.000Z","dependencies_parsed_at":"2023-09-10T00:24:38.068Z","dependency_job_id":"fdd358b4-48e4-4688-9159-88f6aff01b74","html_url":"https://github.com/lucasavila00/beff","commit_stats":{"total_commits":401,"total_committers":1,"mean_commits":401.0,"dds":0.0,"last_synced_commit":"8840be19385944abb57a9d3402eb5481a4752556"},"previous_names":["lucasavila00/beff"],"tags_count":142,"template":false,"template_full_name":null,"purl":"pkg:github/lucasavila00/beff","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lucasavila00%2Fbeff","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lucasavila00%2Fbeff/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lucasavila00%2Fbeff/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lucasavila00%2Fbeff/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lucasavila00","download_url":"https://codeload.github.com/lucasavila00/beff/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lucasavila00%2Fbeff/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32568118,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-03T06:36:36.687Z","status":"ssl_error","status_checked_at":"2026-05-03T06:36:09.306Z","response_time":103,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["jsonschema","parser","typescript","validator"],"created_at":"2024-09-24T19:43:32.756Z","updated_at":"2026-05-03T12:09:23.446Z","avatar_url":"https://github.com/lucasavila00.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 🪄 Beff\n\nBeff is a high-performance validator generator that creates efficient runtime validators from TypeScript types using a blazing-fast compiler.\n\n## Why Choose Beff?\n\n- **TypeScript First**: Unlike zod, io-ts, and similar libraries, Beff doesn't add overhead to the TypeScript compiler. Experience faster editor performance and quicker compile times.\n- **Blazingly Fast**: Written in Rust and compiled to WebAssembly, Beff is cross-platform and lightning-quick. It compiles a hello-world project in 5ms and handles large projects with 200+ types in just 200ms.\n- **Seamlessly Compatible**: Leverages the TypeScript compiler for path resolution. If your editor can resolve the types, Beff can too.\n- **Optimized Output**: Generates highly efficient validator code with extensive compile-time optimizations.\n- **Developer Friendly**: Provides clear, actionable error messages at both compile time and runtime.\n- **Feature Complete**: Supports advanced TypeScript features including recursive types, generics, mapped types, conditional types, utility types (`Omit`, `Exclude`, `Partial`, `Required`, `Record`), and more. If a type can be validated at runtime, Beff understands it.\n\n## Getting Started\n\nGet up and running with Beff in just a few simple steps:\n\n### 1. Install\n\nInstall the required packages from npm:\n\n```shell\nnpm i @beff/cli @beff/client\n```\n\n### 2. Configure\n\nCreate a JSON file to configure Beff. The file can have any name, but it's standard practice to name it `beff.json`.\n\n```json\n{\n  \"parser\": \"./src/parser.ts\",\n  \"outputDir\": \"./src/generated\"\n}\n```\n\n### 3. Create the parser file\n\nCreate a TypeScript file that exports the types you want Beff to generate validators for.\n\nBy convention, this file is typically named `parser.ts`:\n\n```ts\nimport parse from \"./generated/parser\";\n\ntype User = {\n  name: string;\n  age: number;\n};\n\nexport const Parsers = parse.buildParsers\u003c{\n  User: User;\n}\u003e();\n```\n\n### 4. Generate the validators\n\nRun the Beff CLI to generate your validator code:\n\n```shell\nnpx beff -p beff.json\n```\n\n### 5. Use the validators\n\nNow you can use the generated validators in your application:\n\n```ts\nimport { Parsers } from \"./parser.ts\";\n\nconst user1 = Parsers.User.parse({\n  name: \"John Doe\",\n  age: 42,\n});\n\nconst maybeUser = Parsers.User.safeParse(null);\n\nconst isValid: boolean = Parsers.User.validate({\n  name: \"John Doe\",\n  age: 42,\n});\n\nconst jsonSchema = Parsers.User.schema();\n```\n\n### 6. Generate reusable `$ref`-based schemas\n\n`.schema()` stays flat and inlines the full schema for compatibility.\n\nIf you want reusable definitions for JSON Schema or OpenAPI documents, use `SchemaPrintingContext` with `.schemaWithContext(...)`:\n\n```ts\nimport { Parsers } from \"./parser.ts\";\nimport { SchemaPrintingContext } from \"@beff/client\";\n\nconst ctx = new SchemaPrintingContext({\n  refPathTemplate: \"#/components/schemas/{name}\",\n  definitionContainerKey: null,\n});\n\nconst requestSchema = Parsers.User.schemaWithContext(ctx);\n// { $ref: \"#/components/schemas/User\" }\n\nconst openapi = {\n  openapi: \"3.1.0\",\n  paths: {\n    \"/users\": {\n      post: {\n        requestBody: {\n          content: {\n            \"application/json\": {\n              schema: requestSchema,\n            },\n          },\n        },\n      },\n    },\n  },\n  components: {\n    schemas: ctx.exportDefinitions(),\n  },\n};\n```\n\nBy default, `SchemaPrintingContext` emits refs at `#/$defs/{name}` and exports definitions under `$defs`:\n\n```ts\nimport { SchemaPrintingContext } from \"@beff/client\";\n\nconst ctx = new SchemaPrintingContext({\n  refPathTemplate: \"#/$defs/{name}\",\n  definitionContainerKey: \"$defs\",\n});\n\nconst schema = Parsers.User.schemaWithContext(ctx);\nconst definitions = ctx.exportDefinitions();\n```\n\nIf you need a different schema shape only for one export target, pass `namedTypeSchemaOverrides`.\nThis changes the emitted definition for `.schemaWithContext(...)` without changing runtime validation:\n\n```ts\nimport { b, createNamedType, overrideNamedType, SchemaPrintingContext } from \"@beff/client\";\n\nconst RecursiveTree = createNamedType(\"RecursiveTree\", b.Unknown());\n\noverrideNamedType(\n  \"RecursiveTree\",\n  b.Object({\n    value: b.String(),\n    children: b.Array(RecursiveTree),\n  }),\n);\n\nconst ctx = new SchemaPrintingContext({\n  refPathTemplate: \"#/components/schemas/{name}\",\n  definitionContainerKey: null,\n  namedTypeSchemaOverrides: {\n    RecursiveTree: b.Unknown(),\n  },\n});\n\nRecursiveTree.schemaWithContext(ctx);\nctx.exportDefinitions();\n// { RecursiveTree: {} }\n```\n\nUse `overrideNamedType(...)` when you want to change the named type globally, including validation.\nUse `namedTypeSchemaOverrides` when you only need a different schema representation for a specific JSON Schema or OpenAPI export.\n\n## CLI Options\n\nThe `beff` binary can also run in watch mode.\n\n```shell\n$ npx beff -h\nUsage: beff [options]\n\nGenerate validators from TypeScript types\n\nOptions:\n  -p, --project \u003cstring\u003e  Path to the project file\n  -v, --verbose           Print verbose output\n  -w, --watch             Watch for file changes\n  -h, --help              display help for command\n```\n\n## Advanced Features\n\n### Custom String Formats\n\nBeff allows you to define custom string validation formats. First, configure your `beff.json`:\n\n```json\n{\n  \"parser\": \"./src/parser.ts\",\n  \"outputDir\": \"./src/generated\",\n  \"stringFormats\": [\n    {\n      \"name\": \"ValidCurrency\"\n    }\n  ]\n}\n```\n\nThen use the `StringFormat` helper to create a branded TypeScript type and define the runtime validator:\n\n```ts\nimport parse from \"./generated/parser\";\nimport { StringFormat } from \"@beff/client\";\nexport type ValidCurrency = StringFormat\u003c\"ValidCurrency\"\u003e;\n\nexport const Parsers = parse.buildParsers\u003c{\n  ValidCurrency: ValidCurrency;\n}\u003e({\n  stringFormats: {\n    ValidCurrency: {\n      validator: (input: string) =\u003e {\n        if (VALID_CURRENCIES.includes(input)) {\n          return true;\n        }\n        return false;\n      },\n      errorMessage: () =\u003e \"expected a valid ISO currency code\",\n    },\n  },\n});\n```\n\nRuntime format definitions support both forms:\n\n```ts\nstringFormats: {\n  ValidCurrency: (input: string) =\u003e input === \"USD\",\n}\n```\n\n```ts\nstringFormats: {\n  ValidCurrency: {\n    validator: (input: string) =\u003e input === \"USD\",\n    errorMessage: (input: string) =\u003e `expected ISO currency code, got ${input}`,\n  },\n}\n```\n\n`errorMessage` is optional. When provided, failed parses use it instead of the default `expected string with format \"...\"` message.\n\nThis also works with `StringFormatExtends`. If multiple formats in the chain define an `errorMessage`, the upper / more specific one wins:\n\n```ts\nimport { StringFormat, StringFormatExtends } from \"@beff/client\";\n\nexport type UserId = StringFormat\u003c\"UserId\"\u003e;\nexport type ReadAuthorizedUserId = StringFormatExtends\u003cUserId, \"ReadAuthorizedUserId\"\u003e;\nexport type WriteAuthorizedUserId = StringFormatExtends\u003cReadAuthorizedUserId, \"WriteAuthorizedUserId\"\u003e;\n\nconst Parsers = parse.buildParsers({\n  stringFormats: {\n    UserId: {\n      validator: (input: string) =\u003e input.startsWith(\"user_\"),\n      errorMessage: () =\u003e \"expected a valid user id\",\n    },\n    ReadAuthorizedUserId: {\n      validator: (input: string) =\u003e input.includes(\"_read_\"),\n      errorMessage: () =\u003e \"expected user with read permissions\",\n    },\n    WriteAuthorizedUserId: {\n      validator: (input: string) =\u003e input.includes(\"_write_\"),\n      errorMessage: () =\u003e \"expected user with write permissions\",\n    },\n  },\n});\n```\n\n### Custom Number Formats\n\nSimilarly, you can define custom number validation formats. Configure your `beff.json`:\n\n```json\n{\n  \"parser\": \"./src/parser.ts\",\n  \"outputDir\": \"./src/generated\",\n  \"numberFormats\": [\n    {\n      \"name\": \"NonNegativeNumber\"\n    }\n  ]\n}\n```\n\nThen use the `NumberFormat` helper to create a branded TypeScript type and define the runtime validator:\n\n```ts\nimport parse from \"./generated/parser\";\nimport { NumberFormat } from \"@beff/client\";\nexport type NonNegativeNumber = NumberFormat\u003c\"NonNegativeNumber\"\u003e;\n\nexport const Parsers = parse.buildParsers\u003c{\n  NonNegativeNumber: NonNegativeNumber;\n}\u003e({\n  numberFormats: {\n    NonNegativeNumber: {\n      validator: (input: number) =\u003e {\n        return input \u003e= 0;\n      },\n      errorMessage: () =\u003e \"expected a non-negative number\",\n    },\n    NegativeNumber: {\n      validator: (input: number) =\u003e {\n        return input \u003c 0;\n      },\n    },\n  },\n});\n```\n\n`errorMessage` also works for number formats. It can be omitted, and with `NumberFormatExtends` the upper / more specific format message wins when multiple formats define one.\n\n### Ad-hoc Validator Creation\n\nBeff provides a runtime type creation API similar to `zod` and `io-ts` for simple use cases.\n\n**Note:** This API is intentionally limited and supports only basic types to maintain fast editor performance. A more comprehensive runtime API would essentially make Beff just another re-implementation of zod, defeating its core purpose. For complex types, use Beff's primary feature of compiling TypeScript types.\n\nValidators created with the ad-hoc API have the same interface as compiled validators:\n\n```ts\nimport { b } from \"@beff/client\";\n\nconst AdHocItem = b.Object({\n  str: b.String(),\n  num: b.Number(),\n  bool: b.Boolean(),\n  undefined: b.Undefined(),\n  null: b.Null(),\n  any: b.Any(),\n  unknown: b.Unknown(),\n});\n\nconst AdHocList = b.Array(AdHocItem);\n\nconst ls = AdHocList.parse([]);\n```\n\n### Zod Compatibility\n\nBeff provides seamless interoperability with Zod. Call `.zod()` on any Beff parser to get a compatible Zod schema.\n\nThis makes it easy to gradually migrate existing Zod-based codebases:\n\n```ts\nimport { Parsers } from \"./parser.ts\";\nimport { z } from \"zod\";\n\nconst users = z.array(Parsers.User.zod()).parse({\n  name: \"John Doe\",\n  age: 42,\n});\n```\n\n## Contributing\n\nPlease read [CONTRIBUTING.md](/CONTRIBUTING.md)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flucasavila00%2Fbeff","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flucasavila00%2Fbeff","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flucasavila00%2Fbeff/lists"}