content-query 0.3.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +46 -15
  2. package/dist/{build-CI4s0oFP.mjs → build-DWpB69_c.mjs} +826 -69
  3. package/dist/{build-jKnjDjQE.d.mts → build-DfoncKL8.d.mts} +17 -5
  4. package/dist/build.d.mts +1 -1
  5. package/dist/build.mjs +1 -1
  6. package/dist/cli.mjs +14 -8
  7. package/dist/{content-N1gYshjg.mjs → collection-Cb5eWGnv.mjs} +998 -344
  8. package/dist/collection-types-CsQtGw7_.d.mts +119 -0
  9. package/dist/computed.d.mts +2 -2
  10. package/dist/{types-FmUJ3cH1.d.mts → descriptor-bcPa6XLk.d.mts} +17 -1
  11. package/dist/{diagnostics-Cu94mZhl.mjs → diagnostics-DmUZtrJ6.mjs} +3 -1
  12. package/dist/{errors-C2iuBM0G.mjs → errors-Bfd0R4_P.mjs} +16 -1
  13. package/dist/file-DSOcdFj0.mjs +81 -0
  14. package/dist/{glob-Bv0dpvCQ.mjs → glob-BXJuwy_p.mjs} +94 -6
  15. package/dist/index.d.mts +76 -18
  16. package/dist/index.mjs +1 -1
  17. package/dist/internal.d.mts +54 -7
  18. package/dist/internal.mjs +424 -19
  19. package/dist/loaders.d.mts +1 -2
  20. package/dist/loaders.mjs +2 -81
  21. package/dist/next.d.mts +3 -2
  22. package/dist/next.mjs +67 -14
  23. package/dist/operators-D-w1-gDg.mjs +391 -0
  24. package/dist/query-style-C2FcT1f9.d.mts +23 -0
  25. package/dist/query.d.mts +25 -2
  26. package/dist/query.mjs +1 -1
  27. package/dist/{relational-types-B45zM34W.d.mts → relational-types-CTcalUNW.d.mts} +241 -50
  28. package/dist/revision-DBwU-aC9.d.mts +56 -0
  29. package/dist/runtime.d.mts +3 -2
  30. package/dist/runtime.mjs +1 -1
  31. package/dist/types-Dz1vTXa2.d.mts +214 -0
  32. package/dist/vite.d.mts +1 -1
  33. package/dist/vite.mjs +77 -35
  34. package/package.json +1 -1
  35. package/dist/content-lwPxE9Yu.d.mts +0 -109
  36. package/dist/descriptor-BUPT2J7X.d.mts +0 -18
  37. package/dist/operators-UqWUhKQJ.mjs +0 -173
  38. package/dist/types-BC8gVJ6u.d.mts +0 -69
  39. package/dist/validation-D_XdE1pF.mjs +0 -84
package/README.md CHANGED
@@ -9,7 +9,9 @@ Use it with your existing framework. Your application owns its routes, layouts,
9
9
  - **Typed schemas.** Validate metadata with bundled schema builders or any Standard Schema V1 provider, with inferred TypeScript types.
10
10
  - **Flexible sources.** Load local files, use Astro-compatible content loaders, or write your own loader.
11
11
  - **Queries and relationships.** Select fields, filter, sort, paginate, and load related entries with validated references.
12
+ - **Per-collection entries.** Import each collection from its own generated module with named types such as `ContentPost`, so a route bundles and traces only the collections it uses.
12
13
  - **Markdown rendering.** Request HTML, headings, and syntax highlighting as query payloads, loaded only when a query asks for them.
14
+ - **Custom payloads.** Declare schema-validated per-entry data, optionally by variant such as locale, resolved during the build from tracked related files, and loaded only when a query names it. Development edits re-resolve only the variants whose files changed.
13
15
  - **Optional MDX companion.** [`@content-query/mdx`](https://github.com/yangshun/content-query/tree/main/packages/mdx) supplies React islands and ordinary React document modules with Vite SSR. Core has no MDX or React dependency.
14
16
  - **Framework integrations.** Use Vite, Next.js, or the standalone CLI, with content updates during development.
15
17
 
@@ -44,38 +46,65 @@ Add Markdown files with `title` frontmatter under `content/posts/`, then build:
44
46
  npx content-query build
45
47
  ```
46
48
 
47
- Query the generated module from server code:
49
+ Each collection gets its own generated entry, which exports the collection under its name. Query it from server code:
48
50
 
49
51
  ```ts
50
- import { content } from "./.content-query/server.js";
52
+ import { posts } from "./.content-query/collections/posts/server.js";
51
53
  import { eq } from "content-query/query";
52
54
 
53
- const posts = await content
55
+ const summaries = await posts
54
56
  .select("id", "title")
55
- .from("posts")
56
57
  .where((fields) => eq(fields.draft, false))
57
58
  .orderBy("title");
58
59
 
59
- const post = await content.query.posts.findFirst({
60
- where: { id: posts[0]!.id },
60
+ const post = await posts.findFirst({
61
+ where: { id: summaries[0]!.id },
61
62
  payloads: { _rendered: true },
62
63
  });
63
64
  const { html, headings } = post!._payloads._rendered;
64
65
  ```
65
66
 
66
- Add `.content-query/` to `.gitignore`. Follow the quick start for a complete walkthrough, or choose a framework example below.
67
+ Built-in payloads are `_body` and `_rendered`. JSON, YAML, and TOML sources and `file()` collections have none, and a custom `BodyLoader` offers only `_body`. A query for a missing entry returns `undefined`.
68
+
69
+ An entry imports only its own collection's data, so a route that imports `posts` never bundles or traces another collection. With Vite, import from `content-query:collections/posts`. Elsewhere, such as in Next.js, map the entries in `package.json` to import `{ posts }` from `#content-query/posts` at any directory depth:
70
+
71
+ ```json
72
+ {
73
+ "imports": {
74
+ "#content-query/*": "./.content-query/collections/*/server.js"
75
+ }
76
+ }
77
+ ```
78
+
79
+ Queries return only the data they select, not even `id` implicitly. A query must select fields, include a relationship, request a payload, or select adjacent entries; otherwise it fails to type-check and throws an `invalid-query` error. Counts need no selection.
80
+
81
+ To follow a relationship, pass its target collection to `using()`. Nothing related loads implicitly:
82
+
83
+ ```ts
84
+ import { authors } from "#content-query/authors";
85
+ import { posts } from "#content-query/posts";
86
+
87
+ const withAuthors = await posts.using(authors).findMany({
88
+ columns: { title: true },
89
+ with: { author: { columns: { name: true } } },
90
+ });
91
+ ```
67
92
 
68
- ## Migrating to 0.2
93
+ A relationship whose target was not supplied is a type error and throws `invalid-query`. Nested relationships need every collection they reach, such as `posts.using(authors, publishers)`. Self-relationships need nothing.
69
94
 
70
- Version 0.2.0 removes `content.readBody()` and `content.render()`. Request bodies and rendered output as payloads in the query that loads the entry:
95
+ Each entry also exports the collection's types. `ContentPost` is a full entry; pass the selected fields to type query results, such as props for a list component:
71
96
 
72
- | 0.1 | 0.2 |
73
- | ------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
74
- | `await content.readBody("posts", id)` | `(await content.query.posts.findFirst({ where: { id }, payloads: { _body: true } }))?._payloads._body` |
75
- | `await content.render("posts", id)` | `(await content.query.posts.findFirst({ where: { id }, payloads: { _rendered: true } }))?._payloads._rendered` |
76
- | Fluent queries | Add `.withPayload("_rendered")` or `.withPayload("_body")` before the terminal. |
97
+ ```ts
98
+ import type { ContentPost } from "#content-query/posts";
99
+
100
+ type PostLink = ContentPost<"id" | "title">; // What select("id", "title") returns.
101
+ ```
77
102
 
78
- Built-in payload names start with an underscore: `_body` and `_rendered`. A query for a missing entry returns `undefined` instead of rejecting with `entry-not-found`, which no longer exists. JSON, YAML, and TOML sources and `file()` collections offer no payloads, and custom loaders typed as `BodyLoader` offer only `_body`. Rebuild generated content after upgrading; 0.1 artifacts are rejected.
103
+ Type names are `Content` plus the export name, capitalized and made singular by dropping one trailing `s` (`jobs` gives `ContentJob`, `coding` gives `ContentCoding`). Set `typeName: "Category"` in `defineCollection()` for irregular plurals. Declared payloads are typed as `ContentPostPayload<"detail">`. Collection names that are not identifiers are converted for the export and import path, such as `blog-posts` to `blogPosts`; two collections that would share an export or type name fail the build.
104
+
105
+ Paginate root queries in one call. `paginate({ page: 2, size: 10 })` returns `items`, `total`, `page`, `pageCount`, `hasNextPage`, and `hasPreviousPage` for numbered archive pages. `paginate({ size: 10, after: previous.endCursor })` returns cursor pages with `startCursor` and `endCursor` for "load more" lists. Both work in fluent queries and in `posts.paginate()`; see [pagination](https://github.com/yangshun/content-query/blob/main/docs/API.md#pagination).
106
+
107
+ Add `.content-query/` to `.gitignore`. Follow the quick start for a complete walkthrough, or choose a framework example below.
79
108
 
80
109
  ## Documentation
81
110
 
@@ -86,6 +115,8 @@ Built-in payload names start with an underscore: `_body` and `_rendered`. A quer
86
115
 
87
116
  The Vite integration supports Vite 8, and the Next.js integration supports Next.js 15 and 16. Both integrations are optional; standalone builds and queries require neither framework.
88
117
 
118
+ To allow only one query API, export `queryStyle` from the config: `export const queryStyle = "relational";` keeps `posts.findMany()`, `findFirst()`, `paginate()`, and `count(options)`, and `"fluent"` keeps `posts.select()` and the other fluent starters. `count()` without options works in both. Generated types report the disabled API in the editor, and the runtime throws an `invalid-query` error for it. See [query style](https://github.com/yangshun/content-query/blob/main/docs/API.md#query-style).
119
+
89
120
  Pass `contentQuery()` directly to Vite or Vite+'s `plugins` array. No `Plugin` type cast is needed; workspace consumers share the pinned toolchain versions in the dependency catalog.
90
121
 
91
122
  Repository development checks package types and isolated consumers with [tsrs](https://github.com/oxc-project/tsrs). Run `vp run check` in the package directory for formatting, linting, and type checks; build tools use the shared TypeScript 6 compatibility package for its `6.0.3` JavaScript API. Native TypeScript `7.1.0-beta` is available at the repository root as `vp exec tsc`.