feat(slice3): listRFCs accepts facet selections, returns {items,facets} (§22.4a)

This commit is contained in:
Ben Stull
2026-06-07 17:38:16 -07:00
parent 7b269e11c4
commit bcce40d2cb
+20 -4
View File
@@ -203,11 +203,27 @@ export async function createProject({ projectId, name, type, visibility, content
// §22.4 (Plan B) / §22 S2: per-collection serving. With a projectId + a
// collectionId, read the collection-scoped routes; with only a projectId, the
// project default-collection compat path; with neither, the unscoped path.
export async function listRFCs(projectId, collectionId) {
if (projectId && collectionId) {
return jsonOrThrow(await fetch(`/api/projects/${projectId}/collections/${collectionId}/rfcs`))
// §22.4a SLICE-3: faceted catalog. `opts.selections` is { field: string[] }
// (each non-empty array becomes repeated query params, OR within the field);
// `opts.malformed` toggles the malformed-only filter. Returns the full payload
// { items, facets } — callers read both. With no selections it behaves as the
// pre-SLICE-3 list (and a no-fields collection returns facets: {}). Facets are
// served only on the project/collection-scoped paths, not the unscoped one.
export async function listRFCs(projectId, collectionId, opts = {}) {
const { selections = {}, malformed = false } = opts
const qs = new URLSearchParams()
for (const [field, values] of Object.entries(selections)) {
for (const v of values) qs.append(field, v)
}
const url = projectId ? `/api/projects/${projectId}/rfcs` : '/api/rfcs'
if (malformed) qs.set('malformed', 'true')
const query = qs.toString()
let base
if (projectId && collectionId) {
base = `/api/projects/${projectId}/collections/${collectionId}/rfcs`
} else {
base = projectId ? `/api/projects/${projectId}/rfcs` : '/api/rfcs'
}
const url = query ? `${base}?${query}` : base
return jsonOrThrow(await fetch(url))
}