The type-safe query engine for document storage

Turn filesystems, S3 buckets, Git repos, and external APIs into a structured, queryable interface.

Collection
import { fileMarkdown } from '@piqit/resolvers'

const posts = fileMarkdown({
  base: 'content/posts',
  path: '{year}/{slug}.md',
  frontmatter: z.object({
    title: z.string(),
    status: z.enum(['draft', 'published']),
  }),
  body: { html: true }
})
Query
import { piq } from 'piqit'

// Query: scan → filter → select
const results = await piq.from(posts)
  .scan({ year: '2024' })
  .filter({ status: 'published' })
  .select(
    'params.slug',
    'frontmatter.title',
    'body.html'
  )
  .exec()

// Results are flat and fully typed:
// [{ slug, title, html }]

When to use piq

  • Agent workflows that generate and query millions of files
  • Runtime environments where memory and I/O are expensive
  • When you want explicit control over resolution cost
  • Projects where you can design query patterns upfront

When not to use piq

  • × You need writes, updates, or transactions
  • × You need joins at the query layer
  • × You are running ad-hoc analytical queries
  • × You don't want to predesign your access patterns

The piq way

piq makes resolution cost visible. The API contract exposes the true performance cost of each query.

Precision I/O

The API exposes perf cost, encouraging the writing of efficient queries.

Schema-on-Read

Define your data shape up front with Zod. Get a fully-typed query client in return.

Source Agnostic

Decouple queries from storage. Run the same queries against different sources.

Get Started

npm install piqit @piqit/resolvers