{"id":23906748,"url":"https://github.com/briefhq/drizzle-zero","last_synced_at":"2025-05-16T07:04:24.150Z","repository":{"id":269079413,"uuid":"906345420","full_name":"BriefHQ/drizzle-zero","owner":"BriefHQ","description":"Generate Zero schemas from Drizzle ORM schemas.","archived":false,"fork":false,"pushed_at":"2025-05-06T23:17:15.000Z","size":869,"stargazers_count":198,"open_issues_count":1,"forks_count":10,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-05-06T23:22:38.900Z","etag":null,"topics":["drizzle-orm","sync","zero"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/drizzle-zero","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"unlicense","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/BriefHQ.png","metadata":{"files":{"readme":"README.md","changelog":null,"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,"zenodo":null}},"created_at":"2024-12-20T17:32:19.000Z","updated_at":"2025-05-06T23:17:19.000Z","dependencies_parsed_at":"2025-01-13T21:24:07.811Z","dependency_job_id":"129a72cc-8f2a-427d-905f-2a5295cdd978","html_url":"https://github.com/BriefHQ/drizzle-zero","commit_stats":null,"previous_names":["briefhq/drizzle-zero"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BriefHQ%2Fdrizzle-zero","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BriefHQ%2Fdrizzle-zero/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BriefHQ%2Fdrizzle-zero/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BriefHQ%2Fdrizzle-zero/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/BriefHQ","download_url":"https://codeload.github.com/BriefHQ/drizzle-zero/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254485054,"owners_count":22078767,"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":["drizzle-orm","sync","zero"],"created_at":"2025-01-05T02:13:54.483Z","updated_at":"2025-05-16T07:04:24.140Z","avatar_url":"https://github.com/BriefHQ.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# drizzle-zero\n\nGenerate [Zero](https://zero.rocicorp.dev/) schemas from [Drizzle ORM](https://orm.drizzle.team) schemas.\n\n## Installation\n\n```bash\nnpm install drizzle-zero\n# or\nyarn add drizzle-zero\n# or\npnpm add drizzle-zero\n```\n\n## Usage\n\nHere's an example of how to convert a Drizzle schema to a Zero schema with bidirectional relationships:\n\n### Define Drizzle schema\n\nYou should have an existing Drizzle schema, e.g.:\n\n```ts\nimport { relations } from \"drizzle-orm\";\nimport { pgTable, text, jsonb } from \"drizzle-orm/pg-core\";\n\nexport const users = pgTable(\"user\", {\n  id: text(\"id\").primaryKey(),\n  name: text(\"name\"),\n  // custom types are supported for any column type!\n  email: text(\"email\").$type\u003c`${string}@${string}`\u003e().notNull(),\n});\n\nexport const usersRelations = relations(users, ({ many }) =\u003e ({\n  posts: many(posts),\n}));\n\nexport const posts = pgTable(\"post\", {\n  id: text(\"id\").primaryKey(),\n  // this JSON type will be passed to Zero\n  content: jsonb(\"content\").$type\u003c{ textValue: string }\u003e().notNull(),\n  authorId: text(\"author_id\").references(() =\u003e users.id),\n});\n\nexport const postsRelations = relations(posts, ({ one }) =\u003e ({\n  author: one(users, {\n    fields: [posts.authorId],\n    references: [users.id],\n  }),\n}));\n```\n\nSee the [integration test's `schema.ts`](integration/drizzle/schema.ts)\nfor more examples of how to define Drizzle schemas with custom types.\n\n### Add schema generation script\n\nYou can then add the schema generation script to your `package.json`:\n\n```json\n{\n  \"scripts\": {\n    \"generate\": \"drizzle-zero generate --format\",\n    \"postinstall\": \"npm generate\"\n  }\n}\n```\n\nThis command will look for a Drizzle Kit config at `drizzle.config.ts` in the current directory\nand use the Drizzle schema defined in it. _This must be a single TS file and\nnot a folder/glob for type resolution to work_. It will also use the\ncasing defined in your drizzle config.\n\nYou can change this behavior with `-s, --schema \u003cinput-file\u003e`\nas the path to your Drizzle schema file, or\n`-k, --drizzle-kit-config \u003cinput-file\u003e` with the path to your `drizzle.config.ts` file.\n\nBy default, it will output your schema to `zero-schema.gen.ts`.\nYou can customize the generated file path with `-o, --output \u003coutput-file\u003e`.\n\nIf you have Prettier installed, you can use it to format the generated output\nwith `-f, --format`.\n\nTo specify a custom tsconfig file, use `-t, --tsconfig \u003ctsconfig-file\u003e`.\nIt will, by default, look for one in the current directory.\n\n**Important:** the Drizzle schema **must be included in the tsconfig** for\ntype resolution to work. If they are not included, there will be an error similar to\n`Failed to find type definitions`.\n\n### Define Zero schema file\n\nYou can then import the `zero-schema.gen.ts` schema from your Zero `schema.ts`\nand define permissions on top of it.\n\n```ts\nimport { type Row, definePermissions } from \"@rocicorp/zero\";\nimport { schema, type Schema } from \"./zero-schema.gen\";\n\nexport { schema, type Schema };\n\nexport type User = Row\u003ctypeof schema.tables.user\u003e;\n//            ^ {\n//                readonly id: string;\n//                readonly name: string;\n//                readonly email: `${string}@${string}`;\n//              }\n\nexport const permissions = definePermissions\u003c{}, Schema\u003e(schema, () =\u003e {\n  // ...further permissions definitions\n});\n```\n\nUse the generated Zero schema:\n\n```tsx\nimport { useQuery, useZero } from \"@rocicorp/zero/react\";\n\nfunction PostList() {\n  const z = useZero();\n\n  // Build a query for posts with their authors\n  const postsQuery = z.query.post.related(\"author\").limit(10);\n\n  const [posts] = useQuery(postsQuery);\n\n  return (\n    \u003cdiv\u003e\n      {posts.map((post) =\u003e (\n        \u003cdiv key={post.id} className=\"post\"\u003e\n          {/* Access the JSON content from Drizzle */}\n          \u003cp\u003e{post.content.textValue}\u003c/p\u003e\n          \u003cp\u003eBy: {post.author?.name}\u003c/p\u003e\n          \u003cp\u003eEmail: {post.author?.email}\u003c/p\u003e\n        \u003c/div\u003e\n      ))}\n    \u003c/div\u003e\n  );\n}\n```\n\n### Customize with `drizzle-zero.config.ts`\n\nIf you want to customize the tables/columns that are synced by Zero, you can optionally\ncreate a new config file at `drizzle-zero.config.ts` specifying the columns you want to\ninclude in the CLI output:\n\n```ts\nimport { drizzleZeroConfig } from \"drizzle-zero\";\nimport * as drizzleSchema from \"./drizzle-schema\";\n\n// Define your configuration file for the CLI\nexport default drizzleZeroConfig(drizzleSchema, {\n  // Specify which tables and columns to include in the Zero schema.\n  // This allows for the \"expand/migrate/contract\" pattern recommended in the Zero docs.\n  // When a column is first added, it should be set to false, and then changed to true\n  // once the migration has been run.\n\n  // All tables/columns must be defined, but can be set to false to exclude them from the Zero schema.\n  // Column names match your Drizzle schema definitions\n  tables: {\n    // this can be set to false\n    // e.g. user: false,\n    users: {\n      id: true,\n      name: true,\n      email: true,\n    },\n    posts: {\n      // or this can be set to false\n      // e.g. id: false,\n      id: true,\n      content: true,\n      // Use the JavaScript field name (authorId), not the DB column name (author_id)\n      authorId: true,\n    },\n  },\n\n  // Specify the casing style to use for the schema.\n  // This is useful for when you want to use a different casing style than the default.\n  // This works in the same way as the `casing` option in the Drizzle ORM.\n  //\n  // @example\n  // casing: \"snake_case\",\n});\n```\n\nYou can customize this config file path with `-c, --config \u003cinput-file\u003e`.\n\n**Important:** the `drizzle-zero.config.ts` file **must be included in the tsconfig**\nfor the type resolution to work. If they are not included, there will be an error similar to\n`Failed to find type definitions`.\n\n## Many-to-Many Relationships\n\ndrizzle-zero supports many-to-many relationships with a junction table. You can configure them in two ways:\n\n### Simple Configuration\n\n```ts\nexport default drizzleZeroConfig(drizzleSchema, {\n  tables: {\n    user: {\n      id: true,\n      name: true,\n    },\n    usersToGroup: {\n      userId: true,\n      groupId: true,\n    },\n    group: {\n      id: true,\n      name: true,\n    },\n  },\n  manyToMany: {\n    user: {\n      // Simple format: [junction table, target table]\n      // Do not use the same name as any existing relationships\n      groups: [\"usersToGroup\", \"group\"],\n    },\n  },\n});\n```\n\nThen query as usual, skipping the junction table:\n\n```tsx\nconst userQuery = z.query.user.where(\"id\", \"=\", \"1\").related(\"groups\").one();\n\nconst [user] = useQuery(userQuery);\n\nconsole.log(user);\n// {\n//   id: \"user_1\",\n//   name: \"User 1\",\n//   groups: [\n//     { id: \"group_1\", name: \"Group 1\" },\n//     { id: \"group_2\", name: \"Group 2\" },\n//   ],\n// }\n```\n\n### Extended Configuration\n\nFor more complex scenarios like self-referential relationships:\n\n```ts\nexport default drizzleZeroConfig(drizzleSchema, {\n  tables: {\n    user: {\n      id: true,\n      name: true,\n    },\n    friendship: {\n      requestingId: true,\n      acceptingId: true,\n    },\n  },\n  manyToMany: {\n    user: {\n      // Extended format with explicit field mappings\n      friends: [\n        {\n          sourceField: [\"id\"],\n          destTable: \"friendship\",\n          destField: [\"requestingId\"],\n        },\n        {\n          sourceField: [\"acceptingId\"],\n          destTable: \"user\",\n          destField: [\"id\"],\n        },\n      ],\n    },\n  },\n});\n```\n\n## Features\n\n- Output static schemas from the CLI\n- Convert Drizzle ORM schemas to Zero schemas\n  - Sync a subset of tables and columns\n- Handles all Drizzle column types that are supported by Zero\n- Type-safe schema generation with inferred types from Drizzle\n- Supports relationships:\n  - One-to-one relationships\n  - One-to-many relationships\n  - Many-to-many relationships with simple or extended configuration\n  - Self-referential relationships\n- Handles custom schemas and column mappings\n\n## License\n\n[Unlicense](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbriefhq%2Fdrizzle-zero","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbriefhq%2Fdrizzle-zero","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbriefhq%2Fdrizzle-zero/lists"}