{"_id":"@danteissaias/groq-builder","name":"@danteissaias/groq-builder","dist-tags":{"latest":"0.9.2"},"versions":{"0.9.2":{"name":"@danteissaias/groq-builder","version":"0.9.2","license":"MIT","author":{"name":"Formidable","url":"https://formidable.com"},"repository":{"type":"git","url":"git+https://github.com/FormidableLabs/groqd.git"},"homepage":"https://github.com/formidablelabs/groqd","keywords":["sanity","groq","query","typescript"],"main":"./dist/index.js","sideEffects":["./dist/commands/**","./dist/groq-builder"],"module":"dist/index.mjs","types":"dist/index.d.ts","exports":{".":[{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./dist/index.js"],"./package.json":"./package.json"},"dependencies":{"type-fest":"^4.10.1","zod":"^3.22.4"},"devDependencies":{"@sanity/client":"^3.4.1","groq-js":"^1.1.9","rimraf":"^5.0.5","typescript":"^5.0.4","vitest":"^1.3.1"},"engines":{"node":">= 14"},"scripts":{"test:watch":"vitest","test":"vitest run","typecheck":"tsc --noEmit","clean":"rimraf dist","build":"pnpm run clean && tsc --project tsconfig.build.json"},"_id":"@danteissaias/groq-builder@0.9.2","description":"A **schema-aware**, strongly-typed GROQ query builder.   It enables you to build GROQ queries using **auto-completion**, **type-checking**, and **runtime validation**.","bugs":{"url":"https://github.com/FormidableLabs/groqd/issues"},"_integrity":"sha512-XYnUaR4WelKwAc022AjM9E0PTJcnUN9G93ZQiJ6BZkA1uwLFYVgwq+5fx1a7HW28NbV6Vp4nnxL5VG0XebxPwA==","_resolved":"/private/var/folders/33/1mtwcxd941d37vslgydtgr6r0000gn/T/fb1fe0e79e6e986da291a423d5cba3b2/danteissaias-groq-builder-0.9.2.tgz","_from":"file:danteissaias-groq-builder-0.9.2.tgz","_nodeVersion":"22.5.1","_npmVersion":"10.8.2","dist":{"integrity":"sha512-XYnUaR4WelKwAc022AjM9E0PTJcnUN9G93ZQiJ6BZkA1uwLFYVgwq+5fx1a7HW28NbV6Vp4nnxL5VG0XebxPwA==","shasum":"a21ac92cd89b8027916eacc1534c6a937bce1712","tarball":"https://registry.npmjs.org/@danteissaias/groq-builder/-/groq-builder-0.9.2.tgz","fileCount":117,"unpackedSize":126395,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD53fdrD+FGjludG5irrx1gtFdG0t3sqowzQxiRt5i6KAIhAJi6bdIjU/jbWNTGo2F3pbHJd2yMU1sbueAowBKhQANs"}]},"_npmUser":{"name":"danteissaias","email":"dante@issaias.com"},"directories":{},"maintainers":[{"name":"danteissaias","email":"dante@issaias.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/groq-builder_0.9.2_1724152632847_0.8468741384313812"},"_hasShrinkwrap":false}},"time":{"created":"2024-08-20T11:17:12.754Z","0.9.2":"2024-08-20T11:17:13.041Z","modified":"2024-08-20T11:17:13.312Z"},"maintainers":[{"name":"danteissaias","email":"dante@issaias.com"}],"description":"A **schema-aware**, strongly-typed GROQ query builder.   It enables you to build GROQ queries using **auto-completion**, **type-checking**, and **runtime validation**.","homepage":"https://github.com/formidablelabs/groqd","keywords":["sanity","groq","query","typescript"],"repository":{"type":"git","url":"git+https://github.com/FormidableLabs/groqd.git"},"author":{"name":"Formidable","url":"https://formidable.com"},"bugs":{"url":"https://github.com/FormidableLabs/groqd/issues"},"license":"MIT","readme":"# `groq-builder`\n\nA **schema-aware**, strongly-typed GROQ query builder.  \nIt enables you to build GROQ queries using **auto-completion**, **type-checking**, and **runtime validation**.\n\n<details>\n<summary>What is GROQ?</summary>\n\n[GROQ is Sanity's open-source query language.](https://www.sanity.io/docs/groq)\n\n> \"It's a powerful and intuitive language that's easy to learn. With GROQ you can describe exactly what information your application needs, join information from several sets of documents, and stitch together a very specific response with only the exact fields you need.\"\n\n</details>\n\n## Features\n\n- **Schema-aware** - uses your `sanity.config.ts` schema for auto-completion and type-checking.\n- **Strongly-typed** - query results are strongly typed, based on your Sanity schema.\n- **Runtime validation** - validate, parse, and transform query results at run-time, with broad or granular levels.\n\n## Brought to you by the team behind `GroqD`\n\n`groq-builder` is the successor to `GroqD`.  In addition to runtime validation and strongly-typed results, `groq-builder` adds schema-awareness and auto-completion.\n\n## Example\n\n```ts\nimport { createGroqBuilder } from 'groq-builder';\nimport type { SchemaConfig } from './schema-config';\n//            ☝️ Note:\n// Please see the \"Schema Configuration\" docs \n// for an overview of this SchemaConfig type \n\nconst q = createGroqBuilder<SchemaConfig>()\n\nconst productsQuery = (\n  q.star\n   .filterByType('products')\n   .order('price desc')\n   .slice(0, 10)\n   .project(q => ({\n     name: true,\n     price: true,\n     slug: q.field(\"slug.current\"),\n     imageUrls: q.field(\"images[]\").deref().field(\"url\")\n   }))\n);\n```\nIn the above query, ALL fields are strongly-typed, according to the Sanity schema defined in `sanity.config.ts`!  \n\n- All the strings above are strongly-typed, based on field definitions, including `'products'`, `'price desc'`, `'slug.current'`, `'images[]'`, and `'url'`.\n- In the projection, the keys `name` and `price` have auto-completion, and are strongly-typed, based on the fields of `product`.\n- In the projection, the keys `slug` and `imageUrls` are strongly-typed based on their sub-queries.\n\n### Example Query:\n\nThis example above generates the following GROQ query:\n```groq\n*[_type == \"products\"] | order(price desc)[0...10] {\n  name,\n  price,\n  \"slug\": slug.current,\n  \"imageUrls\": images[]->url\n}\n```\n\n\n### Example Types:\n\nThe example above also generates the following result type:\n\n```ts\nimport type { InferResultType } from 'groq-builder';\n\ntype ProductsQueryResult = InferResultType<typeof productsQuery>;\n//   👆 Evaluates to the following:\ntype ProductsQueryResult = Array<{\n  name: string,\n  price: number,\n  slug: string,\n  imageUrls: Array<string>,\n}>;\n```\n\n## Runtime Validation\n\n`groq-builder` enables effortless runtime validation using [Zod](https://zod.dev/): \n\n```ts\nimport { z } from 'zod';\n\nconst products = q.star.filterByType('products').project(q => ({\n  name: z.string(),\n  slug: [\"slug.current\", z.string()],\n  price: q.field(\"price\", z.number().nonnegative()),\n}));\n```\n\n## Custom Parsing\n\nValidation methods can include custom validation and/or parsing logic too:\n\n```ts\nconst products = q.star.filterByType('products').project(q => ({\n  price: z.number(),\n  priceFormatted: q.field(\"price\", price => formatCurrency(price)),\n}));\n```\n\n\n## Sanity Schema Configuration\n\nTo support auto-completion and maximum type-safety, you must configure `groq-builder` by providing type information for your Sanity Schema.\n\nFortunately, the Sanity CLI supports a `typegen` command that will generate the Sanity Schema Types for you!\n\n### Generating Sanity Schema Types\n\nFirst, in your Sanity Studio project (where you have your `sanity.config.ts`), follow [the Sanity documentation](https://www.sanity.io/docs/sanity-typegen) to run the following commands:\n```sh\nsanity schema extract --enforce-required-fields\nsanity typegen generate\n```\n\nThis generates a `sanity.types.ts` file, which contains type definitions for all your Sanity documents.\n\nSecond, copy the newly generated `sanity.types.ts` into your application (where you intend to use `groq-builder`).  \n\n\n### Configuring `groq-builder` with your Sanity Schema:\n\nIn your application, you can create a strongly-typed `groq-builder` using the following snippet:\n\n```ts\n// ./q.ts\nimport { createGroqBuilder } from 'groq-builder';\nimport {\n  AllSanitySchemaTypes,\n  internalGroqTypeReferenceTo,\n} from \"./sanity.types.ts\";\n\nexport const q = createGroqBuilder<{\n  documentTypes: AllSanitySchemaTypes,\n  referenceSymbol: typeof internalGroqTypeReferenceTo;\n}>();\n```\n\nAnd that's it!  Wherever you write queries, be sure to import this strongly-typed `q` and you'll get full auto-completion and type-safety! \n```ts\nimport { q } from './q';\n\nconst productQuery = q.star.filterByType('product');\n```\n","readmeFilename":"README.md"}