@murumets-ee/content 0.0.0-preview-20261014110621

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 (111) hide show
  1. package/LICENSE +94 -0
  2. package/README.md +15 -0
  3. package/dist/admin.d.mts +56 -0
  4. package/dist/admin.d.mts.map +1 -0
  5. package/dist/admin.mjs +1 -0
  6. package/dist/block-resolver.d.mts +320 -0
  7. package/dist/block-resolver.d.mts.map +1 -0
  8. package/dist/block-resolver.mjs +2 -0
  9. package/dist/block-resolver.mjs.map +1 -0
  10. package/dist/breadcrumbs-BqSuMNac.mjs +2 -0
  11. package/dist/breadcrumbs-BqSuMNac.mjs.map +1 -0
  12. package/dist/chrome-entity-names-zYJzP-_U.mjs +2 -0
  13. package/dist/chrome-entity-names-zYJzP-_U.mjs.map +1 -0
  14. package/dist/chrome-provider.d.mts +143 -0
  15. package/dist/chrome-provider.d.mts.map +1 -0
  16. package/dist/chrome-provider.mjs +2 -0
  17. package/dist/chrome-provider.mjs.map +1 -0
  18. package/dist/client.d.mts +89 -0
  19. package/dist/client.d.mts.map +1 -0
  20. package/dist/client.mjs +2 -0
  21. package/dist/client.mjs.map +1 -0
  22. package/dist/content-config-store-8omQF5p5.mjs +2 -0
  23. package/dist/content-config-store-8omQF5p5.mjs.map +1 -0
  24. package/dist/context-D7eEItCY.mjs +2 -0
  25. package/dist/context-D7eEItCY.mjs.map +1 -0
  26. package/dist/detail-template-names-CD1Y9n1U.mjs +2 -0
  27. package/dist/detail-template-names-CD1Y9n1U.mjs.map +1 -0
  28. package/dist/detail-template-provider.d.mts +28 -0
  29. package/dist/detail-template-provider.d.mts.map +1 -0
  30. package/dist/detail-template-provider.mjs +2 -0
  31. package/dist/detail-template-provider.mjs.map +1 -0
  32. package/dist/document-site-B8tmEqLw.mjs +2 -0
  33. package/dist/document-site-B8tmEqLw.mjs.map +1 -0
  34. package/dist/entities/index.d.mts +64 -0
  35. package/dist/entities/index.d.mts.map +1 -0
  36. package/dist/entities/index.mjs +2 -0
  37. package/dist/entities/index.mjs.map +1 -0
  38. package/dist/enumerate-CYHJKQz6.mjs +2 -0
  39. package/dist/enumerate-CYHJKQz6.mjs.map +1 -0
  40. package/dist/errors-NRNILhhm.mjs +2 -0
  41. package/dist/errors-NRNILhhm.mjs.map +1 -0
  42. package/dist/index-cT8Qk4gu.d.mts +275 -0
  43. package/dist/index-cT8Qk4gu.d.mts.map +1 -0
  44. package/dist/index.d.mts +5 -0
  45. package/dist/index.mjs +2 -0
  46. package/dist/index.mjs.map +1 -0
  47. package/dist/locale-entity-CoSq3C77.mjs +2 -0
  48. package/dist/locale-entity-CoSq3C77.mjs.map +1 -0
  49. package/dist/locale-registry-COsJrVZl.mjs +2 -0
  50. package/dist/locale-registry-COsJrVZl.mjs.map +1 -0
  51. package/dist/locale-utils-B0mFoV47.mjs +2 -0
  52. package/dist/locale-utils-B0mFoV47.mjs.map +1 -0
  53. package/dist/lock-service.d.mts +58 -0
  54. package/dist/lock-service.d.mts.map +1 -0
  55. package/dist/lock-service.mjs +2 -0
  56. package/dist/lock-service.mjs.map +1 -0
  57. package/dist/locks-5779ugSW.mjs +2 -0
  58. package/dist/locks-5779ugSW.mjs.map +1 -0
  59. package/dist/plugin-CjgqBSFy.mjs +2 -0
  60. package/dist/plugin-CjgqBSFy.mjs.map +1 -0
  61. package/dist/plugin.d.mts +41 -0
  62. package/dist/plugin.d.mts.map +1 -0
  63. package/dist/plugin.mjs +1 -0
  64. package/dist/query-client.d.mts +131 -0
  65. package/dist/query-client.d.mts.map +1 -0
  66. package/dist/query-client.mjs +2 -0
  67. package/dist/query-client.mjs.map +1 -0
  68. package/dist/registry-CaPbY5lm.mjs +2 -0
  69. package/dist/registry-CaPbY5lm.mjs.map +1 -0
  70. package/dist/resolve-context-DklN53BH.mjs +2 -0
  71. package/dist/resolve-context-DklN53BH.mjs.map +1 -0
  72. package/dist/resolve.d.mts +651 -0
  73. package/dist/resolve.d.mts.map +1 -0
  74. package/dist/resolve.mjs +9 -0
  75. package/dist/resolve.mjs.map +1 -0
  76. package/dist/rolldown-runtime-DK3Fl9T5.mjs +1 -0
  77. package/dist/routes-siXmjKDA.mjs +2 -0
  78. package/dist/routes-siXmjKDA.mjs.map +1 -0
  79. package/dist/routing-strategy-CAG3tZP0.d.mts +155 -0
  80. package/dist/routing-strategy-CAG3tZP0.d.mts.map +1 -0
  81. package/dist/routing-strategy-D6B4ngT9.mjs +2 -0
  82. package/dist/routing-strategy-D6B4ngT9.mjs.map +1 -0
  83. package/dist/schema-BYrYzsmO.mjs +2 -0
  84. package/dist/schema-BYrYzsmO.mjs.map +1 -0
  85. package/dist/schema-LlK6EkOJ.mjs +2 -0
  86. package/dist/schema-LlK6EkOJ.mjs.map +1 -0
  87. package/dist/seed.d.mts +177 -0
  88. package/dist/seed.d.mts.map +1 -0
  89. package/dist/seed.mjs +2 -0
  90. package/dist/seed.mjs.map +1 -0
  91. package/dist/site-chrome-BAtQaAqC.mjs +2 -0
  92. package/dist/site-chrome-BAtQaAqC.mjs.map +1 -0
  93. package/dist/site-chrome-DNCcePSR.d.mts +98 -0
  94. package/dist/site-chrome-DNCcePSR.d.mts.map +1 -0
  95. package/dist/translation-provenance-B41lEDM-.mjs +2 -0
  96. package/dist/translation-provenance-B41lEDM-.mjs.map +1 -0
  97. package/dist/translation-provenance-BZ0MlbFR.d.mts +253 -0
  98. package/dist/translation-provenance-BZ0MlbFR.d.mts.map +1 -0
  99. package/dist/translation.d.mts +144 -0
  100. package/dist/translation.d.mts.map +1 -0
  101. package/dist/translation.mjs +2 -0
  102. package/dist/translation.mjs.map +1 -0
  103. package/dist/types-BOk9tg_9.d.mts +150 -0
  104. package/dist/types-BOk9tg_9.d.mts.map +1 -0
  105. package/dist/versionable-Br_G5VGR.mjs +2 -0
  106. package/dist/versionable-Br_G5VGR.mjs.map +1 -0
  107. package/dist/versionable-CRvV87nZ.d.mts +18 -0
  108. package/dist/versionable-CRvV87nZ.d.mts.map +1 -0
  109. package/dist/versions-w2ui-Vzb.mjs +2 -0
  110. package/dist/versions-w2ui-Vzb.mjs.map +1 -0
  111. package/package.json +93 -0
@@ -0,0 +1,651 @@
1
+ import { Entity } from "@murumets-ee/entity";
2
+ import { Logger, ToolkitApp } from "@murumets-ee/core";
3
+ import { z } from "zod";
4
+ //#region src/redirects/target.d.ts
5
+ /** The stored shape of `toolkit_redirects.target`. */
6
+ type RedirectTarget = {
7
+ kind: 'entity';
8
+ entity: string;
9
+ id: string;
10
+ } | {
11
+ kind: 'url';
12
+ url: string;
13
+ } | {
14
+ kind: 'path';
15
+ path: string;
16
+ };
17
+ //#endregion
18
+ //#region src/paths/index-reader.d.ts
19
+ /**
20
+ * Narrow read surface over `toolkit_paths` (plan/routing PR06).
21
+ *
22
+ * The resolution API (`./resolve.ts`) and the historical-tier helper
23
+ * (`./redirect-target.ts`) both read the path index, but neither needs the full
24
+ * `ToolkitPathsClient` — only `findOne` + `findMany`. Injecting a narrow
25
+ * structural interface (the same pattern `../redirects/validation.ts` uses for
26
+ * its readers) lets unit tests pass a trivial cast-free stub while the real
27
+ * `ToolkitPathsClient` still satisfies it (proven at compile time by the
28
+ * integration tests, which pass the real client straight in).
29
+ *
30
+ * The interface is deliberately a STRUCTURAL SUPERTYPE the real client is
31
+ * assignable to: every `where` field is a plain value (⊆ the client's richer
32
+ * `ColumnOperators` where-clause), `orderBy` only names `updatedAt` (a real
33
+ * column), and the projected {@link PathIndexRow} is a subset of the full row —
34
+ * so the assignment holds under TypeScript's method-parameter bivariance with no
35
+ * `as` casts on either side.
36
+ */
37
+ /**
38
+ * The `toolkit_paths` fields the resolution + historical tiers actually read.
39
+ *
40
+ * Declared as a `type` (not `interface`) deliberately: the real
41
+ * `ToolkitPathsClient`'s `findOne`/`findMany` are typed against `WhereClause`,
42
+ * whose template-literal index signature (`[k: \`${string}.${string}\`]`) a
43
+ * named `interface` can't satisfy as a supertype — a `type`-alias object literal
44
+ * gets the implicit index signature and stays assignable. (Same reason
45
+ * `../redirects/validation.ts` uses inline anonymous reader params.)
46
+ */
47
+ type PathIndexRow = {
48
+ entityType: string;
49
+ entityId: string;
50
+ locale: string;
51
+ path: string;
52
+ isCanonical: boolean;
53
+ };
54
+ /** The (plain-value) where shapes those tiers query by. `type`, per {@link PathIndexRow}. */
55
+ type PathIndexWhere = {
56
+ entityType?: string;
57
+ entityId?: string;
58
+ locale?: string;
59
+ path?: string;
60
+ isCanonical?: boolean;
61
+ };
62
+ /** The read surface `getCanonicalPath` / `resolvePath` / `findRedirectTarget` need. */
63
+ type PathIndexReader = {
64
+ findOne(where: PathIndexWhere): Promise<PathIndexRow | null>;
65
+ findMany(options: {
66
+ where?: PathIndexWhere; /** Only `updatedAt` ordering is used (historical-collision tie-break). */
67
+ orderBy?: Array<{
68
+ column: 'updatedAt';
69
+ dir?: 'asc' | 'desc';
70
+ }>;
71
+ limit?: number;
72
+ }): Promise<PathIndexRow[]>;
73
+ };
74
+ //#endregion
75
+ //#region src/paths/homepage.d.ts
76
+ /** A resolved pointer at the document that serves `/`. */
77
+ interface HomepagePointer {
78
+ entity: string;
79
+ id: string;
80
+ }
81
+ /**
82
+ * Shape of the `homeDocument` JSONB value. `id` is a UUID — entity row ids
83
+ * are UUIDs across this codebase (only USER ids are varchar; CLAUDE.md).
84
+ */
85
+ declare const homepagePointerSchema: z.ZodObject<{
86
+ entity: z.ZodString;
87
+ id: z.ZodString;
88
+ }, "strip", z.ZodTypeAny, {
89
+ id: string;
90
+ entity: string;
91
+ }, {
92
+ id: string;
93
+ entity: string;
94
+ }>;
95
+ /**
96
+ * Parse a raw `homeDocument` value into a {@link HomepagePointer}, or `null`
97
+ * when it's unset / malformed. Never throws.
98
+ */
99
+ declare function parseHomepagePointer(value: unknown): HomepagePointer | null;
100
+ //#endregion
101
+ //#region src/paths/resolve.d.ts
102
+ /** The document that serves the requested path. */
103
+ interface ResolveDocumentResult {
104
+ kind: 'document';
105
+ entityType: string;
106
+ id: string;
107
+ }
108
+ /** A redirect to another URL/path. `301` permanent, `302` temporary. */
109
+ interface ResolveRedirectResult {
110
+ kind: 'redirect';
111
+ to: string;
112
+ status: 301 | 302;
113
+ }
114
+ /** Nothing routes here (404). */
115
+ interface ResolveNoneResult {
116
+ kind: 'none';
117
+ }
118
+ type ResolveResult = ResolveDocumentResult | ResolveRedirectResult | ResolveNoneResult;
119
+ /**
120
+ * Is `(entityType, entityId)` published in `locale`? Backed by
121
+ * `QueryClient.findById`, which applies the publish filter for any principal
122
+ * WITHOUT `view_unpublished` (D017) — so the answer is only "published" if the
123
+ * injected client's context withholds that action, which the real one
124
+ * (`resolve-context.ts`'s reach context) does. See {@link createPublishChecker}.
125
+ * `resolveDraftPath` bypasses this entirely.
126
+ */
127
+ interface PublishChecker {
128
+ isPublished(entityType: string, entityId: string, locale: string): Promise<boolean>;
129
+ }
130
+ /** Resolve an entity TYPE NAME to its `Entity`, or `undefined` when unregistered. */
131
+ type EntityResolver = (entityType: string) => Entity | undefined;
132
+ /** The `QueryClient.findById` surface the publish checker needs (publish filter is internal). */
133
+ interface PublishQueryClient {
134
+ findById(id: string, options?: {
135
+ locale?: string | undefined;
136
+ }): Promise<unknown>;
137
+ }
138
+ /** Build a publish-filtering read client for an entity (real: `new QueryClient(...)`). */
139
+ type QueryClientFactory = (entity: Entity) => PublishQueryClient;
140
+ /** Read the current homepage pointer, or `null` when unset/malformed. */
141
+ type HomepageReader = () => Promise<HomepagePointer | null>;
142
+ /** The manual-redirect lookup surface (locale-specific + catch-all rows). */
143
+ interface RedirectLookupReader {
144
+ findOne(where: {
145
+ fromPath: string; /** A concrete locale, or `null` for the catch-all (all-locales) row. */
146
+ locale: string | null;
147
+ }): Promise<{
148
+ target: RedirectTarget;
149
+ status: number;
150
+ } | null>;
151
+ }
152
+ /** Deps for {@link getCanonicalPath} — the minimal index read. */
153
+ interface CanonicalPathDeps {
154
+ pathsClient: PathIndexReader;
155
+ }
156
+ /** Deps for {@link resolvePath} / {@link resolveDraftPath}. */
157
+ interface ResolvePathDeps extends CanonicalPathDeps {
158
+ redirectsClient: RedirectLookupReader;
159
+ publishChecker: PublishChecker;
160
+ homepageReader: HomepageReader;
161
+ /**
162
+ * Is this entity type still routable (does it declare `frontend.path`)? A
163
+ * `toolkit_paths` row outlives its entity losing the path (F068), so every
164
+ * tier that serves a row's document asks first: a row of a non-routable
165
+ * entity is `none`, never a document or a redirect. `buildResolveDeps`
166
+ * always supplies it; omitted (unit-test builders only) means "every entity
167
+ * is routable".
168
+ */
169
+ isRoutable?: (entityType: string) => boolean;
170
+ /**
171
+ * Optional so the unit-test deps builders stay unchanged. Its only use is
172
+ * letting the historical-redirect lookup report a truncated candidate window
173
+ * — see {@link findRedirectTarget}.
174
+ */
175
+ logger?: Logger;
176
+ }
177
+ /** Deps for {@link getAlternates}. */
178
+ interface AlternatesDeps extends CanonicalPathDeps {
179
+ publishChecker: PublishChecker;
180
+ /** The locales to enumerate (configured content locales). */
181
+ locales: readonly string[];
182
+ }
183
+ /**
184
+ * Hop cap on manual-redirect `path`-chain following at REQUEST time (F021 /
185
+ * F027 point 4). `collapsePathTarget` only collapses ONE hop at save time, so a
186
+ * chain created out-of-order can still need re-hopping here; exceeding the cap
187
+ * resolves to `none` rather than looping or 500ing.
188
+ */
189
+ declare const MAX_REDIRECT_HOPS = 5;
190
+ /**
191
+ * The current canonical path for `(entityType, entityId, locale)`, or `null`
192
+ * when the document has no canonical row in that locale.
193
+ *
194
+ * **No publish filter — deliberate.** This matches the CURRENT behavior of
195
+ * `resolveEntityHref` / search's URL builder (both call `AdminClient.findById`,
196
+ * which does zero publish filtering); Task 2 re-points those consumers onto this
197
+ * function, so changing the filtering here would be an unplanned behavior change.
198
+ * Callers that need a publish gate compose one explicitly (resolution's canonical
199
+ * tier does).
200
+ */
201
+ declare function getCanonicalPath(entityType: string, entityId: string, locale: string, deps: CanonicalPathDeps): Promise<string | null>;
202
+ /**
203
+ * Build a {@link PublishChecker} from an entity resolver + a query-client
204
+ * factory. `isPublished` is `false` for an unknown entity type, else
205
+ * `findById(id, { locale }) !== null` — a non-null result means "published in
206
+ * that locale" because `QueryClient` applies the publish filter (and excludes
207
+ * trashed rows) for every principal without `view_unpublished` (D017). The
208
+ * factory therefore has to hand back a client whose context withholds that
209
+ * action; `resolve-context.ts`'s reach context is the one in-repo
210
+ * implementation and does. F027 point 1.
211
+ */
212
+ declare function createPublishChecker(deps: {
213
+ entityResolver: EntityResolver;
214
+ queryClientFactory: QueryClientFactory;
215
+ }): PublishChecker;
216
+ /**
217
+ * Resolve `(path, locale)` to a document / redirect / none, publish-checking at
218
+ * every document-resolving tier. Public request surface (phase 05 §2).
219
+ */
220
+ declare function resolvePath(path: string, locale: string, deps: ResolvePathDeps): Promise<ResolveResult>;
221
+ /**
222
+ * Admin/preview resolution — identical tier structure to {@link resolvePath} but
223
+ * SKIPS every publish check (draft and published documents both resolve). Per
224
+ * phase 05 §2 this surface is admin-only. Exactly ONE HTTP route may call it —
225
+ * `./routes.ts`'s `GET /api/admin/paths/resolve` (#775), which gates on
226
+ * `path:resolve` and re-checks the caller's `view` grant on whatever it
227
+ * resolves. NEVER wire it to `content-api` (public, published-only).
228
+ */
229
+ declare function resolveDraftPath(path: string, locale: string, deps: ResolvePathDeps): Promise<ResolveResult>;
230
+ /**
231
+ * The published per-locale canonical URLs for a document — the `hreflang`
232
+ * alternates set (phase 05 §2, "published locales only"). A locale is included
233
+ * only when the document has a canonical row AND is published there. Bounded by
234
+ * the (small, fixed) configured-locale count — no fan-out concern.
235
+ */
236
+ declare function getAlternates(entityType: string, id: string, deps: AlternatesDeps): Promise<Array<{
237
+ locale: string;
238
+ path: string;
239
+ }>>;
240
+ //#endregion
241
+ //#region src/paths/enumerate.d.ts
242
+ /**
243
+ * Path enumeration for SSG / sitemaps (plan/routing PR06; phase
244
+ * `05-resolution-and-enumeration-api.md` §2).
245
+ *
246
+ * `enumeratePaths` streams the PUBLISHED canonical `(path, entityType, id,
247
+ * updatedAt)` rows for one locale. It powers `getStaticPaths` + the sitemap
248
+ * helper, so it must NEVER leak an unpublished document (CLAUDE.md #1 — the
249
+ * output feeds public build artifacts).
250
+ *
251
+ * **Security + availability.** Two properties matter here:
252
+ * 1. *No unpublished leak.* `toolkit_paths` carries no publish-status column,
253
+ * so each page's rows are publish-checked against the live entity via the
254
+ * injected {@link EnumeratePathsDeps.filterPublished} — an unpublished (or
255
+ * trashed) document is dropped from the stream.
256
+ * 2. *No unbounded fan-out* (CLAUDE.md "no amplification"). Work is bounded by
257
+ * PAGE SIZE, not by total document count: rows are keyset-paginated on the
258
+ * immutable `id` PK (one index query per page), and the publish check is
259
+ * BATCHED — ONE call per distinct entity-type bucket per page (a handful of
260
+ * types at most; the routable set is config-time-fixed, never
261
+ * attacker-influenced), never one call per row.
262
+ *
263
+ * **Leaf module.** Every cross-package dependency (the index reader, the publish
264
+ * filter) is injected via `deps`; this module imports no `@murumets-ee/core` and
265
+ * no `server-only` graph. Concrete deps are built from an app in
266
+ * `./resolve-context.ts` (`buildEnumerateDeps`), keeping the resolution surface
267
+ * off the `lumi` CLI command graph (F027 guardrail).
268
+ *
269
+ * Function-form-path entities need NO special handling — their rows were already
270
+ * materialized into `toolkit_paths` at write time (F004 / phase 05 §2), so a
271
+ * plain index read includes them.
272
+ */
273
+ /** The projected `toolkit_paths` row the enumeration + batch lookup read. */
274
+ type PathEnumRow = {
275
+ id: string;
276
+ entityType: string;
277
+ entityId: string;
278
+ locale: string;
279
+ path: string;
280
+ updatedAt: Date;
281
+ };
282
+ /**
283
+ * The (operator-carrying) where shapes enumeration issues: keyset `id > cursor`,
284
+ * `entityId IN (...)` for the batch lookup, plus plain-value equality filters.
285
+ * A subset of the real client's `ColumnOperators` where-clause, so the real
286
+ * `ToolkitPathsClient` is assignable to {@link PathEnumReader}.
287
+ */
288
+ type PathEnumWhere = {
289
+ id?: {
290
+ gt: string;
291
+ };
292
+ entityType?: string;
293
+ entityId?: {
294
+ in: string[];
295
+ };
296
+ locale?: string; /** `{ in }` for a batched membership read (`resolvePublishedPathsAmong`). */
297
+ path?: string | {
298
+ in: string[];
299
+ };
300
+ isCanonical?: boolean;
301
+ };
302
+ /**
303
+ * The batched keyset read surface {@link enumeratePaths} / {@link getCanonicalPaths}
304
+ * need. NARROWER than Task 1's point-lookup `PathIndexReader` (which only orders
305
+ * by `updatedAt` and takes plain-value where): enumeration needs `id`-ordering,
306
+ * a `{ gt }` cursor, and `{ in }` batching. Construct the real client directly
307
+ * (`toolkitPathsTable.makeClient(db)`) — it satisfies this type.
308
+ */
309
+ type PathEnumReader = {
310
+ findMany(options: {
311
+ where?: PathEnumWhere;
312
+ orderBy?: Array<{
313
+ column: 'id';
314
+ dir?: 'asc' | 'desc';
315
+ }>;
316
+ limit?: number;
317
+ }): Promise<PathEnumRow[]>;
318
+ };
319
+ /**
320
+ * Batch publish check: return the SUBSET of `entityIds` that is published in
321
+ * `locale`. Called ONCE per entity-type group per page. The concrete
322
+ * implementation (see `resolve-context.ts`) runs an elevated-context
323
+ * `QueryClient.findMany({ where: inArray(getTable().id, ids), locale })` — so no
324
+ * unpublished/trashed id comes back. Since D017 the publish filter is
325
+ * CONDITIONAL (it holds for any principal without `view_unpublished`); what
326
+ * keeps that true here is that the elevated context is a REACH context which
327
+ * withholds that action, not that the filter is unconditional.
328
+ */
329
+ type PublishFilter = (entityType: string, entityIds: readonly string[], locale: string) => Promise<ReadonlySet<string>>;
330
+ /** One enumerated path row (phase 05 §2 — exact shape). */
331
+ interface PathEntry {
332
+ path: string;
333
+ entityType: string;
334
+ id: string;
335
+ updatedAt: Date;
336
+ }
337
+ /** Options for {@link enumeratePaths} (phase 05 §2 — exact shape). */
338
+ interface EnumeratePathsOptions {
339
+ /** Enumerate this locale's canonical rows only. */
340
+ locale: string;
341
+ /** Optionally narrow to a single routable entity type. */
342
+ entityType?: string;
343
+ /**
344
+ * Resume the keyset AFTER this `toolkit_paths` row id (exclusive); omit to
345
+ * start from the beginning. The value is the opaque `toolkit_paths` PK the
346
+ * internal page cursor advances on — NOT the yielded `PathEntry.id`, which is
347
+ * the DOCUMENT (entity) id. A cross-request paginating caller (e.g. the
348
+ * content-api `_paths` endpoint) resolves the last consumed entry's row PK and
349
+ * passes it here to continue exactly where the prior page stopped, with no row
350
+ * skipped or repeated. Fully backward-compatible: existing callers omit it and
351
+ * traverse from the start unchanged.
352
+ */
353
+ afterId?: string;
354
+ }
355
+ /** Injected dependencies for {@link enumeratePaths}. */
356
+ interface EnumeratePathsDeps {
357
+ pathsClient: PathEnumReader;
358
+ filterPublished: PublishFilter;
359
+ }
360
+ /** Internal tuning seam (page size / batch concurrency). Real callers omit it. */
361
+ interface EnumeratePathsTuning {
362
+ /** Rows per index page. Defaults to {@link ENUMERATE_PAGE_SIZE}. Tests force a small value. */
363
+ pageSize?: number;
364
+ /** Peak concurrent publish-check groups. Defaults to {@link PUBLISH_CHECK_CONCURRENCY}. */
365
+ publishConcurrency?: number;
366
+ }
367
+ /**
368
+ * Stream the published canonical paths for `opts.locale` (optionally narrowed to
369
+ * `opts.entityType`), keyset-paginated with a per-page batched publish filter.
370
+ * See the module header for the security + fan-out guarantees.
371
+ */
372
+ declare function enumeratePaths(opts: EnumeratePathsOptions, deps: EnumeratePathsDeps, tuning?: EnumeratePathsTuning): AsyncGenerator<PathEntry>;
373
+ /** Deps for {@link getCanonicalPaths}. */
374
+ interface CanonicalPathsBatchDeps {
375
+ pathsClient: PathEnumReader;
376
+ }
377
+ /**
378
+ * The current canonical paths for many `(entityType, entityId)` in ONE locale,
379
+ * as an `entityId → path` map — the batched sibling of `getCanonicalPath`.
380
+ *
381
+ * **No publish filter — deliberate**, matching `getCanonicalPath` (and the
382
+ * search url builder it re-points): a search result's url is display-only and
383
+ * the caller already gates row visibility. One index query per {@link
384
+ * CANONICAL_BATCH_SIZE}-sized chunk (one query total for a normal search page),
385
+ * so it never fans out per row.
386
+ */
387
+ declare function getCanonicalPaths(entityType: string, entityIds: readonly string[], locale: string, deps: CanonicalPathsBatchDeps): Promise<Map<string, string>>;
388
+ //#endregion
389
+ //#region src/paths/sitemap.d.ts
390
+ /** Options for {@link generateSitemap}. */
391
+ interface SitemapOptions {
392
+ /** The locales to emit a `<urlset>` for (configured content locales). */
393
+ locales: readonly string[];
394
+ /**
395
+ * The default locale — its URL is the `x-default` hreflang target. Explicit
396
+ * (NOT inferred from `locales` order) so callers stay unambiguous.
397
+ */
398
+ defaultLocale: string;
399
+ /** Absolute site origin, e.g. `https://example.com` (trailing slash tolerated). */
400
+ baseUrl: string;
401
+ /**
402
+ * Per-locale URL prefix rule (e.g. `(l) => l === 'en' ? '' : '/' + l`). The
403
+ * frontend owns the locale-prefix convention (D002); omitted → no prefix.
404
+ */
405
+ prefix?: (locale: string) => string;
406
+ /**
407
+ * Max `<url>` entries per file before splitting (sitemap protocol caps at
408
+ * 50 000). Defaults to {@link DEFAULT_MAX_URLS_PER_FILE}.
409
+ */
410
+ maxUrlsPerFile?: number;
411
+ }
412
+ /** Injected dependencies for {@link generateSitemap}. */
413
+ interface SitemapDeps {
414
+ /**
415
+ * Deps for {@link enumeratePaths} — the `toolkit_paths` reader plus the
416
+ * batched `filterPublished`. `filterPublished` is REUSED for the cross-locale
417
+ * alternate publish gate (same batched shape), so no second publish surface is
418
+ * needed.
419
+ */
420
+ enumerate: EnumeratePathsDeps;
421
+ /**
422
+ * Deps for {@link getCanonicalPaths} — the batched cross-locale forward index
423
+ * read (NO publish filter; this module applies `enumerate.filterPublished` on
424
+ * top).
425
+ */
426
+ canonicalBatch: CanonicalPathsBatchDeps;
427
+ /**
428
+ * Optional: batched `noIndex` check, same shape as `filterPublished` but
429
+ * semantics-inverted — returns the subset of `entityIds` that ARE `noIndex`
430
+ * in `locale` (PR 11's `seoMeta()`). Called at most once per (entity-type
431
+ * group, batch), never once per entry — see `excludeNoIndexed`. Omitted →
432
+ * nothing excluded (current default).
433
+ */
434
+ filterNoIndex?: PublishFilter;
435
+ }
436
+ /** Internal tuning seam (batch size / enumerate page size). Real callers omit it. */
437
+ interface SitemapTuning {
438
+ /**
439
+ * Enumerated rows per cross-locale alternate batch. Defaults to
440
+ * {@link SITEMAP_ALTERNATES_BATCH_SIZE}. Tests force a small value to span
441
+ * multiple batches. Bounds the per-batch fan-out (see module header).
442
+ */
443
+ batchSize?: number;
444
+ /** Passed through to {@link enumeratePaths} for its own paging/publish tuning. */
445
+ enumerate?: EnumeratePathsTuning;
446
+ }
447
+ /** One emitted sitemap document. */
448
+ interface SitemapFile {
449
+ /** `'urlset'` for a per-locale URL set, `'index'` for the sitemap index. */
450
+ kind: 'urlset' | 'index';
451
+ /**
452
+ * Suggested filename served at `${baseUrl}/${filename}`. Per-locale urlsets are
453
+ * `sitemap-<locale>.xml` (first) / `sitemap-<locale>-<n>.xml` (splits, n≥2);
454
+ * the index is {@link SITEMAP_INDEX_FILENAME}.
455
+ */
456
+ filename: string;
457
+ /** The complete, well-formed XML document text (trailing newline included). */
458
+ xml: string;
459
+ }
460
+ /** Default `<url>` cap per file — under the sitemap protocol's 50 000 hard limit. */
461
+ declare const DEFAULT_MAX_URLS_PER_FILE = 40000;
462
+ /** Filename of the emitted sitemap index (referenced by the mounting route). */
463
+ declare const SITEMAP_INDEX_FILENAME = "sitemap.xml";
464
+ /**
465
+ * Stream the sitemap document set for `opts.locales`. See the module header for
466
+ * the security + fan-out guarantees. Yields each `<urlset>` file as it fills,
467
+ * then a `<sitemapindex>` LAST iff more than one file was produced.
468
+ */
469
+ declare function generateSitemap(opts: SitemapOptions, deps: SitemapDeps, tuning?: SitemapTuning): AsyncGenerator<SitemapFile>;
470
+ //#endregion
471
+ //#region src/paths/site-sitemap.d.ts
472
+ /** Options for {@link generateSiteSitemap} — everything else comes from the site record. */
473
+ interface SiteSitemapOptions {
474
+ /** Per-locale URL prefix rule — the frontend owns it (routing D002). Omitted → none. */
475
+ prefix?: (locale: string) => string;
476
+ /** Max `<url>` entries per file (see `generateSitemap`). */
477
+ maxUrlsPerFile?: number;
478
+ }
479
+ /**
480
+ * Stream `site`'s sitemap document set. Throws when the site does not exist or
481
+ * declares no public origin (a sitemap of relative URLs is not a sitemap).
482
+ */
483
+ declare function generateSiteSitemap(app: ToolkitApp, site: string, options?: SiteSitemapOptions, tuning?: SitemapTuning): AsyncGenerator<SitemapFile>;
484
+ //#endregion
485
+ //#region src/paths/redirects-list.d.ts
486
+ /** The projected `toolkit_redirects` row the manual-redirect enumeration reads. */
487
+ type RedirectListRow = {
488
+ id: string;
489
+ fromPath: string; /** BCP47 locale, or `null` for the catch-all (all-locales) row. */
490
+ locale: string | null;
491
+ target: RedirectTarget;
492
+ status: number;
493
+ };
494
+ /**
495
+ * The (operator-carrying) where shapes the manual enumeration issues: a keyset
496
+ * `id > cursor` plus a `locale` equality (a concrete locale, or `null` for the
497
+ * catch-all stratum). A subset of the real client's `WhereClause`, so the real
498
+ * `ToolkitRedirectsClient` is assignable to {@link RedirectListReader}.
499
+ */
500
+ type RedirectListWhere = {
501
+ id?: {
502
+ gt: string;
503
+ };
504
+ locale?: string | null;
505
+ };
506
+ /**
507
+ * The batched keyset read surface the manual half needs over `toolkit_redirects`.
508
+ * Construct the real client directly (`toolkitRedirectsTable.makeClient(db)`) —
509
+ * it satisfies this type.
510
+ */
511
+ type RedirectListReader = {
512
+ findMany(options: {
513
+ where?: RedirectListWhere;
514
+ orderBy?: Array<{
515
+ column: 'id';
516
+ dir?: 'asc' | 'desc';
517
+ }>;
518
+ limit?: number;
519
+ }): Promise<RedirectListRow[]>;
520
+ };
521
+ /** One emitted redirect. `301` permanent, `302` temporary (phase 05 §2 shape). */
522
+ interface RedirectEntry {
523
+ from: string;
524
+ to: string;
525
+ status: 301 | 302;
526
+ }
527
+ /** Options for {@link getRedirects}. */
528
+ interface RedirectsListOptions {
529
+ /** Emit this locale's redirects only (mirrors `enumeratePaths` / `generateSitemap`). */
530
+ locale: string;
531
+ }
532
+ /** Injected dependencies for {@link getRedirects}. */
533
+ interface RedirectsListDeps {
534
+ /** Keyset reader over `toolkit_redirects` (manual redirects). */
535
+ redirectsClient: RedirectListReader;
536
+ /**
537
+ * Keyset reader over `toolkit_paths` — the historical (non-canonical) rows AND
538
+ * the `path`-kind existence check. Reuses `enumeratePaths`'s exact reader shape.
539
+ */
540
+ pathsClient: PathEnumReader;
541
+ /** Batched forward index read for owning-document current-canonical resolution. */
542
+ canonicalBatch: CanonicalPathsBatchDeps;
543
+ /** The SAME batched publish filter `enumeratePaths` / `generateSitemap` use. */
544
+ filterPublished: PublishFilter;
545
+ }
546
+ /** Internal tuning seam (page size). Real callers omit it. */
547
+ interface RedirectsListTuning {
548
+ /** Rows per keyset page. Defaults to {@link REDIRECTS_PAGE_SIZE}. Tests force a small value. */
549
+ pageSize?: number;
550
+ }
551
+ /**
552
+ * Stream the redirect list for `opts.locale`: manual redirects (locale-specific
553
+ * then catch-all, deduped by precedence) followed by historical redirects
554
+ * (skipping any `from` a manual redirect already claimed). See the module header
555
+ * for the security + fan-out + precedence guarantees.
556
+ */
557
+ declare function getRedirects(opts: RedirectsListOptions, deps: RedirectsListDeps, tuning?: RedirectsListTuning): AsyncGenerator<RedirectEntry>;
558
+ //#endregion
559
+ //#region src/paths/site-scope.d.ts
560
+ /** Resolves the site an access acts on — see the module docblock. */
561
+ type SiteSource = () => Promise<string>;
562
+ //#endregion
563
+ //#region src/paths/resolve-context.d.ts
564
+ /**
565
+ * Every builder below is SITE-CONFINED (plan `multisite` phase 03): its
566
+ * `toolkit_paths` / `toolkit_redirects` readers, its publish checks and its
567
+ * homepage reader all act on ONE site.
568
+ *
569
+ * - Omit `site` and that is the site of the request RUNNING the call (resolved
570
+ * at call time, so a bundle built once per app still follows each request) —
571
+ * its explicit `RequestContext.site`, else the single-site answer, else a
572
+ * `SiteRequiredError`. This is every existing caller, unchanged.
573
+ * - Pass `site` to pin one explicitly (a per-site sitemap or warmer run from a
574
+ * site-less job). Pinning inside a request confined to another site throws.
575
+ */
576
+ interface SiteScopeOptions {
577
+ site?: string;
578
+ }
579
+ /**
580
+ * Build the minimal deps for {@link import('./resolve.js').getCanonicalPath} —
581
+ * just the `toolkit_paths` reader. Task 2's `resolveEntityHref` / search
582
+ * url-builder re-points use this (no publish checker / settings machinery).
583
+ */
584
+ declare function buildCanonicalPathDeps(app: ToolkitApp, options?: SiteScopeOptions): CanonicalPathDeps;
585
+ /**
586
+ * Build a live {@link PublishChecker} that reads through an elevated-context
587
+ * `QueryClient` per entity (publish filter auto-applied). See file header.
588
+ */
589
+ declare function buildPublishChecker(app: ToolkitApp, options?: SiteScopeOptions): PublishChecker;
590
+ /**
591
+ * Build the homepage reader for a site (plan `multisite` D007): the site
592
+ * registry row's `homeDocument` (`readSiteRecord` — read with reach, cached
593
+ * briefly), zod-parsed defensively (unset / malformed → `null`, never a throw
594
+ * — this runs on every `/` request).
595
+ *
596
+ * The pointer is only as good as the resolution that follows it: `/` publish-
597
+ * checks the document through a client confined to the SAME site, so a pointer
598
+ * at another site's document (legacy data, a hand-edited row) resolves to
599
+ * `none` instead of serving it (D006, defence in depth — writes are refused
600
+ * by `setSiteHomepage`).
601
+ */
602
+ declare function createHomepageReader(app: ToolkitApp, siteOf: SiteSource): HomepageReader;
603
+ /**
604
+ * Build the deps for {@link import('./enumerate.js').enumeratePaths} — the
605
+ * `toolkit_paths` reader plus a BATCHED publish filter. `filterPublished` runs
606
+ * ONE elevated-context `QueryClient.findMany({ where: inArray(getTable().id,
607
+ * ids), locale })` per entity-type group (not per row) — the trash filter
608
+ * applies unconditionally, and the publish filter applies because the elevated
609
+ * context WITHHOLDS `view_unpublished` (D017; see file header), so no
610
+ * unpublished/trashed id is returned. An unknown/unregistered entity type yields the empty set (its
611
+ * rows are treated as unpublished → dropped, fail-closed).
612
+ */
613
+ declare function buildEnumerateDeps(app: ToolkitApp, options?: SiteScopeOptions): EnumeratePathsDeps;
614
+ /**
615
+ * Build the deps for {@link import('./enumerate.js').getCanonicalPaths} — just
616
+ * the `toolkit_paths` reader (batched, NO publish filter, like
617
+ * {@link buildCanonicalPathDeps}). Task 2's search url re-point uses this to
618
+ * resolve a search page's result urls from the index in one query.
619
+ */
620
+ declare function buildCanonicalPathsBatchDeps(app: ToolkitApp, options?: SiteScopeOptions): CanonicalPathsBatchDeps;
621
+ /**
622
+ * Build the deps for {@link import('./sitemap.js').generateSitemap} — the
623
+ * one-stop bundle of {@link buildEnumerateDeps} (per-locale enumeration + its
624
+ * BATCHED publish filter, reused for the cross-locale alternate publish gate),
625
+ * {@link buildCanonicalPathsBatchDeps} (the batched cross-locale forward index
626
+ * read), and {@link buildNoIndexFilter} (PR 11's batched `noIndex` exclusion).
627
+ * Mirrors `buildResolveDeps`'s one-stop-deps pattern.
628
+ */
629
+ declare function buildSitemapDeps(app: ToolkitApp, options?: SiteScopeOptions): SitemapDeps;
630
+ /**
631
+ * Build the deps for {@link import('./redirects-list.js').getRedirects} — the
632
+ * one-stop bundle for the build-time redirect list (PR08). Composes
633
+ * {@link buildEnumerateDeps} (its `toolkit_paths` reader powers both the
634
+ * historical keyset and the `path`-kind existence check; its BATCHED
635
+ * `filterPublished` is the shared publish gate), {@link buildCanonicalPathsBatchDeps}
636
+ * (the batched owning-document current-canonical lookup), and a
637
+ * `toolkit_redirects` reader for the manual-redirect keyset. Mirrors
638
+ * {@link buildSitemapDeps}'s one-stop-deps style.
639
+ */
640
+ declare function buildRedirectsListDeps(app: ToolkitApp, options?: SiteScopeOptions): RedirectsListDeps;
641
+ /**
642
+ * Build the full {@link ResolvePathDeps} (+ {@link AlternatesDeps}) from an app —
643
+ * the one-stop deps for `resolvePath` / `resolveDraftPath` / `getAlternates`.
644
+ * `locales` are the statically-configured content locales (v1 — matches the
645
+ * redirect routes' own configured-locale source; DB-merged locale overrides are
646
+ * a later refinement).
647
+ */
648
+ declare function buildResolveDeps(app: ToolkitApp, options?: SiteScopeOptions): ResolvePathDeps & AlternatesDeps;
649
+ //#endregion
650
+ export { type AlternatesDeps, type CanonicalPathDeps, type CanonicalPathsBatchDeps, DEFAULT_MAX_URLS_PER_FILE, type EntityResolver, type EnumeratePathsDeps, type EnumeratePathsOptions, type EnumeratePathsTuning, type HomepagePointer, type HomepageReader, MAX_REDIRECT_HOPS, type PathEntry, type PathEnumReader, type PathEnumRow, type PathEnumWhere, type PathIndexReader, type PathIndexRow, type PathIndexWhere, type PublishChecker, type PublishFilter, type PublishQueryClient, type QueryClientFactory, type RedirectEntry, type RedirectListReader, type RedirectListRow, type RedirectListWhere, type RedirectLookupReader, type RedirectsListDeps, type RedirectsListOptions, type RedirectsListTuning, type ResolveDocumentResult, type ResolveNoneResult, type ResolvePathDeps, type ResolveRedirectResult, type ResolveResult, SITEMAP_INDEX_FILENAME, type SiteScopeOptions, type SiteSitemapOptions, type SitemapDeps, type SitemapFile, type SitemapOptions, type SitemapTuning, buildCanonicalPathDeps, buildCanonicalPathsBatchDeps, buildEnumerateDeps, buildPublishChecker, buildRedirectsListDeps, buildResolveDeps, buildSitemapDeps, createHomepageReader, createPublishChecker, enumeratePaths, generateSiteSitemap, generateSitemap, getAlternates, getCanonicalPath, getCanonicalPaths, getRedirects, homepagePointerSchema, parseHomepagePointer, resolveDraftPath, resolvePath };
651
+ //# sourceMappingURL=resolve.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve.d.mts","names":[],"sources":["../src/redirects/target.ts","../src/paths/index-reader.ts","../src/paths/homepage.ts","../src/paths/resolve.ts","../src/paths/enumerate.ts","../src/paths/sitemap.ts","../src/paths/site-sitemap.ts","../src/paths/redirects-list.ts","../src/paths/site-scope.ts","../src/paths/resolve-context.ts"],"mappings":"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"}