@lupinum/ginko-content 0.1.2 → 0.1.3
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/README.md +18 -4
- package/compatibility.json +1 -1
- package/dist/cli.mjs +317 -294
- package/dist/cms-import/index.js +5 -1
- package/dist/config.d.mts +1 -1
- package/dist/config.mjs +1 -1
- package/dist/core/cache-hints.d.ts +9 -1
- package/dist/core/content/collection.js +1 -1
- package/dist/core/content/path.js +1 -1
- package/dist/core/errors.js +5 -1
- package/dist/core/provider-errors +1 -0
- package/dist/core/provider-errors.d.ts +10 -0
- package/dist/core/provider-errors.js +27 -0
- package/dist/core/query/execute.js +12 -3
- package/dist/core/query/filter.js +2 -2
- package/dist/core/query/lower.js +5 -4
- package/dist/features/navigation/build.js +14 -6
- package/dist/features/navigation/canonical.js +1 -1
- package/dist/features/sitemap/query.js +2 -2
- package/dist/integrations/nitro/ingest.d.ts +3 -3
- package/dist/integrations/nitro/ingest.js +3 -3
- package/dist/integrations/nitro/storage.js +3 -1
- package/dist/module.d.mts +151 -526
- package/dist/module.json +1 -1
- package/dist/module.mjs +1091 -722
- package/dist/parsers/csv.js +4 -3
- package/dist/parsers/index.d.ts +2 -5
- package/dist/parsers/index.js +2 -2
- package/dist/parsers/markdown-plugins.d.ts +1 -0
- package/dist/parsers/markdown-plugins.js +83 -1
- package/dist/parsers/markdown.js +1 -1
- package/dist/public/client.d.ts +3 -2
- package/dist/public/client.js +2 -2
- package/dist/public/provider-errors.d.ts +2 -1
- package/dist/public/provider-errors.js +1 -18
- package/dist/public/provider.d.ts +3 -10
- package/dist/public/server.d.ts +6 -1
- package/dist/public/server.js +33 -0
- package/dist/runtime/agent-paths +1 -0
- package/dist/runtime/agent-paths.d.ts +6 -0
- package/dist/runtime/agent-paths.js +41 -0
- package/dist/runtime/app/components/internal/MarkdownRenderer.d.ts +1 -1
- package/dist/runtime/app/composables/head.d.ts +3 -0
- package/dist/runtime/app/composables/head.js +2 -1
- package/dist/runtime/app/composables/hot-reload +1 -0
- package/dist/runtime/app/composables/hot-reload.d.ts +5 -0
- package/dist/runtime/app/composables/hot-reload.js +15 -0
- package/dist/runtime/app/composables/locale-context.d.ts +1 -1
- package/dist/runtime/app/composables/locale-context.js +2 -1
- package/dist/runtime/app/composables/locale.js +2 -2
- package/dist/runtime/app/composables/search.js +10 -6
- package/dist/runtime/app/composables/use-content-document +1 -0
- package/dist/runtime/app/composables/use-content-document.d.ts +29 -0
- package/dist/runtime/app/composables/use-content-document.js +44 -0
- package/dist/runtime/app/composables/use-content-list +1 -0
- package/dist/runtime/app/composables/use-content-list.d.ts +43 -0
- package/dist/runtime/app/composables/use-content-list.js +98 -0
- package/dist/runtime/app/composables/use-content-navigation +1 -0
- package/dist/runtime/app/composables/use-content-navigation.d.ts +40 -0
- package/dist/runtime/app/composables/use-content-navigation.js +102 -0
- package/dist/runtime/app/composables/use-content-page +1 -0
- package/dist/runtime/app/composables/use-content-page.d.ts +47 -0
- package/dist/runtime/app/composables/use-content-page.js +142 -0
- package/dist/runtime/app/composables/use-content-shared +1 -0
- package/dist/runtime/app/composables/use-content-shared.d.ts +13 -0
- package/dist/runtime/app/composables/use-content-shared.js +29 -0
- package/dist/runtime/app/composables/use-content.d.ts +11 -206
- package/dist/runtime/app/composables/use-content.js +4 -377
- package/dist/runtime/app/plugins/hot-reload +1 -0
- package/dist/runtime/app/plugins/hot-reload.js +6 -0
- package/dist/runtime/query/backlinks +1 -0
- package/dist/runtime/query/backlinks.d.ts +8 -0
- package/dist/runtime/query/backlinks.js +90 -0
- package/dist/runtime/query/context +1 -0
- package/dist/runtime/query/context.d.ts +20 -0
- package/dist/runtime/query/context.js +0 -0
- package/dist/runtime/query/documents +1 -0
- package/dist/runtime/query/documents.d.ts +6 -0
- package/dist/runtime/query/documents.js +98 -0
- package/dist/runtime/query/errors +1 -0
- package/dist/runtime/query/errors.d.ts +1 -0
- package/dist/runtime/query/errors.js +4 -0
- package/dist/runtime/query/handles +1 -0
- package/dist/runtime/query/handles.d.ts +2 -0
- package/dist/runtime/query/handles.js +7 -0
- package/dist/runtime/query/locale-options +1 -0
- package/dist/runtime/query/locale-options.d.ts +5 -0
- package/dist/runtime/query/locale-options.js +14 -0
- package/dist/runtime/query/localized-docs +1 -0
- package/dist/runtime/query/localized-docs.d.ts +17 -0
- package/dist/runtime/query/localized-docs.js +44 -0
- package/dist/runtime/query/navigation +1 -0
- package/dist/runtime/query/navigation.d.ts +22 -0
- package/dist/runtime/query/navigation.js +73 -0
- package/dist/runtime/query/pagination +1 -0
- package/dist/runtime/query/pagination.d.ts +7 -0
- package/dist/runtime/query/pagination.js +78 -0
- package/dist/runtime/query/populate +1 -0
- package/dist/runtime/query/populate.d.ts +9 -0
- package/dist/runtime/query/populate.js +106 -0
- package/dist/runtime/query/responses +1 -0
- package/dist/runtime/query/responses.d.ts +10 -0
- package/dist/runtime/query/responses.js +47 -0
- package/dist/runtime/query/unified.d.ts +4 -20
- package/dist/runtime/query/unified.js +14 -544
- package/dist/runtime/query/variants +1 -0
- package/dist/runtime/query/variants.d.ts +11 -0
- package/dist/runtime/query/variants.js +36 -0
- package/dist/runtime/server/agent-http +1 -0
- package/dist/runtime/server/agent-http.d.ts +7 -0
- package/dist/runtime/server/agent-http.js +36 -0
- package/dist/runtime/server/agent-markdown +1 -0
- package/dist/runtime/server/agent-markdown.d.ts +83 -0
- package/dist/runtime/server/agent-markdown.js +449 -0
- package/dist/runtime/server/agent-site +1 -0
- package/dist/runtime/server/agent-site.d.ts +38 -0
- package/dist/runtime/server/agent-site.js +273 -0
- package/dist/runtime/server/api/agent-llms +1 -0
- package/dist/runtime/server/api/agent-llms-full +1 -0
- package/dist/runtime/server/api/agent-llms-full.d.ts +2 -0
- package/dist/runtime/server/api/agent-llms-full.js +13 -0
- package/dist/runtime/server/api/agent-llms.d.ts +2 -0
- package/dist/runtime/server/api/agent-llms.js +14 -0
- package/dist/runtime/server/api/agent-raw +1 -0
- package/dist/runtime/server/api/agent-raw.d.ts +2 -0
- package/dist/runtime/server/api/agent-raw.js +17 -0
- package/dist/runtime/server/api/locales.d.ts +2 -2
- package/dist/runtime/server/api/locales.js +4 -2
- package/dist/runtime/server/api/navigation.d.ts +1 -1
- package/dist/runtime/server/api/query.d.ts +1 -1
- package/dist/runtime/server/api/query.js +4 -1
- package/dist/runtime/server/api/revalidate.js +2 -2
- package/dist/runtime/server/api/site-data.d.ts +1 -1
- package/dist/runtime/server/collection-helpers.js +2 -1
- package/dist/runtime/server/middleware/agent-link-headers +1 -0
- package/dist/runtime/server/middleware/agent-link-headers.d.ts +2 -0
- package/dist/runtime/server/middleware/agent-link-headers.js +42 -0
- package/dist/runtime/server/middleware/agent-markdown +1 -0
- package/dist/runtime/server/middleware/agent-markdown.d.ts +2 -0
- package/dist/runtime/server/middleware/agent-markdown.js +43 -0
- package/dist/runtime/server/plugins/sitemap.js +1 -0
- package/dist/runtime/server/provider-query.d.ts +8 -5
- package/dist/runtime/server/provider-query.js +50 -8
- package/dist/runtime/server/provider-result.d.ts +19 -2
- package/dist/runtime/server/providers/filesystem.js +4 -1
- package/dist/runtime/server/providers/index.d.ts +3 -1
- package/dist/runtime/server/providers/index.js +2 -2
- package/dist/runtime/server/query-api.js +2 -1
- package/dist/runtime/server/query-executor.d.ts +3 -2
- package/dist/runtime/server/query-executor.js +13 -5
- package/dist/runtime/server/search.js +1 -1
- package/dist/runtime/server/sitemap-provider.js +40 -1
- package/dist/runtime/server/sitemap.js +3 -2
- package/dist/runtime/transformers/component-resolver.js +2 -1
- package/dist/runtime/utils/content-components.d.ts +0 -5
- package/dist/storage/content.d.ts +2 -9
- package/dist/storage/references.d.ts +1 -8
- package/dist/storage/references.js +9 -4
- package/dist/testing/provider-contract.js +3 -4
- package/dist/testing/provider-fixture.d.ts +3 -1
- package/dist/testing/provider-fixture.js +27 -14
- package/dist/types/config.d.ts +77 -0
- package/dist/types/config.js +23 -0
- package/dist/types/module.d.ts +15 -5
- package/dist/types/query-parts/collections +1 -0
- package/dist/types/query-parts/collections.d.ts +15 -0
- package/dist/types/query-parts/collections.js +0 -0
- package/dist/types/query-parts/public +1 -0
- package/dist/types/query-parts/public.d.ts +202 -0
- package/dist/types/query-parts/public.js +0 -0
- package/dist/types/query-parts/results +1 -0
- package/dist/types/query-parts/results.d.ts +95 -0
- package/dist/types/query-parts/results.js +0 -0
- package/dist/types/query-parts/transport +1 -0
- package/dist/types/query-parts/transport.d.ts +103 -0
- package/dist/types/query-parts/transport.js +0 -0
- package/dist/types/query.d.ts +4 -870
- package/dist/types/query.js +4 -0
- package/dist/types/runtime.d.ts +2 -2
- package/dist/types/virtual.d.ts +54 -0
- package/dist/types.d.mts +2 -2
- package/dist/web-types.json +1 -1
- package/package.json +5 -5
- package/dist/runtime/app/composables/web-socket +0 -1
- package/dist/runtime/app/composables/web-socket.d.ts +0 -3
- package/dist/runtime/app/composables/web-socket.js +0 -65
- package/dist/runtime/app/plugins/ws +0 -1
- package/dist/runtime/app/plugins/ws.js +0 -7
- /package/dist/runtime/app/plugins/{ws.d.ts → hot-reload.d.ts} +0 -0
|
@@ -1,560 +1,30 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
const NAVIGATION_INTERNAL_FIELDS = [
|
|
8
|
-
"_id",
|
|
9
|
-
"_path",
|
|
10
|
-
"_file",
|
|
11
|
-
"_canonicalKey",
|
|
12
|
-
"_locale",
|
|
13
|
-
"_draft",
|
|
14
|
-
"navigation",
|
|
15
|
-
"title"
|
|
16
|
-
];
|
|
17
|
-
const LOCALIZED_DOC_INTERNAL_FIELDS = [
|
|
18
|
-
"_id",
|
|
19
|
-
"_path",
|
|
20
|
-
"_file",
|
|
21
|
-
"_canonicalKey",
|
|
22
|
-
"_locale",
|
|
23
|
-
"_resolvedLocale",
|
|
24
|
-
"_requestedLocale",
|
|
25
|
-
"_fallback",
|
|
26
|
-
"_availableLocales",
|
|
27
|
-
"_variantPaths",
|
|
28
|
-
"_requestedPath",
|
|
29
|
-
"_requestedRoute",
|
|
30
|
-
"_requestedRef",
|
|
31
|
-
"_extension"
|
|
32
|
-
];
|
|
33
|
-
export const navigationSelectFields = (fields = []) => [
|
|
34
|
-
.../* @__PURE__ */ new Set([...NAVIGATION_INTERNAL_FIELDS, ...fields])
|
|
35
|
-
];
|
|
36
|
-
const isNotFoundError = (error) => {
|
|
37
|
-
const statusCode = error?.statusCode ?? error?.response?.status;
|
|
38
|
-
return statusCode === 404;
|
|
39
|
-
};
|
|
40
|
-
const isQueryEnvelope = (response) => Boolean(response && typeof response === "object" && "result" in response);
|
|
41
|
-
const unwrapResponse = (response) => {
|
|
42
|
-
if (!response) return null;
|
|
43
|
-
if (isQueryEnvelope(response)) {
|
|
44
|
-
const result = response.result;
|
|
45
|
-
return result ?? null;
|
|
46
|
-
}
|
|
47
|
-
return response;
|
|
48
|
-
};
|
|
49
|
-
const unwrapFindResponse = (response) => {
|
|
50
|
-
if (!response) {
|
|
51
|
-
return { result: [], total: 0, skip: 0, limit: 0, hasTotal: false };
|
|
52
|
-
}
|
|
53
|
-
if (isQueryEnvelope(response)) {
|
|
54
|
-
const result2 = Array.isArray(response.result) ? response.result : response.result ? [response.result] : [];
|
|
55
|
-
const hasTotal = typeof response.total === "number";
|
|
56
|
-
return {
|
|
57
|
-
result: result2,
|
|
58
|
-
total: hasTotal ? response.total : result2.length,
|
|
59
|
-
skip: typeof response.skip === "number" ? response.skip : 0,
|
|
60
|
-
limit: typeof response.limit === "number" ? response.limit : result2.length,
|
|
61
|
-
hasTotal
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
const result = Array.isArray(response) ? response : [response];
|
|
65
|
-
return { result, total: result.length, skip: 0, limit: result.length, hasTotal: false };
|
|
66
|
-
};
|
|
67
|
-
const unwrapCountResponse = (response) => {
|
|
68
|
-
if (typeof response === "number") {
|
|
69
|
-
return response;
|
|
70
|
-
}
|
|
71
|
-
if (isQueryEnvelope(response) && typeof response.result === "number") {
|
|
72
|
-
return response.result;
|
|
73
|
-
}
|
|
74
|
-
return null;
|
|
75
|
-
};
|
|
76
|
-
const decorate = (doc, collection, runtime, requestedLocale) => {
|
|
77
|
-
if (!doc) return null;
|
|
78
|
-
const collectionI18n = runtime?.collections?.[collection]?.i18n;
|
|
79
|
-
const collectionLocales = collectionI18n && typeof collectionI18n === "object" ? collectionI18n.locales : void 0;
|
|
80
|
-
const collectionDefault = collectionI18n && typeof collectionI18n === "object" ? collectionI18n.defaultLocale : void 0;
|
|
81
|
-
const locales = collectionLocales?.length ? collectionLocales : runtime?.locales?.length ? runtime.locales : [];
|
|
82
|
-
const defaultLocale = collectionDefault || runtime?.defaultLocale;
|
|
83
|
-
const routeMounts = normalizeRouteMounts(runtime?.collections?.[collection]?.route, locales, defaultLocale);
|
|
84
|
-
const hasLocaleConfig = Boolean(locales.length || defaultLocale);
|
|
85
|
-
const page = hasLocaleConfig ? doc : {
|
|
86
|
-
...doc,
|
|
87
|
-
_locale: "",
|
|
88
|
-
_resolvedLocale: void 0,
|
|
89
|
-
_requestedLocale: void 0,
|
|
90
|
-
_variantPaths: void 0,
|
|
91
|
-
_availableLocales: []
|
|
92
|
-
};
|
|
93
|
-
const result = localizePageResult(page, hasLocaleConfig ? requestedLocale : void 0, defaultLocale, locales, routeMounts);
|
|
94
|
-
const fallbackLocale = doc._resolvedLocale || requestedLocale || defaultLocale;
|
|
95
|
-
result.localePaths = decorateLocalePathsWithFallbacks(result.localePaths, locales, fallbackLocale, defaultLocale, routeMounts);
|
|
96
|
-
return result;
|
|
97
|
-
};
|
|
98
|
-
const collectionRouteRoots = (collection, runtime) => {
|
|
99
|
-
const collectionConfig = runtime?.collections?.[collection];
|
|
100
|
-
const collectionI18n = collectionConfig?.i18n;
|
|
101
|
-
const collectionLocales = collectionI18n && typeof collectionI18n === "object" ? collectionI18n.locales : void 0;
|
|
102
|
-
const collectionDefault = collectionI18n && typeof collectionI18n === "object" ? collectionI18n.defaultLocale : void 0;
|
|
103
|
-
const locales = collectionLocales?.length ? collectionLocales : runtime?.locales?.length ? runtime.locales : [];
|
|
104
|
-
const defaultLocale = collectionDefault || runtime?.defaultLocale;
|
|
105
|
-
const routeMounts = normalizeRouteMounts(collectionConfig?.route, locales, defaultLocale);
|
|
106
|
-
return new Set(Object.values(routeMounts || {}).map((value) => normalizeContentPath(value)));
|
|
107
|
-
};
|
|
108
|
-
const isCollectionRouteRoot = (path, collection, runtime) => collectionRouteRoots(collection, runtime).has(normalizeContentPath(path));
|
|
109
|
-
const isAncestorRoutePath = (path, childPath) => {
|
|
110
|
-
const normalized = normalizeContentPath(path);
|
|
111
|
-
const child = normalizeContentPath(childPath);
|
|
112
|
-
return normalized === "/" ? child !== "/" : child.startsWith(`${normalized}/`);
|
|
113
|
-
};
|
|
114
|
-
const isNavigationRootPath = (path, flat) => Boolean(flat[0]?.path && isAncestorRoutePath(path, flat[0].path));
|
|
115
|
-
const collectionDefaultLocale = (collection, runtime) => {
|
|
116
|
-
const collectionI18n = runtime?.collections?.[collection]?.i18n;
|
|
117
|
-
const collectionDefault = collectionI18n && typeof collectionI18n === "object" ? collectionI18n.defaultLocale : void 0;
|
|
118
|
-
return collectionDefault || runtime?.defaultLocale;
|
|
119
|
-
};
|
|
120
|
-
const resolveFallback = (fallback, collection, runtime) => {
|
|
121
|
-
if (fallback !== "default") return fallback;
|
|
122
|
-
return collectionDefaultLocale(collection, runtime);
|
|
123
|
-
};
|
|
124
|
-
const explainResolution = (collection, requestedBy, normalizedBy, requestedLocale, requestedFallback, doc) => {
|
|
125
|
-
const resolvedLocale = doc?.resolved?.locale || doc?.locale;
|
|
126
|
-
return {
|
|
127
|
-
requested: {
|
|
128
|
-
collection,
|
|
129
|
-
by: requestedBy,
|
|
130
|
-
...requestedLocale ? { locale: requestedLocale } : {},
|
|
131
|
-
...requestedFallback !== void 0 ? { fallback: requestedFallback } : {}
|
|
132
|
-
},
|
|
133
|
-
normalized: {
|
|
134
|
-
by: normalizedBy
|
|
135
|
-
},
|
|
136
|
-
matched: {
|
|
137
|
-
found: Boolean(doc),
|
|
138
|
-
collection,
|
|
139
|
-
...doc?.path ? { path: doc.path } : {},
|
|
140
|
-
...doc?.canonicalPath ? { canonicalPath: doc.canonicalPath } : {},
|
|
141
|
-
...doc?.ref ? { ref: doc.ref } : {},
|
|
142
|
-
...resolvedLocale ? { locale: resolvedLocale } : {}
|
|
143
|
-
},
|
|
144
|
-
fallback: {
|
|
145
|
-
used: Boolean(requestedLocale && resolvedLocale && requestedLocale !== resolvedLocale),
|
|
146
|
-
...requestedLocale && resolvedLocale && requestedLocale !== resolvedLocale ? { locale: resolvedLocale } : {}
|
|
147
|
-
}
|
|
148
|
-
};
|
|
149
|
-
};
|
|
150
|
-
const ensureCollectionName = (handle) => {
|
|
151
|
-
if (typeof handle === "string") return handle;
|
|
152
|
-
if (!handle || typeof handle !== "object" || typeof handle.name !== "string") {
|
|
153
|
-
throw new TypeError("query API: expected a string collection name or a collection handle from defineContentConfig({ collections }). Use useContentPage('docs') or config.collections.docs.");
|
|
154
|
-
}
|
|
155
|
-
return handle.name;
|
|
156
|
-
};
|
|
157
|
-
const isRecord = (value) => {
|
|
158
|
-
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
159
|
-
};
|
|
160
|
-
const populateReferenceValue = async (context, target, value, locale, fallback) => {
|
|
161
|
-
if (typeof value !== "string" || !value) {
|
|
162
|
-
return null;
|
|
163
|
-
}
|
|
164
|
-
return one(context, target, {
|
|
165
|
-
by: { ref: value },
|
|
166
|
-
...locale ? { locale } : {},
|
|
167
|
-
...fallback !== void 0 ? { fallback } : {}
|
|
168
|
-
});
|
|
169
|
-
};
|
|
170
|
-
const wildcardReferenceTarget = "*";
|
|
171
|
-
const collectReferenceFieldsByTarget = (source, sourceCollection, runtime) => {
|
|
172
|
-
if (typeof source !== "string") {
|
|
173
|
-
return collectTopLevelReferenceFieldsByTarget(source.schema);
|
|
174
|
-
}
|
|
175
|
-
return runtime?.collections?.[sourceCollection]?.references || {};
|
|
176
|
-
};
|
|
177
|
-
const invertReferenceFields = (references) => {
|
|
178
|
-
const fields = /* @__PURE__ */ new Map();
|
|
179
|
-
for (const [target, targetFields] of Object.entries(references)) {
|
|
180
|
-
for (const field of targetFields) {
|
|
181
|
-
const targets = fields.get(field) || [];
|
|
182
|
-
targets.push(target);
|
|
183
|
-
fields.set(field, targets);
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
return fields;
|
|
187
|
-
};
|
|
188
|
-
const createPopulateTargetMismatchError = (sourceCollection, field, expectedTargets, actualTarget) => new Error([
|
|
189
|
-
`Cannot populate "${sourceCollection}.${field}" from "${actualTarget}".`,
|
|
190
|
-
`Reference metadata declares "${sourceCollection}.${field}" points to ${expectedTargets.map((target) => `"${target}"`).join(" or ")}.`,
|
|
191
|
-
`Change populate.${field} to the declared target collection, or update ${sourceCollection}.schema relation metadata.`
|
|
192
|
-
].join(" "));
|
|
193
|
-
const validatePopulateSpec = (source, sourceCollection, runtime, populate) => {
|
|
194
|
-
if (!populate || !isRecord(populate)) {
|
|
195
|
-
return;
|
|
196
|
-
}
|
|
197
|
-
const references = collectReferenceFieldsByTarget(source, sourceCollection, runtime);
|
|
198
|
-
const fieldTargets = invertReferenceFields(references);
|
|
199
|
-
if (!fieldTargets.size) {
|
|
200
|
-
return;
|
|
201
|
-
}
|
|
202
|
-
for (const [field, target] of Object.entries(populate)) {
|
|
203
|
-
const declaredTargets = fieldTargets.get(field);
|
|
204
|
-
if (!declaredTargets?.length) {
|
|
205
|
-
continue;
|
|
206
|
-
}
|
|
207
|
-
const actualTarget = ensureCollectionName(target);
|
|
208
|
-
if (declaredTargets.includes(actualTarget) || declaredTargets.includes(wildcardReferenceTarget)) {
|
|
209
|
-
continue;
|
|
210
|
-
}
|
|
211
|
-
throw createPopulateTargetMismatchError(
|
|
212
|
-
sourceCollection,
|
|
213
|
-
field,
|
|
214
|
-
declaredTargets.filter((target2) => target2 !== wildcardReferenceTarget),
|
|
215
|
-
actualTarget
|
|
216
|
-
);
|
|
217
|
-
}
|
|
218
|
-
};
|
|
219
|
-
const populateDocument = async (context, doc, populate, locale, fallback) => {
|
|
220
|
-
if (!populate || !isRecord(populate)) {
|
|
221
|
-
return doc;
|
|
222
|
-
}
|
|
223
|
-
const populated = { ...doc };
|
|
224
|
-
await Promise.all(Object.entries(populate).map(async ([field, target]) => {
|
|
225
|
-
const value = doc[field];
|
|
226
|
-
if (Array.isArray(value)) {
|
|
227
|
-
const resolved = await Promise.all(value.map((item) => populateReferenceValue(context, target, item, locale, fallback)));
|
|
228
|
-
populated[field] = resolved.filter(Boolean);
|
|
229
|
-
return;
|
|
230
|
-
}
|
|
231
|
-
populated[field] = await populateReferenceValue(context, target, value, locale, fallback);
|
|
232
|
-
}));
|
|
233
|
-
return populated;
|
|
234
|
-
};
|
|
235
|
-
const selectWithPopulate = (select, populate) => {
|
|
236
|
-
if (!select) {
|
|
237
|
-
return void 0;
|
|
238
|
-
}
|
|
239
|
-
return [.../* @__PURE__ */ new Set([
|
|
240
|
-
...select,
|
|
241
|
-
...LOCALIZED_DOC_INTERNAL_FIELDS,
|
|
242
|
-
...populate && isRecord(populate) ? Object.keys(populate) : []
|
|
243
|
-
])];
|
|
244
|
-
};
|
|
1
|
+
import { resolveBacklinks } from "./backlinks.js";
|
|
2
|
+
import { resolveNeighbors, resolveTree } from "./navigation.js";
|
|
3
|
+
import { resolvePagination } from "./pagination.js";
|
|
4
|
+
import { resolveVariants } from "./variants.js";
|
|
5
|
+
import { resolveDocument, resolveDocumentOnly, resolveManyDocuments } from "./documents.js";
|
|
6
|
+
export { navigationSelectFields } from "./navigation.js";
|
|
245
7
|
export async function resolveOne(context, handle, options) {
|
|
246
|
-
|
|
247
|
-
const runtime = context.runtime;
|
|
248
|
-
validatePopulateSpec(handle, collection, runtime, options.populate);
|
|
249
|
-
const by = options.by;
|
|
250
|
-
const fallback = resolveFallback(options.fallback, collection, runtime);
|
|
251
|
-
const params = compileQueryParams({
|
|
252
|
-
collection,
|
|
253
|
-
by,
|
|
254
|
-
locale: options.locale,
|
|
255
|
-
fallback,
|
|
256
|
-
select: selectWithPopulate(options.select, options.populate)
|
|
257
|
-
});
|
|
258
|
-
params.first = true;
|
|
259
|
-
let response;
|
|
260
|
-
try {
|
|
261
|
-
response = await context.transport("query", params);
|
|
262
|
-
} catch (error) {
|
|
263
|
-
if (isNotFoundError(error)) {
|
|
264
|
-
const explain2 = explainResolution(collection, options.by, by, options.locale, options.fallback, null);
|
|
265
|
-
return { doc: null, explain: explain2 };
|
|
266
|
-
}
|
|
267
|
-
throw error;
|
|
268
|
-
}
|
|
269
|
-
const unwrapped = unwrapResponse(response);
|
|
270
|
-
const doc = Array.isArray(unwrapped) ? unwrapped[0] ?? null : unwrapped ?? null;
|
|
271
|
-
const decorated = decorate(doc, collection, runtime, options.locale);
|
|
272
|
-
const populated = decorated ? await populateDocument(context, decorated, options.populate, options.locale, options.fallback) : null;
|
|
273
|
-
const explain = explainResolution(collection, options.by, by, options.locale, options.fallback, decorated);
|
|
274
|
-
return {
|
|
275
|
-
doc: populated,
|
|
276
|
-
explain
|
|
277
|
-
};
|
|
8
|
+
return resolveDocument(context, one, handle, options);
|
|
278
9
|
}
|
|
279
10
|
export async function one(context, handle, options) {
|
|
280
|
-
|
|
281
|
-
return result.doc;
|
|
11
|
+
return resolveDocumentOnly(context, handle, options);
|
|
282
12
|
}
|
|
283
13
|
export async function many(context, handle, options = {}) {
|
|
284
|
-
|
|
285
|
-
const runtime = context.runtime;
|
|
286
|
-
validatePopulateSpec(handle, collection, runtime, options.populate);
|
|
287
|
-
const fallback = resolveFallback(options.fallback, collection, runtime);
|
|
288
|
-
const params = compileQueryParams({
|
|
289
|
-
collection,
|
|
290
|
-
where: options.where,
|
|
291
|
-
sort: options.sort,
|
|
292
|
-
limit: options.limit,
|
|
293
|
-
skip: options.skip,
|
|
294
|
-
locale: options.locale,
|
|
295
|
-
fallback,
|
|
296
|
-
select: selectWithPopulate(options.select, options.populate)
|
|
297
|
-
});
|
|
298
|
-
let response;
|
|
299
|
-
try {
|
|
300
|
-
response = await context.transport("query", params);
|
|
301
|
-
} catch (error) {
|
|
302
|
-
if (isNotFoundError(error)) return [];
|
|
303
|
-
throw error;
|
|
304
|
-
}
|
|
305
|
-
const unwrapped = unwrapResponse(response);
|
|
306
|
-
const list = Array.isArray(unwrapped) ? unwrapped : unwrapped ? [unwrapped] : [];
|
|
307
|
-
const decorated = list.map((doc) => decorate(doc, collection, runtime, options.locale)).filter((doc) => Boolean(doc));
|
|
308
|
-
const populated = await Promise.all(decorated.map((doc) => populateDocument(context, doc, options.populate, options.locale, options.fallback)));
|
|
309
|
-
return populated;
|
|
14
|
+
return resolveManyDocuments(context, one, handle, options);
|
|
310
15
|
}
|
|
311
|
-
const normalizePositiveInteger = (value, fallback) => {
|
|
312
|
-
const number = typeof value === "number" && Number.isFinite(value) ? Math.floor(value) : fallback;
|
|
313
|
-
return Math.max(1, number);
|
|
314
|
-
};
|
|
315
16
|
export async function paginate(context, handle, options) {
|
|
316
|
-
|
|
317
|
-
const runtime = context.runtime;
|
|
318
|
-
validatePopulateSpec(handle, collection, runtime, options.populate);
|
|
319
|
-
const requestedPage = normalizePositiveInteger(options.page, 1);
|
|
320
|
-
const limit = Math.min(normalizePositiveInteger(options.limit, 10), MAX_PUBLIC_QUERY_LIMIT);
|
|
321
|
-
const skip = Math.min((requestedPage - 1) * limit, MAX_PUBLIC_QUERY_SKIP);
|
|
322
|
-
const page = Math.floor(skip / limit) + 1;
|
|
323
|
-
const fallback = resolveFallback(options.fallback, collection, runtime);
|
|
324
|
-
const params = compileQueryParams({
|
|
325
|
-
collection,
|
|
326
|
-
where: options.where,
|
|
327
|
-
sort: options.sort,
|
|
328
|
-
limit,
|
|
329
|
-
skip,
|
|
330
|
-
locale: options.locale,
|
|
331
|
-
fallback,
|
|
332
|
-
select: selectWithPopulate(options.select, options.populate)
|
|
333
|
-
});
|
|
334
|
-
const countParams = compileQueryParams({
|
|
335
|
-
collection,
|
|
336
|
-
where: options.where,
|
|
337
|
-
locale: options.locale,
|
|
338
|
-
fallback
|
|
339
|
-
});
|
|
340
|
-
countParams.count = true;
|
|
341
|
-
let response;
|
|
342
|
-
try {
|
|
343
|
-
response = await context.transport("query", params);
|
|
344
|
-
} catch (error) {
|
|
345
|
-
if (isNotFoundError(error)) {
|
|
346
|
-
return {
|
|
347
|
-
data: [],
|
|
348
|
-
page,
|
|
349
|
-
limit,
|
|
350
|
-
total: 0,
|
|
351
|
-
pageCount: 0,
|
|
352
|
-
hasNext: false,
|
|
353
|
-
hasPrev: page > 1,
|
|
354
|
-
nextPage: null,
|
|
355
|
-
prevPage: page > 1 ? page - 1 : null
|
|
356
|
-
};
|
|
357
|
-
}
|
|
358
|
-
throw error;
|
|
359
|
-
}
|
|
360
|
-
const envelope = unwrapFindResponse(response);
|
|
361
|
-
let total = envelope.total;
|
|
362
|
-
if (!envelope.hasTotal) {
|
|
363
|
-
const countResponse = await context.transport("query", countParams);
|
|
364
|
-
total = unwrapCountResponse(countResponse) ?? envelope.total;
|
|
365
|
-
}
|
|
366
|
-
const decorated = envelope.result.map((doc) => decorate(doc, collection, runtime, options.locale)).filter((doc) => Boolean(doc));
|
|
367
|
-
const populated = await Promise.all(decorated.map((doc) => populateDocument(context, doc, options.populate, options.locale, options.fallback)));
|
|
368
|
-
const pageCount = total > 0 ? Math.ceil(total / limit) : 0;
|
|
369
|
-
return {
|
|
370
|
-
data: populated,
|
|
371
|
-
page,
|
|
372
|
-
limit,
|
|
373
|
-
total,
|
|
374
|
-
pageCount,
|
|
375
|
-
hasNext: page < pageCount,
|
|
376
|
-
hasPrev: page > 1,
|
|
377
|
-
nextPage: page < pageCount ? page + 1 : null,
|
|
378
|
-
prevPage: page > 1 ? page - 1 : null
|
|
379
|
-
};
|
|
17
|
+
return resolvePagination(context, one, handle, options);
|
|
380
18
|
}
|
|
381
|
-
const backlinkSources = (value) => Array.isArray(value) ? [...value] : [value];
|
|
382
|
-
const isBacklinkFieldMap = (value) => {
|
|
383
|
-
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
384
|
-
};
|
|
385
|
-
const resolveExplicitBacklinkFields = (fields, sourceName) => {
|
|
386
|
-
if (Array.isArray(fields)) {
|
|
387
|
-
return fields.filter((field) => typeof field === "string" && field.length > 0);
|
|
388
|
-
}
|
|
389
|
-
if (!isBacklinkFieldMap(fields)) {
|
|
390
|
-
return [];
|
|
391
|
-
}
|
|
392
|
-
const sourceFields = fields?.[sourceName];
|
|
393
|
-
return Array.isArray(sourceFields) ? sourceFields.filter((field) => typeof field === "string" && field.length > 0) : [];
|
|
394
|
-
};
|
|
395
|
-
const inferBacklinkFields = (source, targetCollection, runtime) => {
|
|
396
|
-
if (typeof source === "string") {
|
|
397
|
-
const references = runtime?.collections?.[source]?.references;
|
|
398
|
-
return [
|
|
399
|
-
...references?.[targetCollection] || [],
|
|
400
|
-
...references?.["*"] || []
|
|
401
|
-
];
|
|
402
|
-
}
|
|
403
|
-
return collectTopLevelReferenceFields(source.schema, targetCollection);
|
|
404
|
-
};
|
|
405
|
-
const targetReferenceCandidates = (doc) => {
|
|
406
|
-
const values = [
|
|
407
|
-
doc.ref,
|
|
408
|
-
doc.id,
|
|
409
|
-
doc._canonicalKey,
|
|
410
|
-
doc._path,
|
|
411
|
-
doc._path ? doc.path : void 0,
|
|
412
|
-
doc._path ? doc.canonicalPath : void 0
|
|
413
|
-
].filter((value) => typeof value === "string" && value.length > 0).flatMap((value) => [value, normalizeReferenceValue(value)]).filter(Boolean);
|
|
414
|
-
return Array.from(new Set(values));
|
|
415
|
-
};
|
|
416
|
-
const backlinkWhere = (fields, candidates) => {
|
|
417
|
-
const clauses = fields.map((field) => ({
|
|
418
|
-
[field]: { $in: candidates }
|
|
419
|
-
}));
|
|
420
|
-
return clauses.length ? { $or: clauses } : void 0;
|
|
421
|
-
};
|
|
422
|
-
const createMissingBacklinkFieldsError = (sourceCollection, targetCollection) => new Error(
|
|
423
|
-
`Cannot infer backlink fields from "${sourceCollection}" to "${targetCollection}". Declare fields.relation('${targetCollection}') / fields.relations('${targetCollection}') in ${sourceCollection}.schema, or pass fields explicitly.`
|
|
424
|
-
);
|
|
425
19
|
export async function backlinks(context, targetHandle, options) {
|
|
426
|
-
|
|
427
|
-
const target = await one(context, targetHandle, {
|
|
428
|
-
by: options.by,
|
|
429
|
-
...options.locale ? { locale: options.locale } : {},
|
|
430
|
-
...options.fallback !== void 0 ? { fallback: options.fallback } : {}
|
|
431
|
-
});
|
|
432
|
-
if (!target) {
|
|
433
|
-
return [];
|
|
434
|
-
}
|
|
435
|
-
const candidates = targetReferenceCandidates(target);
|
|
436
|
-
if (!candidates.length) {
|
|
437
|
-
return [];
|
|
438
|
-
}
|
|
439
|
-
const sources = backlinkSources(options.from);
|
|
440
|
-
const results = await Promise.all(sources.map(async (source) => {
|
|
441
|
-
const sourceName = ensureCollectionName(source);
|
|
442
|
-
const fields = [
|
|
443
|
-
.../* @__PURE__ */ new Set([
|
|
444
|
-
...resolveExplicitBacklinkFields(options.fields, sourceName),
|
|
445
|
-
...inferBacklinkFields(source, targetCollection, context.runtime)
|
|
446
|
-
])
|
|
447
|
-
];
|
|
448
|
-
if (!fields.length) {
|
|
449
|
-
throw createMissingBacklinkFieldsError(sourceName, targetCollection);
|
|
450
|
-
}
|
|
451
|
-
const where = backlinkWhere(fields, candidates);
|
|
452
|
-
if (!where) {
|
|
453
|
-
return [];
|
|
454
|
-
}
|
|
455
|
-
return await many(context, source, {
|
|
456
|
-
where,
|
|
457
|
-
sort: options.sort,
|
|
458
|
-
limit: options.limit,
|
|
459
|
-
skip: options.skip,
|
|
460
|
-
...options.locale ? { locale: options.locale } : {},
|
|
461
|
-
...options.fallback !== void 0 ? { fallback: options.fallback } : {},
|
|
462
|
-
select: options.select,
|
|
463
|
-
populate: options.populate
|
|
464
|
-
});
|
|
465
|
-
}));
|
|
466
|
-
return results.flat();
|
|
20
|
+
return resolveBacklinks(context, one, many, targetHandle, options);
|
|
467
21
|
}
|
|
468
22
|
export async function variants(context, handle, options) {
|
|
469
|
-
|
|
470
|
-
const runtime = context.runtime;
|
|
471
|
-
const collectionI18n = runtime?.collections?.[collection]?.i18n;
|
|
472
|
-
const collectionLocales = collectionI18n && typeof collectionI18n === "object" ? collectionI18n.locales : void 0;
|
|
473
|
-
const collectionDefault = collectionI18n && typeof collectionI18n === "object" ? collectionI18n.defaultLocale : void 0;
|
|
474
|
-
const locales = collectionLocales?.length ? collectionLocales : runtime?.locales || [];
|
|
475
|
-
const defaultLocale = collectionDefault || runtime?.defaultLocale;
|
|
476
|
-
const requestedLocales = options.locales?.length ? options.locales : locales;
|
|
477
|
-
if (!requestedLocales.length) {
|
|
478
|
-
return [];
|
|
479
|
-
}
|
|
480
|
-
const seed = await one(context, handle, {
|
|
481
|
-
by: options.by,
|
|
482
|
-
locale: options.locale || defaultLocale,
|
|
483
|
-
fallback: true
|
|
484
|
-
});
|
|
485
|
-
if (!seed) return [];
|
|
486
|
-
const variantPaths = seed._variantPaths || {};
|
|
487
|
-
const sourceLocale = seed.locale || defaultLocale || "";
|
|
488
|
-
return requestedLocales.map((locale) => {
|
|
489
|
-
const variantPath = variantPaths[locale];
|
|
490
|
-
if (variantPath) {
|
|
491
|
-
return {
|
|
492
|
-
locale,
|
|
493
|
-
path: seed.localePaths?.[locale]?.path || variantPath,
|
|
494
|
-
translated: true
|
|
495
|
-
};
|
|
496
|
-
}
|
|
497
|
-
return {
|
|
498
|
-
locale,
|
|
499
|
-
path: seed.path,
|
|
500
|
-
translated: false,
|
|
501
|
-
fallback: sourceLocale
|
|
502
|
-
};
|
|
503
|
-
});
|
|
23
|
+
return resolveVariants(context, one, handle, options);
|
|
504
24
|
}
|
|
505
25
|
export async function tree(context, handle, options = {}) {
|
|
506
|
-
|
|
507
|
-
const runtime = context.runtime;
|
|
508
|
-
const fallback = resolveFallback(options.fallback, collection, runtime);
|
|
509
|
-
const params = compileQueryParams({
|
|
510
|
-
collection,
|
|
511
|
-
where: options.where,
|
|
512
|
-
sort: options.sort,
|
|
513
|
-
locale: options.locale,
|
|
514
|
-
fallback,
|
|
515
|
-
select: navigationSelectFields(options.fields),
|
|
516
|
-
exact: options.fallback === void 0 ? false : void 0
|
|
517
|
-
});
|
|
518
|
-
const response = await context.transport("navigation", params);
|
|
519
|
-
const list = Array.isArray(response) ? response : Array.isArray(response?.result) ? response.result : [];
|
|
520
|
-
return list;
|
|
26
|
+
return resolveTree(context, handle, options);
|
|
521
27
|
}
|
|
522
28
|
export async function neighbors(context, handle, options) {
|
|
523
|
-
|
|
524
|
-
const runtime = context.runtime;
|
|
525
|
-
const seed = await one(context, handle, {
|
|
526
|
-
by: options.by,
|
|
527
|
-
locale: options.locale,
|
|
528
|
-
fallback: options.fallback ?? true
|
|
529
|
-
});
|
|
530
|
-
if (!seed) return { prev: null, next: null };
|
|
531
|
-
const fullTree = await tree(context, handle, {
|
|
532
|
-
locale: options.locale,
|
|
533
|
-
fallback: options.fallback,
|
|
534
|
-
fields: options.fields
|
|
535
|
-
});
|
|
536
|
-
const flat = [];
|
|
537
|
-
const walk = (nodes) => {
|
|
538
|
-
for (const node of nodes) {
|
|
539
|
-
const n = node;
|
|
540
|
-
if (n.path || n._path) {
|
|
541
|
-
flat.push({ path: n.path || n._path || "", item: node });
|
|
542
|
-
}
|
|
543
|
-
if (Array.isArray(n.children)) walk(n.children);
|
|
544
|
-
}
|
|
545
|
-
};
|
|
546
|
-
walk(fullTree);
|
|
547
|
-
const targetPath = seed.path;
|
|
548
|
-
const idx = flat.findIndex((entry) => entry.path === targetPath);
|
|
549
|
-
if (idx === -1 && (isCollectionRouteRoot(targetPath, collection, runtime) || isNavigationRootPath(targetPath, flat))) {
|
|
550
|
-
return {
|
|
551
|
-
prev: null,
|
|
552
|
-
next: flat[0]?.item ?? null
|
|
553
|
-
};
|
|
554
|
-
}
|
|
555
|
-
if (idx === -1) return { prev: null, next: null };
|
|
556
|
-
return {
|
|
557
|
-
prev: flat[idx - 1]?.item ?? null,
|
|
558
|
-
next: flat[idx + 1]?.item ?? null
|
|
559
|
-
};
|
|
29
|
+
return resolveNeighbors(context, one, tree, handle, options);
|
|
560
30
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './variants.js'
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ParsedContent } from '../../types/content';
|
|
2
|
+
import type { ContentCollectionHandle } from '../../types/config';
|
|
3
|
+
import type { ContentVariant, LocalizedContentDocument, OneOptions, VariantsOptions } from '../../types/query';
|
|
4
|
+
import type { ContentQueryContext } from './context';
|
|
5
|
+
type OneResolver = <H extends ContentCollectionHandle | string>(context: ContentQueryContext, handle: H, options: OneOptions<H>) => Promise<LocalizedContentDocument<ParsedContent> | null>;
|
|
6
|
+
export declare function resolveVariants<H extends ContentCollectionHandle | string>(context: ContentQueryContext, one: OneResolver, handle: H, options: VariantsOptions<H>): Promise<Array<ContentVariant<H extends {
|
|
7
|
+
__schema: {
|
|
8
|
+
_output: infer O;
|
|
9
|
+
};
|
|
10
|
+
} ? O & ParsedContent : ParsedContent>>>;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { ensureCollectionName } from "./handles.js";
|
|
2
|
+
import { collectionDefaultLocale, collectionLocales } from "./locale-options.js";
|
|
3
|
+
export async function resolveVariants(context, one, handle, options) {
|
|
4
|
+
const collection = ensureCollectionName(handle);
|
|
5
|
+
const runtime = context.runtime;
|
|
6
|
+
const locales = collectionLocales(collection, runtime);
|
|
7
|
+
const defaultLocale = collectionDefaultLocale(collection, runtime);
|
|
8
|
+
const requestedLocales = options.locales?.length ? options.locales : locales;
|
|
9
|
+
if (!requestedLocales.length) {
|
|
10
|
+
return [];
|
|
11
|
+
}
|
|
12
|
+
const seed = await one(context, handle, {
|
|
13
|
+
by: options.by,
|
|
14
|
+
locale: options.locale || defaultLocale,
|
|
15
|
+
fallback: true
|
|
16
|
+
});
|
|
17
|
+
if (!seed) return [];
|
|
18
|
+
const variantPaths = seed._variantPaths || {};
|
|
19
|
+
const sourceLocale = seed.locale || defaultLocale || "";
|
|
20
|
+
return requestedLocales.map((locale) => {
|
|
21
|
+
const variantPath = variantPaths[locale];
|
|
22
|
+
if (variantPath) {
|
|
23
|
+
return {
|
|
24
|
+
locale,
|
|
25
|
+
path: seed.localePaths[locale]?.path || variantPath,
|
|
26
|
+
translated: true
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
return {
|
|
30
|
+
locale,
|
|
31
|
+
path: seed.path,
|
|
32
|
+
translated: false,
|
|
33
|
+
fallback: sourceLocale
|
|
34
|
+
};
|
|
35
|
+
});
|
|
36
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './agent-http.js'
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { H3Event } from 'h3';
|
|
2
|
+
export declare const appendResponseHeader: (event: H3Event, name: string, value: string) => void;
|
|
3
|
+
export declare const addVaryHeader: (event: H3Event, value: string) => void;
|
|
4
|
+
export declare const acceptsMarkdown: (event: H3Event) => boolean;
|
|
5
|
+
export declare const setAgentMarkdownHeaders: (event: H3Event, options?: {
|
|
6
|
+
noindex?: boolean;
|
|
7
|
+
}) => void;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { getHeader, setHeader } from "h3";
|
|
2
|
+
export const appendResponseHeader = (event, name, value) => {
|
|
3
|
+
const current = event.node.res.getHeader(name);
|
|
4
|
+
const existing = Array.isArray(current) ? current.filter(Boolean).join(", ") : typeof current === "number" ? String(current) : typeof current === "string" ? current : "";
|
|
5
|
+
setHeader(event, name, existing ? `${existing}, ${value}` : value);
|
|
6
|
+
};
|
|
7
|
+
export const addVaryHeader = (event, value) => {
|
|
8
|
+
const current = event.node.res.getHeader("vary");
|
|
9
|
+
const entries = new Set(
|
|
10
|
+
(typeof current === "string" ? current : Array.isArray(current) ? current.join(",") : "").split(",").map((entry) => entry.trim().toLowerCase()).filter(Boolean)
|
|
11
|
+
);
|
|
12
|
+
entries.add(value.toLowerCase());
|
|
13
|
+
setHeader(event, "vary", Array.from(entries).join(", "));
|
|
14
|
+
};
|
|
15
|
+
const parseAcceptPart = (part) => {
|
|
16
|
+
const [type = "", ...params] = part.split(";").map((value) => value.trim());
|
|
17
|
+
const qParam = params.find((param) => param.toLowerCase().startsWith("q="));
|
|
18
|
+
const q = qParam ? Number(qParam.slice(2)) : 1;
|
|
19
|
+
return {
|
|
20
|
+
type: type.toLowerCase(),
|
|
21
|
+
q: Number.isFinite(q) ? q : 0
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
export const acceptsMarkdown = (event) => {
|
|
25
|
+
const accept = getHeader(event, "accept");
|
|
26
|
+
if (!accept) return false;
|
|
27
|
+
const entries = accept.split(",").map(parseAcceptPart).filter((entry) => entry.q > 0);
|
|
28
|
+
const markdownQ = entries.filter((entry) => entry.type === "text/markdown").reduce((max, entry) => Math.max(max, entry.q), 0);
|
|
29
|
+
if (!markdownQ) return false;
|
|
30
|
+
const htmlQ = entries.filter((entry) => entry.type === "text/html" || entry.type === "application/xhtml+xml").reduce((max, entry) => Math.max(max, entry.q), 0);
|
|
31
|
+
return markdownQ >= htmlQ;
|
|
32
|
+
};
|
|
33
|
+
export const setAgentMarkdownHeaders = (event, options = {}) => {
|
|
34
|
+
setHeader(event, "content-type", "text/markdown; charset=utf-8");
|
|
35
|
+
if (options.noindex) setHeader(event, "x-robots-tag", "noindex");
|
|
36
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './agent-markdown.js'
|