contentrain-query — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited contentrain-query (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
@contentrain/query is a Prisma-pattern generated client that provides type-safe access to Contentrain content. Generated output lives in .contentrain/client/ — never edit it manually.
npx contentrain generate # Generate client from modelsimport { query, singleton, dictionary, document } from '#contentrain'
// Collection
const posts = query('blog-post').where('category', 'eq', 'engineering').sort('published_at', 'desc').limit(10).all()
// Singleton
const hero = singleton('hero').get()
// Dictionary
const t = dictionary('ui-texts').get()
const loginLabel = t['auth.login.button']
// Document
const doc = document('blog-post').bySlug('getting-started')| Method | Description |
|---|---|
.all() | Get all entries |
.first() | Get first entry |
.count() | Return count of matching entries |
.where(field, value) | Equality filter (shorthand for eq) |
.where(field, op, value) | Operator filter: eq, ne, gt, gte, lt, lte, in, contains |
.sort(field, direction?) | Sort (asc/desc, default asc) |
.limit(n) | Limit results |
.offset(n) | Skip results |
.include(relation) | Resolve relation (1 level deep) |
| Method | Description |
|---|---|
.get() | Get the singleton data |
.include(relation) | Resolve relation fields |
| Method | Description |
|---|---|
.get() | Get all key-value pairs |
.get(key) | Get single value by key |
.get(key, params) | Get with interpolation: {placeholder} → value |
| Method | Description |
|---|---|
.all() | Get all documents |
.bySlug(slug) | Get document by slug |
.first() | Get first document |
.count() | Return count of matching documents |
.where(field, value) | Equality filter (shorthand) |
.where(field, op, value) | Operator filter (same ops as QueryBuilder) |
.include(relation) | Resolve relation fields |
For server-side or client-side apps that fetch content from Contentrain Studio CDN:
import { createContentrain } from '@contentrain/query/cdn'
const client = createContentrain({
projectId: '350696e8-...',
apiKey: 'crn_live_xxx',
})
// All CDN queries are async (return Promise)
const posts = await client.collection('faq').locale('en').all()
const hero = await client.singleton('hero').locale('en').get()
const t = await client.dictionary('ui').locale('en').get()
const doc = await client.document('docs').locale('en').bySlug('intro')await neededawait.contentrain/client/ are immutable — always regenerate, never editcontentrain generate after any model change| Framework | Import | Notes |
|---|---|---|
| Nuxt 3 | import { query } from '#contentrain' | Server-only (server routes, plugins) |
| Next.js | import { query } from '#contentrain' | Works in RSC and API routes |
| Astro | import { query } from '#contentrain' | Works in .astro frontmatter |
| SvelteKit | import { query } from '#contentrain' | Works in +page.server.ts |
| Vue + Vite | import { query } from '#contentrain' | Requires Vite alias config |
| React + Vite | import { query } from '#contentrain' | Requires Vite alias config |
| Node.js | import { query } from '#contentrain' | ESM with subpath imports |
| Reference | Description |
|---|---|
| Bundler Configuration | Vite, Next.js, Nuxt, SvelteKit, Metro alias setup |
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.