npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@danteissaias/groq-builder

v0.9.2

Published

A **schema-aware**, strongly-typed GROQ query builder. It enables you to build GROQ queries using **auto-completion**, **type-checking**, and **runtime validation**.

Downloads

42

Readme

groq-builder

A schema-aware, strongly-typed GROQ query builder.
It enables you to build GROQ queries using auto-completion, type-checking, and runtime validation.

GROQ is Sanity's open-source query language.

"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."

Features

  • Schema-aware - uses your sanity.config.ts schema for auto-completion and type-checking.
  • Strongly-typed - query results are strongly typed, based on your Sanity schema.
  • Runtime validation - validate, parse, and transform query results at run-time, with broad or granular levels.

Brought to you by the team behind GroqD

groq-builder is the successor to GroqD. In addition to runtime validation and strongly-typed results, groq-builder adds schema-awareness and auto-completion.

Example

import { createGroqBuilder } from 'groq-builder';
import type { SchemaConfig } from './schema-config';
//            ☝️ Note:
// Please see the "Schema Configuration" docs 
// for an overview of this SchemaConfig type 

const q = createGroqBuilder<SchemaConfig>()

const productsQuery = (
  q.star
   .filterByType('products')
   .order('price desc')
   .slice(0, 10)
   .project(q => ({
     name: true,
     price: true,
     slug: q.field("slug.current"),
     imageUrls: q.field("images[]").deref().field("url")
   }))
);

In the above query, ALL fields are strongly-typed, according to the Sanity schema defined in sanity.config.ts!

  • All the strings above are strongly-typed, based on field definitions, including 'products', 'price desc', 'slug.current', 'images[]', and 'url'.
  • In the projection, the keys name and price have auto-completion, and are strongly-typed, based on the fields of product.
  • In the projection, the keys slug and imageUrls are strongly-typed based on their sub-queries.

Example Query:

This example above generates the following GROQ query:

*[_type == "products"] | order(price desc)[0...10] {
  name,
  price,
  "slug": slug.current,
  "imageUrls": images[]->url
}

Example Types:

The example above also generates the following result type:

import type { InferResultType } from 'groq-builder';

type ProductsQueryResult = InferResultType<typeof productsQuery>;
//   👆 Evaluates to the following:
type ProductsQueryResult = Array<{
  name: string,
  price: number,
  slug: string,
  imageUrls: Array<string>,
}>;

Runtime Validation

groq-builder enables effortless runtime validation using Zod:

import { z } from 'zod';

const products = q.star.filterByType('products').project(q => ({
  name: z.string(),
  slug: ["slug.current", z.string()],
  price: q.field("price", z.number().nonnegative()),
}));

Custom Parsing

Validation methods can include custom validation and/or parsing logic too:

const products = q.star.filterByType('products').project(q => ({
  price: z.number(),
  priceFormatted: q.field("price", price => formatCurrency(price)),
}));

Sanity Schema Configuration

To support auto-completion and maximum type-safety, you must configure groq-builder by providing type information for your Sanity Schema.

Fortunately, the Sanity CLI supports a typegen command that will generate the Sanity Schema Types for you!

Generating Sanity Schema Types

First, in your Sanity Studio project (where you have your sanity.config.ts), follow the Sanity documentation to run the following commands:

sanity schema extract --enforce-required-fields
sanity typegen generate

This generates a sanity.types.ts file, which contains type definitions for all your Sanity documents.

Second, copy the newly generated sanity.types.ts into your application (where you intend to use groq-builder).

Configuring groq-builder with your Sanity Schema:

In your application, you can create a strongly-typed groq-builder using the following snippet:

// ./q.ts
import { createGroqBuilder } from 'groq-builder';
import {
  AllSanitySchemaTypes,
  internalGroqTypeReferenceTo,
} from "./sanity.types.ts";

export const q = createGroqBuilder<{
  documentTypes: AllSanitySchemaTypes,
  referenceSymbol: typeof internalGroqTypeReferenceTo;
}>();

And 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!

import { q } from './q';

const productQuery = q.star.filterByType('product');