@lupinum/ginko-content 0.1.6 → 0.2.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 (230) hide show
  1. package/compatibility.json +1 -1
  2. package/dist/cli.mjs +2 -2
  3. package/dist/cms-contract/build.js +15 -20
  4. package/dist/cms-contract/types.d.ts +12 -7
  5. package/dist/core/content/document +1 -0
  6. package/dist/core/content/document.d.ts +16 -0
  7. package/dist/core/content/document.js +2 -0
  8. package/dist/core/content/graph.d.ts +3 -1
  9. package/dist/core/content/graph.js +21 -20
  10. package/dist/core/content/locale.d.ts +6 -1
  11. package/dist/core/content/locale.js +17 -6
  12. package/dist/core/content/path.d.ts +5 -5
  13. package/dist/core/content/path.js +8 -8
  14. package/dist/core/content/snapshot +1 -0
  15. package/dist/core/content/snapshot.d.ts +25 -0
  16. package/dist/core/content/snapshot.js +99 -0
  17. package/dist/core/provider-errors.d.ts +1 -1
  18. package/dist/core/provider-errors.js +1 -0
  19. package/dist/core/query/builder.js +3 -3
  20. package/dist/core/query/execute.js +75 -36
  21. package/dist/core/query/filter.js +2 -2
  22. package/dist/core/query/lower.js +79 -3
  23. package/dist/core/query/params.js +7 -7
  24. package/dist/core/query/plan.d.ts +18 -0
  25. package/dist/core/query/plan.js +7 -0
  26. package/dist/core/references/resolve.js +6 -9
  27. package/dist/features/agent/agent-markdown +1 -0
  28. package/dist/features/agent/agent-markdown.d.ts +116 -0
  29. package/dist/features/agent/agent-markdown.js +138 -0
  30. package/dist/features/agent/walker +1 -0
  31. package/dist/features/agent/walker.d.ts +10 -0
  32. package/dist/features/agent/walker.js +174 -0
  33. package/dist/features/collections/resolve.d.ts +2 -2
  34. package/dist/features/collections/resolve.js +19 -16
  35. package/dist/features/localization/links.js +1 -1
  36. package/dist/features/localization/results.d.ts +3 -3
  37. package/dist/features/localization/results.js +46 -41
  38. package/dist/features/localization/translated-slugs.js +5 -5
  39. package/dist/features/navigation/build.d.ts +2 -2
  40. package/dist/features/navigation/build.js +23 -26
  41. package/dist/features/navigation/canonical.d.ts +10 -11
  42. package/dist/features/navigation/canonical.js +26 -21
  43. package/dist/features/navigation/resolve.js +4 -4
  44. package/dist/features/navigation/tree.js +3 -3
  45. package/dist/{runtime → features}/query/backlinks.js +3 -5
  46. package/dist/{runtime → features}/query/documents.js +1 -1
  47. package/dist/{runtime → features}/query/localized-docs.d.ts +1 -1
  48. package/dist/{runtime → features}/query/localized-docs.js +3 -6
  49. package/dist/{runtime → features}/query/navigation.d.ts +1 -1
  50. package/dist/{runtime → features}/query/navigation.js +8 -8
  51. package/dist/{runtime → features}/query/populate.js +6 -14
  52. package/dist/{runtime → features}/query/unified.d.ts +4 -4
  53. package/dist/{runtime → features}/query/unified.js +4 -2
  54. package/dist/{runtime → features}/query/variants.js +4 -4
  55. package/dist/features/search/navigation.js +2 -2
  56. package/dist/features/search/sections.d.ts +1 -1
  57. package/dist/features/search/sections.js +1 -1
  58. package/dist/features/sitemap/query.d.ts +5 -5
  59. package/dist/features/sitemap/query.js +6 -6
  60. package/dist/integrations/nitro/ingest.js +9 -20
  61. package/dist/integrations/nitro/storage.d.ts +1 -0
  62. package/dist/integrations/nitro/storage.js +22 -8
  63. package/dist/module.d.mts +135 -812
  64. package/dist/module.json +1 -1
  65. package/dist/module.mjs +70 -27
  66. package/dist/parsers/csv.js +3 -3
  67. package/dist/parsers/index.js +3 -3
  68. package/dist/parsers/json.js +8 -6
  69. package/dist/parsers/markdown-plugins.js +9 -5
  70. package/dist/parsers/markdown.js +7 -6
  71. package/dist/parsers/path-meta.js +21 -19
  72. package/dist/parsers/reserved +1 -0
  73. package/dist/parsers/reserved.d.ts +15 -0
  74. package/dist/parsers/reserved.js +35 -0
  75. package/dist/parsers/yaml.js +6 -4
  76. package/dist/public/agent +1 -0
  77. package/dist/public/agent.d.ts +17 -0
  78. package/dist/public/agent.js +34 -0
  79. package/dist/public/client.d.ts +2 -3
  80. package/dist/public/client.js +1 -2
  81. package/dist/public/provider-query +1 -0
  82. package/dist/public/provider-query.d.ts +58 -0
  83. package/dist/public/provider-query.js +5 -0
  84. package/dist/public/provider.d.ts +8 -3
  85. package/dist/public/provider.js +2 -0
  86. package/dist/public/server.d.ts +7 -12
  87. package/dist/public/server.js +5 -36
  88. package/dist/runtime/app/components/ContentRenderer.d.vue.ts +3 -3
  89. package/dist/runtime/app/components/ContentRenderer.vue +2 -2
  90. package/dist/runtime/app/components/ContentRenderer.vue.d.ts +3 -3
  91. package/dist/runtime/app/components/ContentRendererInline.d.vue.ts +1 -1
  92. package/dist/runtime/app/components/ContentRendererInline.vue.d.ts +1 -1
  93. package/dist/runtime/app/components/Prose/ProseImg.d.vue.ts +4 -4
  94. package/dist/runtime/app/components/Prose/ProseImg.vue.d.ts +4 -4
  95. package/dist/runtime/app/components/Prose/ProsePre.d.vue.ts +1 -1
  96. package/dist/runtime/app/components/Prose/ProsePre.vue.d.ts +1 -1
  97. package/dist/runtime/app/components/internal/ContentRendererMarkdown.d.vue.ts +1 -1
  98. package/dist/runtime/app/components/internal/ContentRendererMarkdown.vue +4 -4
  99. package/dist/runtime/app/components/internal/ContentRendererMarkdown.vue.d.ts +1 -1
  100. package/dist/runtime/app/components/internal/MarkdownRenderer.d.ts +3 -3
  101. package/dist/runtime/app/composables/preview.d.ts +1 -1
  102. package/dist/runtime/app/composables/query-api.d.ts +5 -5
  103. package/dist/runtime/app/composables/query-api.js +5 -3
  104. package/dist/runtime/app/composables/route.d.ts +1 -1
  105. package/dist/runtime/app/composables/route.js +4 -4
  106. package/dist/runtime/app/composables/search.js +1 -1
  107. package/dist/runtime/app/composables/use-content-document.js +1 -1
  108. package/dist/runtime/app/composables/use-content-list.js +1 -1
  109. package/dist/runtime/app/composables/use-content-navigation.js +2 -2
  110. package/dist/runtime/app/composables/use-content-page.js +4 -4
  111. package/dist/runtime/app/pages/content.vue +2 -1
  112. package/dist/runtime/markdown/plugins.js +6 -8
  113. package/dist/runtime/server/agent-markdown.d.ts +5 -65
  114. package/dist/runtime/server/agent-markdown.js +40 -315
  115. package/dist/runtime/server/agent-site.js +1 -1
  116. package/dist/runtime/server/api/agent-raw.js +1 -1
  117. package/dist/runtime/server/api/cache.d.ts +1 -1
  118. package/dist/runtime/server/api/cache.js +43 -4
  119. package/dist/runtime/server/api/locales.js +3 -3
  120. package/dist/runtime/server/api/navigation.d.ts +1 -1
  121. package/dist/runtime/server/api/navigation.js +3 -1
  122. package/dist/runtime/server/api/query.js +2 -2
  123. package/dist/runtime/server/api/search-index.d.ts +1 -1
  124. package/dist/runtime/server/api/sitemap.d.ts +1 -1
  125. package/dist/runtime/server/cache-adapters.d.ts +18 -0
  126. package/dist/runtime/server/cache-adapters.js +12 -0
  127. package/dist/runtime/server/collection-helpers.d.ts +2 -2
  128. package/dist/runtime/server/collection-helpers.js +15 -11
  129. package/dist/runtime/server/index.d.ts +6 -4
  130. package/dist/runtime/server/index.js +10 -3
  131. package/dist/runtime/server/middleware/agent-link-headers.js +1 -1
  132. package/dist/runtime/server/middleware/agent-markdown.js +1 -1
  133. package/dist/runtime/server/navigation-query.d.ts +2 -2
  134. package/dist/runtime/server/navigation-query.js +52 -7
  135. package/dist/runtime/server/navigation.d.ts +1 -1
  136. package/dist/runtime/server/provider-document +1 -0
  137. package/dist/runtime/server/provider-document.d.ts +59 -0
  138. package/dist/runtime/server/provider-document.js +48 -0
  139. package/dist/runtime/server/provider-query-wire +1 -0
  140. package/dist/runtime/server/provider-query-wire.d.ts +32 -0
  141. package/dist/runtime/server/provider-query-wire.js +27 -0
  142. package/dist/runtime/server/provider-query.d.ts +18 -9
  143. package/dist/runtime/server/provider-query.js +62 -28
  144. package/dist/runtime/server/provider-result.d.ts +4 -4
  145. package/dist/runtime/server/providers/filesystem.js +3 -11
  146. package/dist/runtime/server/providers/index.d.ts +18 -1
  147. package/dist/runtime/server/providers/index.js +72 -20
  148. package/dist/runtime/server/query-api.d.ts +5 -5
  149. package/dist/runtime/server/query-api.js +9 -6
  150. package/dist/runtime/server/query-executor.d.ts +3 -3
  151. package/dist/runtime/server/query-executor.js +43 -59
  152. package/dist/runtime/server/search.d.ts +1 -1
  153. package/dist/runtime/server/search.js +4 -4
  154. package/dist/runtime/server/sitemap.js +5 -5
  155. package/dist/runtime/server/storage-access.d.ts +4 -1
  156. package/dist/runtime/server/storage-access.js +27 -2
  157. package/dist/runtime/transformers/component-resolver.d.ts +1 -1
  158. package/dist/storage/content.d.ts +2 -6
  159. package/dist/storage/content.js +19 -8
  160. package/dist/storage/contents.d.ts +9 -1
  161. package/dist/storage/contents.js +26 -19
  162. package/dist/storage/driver.d.ts +2 -2
  163. package/dist/storage/driver.js +2 -1
  164. package/dist/storage/graph.js +4 -0
  165. package/dist/storage/manifest.js +3 -1
  166. package/dist/storage/references.js +9 -5
  167. package/dist/storage/snapshot-runtime +1 -0
  168. package/dist/storage/snapshot-runtime.d.ts +11 -0
  169. package/dist/storage/snapshot-runtime.js +46 -0
  170. package/dist/storage/validation.d.ts +1 -1
  171. package/dist/storage/validation.js +47 -102
  172. package/dist/testing/provider-contract.d.ts +14 -4
  173. package/dist/testing/provider-contract.js +121 -68
  174. package/dist/testing/provider-fixture.d.ts +1 -1
  175. package/dist/testing/provider-fixture.js +124 -120
  176. package/dist/types/config.d.ts +8 -4
  177. package/dist/types/content.d.ts +104 -70
  178. package/dist/types/fields.js +1 -1
  179. package/dist/types/module.d.ts +1 -1
  180. package/dist/types/query-parts/public.d.ts +14 -5
  181. package/dist/types/query-parts/results.d.ts +6 -2
  182. package/dist/types/query-parts/transport.d.ts +19 -0
  183. package/dist/types/virtual.d.ts +6 -0
  184. package/dist/types.d.mts +2 -2
  185. package/dist/web-types.json +1 -1
  186. package/package.json +39 -9
  187. package/dist/runtime/app/plugins/markdown-components +0 -1
  188. package/dist/runtime/app/plugins/markdown-components.d.ts +0 -2
  189. package/dist/runtime/app/plugins/markdown-components.js +0 -19
  190. /package/dist/{runtime → features/agent}/agent-paths +0 -0
  191. /package/dist/{runtime → features/agent}/agent-paths.d.ts +0 -0
  192. /package/dist/{runtime → features/agent}/agent-paths.js +0 -0
  193. /package/dist/{runtime → features}/query/backlinks +0 -0
  194. /package/dist/{runtime → features}/query/backlinks.d.ts +0 -0
  195. /package/dist/{runtime → features}/query/context +0 -0
  196. /package/dist/{runtime → features}/query/context.d.ts +0 -0
  197. /package/dist/{runtime → features}/query/context.js +0 -0
  198. /package/dist/{runtime → features}/query/documents +0 -0
  199. /package/dist/{runtime → features}/query/documents.d.ts +0 -0
  200. /package/dist/{runtime → features}/query/errors +0 -0
  201. /package/dist/{runtime → features}/query/errors.d.ts +0 -0
  202. /package/dist/{runtime → features}/query/errors.js +0 -0
  203. /package/dist/{runtime → features}/query/handles +0 -0
  204. /package/dist/{runtime → features}/query/handles.d.ts +0 -0
  205. /package/dist/{runtime → features}/query/handles.js +0 -0
  206. /package/dist/{runtime → features}/query/locale-options +0 -0
  207. /package/dist/{runtime → features}/query/locale-options.d.ts +0 -0
  208. /package/dist/{runtime → features}/query/locale-options.js +0 -0
  209. /package/dist/{runtime → features}/query/localized-docs +0 -0
  210. /package/dist/{runtime → features}/query/navigation +0 -0
  211. /package/dist/{runtime → features}/query/pagination +0 -0
  212. /package/dist/{runtime → features}/query/pagination.d.ts +0 -0
  213. /package/dist/{runtime → features}/query/pagination.js +0 -0
  214. /package/dist/{runtime → features}/query/populate +0 -0
  215. /package/dist/{runtime → features}/query/populate.d.ts +0 -0
  216. /package/dist/{runtime → features}/query/public-limits +0 -0
  217. /package/dist/{runtime → features}/query/public-limits.d.ts +0 -0
  218. /package/dist/{runtime → features}/query/public-limits.js +0 -0
  219. /package/dist/{runtime → features}/query/resolve +0 -0
  220. /package/dist/{runtime → features}/query/resolve.d.ts +0 -0
  221. /package/dist/{runtime → features}/query/resolve.js +0 -0
  222. /package/dist/{runtime → features}/query/responses +0 -0
  223. /package/dist/{runtime → features}/query/responses.d.ts +0 -0
  224. /package/dist/{runtime → features}/query/responses.js +0 -0
  225. /package/dist/{runtime → features}/query/routes +0 -0
  226. /package/dist/{runtime → features}/query/routes.d.ts +0 -0
  227. /package/dist/{runtime → features}/query/routes.js +0 -0
  228. /package/dist/{runtime → features}/query/unified +0 -0
  229. /package/dist/{runtime → features}/query/variants +0 -0
  230. /package/dist/{runtime → features}/query/variants.d.ts +0 -0
@@ -1,11 +1,11 @@
1
- import { contentProviderResultMarker } from "../public/provider";
1
+ import { contentProviderResultMarker, toContentProviderQuery } from "../public/provider";
2
2
  import { buildContentGraph } from "../core/content/graph";
3
3
  import { executeQueryPlan } from "../core/query/execute";
4
- import { lowerQueryPlan } from "../core/query/lower";
5
- import { findUnsupportedQueryOperator, SUPPORTED_QUERY_OPERATORS } from "../core/query/operators";
4
+ import { SUPPORTED_QUERY_OPERATORS } from "../core/query/operators";
6
5
  import { mergeContentCacheHints } from "../core/cache-hints";
7
- import { normalizeRouteMounts, projectContentPathToLocale } from "../features/localization/path";
6
+ import { normalizeContentPath, normalizeRouteMounts, projectContentPathToLocale } from "../features/localization/path";
8
7
  import { createRouteMeta, localizePageResult } from "../features/localization/results";
8
+ import { normalizeProviderDocument } from "../runtime/server/provider-document";
9
9
  import { createContentProviderError } from "../public/provider-errors";
10
10
  const trimSlashes = (value) => value.replace(/^\/+|\/+$/g, "");
11
11
  const isObject = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
@@ -42,13 +42,13 @@ const localizePath = (fixture, collection, path, locale) => {
42
42
  const navFieldsFromDoc = (doc, fields = []) => Object.fromEntries(fields.filter((field) => field in doc).map((field) => [field, doc[field]]));
43
43
  const navIdentityFromDoc = (doc) => ({
44
44
  ref: doc.ref,
45
- stableId: doc.ref || doc._canonicalKey || doc._id
45
+ stableId: doc.ref || doc.canonicalKey || doc.id
46
46
  });
47
47
  const normalizeCachePath = (path) => {
48
48
  const normalized = path.startsWith("/") ? path : `/${path}`;
49
49
  return normalized.replace(/\/{2,}/g, "/");
50
50
  };
51
- const documentEntryTag = (doc) => `entry:${doc._collection}:${String(doc.ref || doc._canonicalKey || doc._id)}`;
51
+ const documentEntryTag = (doc) => `entry:${doc.collection}:${String(doc.ref || doc.canonicalKey || doc.id)}`;
52
52
  const collectionTag = (collection) => `collection:${collection}`;
53
53
  const routeTag = (path) => `route:${normalizeCachePath(path)}`;
54
54
  const collectStringValues = (value) => {
@@ -85,7 +85,7 @@ export const collectProviderFixtureCacheHint = (event, hint) => {
85
85
  };
86
86
  export const getProviderFixtureCacheHint = (event) => getProviderFixtureRuntimeContext(event).cacheHint;
87
87
  const createCacheHintForDocument = (fixture, doc, path) => {
88
- const collection = doc._collection || "content";
88
+ const collection = doc.collection || "content";
89
89
  return {
90
90
  tags: Array.from(/* @__PURE__ */ new Set([
91
91
  documentEntryTag(doc),
@@ -150,28 +150,31 @@ const invalidateFixtureCache = (cache, input) => {
150
150
  }
151
151
  };
152
152
  export const createProviderFixtureDocument = (input) => {
153
- const collection = String(input._collection || "docs");
154
- const locale = String(input._locale || "en");
155
- const path = String(input._path || "/");
156
- const canonicalKey = String(input._canonicalKey || `${collection}:${trimSlashes(path) || "index"}`);
157
- const extension = input._extension || (input._type === "yaml" ? "yml" : "md");
158
- return {
159
- _id: String(input._id || `content:${locale}:${trimSlashes(path).replace(/\//g, ":") || "index"}.${extension}`),
160
- _source: String(input._source || "content"),
161
- _collection: collection,
162
- _locale: locale,
163
- _canonicalKey: canonicalKey,
164
- _path: path,
165
- _file: String(input._file || `/${locale}/${trimSlashes(path) || "index"}.${extension}`),
166
- _type: input._type || "markdown",
167
- _extension: extension,
153
+ const collection = String(input.collection || "docs");
154
+ const locale = String(input.locale || "en");
155
+ const path = String(input.path || "/");
156
+ const canonicalKey = String(input.canonicalKey || `${collection}:${trimSlashes(path) || "index"}`);
157
+ const type = input.type || "markdown";
158
+ const extension = input.file?.extension || (input.type === "yaml" ? "yml" : "md");
159
+ return normalizeProviderDocument({
160
+ ...input,
161
+ collection,
162
+ locale,
163
+ path,
164
+ canonicalKey,
165
+ type,
166
+ id: String(input.id || `content:${locale}:${trimSlashes(path).replace(/\//g, ":") || "index"}.${extension}`),
167
+ file: {
168
+ source: String(input.file?.source || "content"),
169
+ path: String(input.file?.path || `/${locale}/${trimSlashes(path) || "index"}.${extension}`),
170
+ extension
171
+ },
168
172
  title: String(input.title || canonicalKey),
169
- body: {
173
+ body: input.body ?? {
170
174
  type: "root",
171
175
  children: []
172
- },
173
- ...input
174
- };
176
+ }
177
+ });
175
178
  };
176
179
  export const createProviderFixture = (input) => {
177
180
  const defaultLocale = input.defaultLocale || "en";
@@ -228,26 +231,21 @@ export const createFixtureContentProvider = (fixture, name = fixture.providerNam
228
231
  throw createContentProviderError("unknown_collection", `Unknown collection: ${collection}`, { collection });
229
232
  }
230
233
  };
231
- const query = async (event, params) => {
232
- assertCollection(params.collection);
233
- const unsupported = findUnsupportedQueryOperator(params.where);
234
- if (unsupported) {
235
- throw createContentProviderError("unsupported_query_operator", `Unsupported query operator: ${unsupported}`, {
236
- operator: unsupported
237
- });
238
- }
234
+ const query = async (event, providerQuery) => {
235
+ assertCollection(providerQuery.plan.collection);
239
236
  collectProviderFixtureCacheHint(event, {
240
- tags: params.collection ? [collectionTag(params.collection)] : []
237
+ tags: providerQuery.collection ? [collectionTag(providerQuery.collection)] : []
241
238
  });
242
239
  return executeQueryPlan(
243
240
  fixture.graph,
244
- lowerQueryPlan(params),
241
+ providerQuery.plan,
245
242
  fixture.runtime
246
243
  );
247
244
  };
245
+ const queryWithParams = (event, params) => query(event, toContentProviderQuery(params));
248
246
  const docsForNavigation = async (event, params) => {
249
- const response = await query(event, params);
250
- return normalizeQueryResult(unwrapResponseResult(response)).filter((doc) => !doc._draft && !doc._partial && !doc._navigation && doc.navigation !== false && doc._path);
247
+ const response = await queryWithParams(event, params);
248
+ return normalizeQueryResult(unwrapResponseResult(response)).filter((doc) => !doc.draft && !doc.partial && !doc.navigationFile && doc.navigation !== false && doc.path);
251
249
  };
252
250
  const provider = {
253
251
  name,
@@ -268,21 +266,23 @@ export const createFixtureContentProvider = (fixture, name = fixture.providerNam
268
266
  }
269
267
  },
270
268
  query,
271
- navigationQuery: async (event, params) => {
272
- const docs = await docsForNavigation(event, params);
269
+ navigationQuery: async (event, providerQuery, navigationOptions = {}) => {
270
+ const response = await query(event, providerQuery);
271
+ const docs = normalizeQueryResult(unwrapResponseResult(response)).filter((doc) => !doc.draft && !doc.partial && !doc.navigationFile && doc.navigation !== false && doc.path);
272
+ const collection = providerQuery.collection ?? void 0;
273
+ const queryLocale = navigationOptions.resolveLocale?.locale;
273
274
  collectProviderFixtureCacheHint(event, {
274
275
  tags: [
275
- ...params.collection ? [collectionTag(params.collection)] : [],
276
- ...params.resolveLocale?.locale ? [`nav:${params.collection || "all"}:${params.resolveLocale.locale}`] : []
276
+ ...collection ? [collectionTag(collection)] : [],
277
+ ...queryLocale ? [`nav:${collection || "all"}:${queryLocale}`] : []
277
278
  ]
278
279
  });
279
- const queryLocale = params.resolveLocale?.locale;
280
280
  return docs.map((doc) => ({
281
281
  title: doc.title,
282
282
  ...navIdentityFromDoc(doc),
283
- _path: doc._path,
284
- path: localizePath(fixture, doc._collection || params.collection || "", doc._path || "/", queryLocale || doc._requestedLocale || doc._locale),
285
- _locale: doc._locale
283
+ unprefixedPath: normalizeContentPath(doc.path || "/"),
284
+ path: localizePath(fixture, doc.collection || collection || "", doc.path || "/", queryLocale || doc.resolved?.requestedLocale || doc.locale),
285
+ locale: doc.locale
286
286
  }));
287
287
  },
288
288
  navigation: async (event, collection, options = {}) => {
@@ -298,15 +298,15 @@ export const createFixtureContentProvider = (fixture, name = fixture.providerNam
298
298
  locale,
299
299
  fallback: fixture.localeFallback[locale] || [fixture.defaultLocale]
300
300
  } : void 0,
301
- sort: [{ _path: 1 }]
301
+ sort: [{ path: 1 }]
302
302
  });
303
303
  return docs.map((doc) => ({
304
304
  title: doc.title,
305
305
  ...navFieldsFromDoc(doc, fields),
306
306
  ...navIdentityFromDoc(doc),
307
- _path: doc._path,
308
- path: localizePath(fixture, collection, doc._path || "/", locale || doc._locale),
309
- _locale: doc._locale
307
+ unprefixedPath: normalizeContentPath(doc.path || "/"),
308
+ path: localizePath(fixture, collection, doc.path || "/", locale || doc.locale),
309
+ locale: doc.locale
310
310
  }));
311
311
  },
312
312
  surroundings: async (event, collection, path, options = {}) => {
@@ -318,14 +318,14 @@ export const createFixtureContentProvider = (fixture, name = fixture.providerNam
318
318
  locale,
319
319
  fallback: fixture.localeFallback[locale] || [fixture.defaultLocale]
320
320
  } : void 0,
321
- sort: [{ _path: 1 }]
321
+ sort: [{ path: 1 }]
322
322
  });
323
- const index = docs.findIndex((doc) => doc._path === path || localizePath(fixture, collection, doc._path || "/", locale || doc._locale) === path);
323
+ const index = docs.findIndex((doc) => doc.path === path || localizePath(fixture, collection, doc.path || "/", locale || doc.locale) === path);
324
324
  if (index === -1) return [null, null];
325
325
  return [docs[index - 1] || null, docs[index + 1] || null].map((doc) => doc ? {
326
326
  title: doc.title,
327
- _path: doc._path,
328
- path: localizePath(fixture, collection, doc._path || "/", locale || doc._locale)
327
+ unprefixedPath: normalizeContentPath(doc.path || "/"),
328
+ path: localizePath(fixture, collection, doc.path || "/", locale || doc.locale)
329
329
  } : null);
330
330
  },
331
331
  searchSections: async (event, collection, options = {}) => {
@@ -344,7 +344,7 @@ export const createFixtureContentProvider = (fixture, name = fixture.providerNam
344
344
  const extraFields = options.extraFields || [];
345
345
  return docs.map((doc) => ({
346
346
  ...Object.fromEntries(extraFields.filter((field) => field in doc).map((field) => [field, doc[field]])),
347
- id: localizePath(fixture, collection, doc._path || "/", options.locale || doc._locale),
347
+ id: localizePath(fixture, collection, doc.path || "/", options.locale || doc.locale),
348
348
  title: doc.title || "",
349
349
  titles: [doc.title || ""],
350
350
  content: String(doc.description || doc.title || ""),
@@ -353,13 +353,13 @@ export const createFixtureContentProvider = (fixture, name = fixture.providerNam
353
353
  },
354
354
  search: async (_event, request) => {
355
355
  const term = request.term.toLocaleLowerCase();
356
- return fixture.documents.filter((doc) => !request.collections?.length || request.collections.includes(doc._collection || "")).filter((doc) => !request.locale || doc._locale === request.locale).filter((doc) => String(doc.title || "").toLocaleLowerCase().includes(term)).map((doc) => ({
356
+ return fixture.documents.filter((doc) => !request.collections?.length || request.collections.includes(doc.collection || "")).filter((doc) => !request.locale || doc.locale === request.locale).filter((doc) => String(doc.title || "").toLocaleLowerCase().includes(term)).map((doc) => ({
357
357
  score: 1,
358
- collection: doc._collection || "",
358
+ collection: doc.collection || "",
359
359
  title: doc.title || "",
360
360
  excerpt: String(doc.description || ""),
361
- path: localizePath(fixture, doc._collection || "", doc._path || "/", doc._locale),
362
- locale: doc._locale
361
+ path: localizePath(fixture, doc.collection || "", doc.path || "/", doc.locale),
362
+ locale: doc.locale
363
363
  }));
364
364
  },
365
365
  siteData: async (event, request) => {
@@ -382,7 +382,7 @@ export const createFixtureContentProvider = (fixture, name = fixture.providerNam
382
382
  const routeLocale = segments[0] && fixture.locales.includes(segments[0]) ? segments[0] : void 0;
383
383
  const providerRoute = routeLocale ? `/${segments.slice(1).join("/")}` : routeOrPath;
384
384
  const requestedLocale = options.locale || routeLocale;
385
- const response = await query(event, {
385
+ const response = await queryWithParams(event, {
386
386
  collection,
387
387
  first: true,
388
388
  resolveVariant: {
@@ -396,7 +396,7 @@ export const createFixtureContentProvider = (fixture, name = fixture.providerNam
396
396
  if (!doc) return null;
397
397
  const page = localizePageResult(
398
398
  doc,
399
- requestedLocale || doc._resolvedLocale || doc._locale,
399
+ requestedLocale || doc.resolved?.locale || doc.locale,
400
400
  fixture.defaultLocale,
401
401
  fixture.locales,
402
402
  routeMountsFor(fixture, collection)
@@ -408,7 +408,11 @@ export const createFixtureContentProvider = (fixture, name = fixture.providerNam
408
408
  },
409
409
  routeMeta: async (event, collection, routeOrPath = "/", options = {}) => {
410
410
  const page = await provider.page(event, collection, routeOrPath, options);
411
- return page ? createRouteMeta(page, options.locale || page.locale, fixture.defaultLocale, routeMountsFor(fixture, collection)) : null;
411
+ const routePage = page;
412
+ return routePage ? createRouteMeta({
413
+ ...routePage,
414
+ path: routePage.unprefixedPath || routePage.path
415
+ }, options.locale || routePage.locale, fixture.defaultLocale, fixture.locales, routeMountsFor(fixture, collection)) : null;
412
416
  },
413
417
  sitemapEntries: async (event, options = {}) => {
414
418
  collectProviderFixtureCacheHint(event, { tags: ["sitemap"] });
@@ -423,9 +427,9 @@ export const createFixtureContentProvider = (fixture, name = fixture.providerNam
423
427
  }
424
428
  continue;
425
429
  }
426
- for (const doc of fixture.documents.filter((doc2) => doc2._collection === collection && !doc2._draft && !doc2._partial && !doc2._navigation)) {
430
+ for (const doc of fixture.documents.filter((doc2) => doc2.collection === collection && !doc2.draft && !doc2.partial && !doc2.navigationFile)) {
427
431
  entries.push({
428
- loc: localizePath(fixture, collection, doc._path || "/", doc._locale)
432
+ loc: localizePath(fixture, collection, doc.path || "/", doc.locale)
429
433
  });
430
434
  }
431
435
  }
@@ -437,7 +441,7 @@ export const createFixtureContentProvider = (fixture, name = fixture.providerNam
437
441
  };
438
442
  return Object.assign(provider, { cache });
439
443
  };
440
- export const createSaasProviderFixture = () => createProviderFixture({
444
+ export const createDefaultProviderFixture = () => createProviderFixture({
441
445
  name: "saas-i18n",
442
446
  providerName: "fixture",
443
447
  defaultLocale: "en",
@@ -467,81 +471,81 @@ export const createSaasProviderFixture = () => createProviderFixture({
467
471
  },
468
472
  documents: [
469
473
  {
470
- _collection: "docs",
471
- _locale: "en",
472
- _canonicalKey: "docs:getting-started",
473
- _path: "/docs/getting-started",
474
+ collection: "docs",
475
+ locale: "en",
476
+ canonicalKey: "docs:getting-started",
477
+ path: "/docs/getting-started",
474
478
  ref: "docs.getting-started",
475
479
  title: "Getting Started",
476
480
  description: "Start here",
477
481
  order: 1
478
482
  },
479
483
  {
480
- _collection: "docs",
481
- _locale: "de",
482
- _canonicalKey: "docs:getting-started",
483
- _path: "/dokumentation/einstieg",
484
+ collection: "docs",
485
+ locale: "de",
486
+ canonicalKey: "docs:getting-started",
487
+ path: "/dokumentation/einstieg",
484
488
  ref: "docs.getting-started",
485
489
  title: "Einstieg",
486
490
  description: "Hier starten",
487
491
  order: 1
488
492
  },
489
493
  {
490
- _collection: "docs",
491
- _locale: "de",
492
- _canonicalKey: "docs:getting-started-installation",
493
- _path: "/dokumentation/einstieg/installation",
494
+ collection: "docs",
495
+ locale: "de",
496
+ canonicalKey: "docs:getting-started-installation",
497
+ path: "/dokumentation/einstieg/installation",
494
498
  ref: "docs.getting-started.installation",
495
499
  title: "Installation",
496
500
  description: "Installieren",
497
501
  order: 2
498
502
  },
499
503
  {
500
- _collection: "docs",
501
- _locale: "de",
502
- _canonicalKey: "docs:getting-started-everyday",
503
- _path: "/dokumentation/einstieg/alltag",
504
+ collection: "docs",
505
+ locale: "de",
506
+ canonicalKey: "docs:getting-started-everyday",
507
+ path: "/dokumentation/einstieg/alltag",
504
508
  ref: "docs.getting-started.everyday",
505
509
  title: "Alltag",
506
510
  description: "Arbeiten",
507
511
  order: 3
508
512
  },
509
513
  {
510
- _collection: "docs",
511
- _locale: "en",
512
- _canonicalKey: "docs:markdown-syntax",
513
- _path: "/docs/essentials/markdown-syntax",
514
+ collection: "docs",
515
+ locale: "en",
516
+ canonicalKey: "docs:markdown-syntax",
517
+ path: "/docs/essentials/markdown-syntax",
514
518
  ref: "docs.markdown-syntax",
515
519
  title: "Markdown Syntax",
516
520
  description: "Writing docs",
517
521
  order: 4
518
522
  },
519
523
  {
520
- _collection: "docs",
521
- _locale: "en",
522
- _canonicalKey: "docs:draft-roadmap",
523
- _path: "/docs/draft-roadmap",
524
+ collection: "docs",
525
+ locale: "en",
526
+ canonicalKey: "docs:draft-roadmap",
527
+ path: "/docs/draft-roadmap",
524
528
  ref: "docs.draft-roadmap",
525
529
  title: "Draft Roadmap",
526
530
  description: "Unpublished draft",
527
- _draft: true,
531
+ draft: true,
528
532
  order: 5
529
533
  },
530
534
  {
531
- _collection: "docs",
532
- _locale: "de",
533
- _canonicalKey: "docs:markdown-syntax",
534
- _path: "/dokumentation/grundlagen/markdown-syntax",
535
+ collection: "docs",
536
+ locale: "de",
537
+ canonicalKey: "docs:markdown-syntax",
538
+ path: "/dokumentation/grundlagen/markdown-syntax",
535
539
  ref: "docs.markdown-syntax",
536
540
  title: "Markdown Syntax DE",
537
541
  description: "Dokumentation schreiben",
538
542
  order: 4
539
543
  },
540
544
  {
541
- _collection: "posts",
542
- _locale: "en",
543
- _canonicalKey: "posts:onboarding",
544
- _path: "/blog/multilingual-onboarding",
545
+ collection: "posts",
546
+ locale: "en",
547
+ canonicalKey: "posts:onboarding",
548
+ path: "/blog/multilingual-onboarding",
545
549
  ref: "posts.onboarding",
546
550
  title: "Multilingual Onboarding",
547
551
  description: "Launch notes",
@@ -549,10 +553,10 @@ export const createSaasProviderFixture = () => createProviderFixture({
549
553
  authors: ["authors.emily"]
550
554
  },
551
555
  {
552
- _collection: "posts",
553
- _locale: "de",
554
- _canonicalKey: "posts:onboarding",
555
- _path: "/magazin/mehrsprachiges-onboarding",
556
+ collection: "posts",
557
+ locale: "de",
558
+ canonicalKey: "posts:onboarding",
559
+ path: "/magazin/mehrsprachiges-onboarding",
556
560
  ref: "posts.onboarding",
557
561
  title: "Mehrsprachiges Onboarding",
558
562
  description: "Startnotizen",
@@ -560,30 +564,30 @@ export const createSaasProviderFixture = () => createProviderFixture({
560
564
  authors: ["authors.emily"]
561
565
  },
562
566
  {
563
- _collection: "authors",
564
- _locale: "en",
565
- _canonicalKey: "authors:emily",
566
- _path: "/authors/emily",
567
+ collection: "authors",
568
+ locale: "en",
569
+ canonicalKey: "authors:emily",
570
+ path: "/authors/emily",
567
571
  ref: "authors.emily",
568
572
  title: "Emily",
569
573
  name: "Emily",
570
574
  description: "Author"
571
575
  },
572
576
  {
573
- _collection: "authors",
574
- _locale: "de",
575
- _canonicalKey: "authors:emily",
576
- _path: "/autoren/emily",
577
+ collection: "authors",
578
+ locale: "de",
579
+ canonicalKey: "authors:emily",
580
+ path: "/autoren/emily",
577
581
  ref: "authors.emily",
578
582
  title: "Emily DE",
579
583
  name: "Emily",
580
584
  description: "Autorin"
581
585
  },
582
586
  {
583
- _collection: "versions",
584
- _locale: "en",
585
- _canonicalKey: "versions:launch-readiness",
586
- _path: "/changelog/launch-readiness",
587
+ collection: "versions",
588
+ locale: "en",
589
+ canonicalKey: "versions:launch-readiness",
590
+ path: "/changelog/launch-readiness",
587
591
  ref: "versions.launch-readiness",
588
592
  title: "Launch readiness",
589
593
  date: "2026-01-01"
@@ -600,18 +604,18 @@ export const createAuthorDependencyProviderFixture = () => createProviderFixture
600
604
  authors: { type: "page", route: "/authors" }
601
605
  },
602
606
  documents: [
603
- { _collection: "authors", _path: "/authors/alice", ref: "authors.alice", title: "Alice", name: "Alice" },
604
- { _collection: "authors", _path: "/authors/bob", ref: "authors.bob", title: "Bob", name: "Bob" },
607
+ { collection: "authors", path: "/authors/alice", ref: "authors.alice", title: "Alice", name: "Alice" },
608
+ { collection: "authors", path: "/authors/bob", ref: "authors.bob", title: "Bob", name: "Bob" },
605
609
  ...Array.from({ length: 5 }, (_, index) => ({
606
- _collection: "blog",
607
- _path: `/blog/post-${index + 1}`,
610
+ collection: "blog",
611
+ path: `/blog/post-${index + 1}`,
608
612
  ref: `blog.post-${index + 1}`,
609
613
  title: `Post ${index + 1}`,
610
614
  authors: ["authors.alice"]
611
615
  })),
612
616
  {
613
- _collection: "blog",
614
- _path: "/blog/post-6",
617
+ collection: "blog",
618
+ path: "/blog/post-6",
615
619
  ref: "blog.post-6",
616
620
  title: "Post 6",
617
621
  authors: ["authors.bob"]
@@ -32,14 +32,10 @@ export interface ContentCmsFieldConfig {
32
32
  description?: string | null;
33
33
  required?: boolean;
34
34
  localized?: boolean;
35
- hidden?: boolean;
36
35
  searchable?: boolean;
37
36
  sortable?: boolean;
38
- order?: number;
39
- width?: 'full' | 'half';
40
37
  defaultValue?: unknown;
41
38
  validation?: Record<string, unknown> | null;
42
- condition?: Record<string, unknown> | null;
43
39
  options?: string[] | null;
44
40
  relation?: ContentCmsRelationConfig | null;
45
41
  fields?: Record<string, ContentCmsFieldConfig> | ContentCmsFieldConfig[] | null;
@@ -48,6 +44,14 @@ export interface ContentCmsFieldConfig {
48
44
  step?: number | null;
49
45
  slugFrom?: string | null;
50
46
  language?: string | null;
47
+ /**
48
+ * Opaque editor-layout passthrough. ginko-content does not type or interpret
49
+ * this bag; it stores and forwards it byte-for-byte through `buildCmsContract`
50
+ * to the CMS field contract. Pure layout policy (field width, display order,
51
+ * hidden state, conditional visibility, etc.) belongs here — its schema is
52
+ * owned entirely by the consuming CMS (e.g. `@lupinum/ginko-cms`).
53
+ */
54
+ editor?: Record<string, unknown>;
51
55
  }
52
56
  export interface ContentCmsCollectionConfig {
53
57
  label?: string | Record<string, string>;