Skip to content

feat(plugins): add where filter to ContentListOptions#540

Merged
ascorbic merged 2 commits intoemdash-cms:mainfrom
jdevalk:feat/content-list-where-status
Apr 13, 2026
Merged

feat(plugins): add where filter to ContentListOptions#540
ascorbic merged 2 commits intoemdash-cms:mainfrom
jdevalk:feat/content-list-where-status

Conversation

@jdevalk
Copy link
Copy Markdown
Contributor

@jdevalk jdevalk commented Apr 13, 2026

What does this PR do?

Adds where: { status?, locale? } to the plugin-facing ContentListOptions, letting plugins narrow ContentAccess.list() results at the database layer instead of pulling every row and filtering in userland.

The underlying ContentRepository.findMany already accepts where.status / where.locale / where.authorId (packages/core/src/database/repositories/types.ts:66) — this PR only plumbs the commonly-needed subset through the public API. authorId is left out for now since no current ask requires it; easy follow-up if someone needs it.

Why: today, a plugin that wants "published items only" has to pull every row (drafts, trashed, everything), filter in memory, and discard most of them. On a site with thousands of drafts this is wasteful and paginates wrong (the cursor counts pre-filter rows). A where.status filter pushes the narrowing into the SQL query, which is what the repository was designed to do.

Discussion: #530. Companion PR #539 handles the locale field addition to ContentItem.

Type of change

  • Feature (additive — new optional field on an existing options type, no behavior change for consumers that don't pass it)

Checklist

AI-generated code disclosure

  • This PR includes AI-generated code

Exposes `where: { status?, locale? }` on the plugin-facing
ContentListOptions so plugins can narrow `ContentAccess.list()` results
at the database layer. The underlying ContentRepository.findMany
already supports both filters (plus authorId) — this PR only plumbs
the commonly-needed subset through the public API.

Without these, plugins either (a) filter in userland, which still pays
for pulling every row across the plugin boundary, or (b) drop to raw
`ctx.db` access, which defeats the purpose of the typed API.

Follow-up to Discussion emdash-cms#530.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings April 13, 2026 20:05
@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Apr 13, 2026

🦋 Changeset detected

Latest commit: 4ff98d0

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 9 packages
Name Type
emdash Minor
@emdash-cms/cloudflare Minor
@emdash-cms/admin Minor
@emdash-cms/auth Minor
@emdash-cms/blocks Minor
@emdash-cms/gutenberg-to-portable-text Minor
@emdash-cms/x402 Minor
create-emdash Minor
@emdash-cms/plugin-embeds Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Apr 13, 2026

Open in StackBlitz

@emdash-cms/admin

npm i https://pkg.pr.new/@emdash-cms/admin@540

@emdash-cms/auth

npm i https://pkg.pr.new/@emdash-cms/auth@540

@emdash-cms/blocks

npm i https://pkg.pr.new/@emdash-cms/blocks@540

@emdash-cms/cloudflare

npm i https://pkg.pr.new/@emdash-cms/cloudflare@540

emdash

npm i https://pkg.pr.new/emdash@540

create-emdash

npm i https://pkg.pr.new/create-emdash@540

@emdash-cms/gutenberg-to-portable-text

npm i https://pkg.pr.new/@emdash-cms/gutenberg-to-portable-text@540

@emdash-cms/x402

npm i https://pkg.pr.new/@emdash-cms/x402@540

@emdash-cms/plugin-ai-moderation

npm i https://pkg.pr.new/@emdash-cms/plugin-ai-moderation@540

@emdash-cms/plugin-atproto

npm i https://pkg.pr.new/@emdash-cms/plugin-atproto@540

@emdash-cms/plugin-audit-log

npm i https://pkg.pr.new/@emdash-cms/plugin-audit-log@540

@emdash-cms/plugin-color

npm i https://pkg.pr.new/@emdash-cms/plugin-color@540

@emdash-cms/plugin-embeds

npm i https://pkg.pr.new/@emdash-cms/plugin-embeds@540

@emdash-cms/plugin-forms

npm i https://pkg.pr.new/@emdash-cms/plugin-forms@540

@emdash-cms/plugin-webhook-notifier

npm i https://pkg.pr.new/@emdash-cms/plugin-webhook-notifier@540

commit: 4ff98d0

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds plugin-facing query narrowing to the plugin content API by introducing a where filter on ContentListOptions, allowing ContentAccess.list() to push common filters down into ContentRepository.findMany() (SQL-layer filtering, pre-pagination).

Changes:

  • Introduces ContentListWhere and adds where?: ContentListWhere to ContentListOptions.
  • Plumbs options.where through createContentAccess().list() into ContentRepository.findMany().
  • Adds a changeset bumping emdash minor for the new plugin API surface.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
packages/core/src/plugins/types.ts Adds ContentListWhere and exposes where on ContentListOptions for plugins.
packages/core/src/plugins/context.ts Forwards ContentListOptions.where to ContentRepository.findMany() during listing.
.changeset/content-list-where-status.md Declares a minor release and documents the new where option for plugins.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 234 to 239
const result = await contentRepo.findMany(collection, {
limit: options?.limit ?? 50,
cursor: options?.cursor,
orderBy,
where: options?.where,
});
Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ContentAccess.list() now forwards options.where down to ContentRepository.findMany(), but the integration tests for plugin content access currently only cover unfiltered listing. Please add a test that asserts where.status and/or where.locale actually narrows results (and that pagination/cursor behavior is consistent when filtering).

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added 5 integration tests in tests/integration/plugins/capabilities.test.ts covering where.status, where.locale, combined filters, and cursor pagination with filters applied (4ff98d0).

Copy link
Copy Markdown
Collaborator

@ascorbic ascorbic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a test too please

- Removes the verbose docblock on ContentListWhere per @ascorbic review.
- Adds five integration tests covering where.status, where.locale, the
  combined filter, and cursor pagination under a where clause (per
  Copilot review).
@jdevalk
Copy link
Copy Markdown
Contributor Author

jdevalk commented Apr 13, 2026

Can you add a test too please

Done.

@github-actions github-actions bot added size/M and removed size/S labels Apr 13, 2026
Copy link
Copy Markdown
Collaborator

@ascorbic ascorbic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks

@ascorbic ascorbic merged commit 82c6345 into emdash-cms:main Apr 13, 2026
28 of 29 checks passed
@emdashbot emdashbot bot mentioned this pull request Apr 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants