@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.
- package/compatibility.json +1 -1
- package/dist/cli.mjs +2 -2
- package/dist/cms-contract/build.js +15 -20
- package/dist/cms-contract/types.d.ts +12 -7
- package/dist/core/content/document +1 -0
- package/dist/core/content/document.d.ts +16 -0
- package/dist/core/content/document.js +2 -0
- package/dist/core/content/graph.d.ts +3 -1
- package/dist/core/content/graph.js +21 -20
- package/dist/core/content/locale.d.ts +6 -1
- package/dist/core/content/locale.js +17 -6
- package/dist/core/content/path.d.ts +5 -5
- package/dist/core/content/path.js +8 -8
- package/dist/core/content/snapshot +1 -0
- package/dist/core/content/snapshot.d.ts +25 -0
- package/dist/core/content/snapshot.js +99 -0
- package/dist/core/provider-errors.d.ts +1 -1
- package/dist/core/provider-errors.js +1 -0
- package/dist/core/query/builder.js +3 -3
- package/dist/core/query/execute.js +75 -36
- package/dist/core/query/filter.js +2 -2
- package/dist/core/query/lower.js +79 -3
- package/dist/core/query/params.js +7 -7
- package/dist/core/query/plan.d.ts +18 -0
- package/dist/core/query/plan.js +7 -0
- package/dist/core/references/resolve.js +6 -9
- package/dist/features/agent/agent-markdown +1 -0
- package/dist/features/agent/agent-markdown.d.ts +116 -0
- package/dist/features/agent/agent-markdown.js +138 -0
- package/dist/features/agent/walker +1 -0
- package/dist/features/agent/walker.d.ts +10 -0
- package/dist/features/agent/walker.js +174 -0
- package/dist/features/collections/resolve.d.ts +2 -2
- package/dist/features/collections/resolve.js +19 -16
- package/dist/features/localization/links.js +1 -1
- package/dist/features/localization/results.d.ts +3 -3
- package/dist/features/localization/results.js +46 -41
- package/dist/features/localization/translated-slugs.js +5 -5
- package/dist/features/navigation/build.d.ts +2 -2
- package/dist/features/navigation/build.js +23 -26
- package/dist/features/navigation/canonical.d.ts +10 -11
- package/dist/features/navigation/canonical.js +26 -21
- package/dist/features/navigation/resolve.js +4 -4
- package/dist/features/navigation/tree.js +3 -3
- package/dist/{runtime → features}/query/backlinks.js +3 -5
- package/dist/{runtime → features}/query/documents.js +1 -1
- package/dist/{runtime → features}/query/localized-docs.d.ts +1 -1
- package/dist/{runtime → features}/query/localized-docs.js +3 -6
- package/dist/{runtime → features}/query/navigation.d.ts +1 -1
- package/dist/{runtime → features}/query/navigation.js +8 -8
- package/dist/{runtime → features}/query/populate.js +6 -14
- package/dist/{runtime → features}/query/unified.d.ts +4 -4
- package/dist/{runtime → features}/query/unified.js +4 -2
- package/dist/{runtime → features}/query/variants.js +4 -4
- package/dist/features/search/navigation.js +2 -2
- package/dist/features/search/sections.d.ts +1 -1
- package/dist/features/search/sections.js +1 -1
- package/dist/features/sitemap/query.d.ts +5 -5
- package/dist/features/sitemap/query.js +6 -6
- package/dist/integrations/nitro/ingest.js +9 -20
- package/dist/integrations/nitro/storage.d.ts +1 -0
- package/dist/integrations/nitro/storage.js +22 -8
- package/dist/module.d.mts +135 -812
- package/dist/module.json +1 -1
- package/dist/module.mjs +70 -27
- package/dist/parsers/csv.js +3 -3
- package/dist/parsers/index.js +3 -3
- package/dist/parsers/json.js +8 -6
- package/dist/parsers/markdown-plugins.js +9 -5
- package/dist/parsers/markdown.js +7 -6
- package/dist/parsers/path-meta.js +21 -19
- package/dist/parsers/reserved +1 -0
- package/dist/parsers/reserved.d.ts +15 -0
- package/dist/parsers/reserved.js +35 -0
- package/dist/parsers/yaml.js +6 -4
- package/dist/public/agent +1 -0
- package/dist/public/agent.d.ts +17 -0
- package/dist/public/agent.js +34 -0
- package/dist/public/client.d.ts +2 -3
- package/dist/public/client.js +1 -2
- package/dist/public/provider-query +1 -0
- package/dist/public/provider-query.d.ts +58 -0
- package/dist/public/provider-query.js +5 -0
- package/dist/public/provider.d.ts +8 -3
- package/dist/public/provider.js +2 -0
- package/dist/public/server.d.ts +7 -12
- package/dist/public/server.js +5 -36
- package/dist/runtime/app/components/ContentRenderer.d.vue.ts +3 -3
- package/dist/runtime/app/components/ContentRenderer.vue +2 -2
- package/dist/runtime/app/components/ContentRenderer.vue.d.ts +3 -3
- package/dist/runtime/app/components/ContentRendererInline.d.vue.ts +1 -1
- package/dist/runtime/app/components/ContentRendererInline.vue.d.ts +1 -1
- package/dist/runtime/app/components/Prose/ProseImg.d.vue.ts +4 -4
- package/dist/runtime/app/components/Prose/ProseImg.vue.d.ts +4 -4
- package/dist/runtime/app/components/Prose/ProsePre.d.vue.ts +1 -1
- package/dist/runtime/app/components/Prose/ProsePre.vue.d.ts +1 -1
- package/dist/runtime/app/components/internal/ContentRendererMarkdown.d.vue.ts +1 -1
- package/dist/runtime/app/components/internal/ContentRendererMarkdown.vue +4 -4
- package/dist/runtime/app/components/internal/ContentRendererMarkdown.vue.d.ts +1 -1
- package/dist/runtime/app/components/internal/MarkdownRenderer.d.ts +3 -3
- package/dist/runtime/app/composables/preview.d.ts +1 -1
- package/dist/runtime/app/composables/query-api.d.ts +5 -5
- package/dist/runtime/app/composables/query-api.js +5 -3
- package/dist/runtime/app/composables/route.d.ts +1 -1
- package/dist/runtime/app/composables/route.js +4 -4
- package/dist/runtime/app/composables/search.js +1 -1
- package/dist/runtime/app/composables/use-content-document.js +1 -1
- package/dist/runtime/app/composables/use-content-list.js +1 -1
- package/dist/runtime/app/composables/use-content-navigation.js +2 -2
- package/dist/runtime/app/composables/use-content-page.js +4 -4
- package/dist/runtime/app/pages/content.vue +2 -1
- package/dist/runtime/markdown/plugins.js +6 -8
- package/dist/runtime/server/agent-markdown.d.ts +5 -65
- package/dist/runtime/server/agent-markdown.js +40 -315
- package/dist/runtime/server/agent-site.js +1 -1
- package/dist/runtime/server/api/agent-raw.js +1 -1
- package/dist/runtime/server/api/cache.d.ts +1 -1
- package/dist/runtime/server/api/cache.js +43 -4
- package/dist/runtime/server/api/locales.js +3 -3
- package/dist/runtime/server/api/navigation.d.ts +1 -1
- package/dist/runtime/server/api/navigation.js +3 -1
- package/dist/runtime/server/api/query.js +2 -2
- package/dist/runtime/server/api/search-index.d.ts +1 -1
- package/dist/runtime/server/api/sitemap.d.ts +1 -1
- package/dist/runtime/server/cache-adapters.d.ts +18 -0
- package/dist/runtime/server/cache-adapters.js +12 -0
- package/dist/runtime/server/collection-helpers.d.ts +2 -2
- package/dist/runtime/server/collection-helpers.js +15 -11
- package/dist/runtime/server/index.d.ts +6 -4
- package/dist/runtime/server/index.js +10 -3
- package/dist/runtime/server/middleware/agent-link-headers.js +1 -1
- package/dist/runtime/server/middleware/agent-markdown.js +1 -1
- package/dist/runtime/server/navigation-query.d.ts +2 -2
- package/dist/runtime/server/navigation-query.js +52 -7
- package/dist/runtime/server/navigation.d.ts +1 -1
- package/dist/runtime/server/provider-document +1 -0
- package/dist/runtime/server/provider-document.d.ts +59 -0
- package/dist/runtime/server/provider-document.js +48 -0
- package/dist/runtime/server/provider-query-wire +1 -0
- package/dist/runtime/server/provider-query-wire.d.ts +32 -0
- package/dist/runtime/server/provider-query-wire.js +27 -0
- package/dist/runtime/server/provider-query.d.ts +18 -9
- package/dist/runtime/server/provider-query.js +62 -28
- package/dist/runtime/server/provider-result.d.ts +4 -4
- package/dist/runtime/server/providers/filesystem.js +3 -11
- package/dist/runtime/server/providers/index.d.ts +18 -1
- package/dist/runtime/server/providers/index.js +72 -20
- package/dist/runtime/server/query-api.d.ts +5 -5
- package/dist/runtime/server/query-api.js +9 -6
- package/dist/runtime/server/query-executor.d.ts +3 -3
- package/dist/runtime/server/query-executor.js +43 -59
- package/dist/runtime/server/search.d.ts +1 -1
- package/dist/runtime/server/search.js +4 -4
- package/dist/runtime/server/sitemap.js +5 -5
- package/dist/runtime/server/storage-access.d.ts +4 -1
- package/dist/runtime/server/storage-access.js +27 -2
- package/dist/runtime/transformers/component-resolver.d.ts +1 -1
- package/dist/storage/content.d.ts +2 -6
- package/dist/storage/content.js +19 -8
- package/dist/storage/contents.d.ts +9 -1
- package/dist/storage/contents.js +26 -19
- package/dist/storage/driver.d.ts +2 -2
- package/dist/storage/driver.js +2 -1
- package/dist/storage/graph.js +4 -0
- package/dist/storage/manifest.js +3 -1
- package/dist/storage/references.js +9 -5
- package/dist/storage/snapshot-runtime +1 -0
- package/dist/storage/snapshot-runtime.d.ts +11 -0
- package/dist/storage/snapshot-runtime.js +46 -0
- package/dist/storage/validation.d.ts +1 -1
- package/dist/storage/validation.js +47 -102
- package/dist/testing/provider-contract.d.ts +14 -4
- package/dist/testing/provider-contract.js +121 -68
- package/dist/testing/provider-fixture.d.ts +1 -1
- package/dist/testing/provider-fixture.js +124 -120
- package/dist/types/config.d.ts +8 -4
- package/dist/types/content.d.ts +104 -70
- package/dist/types/fields.js +1 -1
- package/dist/types/module.d.ts +1 -1
- package/dist/types/query-parts/public.d.ts +14 -5
- package/dist/types/query-parts/results.d.ts +6 -2
- package/dist/types/query-parts/transport.d.ts +19 -0
- package/dist/types/virtual.d.ts +6 -0
- package/dist/types.d.mts +2 -2
- package/dist/web-types.json +1 -1
- package/package.json +39 -9
- package/dist/runtime/app/plugins/markdown-components +0 -1
- package/dist/runtime/app/plugins/markdown-components.d.ts +0 -2
- package/dist/runtime/app/plugins/markdown-components.js +0 -19
- /package/dist/{runtime → features/agent}/agent-paths +0 -0
- /package/dist/{runtime → features/agent}/agent-paths.d.ts +0 -0
- /package/dist/{runtime → features/agent}/agent-paths.js +0 -0
- /package/dist/{runtime → features}/query/backlinks +0 -0
- /package/dist/{runtime → features}/query/backlinks.d.ts +0 -0
- /package/dist/{runtime → features}/query/context +0 -0
- /package/dist/{runtime → features}/query/context.d.ts +0 -0
- /package/dist/{runtime → features}/query/context.js +0 -0
- /package/dist/{runtime → features}/query/documents +0 -0
- /package/dist/{runtime → features}/query/documents.d.ts +0 -0
- /package/dist/{runtime → features}/query/errors +0 -0
- /package/dist/{runtime → features}/query/errors.d.ts +0 -0
- /package/dist/{runtime → features}/query/errors.js +0 -0
- /package/dist/{runtime → features}/query/handles +0 -0
- /package/dist/{runtime → features}/query/handles.d.ts +0 -0
- /package/dist/{runtime → features}/query/handles.js +0 -0
- /package/dist/{runtime → features}/query/locale-options +0 -0
- /package/dist/{runtime → features}/query/locale-options.d.ts +0 -0
- /package/dist/{runtime → features}/query/locale-options.js +0 -0
- /package/dist/{runtime → features}/query/localized-docs +0 -0
- /package/dist/{runtime → features}/query/navigation +0 -0
- /package/dist/{runtime → features}/query/pagination +0 -0
- /package/dist/{runtime → features}/query/pagination.d.ts +0 -0
- /package/dist/{runtime → features}/query/pagination.js +0 -0
- /package/dist/{runtime → features}/query/populate +0 -0
- /package/dist/{runtime → features}/query/populate.d.ts +0 -0
- /package/dist/{runtime → features}/query/public-limits +0 -0
- /package/dist/{runtime → features}/query/public-limits.d.ts +0 -0
- /package/dist/{runtime → features}/query/public-limits.js +0 -0
- /package/dist/{runtime → features}/query/resolve +0 -0
- /package/dist/{runtime → features}/query/resolve.d.ts +0 -0
- /package/dist/{runtime → features}/query/resolve.js +0 -0
- /package/dist/{runtime → features}/query/responses +0 -0
- /package/dist/{runtime → features}/query/responses.d.ts +0 -0
- /package/dist/{runtime → features}/query/responses.js +0 -0
- /package/dist/{runtime → features}/query/routes +0 -0
- /package/dist/{runtime → features}/query/routes.d.ts +0 -0
- /package/dist/{runtime → features}/query/routes.js +0 -0
- /package/dist/{runtime → features}/query/unified +0 -0
- /package/dist/{runtime → features}/query/variants +0 -0
- /package/dist/{runtime → features}/query/variants.d.ts +0 -0
|
@@ -71,28 +71,19 @@ const collectDerivedReferenceIssues = (references, value, resolveReference, issu
|
|
|
71
71
|
}
|
|
72
72
|
};
|
|
73
73
|
const internalDocumentFields = /* @__PURE__ */ new Set([
|
|
74
|
-
"
|
|
75
|
-
"
|
|
76
|
-
"
|
|
77
|
-
"
|
|
78
|
-
"
|
|
79
|
-
"
|
|
80
|
-
"
|
|
81
|
-
"
|
|
82
|
-
"
|
|
83
|
-
"
|
|
84
|
-
"
|
|
85
|
-
"
|
|
86
|
-
"
|
|
87
|
-
"_resolvedLocale",
|
|
88
|
-
"_requestedLocale",
|
|
89
|
-
"_fallback",
|
|
90
|
-
"_availableLocales",
|
|
91
|
-
"_variantPaths",
|
|
92
|
-
"_resolvedRefs",
|
|
93
|
-
"_source",
|
|
94
|
-
"body",
|
|
95
|
-
"draft"
|
|
74
|
+
"id",
|
|
75
|
+
"file",
|
|
76
|
+
"path",
|
|
77
|
+
"type",
|
|
78
|
+
"collection",
|
|
79
|
+
"canonicalKey",
|
|
80
|
+
"partial",
|
|
81
|
+
"draft",
|
|
82
|
+
"dir",
|
|
83
|
+
"locale",
|
|
84
|
+
"navigationFile",
|
|
85
|
+
"resolved",
|
|
86
|
+
"body"
|
|
96
87
|
]);
|
|
97
88
|
const toUserContentDocument = (document) => {
|
|
98
89
|
const userDocument = {};
|
|
@@ -104,7 +95,7 @@ const toUserContentDocument = (document) => {
|
|
|
104
95
|
return userDocument;
|
|
105
96
|
};
|
|
106
97
|
const validateNavigationDocument = (document) => {
|
|
107
|
-
if (!document.
|
|
98
|
+
if (!document.navigationFile) {
|
|
108
99
|
return ok(void 0);
|
|
109
100
|
}
|
|
110
101
|
const invalidFields = [];
|
|
@@ -129,7 +120,7 @@ const validateNavigationDocument = (document) => {
|
|
|
129
120
|
if (invalidFields.length) {
|
|
130
121
|
return fail(createContentError(
|
|
131
122
|
"INVALID_NAVIGATION_YAML",
|
|
132
|
-
document.
|
|
123
|
+
document.file?.path || document.id,
|
|
133
124
|
"malformed .navigation.yml",
|
|
134
125
|
invalidFields.join("; ")
|
|
135
126
|
));
|
|
@@ -137,13 +128,10 @@ const validateNavigationDocument = (document) => {
|
|
|
137
128
|
return ok(void 0);
|
|
138
129
|
};
|
|
139
130
|
export const getCanonicalContentId = (document, locales = []) => {
|
|
140
|
-
if (typeof document.
|
|
141
|
-
return document.
|
|
131
|
+
if (typeof document.canonicalKey === "string" && document.canonicalKey.length) {
|
|
132
|
+
return document.canonicalKey;
|
|
142
133
|
}
|
|
143
|
-
|
|
144
|
-
return document._canonicalKey;
|
|
145
|
-
}
|
|
146
|
-
const file = (document._file || "").replace(/^\/+/, "");
|
|
134
|
+
const file = (document.file?.path || "").replace(/^\/+/, "");
|
|
147
135
|
const parts = file.split("/").filter(Boolean);
|
|
148
136
|
const normalized = parts[0] && locales.includes(parts[0]) ? parts.slice(1) : parts;
|
|
149
137
|
return normalized.join("/").replace(/\.[^.]+$/, "");
|
|
@@ -153,10 +141,10 @@ export const validateCollectionDocument = (document, collections = {}) => {
|
|
|
153
141
|
if (!navigationResult.ok) {
|
|
154
142
|
return navigationResult;
|
|
155
143
|
}
|
|
156
|
-
if (!document.
|
|
144
|
+
if (!document.collection) {
|
|
157
145
|
return ok(document);
|
|
158
146
|
}
|
|
159
|
-
const collection = getCollectionConfig(document.
|
|
147
|
+
const collection = getCollectionConfig(document.collection, collections);
|
|
160
148
|
const schema = collection?.schema;
|
|
161
149
|
if (!hasSafeParse(schema)) {
|
|
162
150
|
return ok(document);
|
|
@@ -172,7 +160,7 @@ export const validateCollectionDocument = (document, collections = {}) => {
|
|
|
172
160
|
const path = issue.path?.length ? issue.path.join(".") : "document";
|
|
173
161
|
return `${path}: ${issue.message}`;
|
|
174
162
|
}).join("; ");
|
|
175
|
-
const message = `Invalid content in ${document.
|
|
163
|
+
const message = `Invalid content in ${document.file?.path || document.id}${details ? ` (${details})` : ""}`;
|
|
176
164
|
if (collection?.strict === false) {
|
|
177
165
|
console.warn(message);
|
|
178
166
|
return ok(document);
|
|
@@ -181,32 +169,30 @@ export const validateCollectionDocument = (document, collections = {}) => {
|
|
|
181
169
|
"SCHEMA_VALIDATION_FAILED",
|
|
182
170
|
message,
|
|
183
171
|
{
|
|
184
|
-
file: document.
|
|
185
|
-
collection: document.
|
|
172
|
+
file: document.file?.path || document.id,
|
|
173
|
+
collection: document.collection,
|
|
186
174
|
...details ? { details } : {}
|
|
187
175
|
}
|
|
188
176
|
));
|
|
189
177
|
};
|
|
190
178
|
export const validateContentGraph = (contents, config) => {
|
|
191
179
|
const locales = config.locales || [];
|
|
192
|
-
const docs = contents.filter((content) => content && content.
|
|
193
|
-
const routeEntries = docs.filter((content) => !content.
|
|
194
|
-
const markdownEntries = routeEntries.filter((content) => content.
|
|
180
|
+
const docs = contents.filter((content) => content && content.path);
|
|
181
|
+
const routeEntries = docs.filter((content) => !content.partial && !content.navigationFile);
|
|
182
|
+
const markdownEntries = routeEntries.filter((content) => content.type === "markdown");
|
|
195
183
|
const idsByLocale = /* @__PURE__ */ new Map();
|
|
196
184
|
const pathsByLocale = /* @__PURE__ */ new Map();
|
|
197
185
|
const referenceTargets = buildReferenceTargets(routeEntries, locales);
|
|
198
186
|
const targetCollections = /* @__PURE__ */ new Map();
|
|
199
|
-
const variantsByCanonicalKey = /* @__PURE__ */ new Map();
|
|
200
187
|
const markdownVariantsByCanonicalKey = /* @__PURE__ */ new Map();
|
|
201
|
-
const explicitIdsByValue = /* @__PURE__ */ new Map();
|
|
202
188
|
const refsByValue = /* @__PURE__ */ new Map();
|
|
203
189
|
for (const document of routeEntries) {
|
|
204
|
-
const canonicalId = document.
|
|
205
|
-
if (!canonicalId || !document.
|
|
190
|
+
const canonicalId = document.canonicalKey || getCanonicalContentId(document, locales);
|
|
191
|
+
if (!canonicalId || !document.collection) {
|
|
206
192
|
continue;
|
|
207
193
|
}
|
|
208
194
|
const collections = targetCollections.get(canonicalId) || /* @__PURE__ */ new Set();
|
|
209
|
-
collections.add(document.
|
|
195
|
+
collections.add(document.collection);
|
|
210
196
|
targetCollections.set(canonicalId, collections);
|
|
211
197
|
}
|
|
212
198
|
for (const issue of collectTranslatedSlugValidationIssues(markdownEntries, {
|
|
@@ -222,85 +208,44 @@ export const validateContentGraph = (contents, config) => {
|
|
|
222
208
|
}
|
|
223
209
|
return fail(createContentError("TRANSLATED_SLUG_CONFLICT", issue.file, issue.reason, issue.details));
|
|
224
210
|
}
|
|
225
|
-
for (const document of routeEntries) {
|
|
226
|
-
const variantKey = document._canonicalKey || getCanonicalContentId(document, locales);
|
|
227
|
-
const siblings = variantsByCanonicalKey.get(variantKey) || [];
|
|
228
|
-
siblings.push(document);
|
|
229
|
-
variantsByCanonicalKey.set(variantKey, siblings);
|
|
230
|
-
}
|
|
231
211
|
for (const document of markdownEntries) {
|
|
232
|
-
const variantKey = document.
|
|
212
|
+
const variantKey = document.canonicalKey || getCanonicalContentId(document, locales);
|
|
233
213
|
const siblings = markdownVariantsByCanonicalKey.get(variantKey) || [];
|
|
234
214
|
siblings.push(document);
|
|
235
215
|
markdownVariantsByCanonicalKey.set(variantKey, siblings);
|
|
236
216
|
}
|
|
237
|
-
for (const [variantKey, variants] of variantsByCanonicalKey.entries()) {
|
|
238
|
-
const explicitIds = Array.from(new Set(variants.map((document) => typeof document.id === "string" && document.id.length ? document.id : void 0).filter((value) => Boolean(value))));
|
|
239
|
-
if (explicitIds.length > 1) {
|
|
240
|
-
return fail(createContentError(
|
|
241
|
-
"CONFLICTING_REFS",
|
|
242
|
-
variants[0]?._file || variants[0]?._id || variantKey,
|
|
243
|
-
`conflicting explicit ids across locale variants for canonical key "${variantKey}"`,
|
|
244
|
-
explicitIds.join(", ")
|
|
245
|
-
));
|
|
246
|
-
}
|
|
247
|
-
if (explicitIds.length === 1 && variants.some((document) => document.id !== explicitIds[0])) {
|
|
248
|
-
return fail(createContentError(
|
|
249
|
-
"CONFLICTING_REFS",
|
|
250
|
-
variants[0]?._file || variants[0]?._id || variantKey,
|
|
251
|
-
`explicit id "${explicitIds[0]}" must be declared consistently across locale variants for canonical key "${variantKey}"`
|
|
252
|
-
));
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
for (const document of routeEntries) {
|
|
256
|
-
const explicitId = typeof document.id === "string" && document.id.length ? document.id : void 0;
|
|
257
|
-
if (!explicitId) {
|
|
258
|
-
continue;
|
|
259
|
-
}
|
|
260
|
-
const variantKey = document._canonicalKey || getCanonicalContentId(document, locales);
|
|
261
|
-
const previous = explicitIdsByValue.get(explicitId);
|
|
262
|
-
if (previous && previous.variantKey !== variantKey) {
|
|
263
|
-
return fail(createContentError(
|
|
264
|
-
"CONFLICTING_REFS",
|
|
265
|
-
document._file || document._id,
|
|
266
|
-
`duplicate explicit id "${explicitId}"`,
|
|
267
|
-
`conflicts with ${previous.document._file || previous.document._id}`
|
|
268
|
-
));
|
|
269
|
-
}
|
|
270
|
-
explicitIdsByValue.set(explicitId, { document, variantKey });
|
|
271
|
-
}
|
|
272
217
|
for (const [variantKey, variants] of markdownVariantsByCanonicalKey.entries()) {
|
|
273
218
|
const explicitRefs = Array.from(new Set(variants.map((document) => typeof document.ref === "string" && document.ref.length ? document.ref : void 0).filter((value) => Boolean(value))));
|
|
274
219
|
if (explicitRefs.length > 1) {
|
|
275
220
|
return fail(createContentError(
|
|
276
221
|
"CONFLICTING_REFS",
|
|
277
|
-
variants[0]?.
|
|
222
|
+
variants[0]?.file?.path || variants[0]?.id || variantKey,
|
|
278
223
|
`conflicting refs across locale variants for canonical key "${variantKey}"`,
|
|
279
224
|
explicitRefs.join(", ")
|
|
280
225
|
));
|
|
281
226
|
}
|
|
282
227
|
}
|
|
283
228
|
for (const document of routeEntries) {
|
|
284
|
-
const canonicalId = document.
|
|
285
|
-
const localeKey = `${canonicalId}:${document.
|
|
229
|
+
const canonicalId = document.canonicalKey || getCanonicalContentId(document, locales);
|
|
230
|
+
const localeKey = `${canonicalId}:${document.locale || ""}`;
|
|
286
231
|
if (idsByLocale.has(localeKey)) {
|
|
287
232
|
const previous = idsByLocale.get(localeKey);
|
|
288
233
|
return fail(createContentError(
|
|
289
234
|
"DUPLICATE_CANONICAL_ID",
|
|
290
|
-
document.
|
|
291
|
-
`duplicate canonical id "${canonicalId}" for locale "${document.
|
|
292
|
-
`conflicts with ${previous.
|
|
235
|
+
document.file?.path || document.id,
|
|
236
|
+
`duplicate canonical id "${canonicalId}" for locale "${document.locale || "default"}"`,
|
|
237
|
+
`conflicts with ${previous.file?.path || previous.id}`
|
|
293
238
|
));
|
|
294
239
|
}
|
|
295
240
|
idsByLocale.set(localeKey, document);
|
|
296
|
-
const pathKey = `${document.
|
|
241
|
+
const pathKey = `${document.locale || ""}:${document.path || ""}`;
|
|
297
242
|
if (pathsByLocale.has(pathKey)) {
|
|
298
243
|
const previous = pathsByLocale.get(pathKey);
|
|
299
244
|
return fail(createContentError(
|
|
300
245
|
"DUPLICATE_LOCALIZED_PATH",
|
|
301
|
-
document.
|
|
302
|
-
`duplicate localized path "${document.
|
|
303
|
-
`conflicts with ${previous.
|
|
246
|
+
document.file?.path || document.id,
|
|
247
|
+
`duplicate localized path "${document.path}" for locale "${document.locale || "default"}"`,
|
|
248
|
+
`conflicts with ${previous.file?.path || previous.id}`
|
|
304
249
|
));
|
|
305
250
|
}
|
|
306
251
|
pathsByLocale.set(pathKey, document);
|
|
@@ -309,7 +254,7 @@ export const validateContentGraph = (contents, config) => {
|
|
|
309
254
|
if (typeof document.ref !== "undefined" && (typeof document.ref !== "string" || !document.ref.length)) {
|
|
310
255
|
return fail(createContentError(
|
|
311
256
|
"INVALID_REF_VALUE",
|
|
312
|
-
document.
|
|
257
|
+
document.file?.path || document.id,
|
|
313
258
|
"ref must be a non-empty string"
|
|
314
259
|
));
|
|
315
260
|
}
|
|
@@ -318,21 +263,21 @@ export const validateContentGraph = (contents, config) => {
|
|
|
318
263
|
continue;
|
|
319
264
|
}
|
|
320
265
|
const previous = refsByValue.get(ref);
|
|
321
|
-
if (previous && (previous.
|
|
266
|
+
if (previous && (previous.canonicalKey || getCanonicalContentId(previous, locales)) !== (document.canonicalKey || getCanonicalContentId(document, locales))) {
|
|
322
267
|
return fail(createContentError(
|
|
323
268
|
"CONFLICTING_REFS",
|
|
324
|
-
document.
|
|
269
|
+
document.file?.path || document.id,
|
|
325
270
|
`duplicate ref "${ref}"`,
|
|
326
|
-
`conflicts with ${previous.
|
|
271
|
+
`conflicts with ${previous.file?.path || previous.id}`
|
|
327
272
|
));
|
|
328
273
|
}
|
|
329
274
|
refsByValue.set(ref, document);
|
|
330
275
|
}
|
|
331
276
|
for (const document of docs) {
|
|
332
|
-
if (!document.
|
|
277
|
+
if (!document.collection) {
|
|
333
278
|
continue;
|
|
334
279
|
}
|
|
335
|
-
const collection = getCollectionConfig(document.
|
|
280
|
+
const collection = getCollectionConfig(document.collection, config.collections);
|
|
336
281
|
const references = collection?.references;
|
|
337
282
|
const schema = collection?.schema;
|
|
338
283
|
if (!schema && !references) {
|
|
@@ -356,7 +301,7 @@ export const validateContentGraph = (contents, config) => {
|
|
|
356
301
|
}
|
|
357
302
|
const error = createContentError(
|
|
358
303
|
"SCHEMA_VALIDATION_FAILED",
|
|
359
|
-
document.
|
|
304
|
+
document.file?.path || document.id,
|
|
360
305
|
"unresolved content references",
|
|
361
306
|
issues.join("; ")
|
|
362
307
|
);
|
|
@@ -1,11 +1,21 @@
|
|
|
1
|
-
import { type ContentProvider } from '../public/provider';
|
|
2
|
-
export interface
|
|
1
|
+
import { type ContentProvider, type ContentProviderCapabilities } from '../public/provider';
|
|
2
|
+
export interface ProviderContractSuiteOptions {
|
|
3
3
|
name: string;
|
|
4
4
|
expectedProviderName: string;
|
|
5
5
|
loadProvider: () => Promise<ContentProvider>;
|
|
6
6
|
createEvent: () => any;
|
|
7
|
+
/**
|
|
8
|
+
* The capabilities the provider under test declares. Each capability block
|
|
9
|
+
* runs its positive assertions only when the matching flag is `true`.
|
|
10
|
+
* Operation capabilities (`routeBackedCollections`, `navigation`,
|
|
11
|
+
* `surroundings`, `searchSections`, `sitemap`) and the query sub-capabilities
|
|
12
|
+
* (`query.limit`/`skip`/`count`) additionally assert the typed provider error
|
|
13
|
+
* when declared `false`; descriptive flags (`dataCollections`,
|
|
14
|
+
* `localizedRoutes`, `translatedSlugs`) only gate their positive block.
|
|
15
|
+
*/
|
|
16
|
+
expectedCapabilities: ContentProviderCapabilities;
|
|
7
17
|
collectNavPaths?: (items: Array<{
|
|
8
|
-
|
|
18
|
+
unprefixedPath?: string;
|
|
9
19
|
children?: any[];
|
|
10
20
|
}>) => string[];
|
|
11
21
|
}
|
|
@@ -18,7 +28,7 @@ export interface AuthorDependencyContractOptions {
|
|
|
18
28
|
key: string;
|
|
19
29
|
}>;
|
|
20
30
|
}
|
|
21
|
-
export declare const
|
|
31
|
+
export declare const runProviderContractSuite: ({ name, expectedProviderName, loadProvider, createEvent, expectedCapabilities, collectNavPaths }: ProviderContractSuiteOptions) => void;
|
|
22
32
|
export declare const createAuthorDependencyContractProvider: () => {
|
|
23
33
|
fixture: import("./provider-fixture").ProviderFixture;
|
|
24
34
|
provider: ContentProvider & {
|
|
@@ -1,42 +1,53 @@
|
|
|
1
1
|
import { expect, test } from "vitest";
|
|
2
|
-
import { contentProviderResultMarker } from "../public/provider";
|
|
2
|
+
import { contentProviderResultMarker, toContentProviderNavigationQuery, toContentProviderQuery } from "../public/provider";
|
|
3
3
|
import { createAuthorDependencyProviderFixture, createFixtureContentProvider, createProviderFixtureEvent, getProviderFixtureCacheHint } from "./provider-fixture.js";
|
|
4
4
|
const defaultCollectNavPaths = (items) => items.flatMap((item) => [
|
|
5
|
-
item.
|
|
5
|
+
item.unprefixedPath,
|
|
6
6
|
...defaultCollectNavPaths(item.children || [])
|
|
7
7
|
].filter(Boolean));
|
|
8
8
|
const unwrapProviderResult = (value) => value && typeof value === "object" && value[contentProviderResultMarker] ? value.data : value;
|
|
9
|
-
|
|
9
|
+
const expectUnsupportedOperation = (run, operation) => expect(Promise.resolve().then(run)).rejects.toMatchObject({
|
|
10
|
+
statusCode: 400,
|
|
11
|
+
statusMessage: "unsupported_provider_operation",
|
|
12
|
+
data: { code: "unsupported_provider_operation", operation }
|
|
13
|
+
});
|
|
14
|
+
const expectUnsupportedQueryShape = (run, field) => expect(Promise.resolve().then(run)).rejects.toMatchObject({
|
|
15
|
+
statusCode: 400,
|
|
16
|
+
statusMessage: "unsupported_query_shape",
|
|
17
|
+
data: { code: "unsupported_query_shape", field }
|
|
18
|
+
});
|
|
19
|
+
export const runProviderContractSuite = ({
|
|
10
20
|
name,
|
|
11
21
|
expectedProviderName,
|
|
12
22
|
loadProvider,
|
|
13
23
|
createEvent,
|
|
24
|
+
expectedCapabilities,
|
|
14
25
|
collectNavPaths = defaultCollectNavPaths
|
|
15
26
|
}) => {
|
|
27
|
+
const caps = expectedCapabilities;
|
|
16
28
|
test(`${name} exposes explicit capabilities`, async () => {
|
|
17
29
|
const provider = await loadProvider();
|
|
18
30
|
expect(provider.name).toBe(expectedProviderName);
|
|
19
31
|
expect(provider.capabilities).toMatchObject({
|
|
20
|
-
|
|
21
|
-
dataCollections: true,
|
|
22
|
-
localizedRoutes: true,
|
|
23
|
-
translatedSlugs: true,
|
|
24
|
-
navigation: true,
|
|
25
|
-
surroundings: true,
|
|
26
|
-
searchSections: true,
|
|
27
|
-
sitemap: true,
|
|
32
|
+
...caps,
|
|
28
33
|
query: {
|
|
29
|
-
limit:
|
|
30
|
-
skip:
|
|
31
|
-
count:
|
|
34
|
+
limit: caps.query.limit,
|
|
35
|
+
skip: caps.query.skip,
|
|
36
|
+
count: caps.query.count
|
|
32
37
|
}
|
|
33
38
|
});
|
|
34
|
-
expect(provider.capabilities.query.operators).
|
|
35
|
-
|
|
39
|
+
expect(provider.capabilities.query.operators).toEqual(
|
|
40
|
+
expect.arrayContaining(caps.query.operators)
|
|
41
|
+
);
|
|
36
42
|
});
|
|
37
43
|
test(`${name} returns complete localized page and route metadata`, async () => {
|
|
38
44
|
const provider = await loadProvider();
|
|
39
45
|
const event = createEvent();
|
|
46
|
+
if (!caps.routeBackedCollections) {
|
|
47
|
+
await expectUnsupportedOperation(() => provider.page?.(event, "docs", "/de/dokumentation/einstieg"), "route-backed pages");
|
|
48
|
+
await expectUnsupportedOperation(() => provider.routeMeta?.(event, "docs", "/de/dokumentation/einstieg", { locale: "de" }), "route metadata");
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
40
51
|
const page = unwrapProviderResult(await provider.page?.(event, "docs", "/de/dokumentation/einstieg"));
|
|
41
52
|
expect(page).toMatchObject({
|
|
42
53
|
title: "Einstieg",
|
|
@@ -61,43 +72,62 @@ export const runSaasProviderFixtureContractSuite = ({
|
|
|
61
72
|
locale: "de"
|
|
62
73
|
})
|
|
63
74
|
});
|
|
64
|
-
});
|
|
65
|
-
test(`${name} supports localized page misses without fallback routes`, async () => {
|
|
66
|
-
const provider = await loadProvider();
|
|
67
75
|
const miss = unwrapProviderResult(await provider.page?.(createEvent(), "docs", "/de/dokumentation/not-found"));
|
|
68
76
|
expect(miss).toBeNull();
|
|
69
77
|
});
|
|
70
78
|
test(`${name} supports list queries with locale, ordering, limit, count, and projection`, async () => {
|
|
71
79
|
const provider = await loadProvider();
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
80
|
+
if (!caps.query.limit) {
|
|
81
|
+
await expectUnsupportedQueryShape(() => provider.query(createEvent(), toContentProviderQuery({
|
|
82
|
+
collection: "posts",
|
|
83
|
+
resolveLocale: { locale: "de", fallback: false },
|
|
84
|
+
limit: 1
|
|
85
|
+
})), "limit");
|
|
86
|
+
} else {
|
|
87
|
+
const response = unwrapProviderResult(await provider.query(createEvent(), toContentProviderQuery({
|
|
88
|
+
collection: "posts",
|
|
89
|
+
resolveLocale: { locale: "de", fallback: false },
|
|
90
|
+
sort: [{ date: -1 }],
|
|
91
|
+
limit: 1,
|
|
92
|
+
only: ["title", "path", "locale"]
|
|
93
|
+
})));
|
|
94
|
+
expect(response.result).toEqual([
|
|
95
|
+
{
|
|
96
|
+
title: "Mehrsprachiges Onboarding",
|
|
97
|
+
path: "/magazin/mehrsprachiges-onboarding",
|
|
98
|
+
locale: "de"
|
|
99
|
+
}
|
|
100
|
+
]);
|
|
101
|
+
expect(typeof response.total).toBe("number");
|
|
102
|
+
}
|
|
103
|
+
if (!caps.query.count) {
|
|
104
|
+
await expectUnsupportedQueryShape(() => provider.query(createEvent(), toContentProviderQuery({
|
|
105
|
+
collection: "posts",
|
|
106
|
+
resolveLocale: { locale: "de", fallback: false },
|
|
107
|
+
count: true
|
|
108
|
+
})), "count");
|
|
109
|
+
} else {
|
|
110
|
+
const countResponse = unwrapProviderResult(await provider.query(createEvent(), toContentProviderQuery({
|
|
111
|
+
collection: "posts",
|
|
112
|
+
resolveLocale: { locale: "de", fallback: false },
|
|
113
|
+
count: true
|
|
114
|
+
})));
|
|
115
|
+
expect(countResponse).toEqual({ result: 1 });
|
|
116
|
+
}
|
|
93
117
|
});
|
|
94
|
-
test(`${name} produces navigation
|
|
118
|
+
test(`${name} produces navigation entries`, async () => {
|
|
95
119
|
const provider = await loadProvider();
|
|
96
120
|
const event = createEvent();
|
|
121
|
+
if (!caps.navigation) {
|
|
122
|
+
await expectUnsupportedOperation(() => provider.navigation?.(event, "docs", { locale: "de" }), "navigation");
|
|
123
|
+
const wire = toContentProviderNavigationQuery({ where: { locale: "de" } });
|
|
124
|
+
await expectUnsupportedOperation(() => provider.navigationQuery?.(event, wire.query, wire.options), "navigation");
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
97
127
|
const nav = unwrapProviderResult(await provider.navigation?.(event, "docs", { locale: "de" }));
|
|
98
128
|
expect(collectNavPaths(nav || [])).toContain("/dokumentation/einstieg");
|
|
99
129
|
expect(nav?.[0]).toEqual(expect.objectContaining({
|
|
100
|
-
|
|
130
|
+
locale: "de",
|
|
101
131
|
ref: expect.any(String),
|
|
102
132
|
stableId: expect.any(String)
|
|
103
133
|
}));
|
|
@@ -112,27 +142,54 @@ export const runSaasProviderFixtureContractSuite = ({
|
|
|
112
142
|
title: expect.any(String),
|
|
113
143
|
description: expect.any(String)
|
|
114
144
|
}));
|
|
115
|
-
const
|
|
145
|
+
const globalNavWire = toContentProviderNavigationQuery({ where: { locale: "de" } });
|
|
146
|
+
const globalNav = unwrapProviderResult(await provider.navigationQuery?.(event, globalNavWire.query, globalNavWire.options));
|
|
116
147
|
const globalNavPaths = collectNavPaths(globalNav || []);
|
|
117
148
|
expect(globalNavPaths).toContain("/dokumentation/einstieg");
|
|
118
149
|
expect(globalNavPaths.length).toBeGreaterThan(0);
|
|
119
|
-
const
|
|
150
|
+
const resolvedLocaleNavWire = toContentProviderNavigationQuery({
|
|
120
151
|
collection: "docs",
|
|
121
152
|
resolveLocale: { locale: "de", fallback: false, exact: true }
|
|
122
|
-
})
|
|
153
|
+
});
|
|
154
|
+
const resolvedLocaleNav = unwrapProviderResult(await provider.navigationQuery?.(event, resolvedLocaleNavWire.query, resolvedLocaleNavWire.options));
|
|
123
155
|
expect(collectNavPaths(resolvedLocaleNav || [])).toContain("/dokumentation/einstieg");
|
|
156
|
+
expect(JSON.stringify(nav)).not.toContain("Draft Roadmap");
|
|
157
|
+
});
|
|
158
|
+
test(`${name} produces surroundings entries`, async () => {
|
|
159
|
+
const provider = await loadProvider();
|
|
160
|
+
const event = createEvent();
|
|
161
|
+
if (!caps.surroundings) {
|
|
162
|
+
await expectUnsupportedOperation(() => provider.surroundings?.(event, "docs", "/de/dokumentation/einstieg/installation", { locale: "de" }), "surroundings");
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
124
165
|
const surround = unwrapProviderResult(await provider.surroundings?.(event, "docs", "/de/dokumentation/einstieg/installation", { locale: "de" }));
|
|
125
166
|
expect(surround).toHaveLength(2);
|
|
126
|
-
expect(surround?.map((item) => item?.
|
|
167
|
+
expect(surround?.map((item) => item?.unprefixedPath)).toContain("/dokumentation/einstieg/alltag");
|
|
168
|
+
});
|
|
169
|
+
test(`${name} produces search sections`, async () => {
|
|
170
|
+
const provider = await loadProvider();
|
|
171
|
+
const event = createEvent();
|
|
172
|
+
if (!caps.searchSections) {
|
|
173
|
+
await expectUnsupportedOperation(() => provider.searchSections?.(event, "docs", { locale: "de" }), "search sections");
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
127
176
|
const sections = unwrapProviderResult(await provider.searchSections?.(event, "docs", { locale: "de" }));
|
|
128
177
|
expect(sections?.some((section) => section.id.startsWith("/de/dokumentation/einstieg") || section.id.startsWith("/dokumentation/einstieg"))).toBe(true);
|
|
129
178
|
expect(JSON.stringify(sections)).not.toContain("Draft Roadmap");
|
|
179
|
+
});
|
|
180
|
+
test(`${name} produces sitemap entries`, async () => {
|
|
181
|
+
const provider = await loadProvider();
|
|
182
|
+
const event = createEvent();
|
|
183
|
+
if (!caps.sitemap) {
|
|
184
|
+
await expectUnsupportedOperation(() => provider.sitemapEntries?.(event, { include: ["docs"] }), "sitemap entries");
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
130
187
|
const sitemap = unwrapProviderResult(await provider.sitemapEntries?.(event, { include: ["docs"] }));
|
|
131
188
|
expect(sitemap?.some((entry) => entry.loc.endsWith("/de/dokumentation/einstieg"))).toBe(true);
|
|
132
189
|
expect(JSON.stringify(sitemap)).not.toContain("/docs/draft-roadmap");
|
|
133
|
-
expect(JSON.stringify(nav)).not.toContain("Draft Roadmap");
|
|
134
190
|
});
|
|
135
191
|
test(`${name} emits cache hints for rendered content`, async () => {
|
|
192
|
+
if (!caps.routeBackedCollections) return;
|
|
136
193
|
const provider = await loadProvider();
|
|
137
194
|
const event = createEvent();
|
|
138
195
|
await provider.page?.(event, "posts", "/de/magazin/mehrsprachiges-onboarding");
|
|
@@ -154,38 +211,34 @@ export const runSaasProviderFixtureContractSuite = ({
|
|
|
154
211
|
}
|
|
155
212
|
});
|
|
156
213
|
test(`${name} supports data-only collection reads and rejects data-only sitemap access`, async () => {
|
|
214
|
+
if (!caps.dataCollections) return;
|
|
157
215
|
const provider = await loadProvider();
|
|
158
|
-
const response = unwrapProviderResult(await provider.query(createEvent(), {
|
|
216
|
+
const response = unwrapProviderResult(await provider.query(createEvent(), toContentProviderQuery({
|
|
159
217
|
collection: "versions",
|
|
160
218
|
resolveLocale: { locale: "en", fallback: false },
|
|
161
219
|
sort: [{ date: -1 }]
|
|
162
|
-
}));
|
|
220
|
+
})));
|
|
163
221
|
expect(response.result[0]?.title).toBe("Launch readiness");
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
222
|
+
if (caps.sitemap) {
|
|
223
|
+
await expect(provider.sitemapEntries?.(createEvent(), { include: ["versions"] })).rejects.toMatchObject({
|
|
224
|
+
statusCode: 400,
|
|
225
|
+
statusMessage: "data_collection_sitemap_access",
|
|
226
|
+
data: {
|
|
227
|
+
code: "data_collection_sitemap_access",
|
|
228
|
+
collection: "versions"
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
}
|
|
172
232
|
});
|
|
173
233
|
test(`${name} fails loudly for unsupported query operators and unknown collections`, async () => {
|
|
174
234
|
const provider = await loadProvider();
|
|
175
|
-
|
|
235
|
+
expect(() => toContentProviderQuery({
|
|
176
236
|
collection: "posts",
|
|
177
237
|
where: { title: { $near: "launch" } }
|
|
178
|
-
})).
|
|
179
|
-
|
|
180
|
-
statusMessage: "unsupported_query_operator",
|
|
181
|
-
data: {
|
|
182
|
-
code: "unsupported_query_operator",
|
|
183
|
-
operator: "$near"
|
|
184
|
-
}
|
|
185
|
-
});
|
|
186
|
-
await expect(provider.query(createEvent(), {
|
|
238
|
+
})).toThrow(/Unsupported content query operator: \$near/);
|
|
239
|
+
await expect(provider.query(createEvent(), toContentProviderQuery({
|
|
187
240
|
collection: "missing"
|
|
188
|
-
})).rejects.toMatchObject({
|
|
241
|
+
}))).rejects.toMatchObject({
|
|
189
242
|
statusCode: 400,
|
|
190
243
|
statusMessage: "unknown_collection",
|
|
191
244
|
data: {
|
|
@@ -63,5 +63,5 @@ export declare const createProviderFixtureEvent: (options?: ProviderFixtureEvent
|
|
|
63
63
|
export declare const createFixtureContentProvider: (fixture: ProviderFixture, name?: string) => ContentProvider & {
|
|
64
64
|
cache: ProviderFixtureCacheState;
|
|
65
65
|
};
|
|
66
|
-
export declare const
|
|
66
|
+
export declare const createDefaultProviderFixture: () => ProviderFixture;
|
|
67
67
|
export declare const createAuthorDependencyProviderFixture: () => ProviderFixture;
|