content-query 0.4.0 → 0.5.1

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.
package/dist/internal.mjs CHANGED
@@ -1,8 +1,7 @@
1
1
  import { t as ContentError } from "./errors-Bfd0R4_P.mjs";
2
2
  import { r as decode } from "./values-BbTV4QT-.mjs";
3
- import { n as createRuntime, o as prepareRelationships, r as isQueryStyle, t as createLiveRuntime } from "./content-BXrgP7nL.mjs";
3
+ import { i as isQueryStyle, n as createCollections, r as createLiveCollection, t as createCollection } from "./collection-Cb5eWGnv.mjs";
4
4
  import { t as restoreContentError } from "./diagnostics-DmUZtrJ6.mjs";
5
- import { gunzipSync } from "fflate/browser";
6
5
  //#region src/artifacts/runtime.ts
7
6
  /** Checks that a value is a plain record before reading generated payload tables from it. */
8
7
  function isTable(value) {
@@ -25,10 +24,38 @@ function customPayloadTable(collection, payloads) {
25
24
  }))];
26
25
  }));
27
26
  }
28
- /** Initializes generated/embedded prepared content. This versioned wiring is internal. */
27
+ /**
28
+ * Decoded collections by generated collection module. The main server entry and collection
29
+ * entries import the same module, so a process that loads several entries decodes it once.
30
+ * Prepared records are never mutated, since queries project copies.
31
+ */
32
+ const decodedCollections = /* @__PURE__ */ new WeakMap();
33
+ /** Decodes and checks one generated collection module, reusing an earlier decoding of it. */
34
+ function decodeCollection(name, encoded) {
35
+ const cached = decodedCollections.get(encoded);
36
+ if (cached) return cached;
37
+ const records = encoded.records.map((record) => decode(record));
38
+ if (records.some((record) => !record || typeof record !== "object" || Array.isArray(record) || !Object.hasOwn(record, "id") || typeof record.id !== "string" || !record.id || Object.hasOwn(record, "_adjacent") || Object.hasOwn(record, "_payloads")) || new Set(records.map((record) => record.id)).size !== records.length) throw new Error(`Invalid query records for collection "${name}".`);
39
+ const decoded = {
40
+ records,
41
+ builtins: new Map(Object.entries(encoded.builtins ?? {}).map(([id, load]) => [id, async () => decode((await load()).default)])),
42
+ ...encoded.payloads ? { payloads: customPayloadTable(name, encoded.payloads) } : {}
43
+ };
44
+ decodedCollections.set(encoded, decoded);
45
+ return decoded;
46
+ }
47
+ /**
48
+ * Initializes generated/embedded prepared content. This versioned wiring is internal.
49
+ * Relationships are related when a query scope combines the collections it loads.
50
+ *
51
+ * @param manifest - The entry's manifest; its registry lists exactly the collections it serves.
52
+ * @param collections - Generated collection modules by name.
53
+ * @param renderMarkdown - The packaged renderer, when a served collection captured Markdown.
54
+ * @returns The prepared revision.
55
+ */
29
56
  function createArtifactRevision(manifest, collections, renderMarkdown) {
30
57
  try {
31
- if (manifest.version !== 2 || manifest.codec !== "devalue-6.0.2") throw new Error("Incompatible content artifact or codec version; regenerate content.");
58
+ if (manifest.version !== 3 || manifest.codec !== "devalue-6.0.2") throw new Error("Incompatible content artifact or codec version; regenerate content.");
32
59
  if (manifest.queryStyle !== void 0 && !isQueryStyle(manifest.queryStyle)) throw new Error("Invalid query style in content artifact; regenerate content.");
33
60
  const revision = {
34
61
  registry: manifest.collections,
@@ -42,18 +69,12 @@ function createArtifactRevision(manifest, collections, renderMarkdown) {
42
69
  };
43
70
  for (const [name, descriptor] of Object.entries(manifest.collections)) {
44
71
  const encoded = collections[name];
45
- if (!encoded || !Array.isArray(encoded.records)) throw new Error(`Missing collection artifact "${name}".`);
46
- const records = encoded.records.map((record) => decode(record));
47
- if (records.some((record) => !record || typeof record !== "object" || Array.isArray(record) || !Object.hasOwn(record, "id") || typeof record.id !== "string" || !record.id || Object.hasOwn(record, "_adjacent") || Object.hasOwn(record, "_payloads")) || new Set(records.map((record) => record.id)).size !== records.length) throw new Error(`Invalid query records for collection "${name}".`);
72
+ if (!encoded || typeof encoded !== "object" || !Array.isArray(encoded.records)) throw new Error(`Missing collection artifact "${name}".`);
48
73
  revision.collections[name] = {
49
- records,
50
- relationships: descriptor.relationships,
51
- builtins: new Map(Object.entries(encoded.builtins ?? {}).map(([id, load]) => [id, async () => decode((await load()).default)])),
52
- ...encoded.payloads ? { payloads: customPayloadTable(name, encoded.payloads) } : {}
74
+ ...decodeCollection(name, encoded),
75
+ relationships: descriptor.relationships
53
76
  };
54
77
  }
55
- const errors = prepareRelationships(revision);
56
- if (errors.length) throw errors[0];
57
78
  return revision;
58
79
  } catch (cause) {
59
80
  throw new ContentError({
@@ -63,10 +84,370 @@ function createArtifactRevision(manifest, collections, renderMarkdown) {
63
84
  });
64
85
  }
65
86
  }
66
- /** Initializes the public generated server export from a complete immutable artifact revision. */
67
- function createArtifactRuntime(manifest, collections, renderMarkdown) {
68
- return createRuntime({ revision: createArtifactRevision(manifest, collections, renderMarkdown) });
87
+ /**
88
+ * Initializes one generated collection entry's export.
89
+ *
90
+ * @param manifest - The entry's manifest, which lists only this collection.
91
+ * @param name - The collection's name.
92
+ * @param collection - The generated collection module.
93
+ * @param renderMarkdown - The packaged renderer, when the collection captured Markdown.
94
+ * @returns The collection handle the entry exports.
95
+ */
96
+ function createArtifactCollection(manifest, name, collection, renderMarkdown) {
97
+ const revision = createArtifactRevision(manifest, { [name]: collection }, renderMarkdown);
98
+ if (!Object.hasOwn(revision.collections, name)) throw new ContentError({
99
+ code: "artifact-error",
100
+ message: `Missing collection artifact "${name}".`
101
+ });
102
+ return createCollection({
103
+ name,
104
+ state: { revision }
105
+ });
106
+ }
107
+ /**
108
+ * Initializes handles for every collection of one artifact revision, sharing its caches. Tests
109
+ * and integrations use it; applications import each collection's own entry instead.
110
+ *
111
+ * @param manifest - A manifest that lists every collection in `collections`.
112
+ * @param collections - Generated collection modules by name.
113
+ * @param renderMarkdown - The packaged renderer, when a collection captured Markdown.
114
+ * @returns Collection handles keyed by collection name.
115
+ */
116
+ function createArtifactCollections(manifest, collections, renderMarkdown) {
117
+ return createCollections({ revision: createArtifactRevision(manifest, collections, renderMarkdown) });
118
+ }
119
+ //#endregion
120
+ //#region ../../node_modules/.pnpm/fflate@0.8.3/node_modules/fflate/esm/browser.js
121
+ var u8 = Uint8Array;
122
+ var u16 = Uint16Array;
123
+ var i32 = Int32Array;
124
+ var fleb = new u8([
125
+ 0,
126
+ 0,
127
+ 0,
128
+ 0,
129
+ 0,
130
+ 0,
131
+ 0,
132
+ 0,
133
+ 1,
134
+ 1,
135
+ 1,
136
+ 1,
137
+ 2,
138
+ 2,
139
+ 2,
140
+ 2,
141
+ 3,
142
+ 3,
143
+ 3,
144
+ 3,
145
+ 4,
146
+ 4,
147
+ 4,
148
+ 4,
149
+ 5,
150
+ 5,
151
+ 5,
152
+ 5,
153
+ 0,
154
+ 0,
155
+ 0,
156
+ 0
157
+ ]);
158
+ var fdeb = new u8([
159
+ 0,
160
+ 0,
161
+ 0,
162
+ 0,
163
+ 1,
164
+ 1,
165
+ 2,
166
+ 2,
167
+ 3,
168
+ 3,
169
+ 4,
170
+ 4,
171
+ 5,
172
+ 5,
173
+ 6,
174
+ 6,
175
+ 7,
176
+ 7,
177
+ 8,
178
+ 8,
179
+ 9,
180
+ 9,
181
+ 10,
182
+ 10,
183
+ 11,
184
+ 11,
185
+ 12,
186
+ 12,
187
+ 13,
188
+ 13,
189
+ 0,
190
+ 0
191
+ ]);
192
+ var clim = new u8([
193
+ 16,
194
+ 17,
195
+ 18,
196
+ 0,
197
+ 8,
198
+ 7,
199
+ 9,
200
+ 6,
201
+ 10,
202
+ 5,
203
+ 11,
204
+ 4,
205
+ 12,
206
+ 3,
207
+ 13,
208
+ 2,
209
+ 14,
210
+ 1,
211
+ 15
212
+ ]);
213
+ var freb = function(eb, start) {
214
+ var b = new u16(31);
215
+ for (var i = 0; i < 31; ++i) b[i] = start += 1 << eb[i - 1];
216
+ var r = new i32(b[30]);
217
+ for (var i = 1; i < 30; ++i) for (var j = b[i]; j < b[i + 1]; ++j) r[j] = j - b[i] << 5 | i;
218
+ return {
219
+ b,
220
+ r
221
+ };
222
+ };
223
+ var _a = freb(fleb, 2);
224
+ var fl = _a.b;
225
+ var revfl = _a.r;
226
+ fl[28] = 258, revfl[258] = 28;
227
+ var _b = freb(fdeb, 0);
228
+ var fd = _b.b;
229
+ _b.r;
230
+ var rev = new u16(32768);
231
+ for (var i = 0; i < 32768; ++i) {
232
+ var x = (i & 43690) >> 1 | (i & 21845) << 1;
233
+ x = (x & 52428) >> 2 | (x & 13107) << 2;
234
+ x = (x & 61680) >> 4 | (x & 3855) << 4;
235
+ rev[i] = ((x & 65280) >> 8 | (x & 255) << 8) >> 1;
236
+ }
237
+ var hMap = (function(cd, mb, r) {
238
+ var s = cd.length;
239
+ var i = 0;
240
+ var l = new u16(mb);
241
+ for (; i < s; ++i) if (cd[i]) ++l[cd[i] - 1];
242
+ var le = new u16(mb);
243
+ for (i = 1; i < mb; ++i) le[i] = le[i - 1] + l[i - 1] << 1;
244
+ var co;
245
+ if (r) {
246
+ co = new u16(1 << mb);
247
+ var rvb = 15 - mb;
248
+ for (i = 0; i < s; ++i) if (cd[i]) {
249
+ var sv = i << 4 | cd[i];
250
+ var r_1 = mb - cd[i];
251
+ var v = le[cd[i] - 1]++ << r_1;
252
+ for (var m = v | (1 << r_1) - 1; v <= m; ++v) co[rev[v] >> rvb] = sv;
253
+ }
254
+ } else {
255
+ co = new u16(s);
256
+ for (i = 0; i < s; ++i) if (cd[i]) co[i] = rev[le[cd[i] - 1]++] >> 15 - cd[i];
257
+ }
258
+ return co;
259
+ });
260
+ var flt = new u8(288);
261
+ for (var i = 0; i < 144; ++i) flt[i] = 8;
262
+ for (var i = 144; i < 256; ++i) flt[i] = 9;
263
+ for (var i = 256; i < 280; ++i) flt[i] = 7;
264
+ for (var i = 280; i < 288; ++i) flt[i] = 8;
265
+ var fdt = new u8(32);
266
+ for (var i = 0; i < 32; ++i) fdt[i] = 5;
267
+ var flrm = /*#__PURE__*/ hMap(flt, 9, 1);
268
+ var fdrm = /*#__PURE__*/ hMap(fdt, 5, 1);
269
+ var max = function(a) {
270
+ var m = a[0];
271
+ for (var i = 1; i < a.length; ++i) if (a[i] > m) m = a[i];
272
+ return m;
273
+ };
274
+ var bits = function(d, p, m) {
275
+ var o = p / 8 | 0;
276
+ return (d[o] | d[o + 1] << 8) >> (p & 7) & m;
277
+ };
278
+ var bits16 = function(d, p) {
279
+ var o = p / 8 | 0;
280
+ return (d[o] | d[o + 1] << 8 | d[o + 2] << 16) >> (p & 7);
281
+ };
282
+ var shft = function(p) {
283
+ return (p + 7) / 8 | 0;
284
+ };
285
+ var slc = function(v, s, e) {
286
+ if (s == null || s < 0) s = 0;
287
+ if (e == null || e > v.length) e = v.length;
288
+ return new u8(v.subarray(s, e));
289
+ };
290
+ var ec = [
291
+ "unexpected EOF",
292
+ "invalid block type",
293
+ "invalid length/literal",
294
+ "invalid distance",
295
+ "stream finished",
296
+ "no stream handler",
297
+ ,
298
+ "no callback",
299
+ "invalid UTF-8 data",
300
+ "extra field too long",
301
+ "date not in range 1980-2099",
302
+ "filename too long",
303
+ "stream finishing",
304
+ "invalid zip data"
305
+ ];
306
+ var err = function(ind, msg, nt) {
307
+ var e = new Error(msg || ec[ind]);
308
+ e.code = ind;
309
+ if (Error.captureStackTrace) Error.captureStackTrace(e, err);
310
+ if (!nt) throw e;
311
+ return e;
312
+ };
313
+ var inflt = function(dat, st, buf, dict) {
314
+ var sl = dat.length, dl = dict ? dict.length : 0;
315
+ if (!sl || st.f && !st.l) return buf || new u8(0);
316
+ var noBuf = !buf;
317
+ var resize = noBuf || st.i != 2;
318
+ var noSt = st.i;
319
+ if (noBuf) buf = new u8(sl * 3);
320
+ var cbuf = function(l) {
321
+ var bl = buf.length;
322
+ if (l > bl) {
323
+ var nbuf = new u8(Math.max(bl * 2, l));
324
+ nbuf.set(buf);
325
+ buf = nbuf;
326
+ }
327
+ };
328
+ var final = st.f || 0, pos = st.p || 0, bt = st.b || 0, lm = st.l, dm = st.d, lbt = st.m, dbt = st.n;
329
+ var tbts = sl * 8;
330
+ do {
331
+ if (!lm) {
332
+ final = bits(dat, pos, 1);
333
+ var type = bits(dat, pos + 1, 3);
334
+ pos += 3;
335
+ if (!type) {
336
+ var s = shft(pos) + 4, l = dat[s - 4] | dat[s - 3] << 8, t = s + l;
337
+ if (t > sl) {
338
+ if (noSt) err(0);
339
+ break;
340
+ }
341
+ if (resize) cbuf(bt + l);
342
+ buf.set(dat.subarray(s, t), bt);
343
+ st.b = bt += l, st.p = pos = t * 8, st.f = final;
344
+ continue;
345
+ } else if (type == 1) lm = flrm, dm = fdrm, lbt = 9, dbt = 5;
346
+ else if (type == 2) {
347
+ var hLit = bits(dat, pos, 31) + 257, hcLen = bits(dat, pos + 10, 15) + 4;
348
+ var tl = hLit + bits(dat, pos + 5, 31) + 1;
349
+ pos += 14;
350
+ var ldt = new u8(tl);
351
+ var clt = new u8(19);
352
+ for (var i = 0; i < hcLen; ++i) clt[clim[i]] = bits(dat, pos + i * 3, 7);
353
+ pos += hcLen * 3;
354
+ var clb = max(clt), clbmsk = (1 << clb) - 1;
355
+ var clm = hMap(clt, clb, 1);
356
+ for (var i = 0; i < tl;) {
357
+ var r = clm[bits(dat, pos, clbmsk)];
358
+ pos += r & 15;
359
+ var s = r >> 4;
360
+ if (s < 16) ldt[i++] = s;
361
+ else {
362
+ var c = 0, n = 0;
363
+ if (s == 16) n = 3 + bits(dat, pos, 3), pos += 2, c = ldt[i - 1];
364
+ else if (s == 17) n = 3 + bits(dat, pos, 7), pos += 3;
365
+ else if (s == 18) n = 11 + bits(dat, pos, 127), pos += 7;
366
+ while (n--) ldt[i++] = c;
367
+ }
368
+ }
369
+ var lt = ldt.subarray(0, hLit), dt = ldt.subarray(hLit);
370
+ lbt = max(lt);
371
+ dbt = max(dt);
372
+ lm = hMap(lt, lbt, 1);
373
+ dm = hMap(dt, dbt, 1);
374
+ } else err(1);
375
+ if (pos > tbts) {
376
+ if (noSt) err(0);
377
+ break;
378
+ }
379
+ }
380
+ if (resize) cbuf(bt + 131072);
381
+ var lms = (1 << lbt) - 1, dms = (1 << dbt) - 1;
382
+ var lpos = pos;
383
+ for (;; lpos = pos) {
384
+ var c = lm[bits16(dat, pos) & lms], sym = c >> 4;
385
+ pos += c & 15;
386
+ if (pos > tbts) {
387
+ if (noSt) err(0);
388
+ break;
389
+ }
390
+ if (!c) err(2);
391
+ if (sym < 256) buf[bt++] = sym;
392
+ else if (sym == 256) {
393
+ lpos = pos, lm = null;
394
+ break;
395
+ } else {
396
+ var add = sym - 254;
397
+ if (sym > 264) {
398
+ var i = sym - 257, b = fleb[i];
399
+ add = bits(dat, pos, (1 << b) - 1) + fl[i];
400
+ pos += b;
401
+ }
402
+ var d = dm[bits16(dat, pos) & dms], dsym = d >> 4;
403
+ if (!d) err(3);
404
+ pos += d & 15;
405
+ var dt = fd[dsym];
406
+ if (dsym > 3) {
407
+ var b = fdeb[dsym];
408
+ dt += bits16(dat, pos) & (1 << b) - 1, pos += b;
409
+ }
410
+ if (pos > tbts) {
411
+ if (noSt) err(0);
412
+ break;
413
+ }
414
+ if (resize) cbuf(bt + 131072);
415
+ var end = bt + add;
416
+ if (bt < dt) {
417
+ var shift = dl - dt, dend = Math.min(dt, end);
418
+ if (shift + bt < 0) err(3);
419
+ for (; bt < dend; ++bt) buf[bt] = dict[shift + bt];
420
+ }
421
+ for (; bt < end; ++bt) buf[bt] = buf[bt - dt];
422
+ }
423
+ }
424
+ st.l = lm, st.p = lpos, st.b = bt, st.f = final;
425
+ if (lm) final = 1, st.m = lbt, st.d = dm, st.n = dbt;
426
+ } while (!final);
427
+ return bt != buf.length && noBuf ? slc(buf, 0, bt) : buf.subarray(0, bt);
428
+ };
429
+ var et = /*#__PURE__*/ new u8(0);
430
+ var gzs = function(d) {
431
+ if (d[0] != 31 || d[1] != 139 || d[2] != 8) err(6, "invalid gzip data");
432
+ var flg = d[3];
433
+ var st = 10;
434
+ if (flg & 4) st += (d[10] | d[11] << 8) + 2;
435
+ for (var zs = (flg >> 3 & 1) + (flg >> 4 & 1); zs > 0; zs -= !d[st++]);
436
+ return st + (flg & 2);
437
+ };
438
+ var gzl = function(d) {
439
+ var l = d.length;
440
+ return (d[l - 4] | d[l - 3] << 8 | d[l - 2] << 16 | d[l - 1] << 24) >>> 0;
441
+ };
442
+ function gunzipSync(data, opts) {
443
+ var st = gzs(data);
444
+ if (st + 8 > data.length) err(6, "invalid gzip data");
445
+ return inflt(data.subarray(st, -8), { i: 2 }, opts && opts.out || new u8(gzl(data)), opts && opts.dictionary);
69
446
  }
447
+ var td = typeof TextDecoder != "undefined" && /*#__PURE__*/ new TextDecoder();
448
+ try {
449
+ td.decode(et, { stream: true });
450
+ } catch (e) {}
70
451
  //#endregion
71
452
  //#region src/artifacts/payloads.ts
72
453
  /**
@@ -110,4 +491,4 @@ function createPayloadLoaders(chunks) {
110
491
  return loaders;
111
492
  }
112
493
  //#endregion
113
- export { createArtifactRevision, createArtifactRuntime, createLiveRuntime, createPayloadLoaders, decodeCompressed, restoreContentError };
494
+ export { createArtifactCollection, createArtifactCollections, createArtifactRevision, createLiveCollection, createPayloadLoaders, decodeCompressed, restoreContentError };
package/dist/next.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { t as BuildContentOptions } from "./build-DL1GzmRy.mjs";
1
+ import { t as BuildContentOptions } from "./build-Aoi7Unm0.mjs";
2
2
  import { NextConfig } from "next";
3
3
  //#region src/integrations/next/plugin.d.ts
4
4
  /** Content locations for Next.js; the adapter chooses generated storage and the watch lifecycle. */
@@ -9,7 +9,8 @@ type ConfigContext = {
9
9
  type ConfigInput = NextConfig | Promise<NextConfig> | ((phase: string, context: ConfigContext) => NextConfig | Promise<NextConfig>);
10
10
  /**
11
11
  * Builds content before Next compiles, retaining one managed watcher during `next dev`.
12
- * Import the generated server entry from Server Components; Next's HMR observes its updates.
12
+ * Import each collection's generated entry, such as `#content-query/posts`, from Server
13
+ * Components; Next's HMR observes their updates, and each route traces only what it imports.
13
14
  * Next's detached telemetry helper evaluates configuration without starting content sessions.
14
15
  * @param nextConfig Existing object, promise, or phase-aware Next.js configuration.
15
16
  * @param options Optional content configuration file and generated output directory.
package/dist/next.mjs CHANGED
@@ -1,10 +1,12 @@
1
- import { c as contentDeclarations, i as resolveConfigPath, t as buildAtRoot } from "./build-CcqIpkes.mjs";
1
+ import { I as collectionNames } from "./operators-D-w1-gDg.mjs";
2
+ import { c as collectionDeclarations, i as resolveConfigPath, t as buildAtRoot } from "./build-CIw4yWs9.mjs";
2
3
  import { n as serializeContentError } from "./diagnostics-DmUZtrJ6.mjs";
3
4
  import path from "node:path";
4
5
  import { randomUUID } from "node:crypto";
5
- import { mkdirSync, readFileSync, readdirSync, renameSync, rmSync, writeFileSync } from "node:fs";
6
+ import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, rmdirSync, writeFileSync } from "node:fs";
6
7
  import { PHASE_DEVELOPMENT_SERVER, PHASE_PRODUCTION_BUILD } from "next/constants.js";
7
8
  //#region src/integrations/next/publication.ts
9
+ const developmentEntry = /^next-dev-[a-f0-9]{8}(?:-[a-f0-9]{4}){3}-[a-f0-9]{12}\.js$/;
8
10
  /** Switches a development entry synchronously so error delivery cannot race a later publication. */
9
11
  function writeEntry(filename, source) {
10
12
  try {
@@ -19,25 +21,75 @@ function writeEntry(filename, source) {
19
21
  rmSync(temporary, { force: true });
20
22
  }
21
23
  }
22
- /** Publishes fresh runtime imports and optionally prunes previous runs after a successful build. */
24
+ /** Lists one directory's entries, treating a missing directory as empty. */
25
+ function entriesOf(directory) {
26
+ try {
27
+ return readdirSync(directory);
28
+ } catch (cause) {
29
+ const code = cause && typeof cause === "object" && "code" in cause ? cause.code : void 0;
30
+ if (code === "ENOENT" || code === "ENOTDIR") return [];
31
+ throw cause;
32
+ }
33
+ }
34
+ /** Lists the directories of collection entries that exist from an earlier publication. */
35
+ function publishedCollections(outDir) {
36
+ const collections = path.join(outDir, "collections");
37
+ return entriesOf(collections).map((name) => path.join(collections, name)).filter((directory) => existsSync(path.join(directory, "server.js")));
38
+ }
39
+ /** Points one entry at a fresh copy of its runtime, so Next reloads it even for identical bytes. */
40
+ function redirectEntry(directory, exportName, filename) {
41
+ const entry = path.join(directory, "server.js");
42
+ const runtime = path.join(directory, filename);
43
+ writeEntry(runtime, readFileSync(entry, "utf8"));
44
+ writeEntry(entry, `export { ${exportName} } from ${JSON.stringify(`./${filename}`)};\n`);
45
+ return runtime;
46
+ }
47
+ /**
48
+ * Publishes fresh runtime imports and optionally prunes previous runs after a successful build.
49
+ *
50
+ * Each collection entry, `collections/<export name>/server.js`, is pointed at a fresh copy of its
51
+ * runtime. A preparation error replaces every entry, so each route that imports one reports it.
52
+ *
53
+ * @param outDir - Generated output directory.
54
+ * @param config - Absolute path of content-query.config.
55
+ * @param state - The session's current revision or error.
56
+ * @param options - `prune` removes development entries from previous runs.
57
+ * @returns The new runtime modules, or `undefined` when nothing valid was published.
58
+ */
23
59
  function publishDevelopment(outDir, config, state, { prune = false } = {}) {
24
60
  if (!state.error) {
25
61
  if (!state.revision) return;
26
- const entry = path.join(outDir, "server.js");
27
62
  const filename = `next-dev-${randomUUID()}.js`;
28
- const runtime = path.join(outDir, filename);
29
- writeEntry(runtime, readFileSync(entry, "utf8"));
30
- writeEntry(entry, `export { content } from ${JSON.stringify(`./${filename}`)};\n`);
63
+ const runtimes = [...collectionNames(state.revision.registry).values()].map(({ exportName }) => redirectEntry(path.join(outDir, "collections", exportName), exportName, filename));
31
64
  if (prune) pruneDevelopmentEntries(outDir, filename);
32
- return runtime;
65
+ return runtimes;
66
+ }
67
+ const failure = `import { restoreContentError } from "content-query/internal";\nthrow restoreContentError(${JSON.stringify(serializeContentError(state.error))});\n`;
68
+ const directories = new Map(publishedCollections(outDir).map((directory) => [directory, path.basename(directory)]));
69
+ for (const [name, generated] of collectionNames(state.registry ?? {})) {
70
+ const directory = path.join(outDir, "collections", generated.exportName);
71
+ directories.set(directory, generated.exportName);
72
+ writeEntry(path.join(directory, "server.d.ts"), collectionDeclarations(directory, config, name, generated));
33
73
  }
34
74
  writeEntry(path.join(outDir, "package.json"), "{\"type\":\"module\",\"private\":true}\n");
35
- writeEntry(path.join(outDir, "server.d.ts"), contentDeclarations(outDir, config));
36
- writeEntry(path.join(outDir, "server.js"), `import { restoreContentError } from "content-query/internal";\nthrow restoreContentError(${JSON.stringify(serializeContentError(state.error))});\nexport const content = undefined;\n`);
75
+ for (const [directory, exportName] of directories) writeEntry(path.join(directory, "server.js"), `${failure}export const ${exportName} = undefined;\n`);
37
76
  }
38
- /** Removes owned runtime entries from previous runs, preserving the current facade's target. */
77
+ /**
78
+ * Removes owned runtime entries from previous runs, preserving the current entries' target.
79
+ *
80
+ * @param outDir - Generated output directory.
81
+ * @param keep - The current publication's runtime filename, shared by every entry.
82
+ */
39
83
  function pruneDevelopmentEntries(outDir, keep) {
40
- for (const filename of readdirSync(outDir)) if (filename !== keep && /^next-dev-[a-f0-9]{8}(?:-[a-f0-9]{4}){3}-[a-f0-9]{12}\.js$/.test(filename)) rmSync(path.join(outDir, filename), { force: true });
84
+ const collections = path.join(outDir, "collections");
85
+ const directories = [outDir, ...entriesOf(collections).map((name) => path.join(collections, name))];
86
+ for (const directory of directories) {
87
+ const entries = entriesOf(directory);
88
+ for (const filename of entries) if (filename !== keep && developmentEntry.test(filename)) rmSync(path.join(directory, filename), { force: true });
89
+ if (directory !== outDir && entries.every((filename) => developmentEntry.test(filename))) try {
90
+ rmdirSync(directory);
91
+ } catch {}
92
+ }
41
93
  }
42
94
  //#endregion
43
95
  //#region src/integrations/next/plugin.ts
@@ -114,7 +166,8 @@ async function startDevelopment(root, options) {
114
166
  }
115
167
  /**
116
168
  * Builds content before Next compiles, retaining one managed watcher during `next dev`.
117
- * Import the generated server entry from Server Components; Next's HMR observes its updates.
169
+ * Import each collection's generated entry, such as `#content-query/posts`, from Server
170
+ * Components; Next's HMR observes their updates, and each route traces only what it imports.
118
171
  * Next's detached telemetry helper evaluates configuration without starting content sessions.
119
172
  * @param nextConfig Existing object, promise, or phase-aware Next.js configuration.
120
173
  * @param options Optional content configuration file and generated output directory.