@lupinum/ginko-content 0.1.5 → 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 +21 -34
- package/dist/module.d.mts +135 -803
- package/dist/module.json +1 -1
- package/dist/module.mjs +143 -51
- 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 +9 -2
- 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 +79 -105
- 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 +17 -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
|
@@ -2,10 +2,10 @@ import type { H3Event } from 'h3';
|
|
|
2
2
|
import type { ParsedContent } from '../../types/content';
|
|
3
3
|
import type { ContentCollectionItemSurroundingsOptions, ContentCollectionNavigationOptions, ContentCollectionPageOptions, ContentCollectionRouteMetaOptions, ContentCollectionSearchSectionsOptions, ContentPageResult, ContentSearchSection } from '../../types/query';
|
|
4
4
|
export declare function queryFilesystemCollectionNavigation(event: H3Event, collection: string, fieldsOrOptions?: string[] | ContentCollectionNavigationOptions): Promise<any[]>;
|
|
5
|
-
export declare function queryFilesystemCollectionItemSurroundings(event: H3Event, collection: string, path: string, opts?: ContentCollectionItemSurroundingsOptions): Promise<(import("../../types").NavItem | null)[]>;
|
|
5
|
+
export declare function queryFilesystemCollectionItemSurroundings(event: H3Event, collection: string, path: string, opts?: ContentCollectionItemSurroundingsOptions): Promise<(import("../../types/content").NavItem | null)[]>;
|
|
6
6
|
export declare function queryFilesystemCollectionSearchSections(event: H3Event, collection: string, opts?: ContentCollectionSearchSectionsOptions): Promise<ContentSearchSection[]>;
|
|
7
7
|
export declare function queryFilesystemCollectionPage<T = ParsedContent>(event: H3Event, collection: string, routeOrPath?: string, options?: ContentCollectionPageOptions): Promise<ContentPageResult<T> | null>;
|
|
8
|
-
export declare function queryFilesystemCollectionRouteMeta(event: H3Event, collection: string, routeOrPath?: string, options?: ContentCollectionRouteMetaOptions): Promise<import("../../types").ContentRouteMeta | null>;
|
|
8
|
+
export declare function queryFilesystemCollectionRouteMeta(event: H3Event, collection: string, routeOrPath?: string, options?: ContentCollectionRouteMetaOptions): Promise<import("../../types/query").ContentRouteMeta | null>;
|
|
9
9
|
export declare const queryCollectionNavigation: typeof queryFilesystemCollectionNavigation;
|
|
10
10
|
export declare const queryCollectionItemSurroundings: typeof queryFilesystemCollectionItemSurroundings;
|
|
11
11
|
export declare const queryCollectionSearchSections: typeof queryFilesystemCollectionSearchSections;
|
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
import { resolveCollectionItemSurroundingsData, resolveCollectionNavigationData, resolveCollectionPageData, resolveCollectionRouteMetaData, resolveCollectionSearchSectionsData } from "../../features/collections/resolve";
|
|
2
2
|
import { resolveContentNavigation } from "./navigation-query.js";
|
|
3
3
|
import { executeFilesystemContentQuery } from "./query-executor.js";
|
|
4
|
+
import { createProviderNavigationQuery, createProviderQuery } from "./provider-query.js";
|
|
4
5
|
import { serverQueryCollection } from "./storage.js";
|
|
5
6
|
import { contentConfig } from "./storage-access.js";
|
|
6
7
|
const isNotFoundError = (error) => {
|
|
7
8
|
return error?.statusCode === 404;
|
|
8
9
|
};
|
|
9
10
|
const searchPageFields = (fields = []) => [
|
|
10
|
-
"
|
|
11
|
+
"path",
|
|
11
12
|
"title",
|
|
12
13
|
"description",
|
|
13
14
|
"body",
|
|
14
15
|
...fields
|
|
15
16
|
];
|
|
16
17
|
const mergeFilterQuery = (filterQuery, locale) => {
|
|
17
|
-
const localeFilter = locale ? {
|
|
18
|
+
const localeFilter = locale ? { locale } : void 0;
|
|
18
19
|
if (filterQuery && localeFilter) {
|
|
19
20
|
return { $and: [filterQuery, localeFilter] };
|
|
20
21
|
}
|
|
@@ -25,12 +26,15 @@ export async function queryFilesystemCollectionNavigation(event, collection, fie
|
|
|
25
26
|
const locale = options.locale;
|
|
26
27
|
return await resolveCollectionNavigationData(collection, contentConfig(), {
|
|
27
28
|
...options,
|
|
28
|
-
loadNavigation: () =>
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
29
|
+
loadNavigation: () => {
|
|
30
|
+
const { query, options: navigationOptions } = createProviderNavigationQuery({
|
|
31
|
+
collection,
|
|
32
|
+
...options.fields?.length ? { navigationFields: options.fields } : {},
|
|
33
|
+
...typeof options.canonical === "boolean" ? { canonical: options.canonical } : {},
|
|
34
|
+
...locale ? { resolveLocale: { locale, fallback: true } } : {}
|
|
35
|
+
});
|
|
36
|
+
return resolveContentNavigation(event, query, navigationOptions);
|
|
37
|
+
}
|
|
34
38
|
});
|
|
35
39
|
}
|
|
36
40
|
export async function queryFilesystemCollectionItemSurroundings(event, collection, path, opts = {}) {
|
|
@@ -57,7 +61,7 @@ export async function queryFilesystemCollectionPage(event, collection, routeOrPa
|
|
|
57
61
|
...options,
|
|
58
62
|
loadVariantPage: async (input) => {
|
|
59
63
|
try {
|
|
60
|
-
const response = await executeFilesystemContentQuery(event, {
|
|
64
|
+
const response = await executeFilesystemContentQuery(event, createProviderQuery({
|
|
61
65
|
collection,
|
|
62
66
|
first: true,
|
|
63
67
|
resolveVariant: {
|
|
@@ -65,7 +69,7 @@ export async function queryFilesystemCollectionPage(event, collection, routeOrPa
|
|
|
65
69
|
locale: input.locale,
|
|
66
70
|
fallback: input.fallback
|
|
67
71
|
}
|
|
68
|
-
});
|
|
72
|
+
}).plan);
|
|
69
73
|
return response.result || null;
|
|
70
74
|
} catch (error) {
|
|
71
75
|
if (isNotFoundError(error)) {
|
|
@@ -76,7 +80,7 @@ export async function queryFilesystemCollectionPage(event, collection, routeOrPa
|
|
|
76
80
|
},
|
|
77
81
|
loadPathPage: async (path) => {
|
|
78
82
|
try {
|
|
79
|
-
return await serverQueryCollection(event, collection).where("
|
|
83
|
+
return await serverQueryCollection(event, collection).where("path", "=", path).first();
|
|
80
84
|
} catch (error) {
|
|
81
85
|
if (isNotFoundError(error)) {
|
|
82
86
|
return null;
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
export { one, many, paginate, backlinks, resolveOne, variants, tree, neighbors, createServerContentQueryContext } from './query-api';
|
|
2
|
-
export { getCollectionPath } from '
|
|
2
|
+
export { getCollectionPath } from '../../features/query/routes';
|
|
3
3
|
export { queryCollectionsSitemapEntries } from './sitemap-provider';
|
|
4
|
-
export { contentCacheHeaders, noopContentCache, vercelContentCache, type VercelContentCacheOptions } from './cache-adapters';
|
|
4
|
+
export { contentCacheHeaders, noopContentCache, vercelContentCache, headersContentCache, type VercelContentCacheOptions } from './cache-adapters';
|
|
5
5
|
export { clearContentCacheHint, collectContentCacheHint, getContentCacheHint } from './cache-hints';
|
|
6
6
|
export { createContentProviderError } from '../../public/provider-errors';
|
|
7
|
-
export { withContentCache } from '../../public/provider';
|
|
8
|
-
export
|
|
7
|
+
export { PROVIDER_QUERY_VERSION, toContentProviderNavigationQuery, toContentProviderQuery, withContentCache } from '../../public/provider';
|
|
8
|
+
export { normalizeProviderDocument, shapeProviderDocument } from './provider-document';
|
|
9
|
+
export type { ProviderDocumentInput, ShapeProviderDocumentOptions } from './provider-document';
|
|
10
|
+
export type { ContentCacheAdapter, ContentCacheHint, ContentCacheHintInput, ContentCacheInvalidateInput, ContentProvider, ContentProviderCapabilities, ContentProviderNavigationOptions, ContentProviderQuery, ContentProviderResult, MaybeContentProviderResult } from '../../public/provider';
|
|
9
11
|
export type { ContentProviderErrorCode } from '../../public/provider-errors';
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
export { one, many, paginate, backlinks, resolveOne, variants, tree, neighbors, createServerContentQueryContext } from "./query-api.js";
|
|
2
|
-
export { getCollectionPath } from "
|
|
2
|
+
export { getCollectionPath } from "../../features/query/routes";
|
|
3
3
|
export { queryCollectionsSitemapEntries } from "./sitemap-provider.js";
|
|
4
4
|
export {
|
|
5
5
|
contentCacheHeaders,
|
|
6
6
|
noopContentCache,
|
|
7
|
-
vercelContentCache
|
|
7
|
+
vercelContentCache,
|
|
8
|
+
headersContentCache
|
|
8
9
|
} from "./cache-adapters.js";
|
|
9
10
|
export {
|
|
10
11
|
clearContentCacheHint,
|
|
@@ -12,4 +13,10 @@ export {
|
|
|
12
13
|
getContentCacheHint
|
|
13
14
|
} from "./cache-hints.js";
|
|
14
15
|
export { createContentProviderError } from "../../public/provider-errors";
|
|
15
|
-
export {
|
|
16
|
+
export {
|
|
17
|
+
PROVIDER_QUERY_VERSION,
|
|
18
|
+
toContentProviderNavigationQuery,
|
|
19
|
+
toContentProviderQuery,
|
|
20
|
+
withContentCache
|
|
21
|
+
} from "../../public/provider";
|
|
22
|
+
export { normalizeProviderDocument, shapeProviderDocument } from "./provider-document.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { defineEventHandler, getRequestURL, setHeader } from "h3";
|
|
2
2
|
import { getAgentLocales, localeFromAgentPath, resolveMarkdownForPublicRoute } from "../agent-site.js";
|
|
3
|
-
import { agentRawPathForRoute, normalizeAgentRoutePath } from "
|
|
3
|
+
import { agentRawPathForRoute, normalizeAgentRoutePath } from "../../../features/agent/agent-paths";
|
|
4
4
|
import { appendResponseHeader } from "../agent-http.js";
|
|
5
5
|
import { contentConfig } from "../storage-access.js";
|
|
6
6
|
const shouldAdvertise = (pathname) => !pathname.startsWith("/_") && !pathname.startsWith("/api/") && !pathname.endsWith(".css") && !pathname.endsWith(".js") && !pathname.endsWith(".png") && !pathname.endsWith(".jpg") && !pathname.endsWith(".jpeg") && !pathname.endsWith(".webp") && !pathname.endsWith(".svg") && !pathname.endsWith(".ico");
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
resolveMarkdownForPublicRoute
|
|
8
8
|
} from "../agent-site.js";
|
|
9
9
|
import { acceptsMarkdown, addVaryHeader, setAgentMarkdownHeaders } from "../agent-http.js";
|
|
10
|
-
import { isUnsafeAgentRoutePath, normalizeAgentRoutePath } from "
|
|
10
|
+
import { isUnsafeAgentRoutePath, normalizeAgentRoutePath } from "../../../features/agent/agent-paths";
|
|
11
11
|
const shouldSkip = (pathname) => pathname.startsWith("/_") || pathname.startsWith("/api/") || pathname.startsWith("/raw/") || pathname === "/robots.txt" || pathname === "/sitemap.xml" || pathname.endsWith(".txt") || pathname.endsWith(".xml") || pathname.endsWith(".json") || pathname.endsWith(".ico") || pathname.endsWith(".png") || pathname.endsWith(".jpg") || pathname.endsWith(".jpeg") || pathname.endsWith(".webp") || pathname.endsWith(".svg") || pathname.endsWith(".css") || pathname.endsWith(".js");
|
|
12
12
|
export default defineEventHandler(async (event) => {
|
|
13
13
|
const { pathname } = getRequestURL(event);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { H3Event } from 'h3';
|
|
2
2
|
import type { NavItem } from '../../types/content';
|
|
3
|
-
import type {
|
|
4
|
-
export declare function resolveContentNavigation(event: H3Event,
|
|
3
|
+
import type { ContentProviderNavigationOptions, ContentProviderQuery } from '../../public/provider-query';
|
|
4
|
+
export declare function resolveContentNavigation(event: H3Event, query: ContentProviderQuery, navigationOptions?: ContentProviderNavigationOptions): Promise<NavItem[]>;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isPlanRegex } from "../../core/query/plan";
|
|
1
2
|
import { resolveContentNavigationData } from "../../features/navigation/query";
|
|
2
3
|
import { buildCanonicalNavigation } from "../../features/navigation/build";
|
|
3
4
|
import { markCollectionNavigationRoot, projectNavigationTree } from "../../features/navigation/canonical";
|
|
@@ -7,7 +8,51 @@ import { isPreview } from "./preview.js";
|
|
|
7
8
|
import { cacheStorage } from "./storage-access.js";
|
|
8
9
|
import { createServerContentQuery } from "./storage.js";
|
|
9
10
|
import { resolveLocaleChain } from "./manifest.js";
|
|
10
|
-
|
|
11
|
+
const reviveFilterValue = (value) => isPlanRegex(value) ? new RegExp(value.source, value.flags) : value;
|
|
12
|
+
const conditionsToWhereCondition = (conditions) => {
|
|
13
|
+
if (!conditions.length) return {};
|
|
14
|
+
if (conditions.length === 1) return conditions[0];
|
|
15
|
+
return { $and: conditions };
|
|
16
|
+
};
|
|
17
|
+
const filterToWhereConditions = (filter) => {
|
|
18
|
+
switch (filter.type) {
|
|
19
|
+
case "true":
|
|
20
|
+
return [];
|
|
21
|
+
case "compare":
|
|
22
|
+
return [
|
|
23
|
+
filter.operator === "eq" ? { [filter.field]: reviveFilterValue(filter.value) } : { [filter.field]: { [`$${filter.operator}`]: reviveFilterValue(filter.value) } }
|
|
24
|
+
];
|
|
25
|
+
case "and":
|
|
26
|
+
return filter.clauses.flatMap(filterToWhereConditions);
|
|
27
|
+
case "or":
|
|
28
|
+
return [{ $or: filter.clauses.map((clause) => conditionsToWhereCondition(filterToWhereConditions(clause))) }];
|
|
29
|
+
case "not":
|
|
30
|
+
return [{ $not: conditionsToWhereCondition(filterToWhereConditions(filter.clause)) }];
|
|
31
|
+
default:
|
|
32
|
+
throw new TypeError(`Unknown query filter node: ${filter.type}`);
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
const sortClausesToBuilder = (sort) => sort.map((clause) => ({
|
|
36
|
+
[clause.field]: clause.direction,
|
|
37
|
+
...clause.locale ? { $locale: clause.locale } : {},
|
|
38
|
+
...typeof clause.numeric === "boolean" ? { $numeric: clause.numeric } : {},
|
|
39
|
+
...clause.caseFirst ? { $caseFirst: clause.caseFirst } : {},
|
|
40
|
+
...clause.sensitivity ? { $sensitivity: clause.sensitivity } : {}
|
|
41
|
+
}));
|
|
42
|
+
const providerQueryToNavigationParams = (query, options) => {
|
|
43
|
+
const where = filterToWhereConditions(query.plan.filter);
|
|
44
|
+
const sort = sortClausesToBuilder(query.plan.sort);
|
|
45
|
+
return {
|
|
46
|
+
...query.collection ? { collection: query.collection } : {},
|
|
47
|
+
...where.length ? { where } : {},
|
|
48
|
+
...sort.length ? { sort } : {},
|
|
49
|
+
...options.resolveLocale ? { resolveLocale: options.resolveLocale } : {},
|
|
50
|
+
...options.fields?.length ? { only: options.fields } : {},
|
|
51
|
+
...options.canonical ? { canonical: true } : {}
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
export async function resolveContentNavigation(event, query, navigationOptions = {}) {
|
|
55
|
+
const inputQuery = providerQueryToNavigationParams(query, navigationOptions);
|
|
11
56
|
const runtimeConfig = getContentRuntimeConfig();
|
|
12
57
|
const requestedFields = [
|
|
13
58
|
...Array.isArray(inputQuery.only) ? inputQuery.only.map(String) : [],
|
|
@@ -39,18 +84,18 @@ export async function resolveContentNavigation(event, inputQuery = {}) {
|
|
|
39
84
|
return cached;
|
|
40
85
|
},
|
|
41
86
|
loadLocaleNavigation: async (locale) => {
|
|
42
|
-
let contentsQuery = createServerContentQuery(event, sourceQuery).where("
|
|
87
|
+
let contentsQuery = createServerContentQuery(event, sourceQuery).where("partial", "=", false).where("type", "=", "markdown").where("navigation", "!=", false);
|
|
43
88
|
if (locale) {
|
|
44
|
-
contentsQuery = contentsQuery.where("
|
|
89
|
+
contentsQuery = contentsQuery.where("locale", "=", locale);
|
|
45
90
|
}
|
|
46
|
-
let dirConfigsQuery = createServerContentQuery(event).where("
|
|
91
|
+
let dirConfigsQuery = createServerContentQuery(event).where("navigationFile", "=", true).where("partial", "=", true);
|
|
47
92
|
if (locale) {
|
|
48
|
-
dirConfigsQuery = dirConfigsQuery.where("
|
|
93
|
+
dirConfigsQuery = dirConfigsQuery.where("locale", "=", locale);
|
|
49
94
|
}
|
|
50
95
|
const contents = await contentsQuery.all();
|
|
51
96
|
const dirConfigs = await dirConfigsQuery.all();
|
|
52
97
|
const configs = dirConfigs.reduce((accumulator, config) => {
|
|
53
|
-
accumulator[config.
|
|
98
|
+
accumulator[config.path || "/"] = {
|
|
54
99
|
...config,
|
|
55
100
|
...config.body
|
|
56
101
|
};
|
|
@@ -60,7 +105,7 @@ export async function resolveContentNavigation(event, inputQuery = {}) {
|
|
|
60
105
|
return buildCanonicalNavigation(contents, configs, [.../* @__PURE__ */ new Set([...configuredFields, ...requestedFields])]);
|
|
61
106
|
},
|
|
62
107
|
resolveLocaleChain,
|
|
63
|
-
localizeNavigation: async (items, locale,
|
|
108
|
+
localizeNavigation: async (items, locale, _unusedFallback = [], collection, canonical) => {
|
|
64
109
|
const collectionI18n = collection ? runtimeConfig.content.collections?.[collection]?.i18n : void 0;
|
|
65
110
|
const collectionLocales = collectionI18n && typeof collectionI18n === "object" ? collectionI18n.locales : void 0;
|
|
66
111
|
const collectionDefault = collectionI18n && typeof collectionI18n === "object" ? collectionI18n.defaultLocale : void 0;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { ParsedContentMeta } from '../../types/content';
|
|
2
|
-
export declare function createNav(contents: ParsedContentMeta[], configs: Record<string, ParsedContentMeta>): import("../../types").NavItem[];
|
|
2
|
+
export declare function createNav(contents: ParsedContentMeta[], configs: Record<string, ParsedContentMeta>): import("../../types/content").NavItem[];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './provider-document.js'
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { ContentFileMeta, ParsedContent } from '../../types/content';
|
|
2
|
+
import type { ContentPageResult } from '../../types/query';
|
|
3
|
+
import { type RouteMounts } from '../../features/localization/path';
|
|
4
|
+
/**
|
|
5
|
+
* Minimal document a third-party provider must emit. Only `collection`,
|
|
6
|
+
* `locale`, `path` and `body` are strictly required — `id`, `canonicalKey` and
|
|
7
|
+
* `type` are derived when omitted, and `file` is optional (absent for providers
|
|
8
|
+
* with no backing file, e.g. CMS-backed documents). Any additional frontmatter
|
|
9
|
+
* fields are passed through untouched.
|
|
10
|
+
*/
|
|
11
|
+
export interface ProviderDocumentInput extends Record<string, unknown> {
|
|
12
|
+
/** Collection the document belongs to. */
|
|
13
|
+
collection: string;
|
|
14
|
+
/** Locale code for this concrete variant. */
|
|
15
|
+
locale: string;
|
|
16
|
+
/** Canonical (source-agnostic) route path this variant serves at. */
|
|
17
|
+
path: string;
|
|
18
|
+
/** Parsed body payload (`null` for documents with no renderable body). */
|
|
19
|
+
body: ParsedContent['body'];
|
|
20
|
+
/** Fully-qualified system id. Derived from `locale` + `path` when omitted. */
|
|
21
|
+
id?: string;
|
|
22
|
+
/**
|
|
23
|
+
* Opaque, locale-agnostic identity join key. Derived from `collection` +
|
|
24
|
+
* `path` when omitted. Never parse or render it as a URL.
|
|
25
|
+
*/
|
|
26
|
+
canonicalKey?: string;
|
|
27
|
+
/** Document kind. Defaults to `'markdown'`. */
|
|
28
|
+
type?: ParsedContent['type'];
|
|
29
|
+
/** Optional file provenance. Absent for providers with no backing file. */
|
|
30
|
+
file?: ContentFileMeta;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Options describing the provider's locale/route configuration so core can
|
|
34
|
+
* derive the localized route envelope. For single-locale providers these can be
|
|
35
|
+
* omitted entirely.
|
|
36
|
+
*/
|
|
37
|
+
export interface ShapeProviderDocumentOptions {
|
|
38
|
+
/** Default locale of the site (defaults to the document's own locale). */
|
|
39
|
+
defaultLocale?: string;
|
|
40
|
+
/** All configured locales (defaults to the document's own locale). */
|
|
41
|
+
locales?: string[];
|
|
42
|
+
/** Route mount(s) for the collection, used to project localized paths. */
|
|
43
|
+
route?: string | Record<string, string>;
|
|
44
|
+
/** Pre-computed route mounts (takes precedence over `route`). */
|
|
45
|
+
routeMounts?: RouteMounts;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Normalize a provider's raw document into the canonical content envelope,
|
|
49
|
+
* filling in the derivable identity fields (`id`, `canonicalKey`, `type`) while
|
|
50
|
+
* leaving `file` absent unless the provider supplied it.
|
|
51
|
+
*/
|
|
52
|
+
export declare const normalizeProviderDocument: (input: ProviderDocumentInput) => ParsedContent;
|
|
53
|
+
/**
|
|
54
|
+
* Normalize a provider's raw document and derive the full route envelope
|
|
55
|
+
* (`path`, `variants`, `localePaths`, `resolved`). The result is the canonical
|
|
56
|
+
* `ContentPageResult` route helpers return, so a provider can back its `page`,
|
|
57
|
+
* `routeMeta` and `query` methods from the minimal document set alone.
|
|
58
|
+
*/
|
|
59
|
+
export declare const shapeProviderDocument: <T = ParsedContent>(input: ProviderDocumentInput, options?: ShapeProviderDocumentOptions) => ContentPageResult<T>;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { normalizeRouteMounts } from "../../features/localization/path";
|
|
2
|
+
import { localizePageResult } from "../../features/localization/results";
|
|
3
|
+
const trimSlashes = (value) => value.replace(/^\/+|\/+$/g, "");
|
|
4
|
+
const extensionForType = (type) => {
|
|
5
|
+
switch (type) {
|
|
6
|
+
case "yaml":
|
|
7
|
+
return "yml";
|
|
8
|
+
case "json":
|
|
9
|
+
return "json";
|
|
10
|
+
case "csv":
|
|
11
|
+
return "csv";
|
|
12
|
+
default:
|
|
13
|
+
return "md";
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
export const normalizeProviderDocument = (input) => {
|
|
17
|
+
const collection = input.collection;
|
|
18
|
+
const locale = input.locale;
|
|
19
|
+
const path = input.path;
|
|
20
|
+
const type = input.type ?? "markdown";
|
|
21
|
+
const canonicalKey = input.canonicalKey ?? `${collection}:${trimSlashes(path) || "index"}`;
|
|
22
|
+
const extension = input.file?.extension ?? extensionForType(type);
|
|
23
|
+
const id = input.id ?? `content:${locale}:${trimSlashes(path).replace(/\//g, ":") || "index"}.${extension}`;
|
|
24
|
+
return {
|
|
25
|
+
...input,
|
|
26
|
+
id,
|
|
27
|
+
collection,
|
|
28
|
+
locale,
|
|
29
|
+
path,
|
|
30
|
+
canonicalKey,
|
|
31
|
+
type,
|
|
32
|
+
...input.file ? { file: input.file } : {},
|
|
33
|
+
body: input.body
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
export const shapeProviderDocument = (input, options = {}) => {
|
|
37
|
+
const document = normalizeProviderDocument(input);
|
|
38
|
+
const defaultLocale = options.defaultLocale ?? input.locale;
|
|
39
|
+
const locales = options.locales ?? [input.locale];
|
|
40
|
+
const routeMounts = options.routeMounts ?? normalizeRouteMounts(options.route, locales, defaultLocale);
|
|
41
|
+
return localizePageResult(
|
|
42
|
+
document,
|
|
43
|
+
input.locale,
|
|
44
|
+
defaultLocale,
|
|
45
|
+
locales,
|
|
46
|
+
routeMounts
|
|
47
|
+
);
|
|
48
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './provider-query-wire.js'
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builder-params → provider-wire lowering seam.
|
|
3
|
+
*
|
|
4
|
+
* These helpers translate the internal query IR (`ContentQueryBuilderParams`,
|
|
5
|
+
* see `../../types/query-parts/transport.ts`) into the closed, JSON-pure
|
|
6
|
+
* `ContentProviderQuery` wire envelope. They live in the runtime adapter layer
|
|
7
|
+
* — NOT in the `public/` facade — because the IR is internal plumbing: keeping
|
|
8
|
+
* its name out of `src/public/` is what makes the IR "not public" while the
|
|
9
|
+
* lowering functions themselves stay part of the exported surface (re-exported
|
|
10
|
+
* from `../../public/provider-query`).
|
|
11
|
+
*/
|
|
12
|
+
import type { ContentQueryBuilderParams } from '../../types/query';
|
|
13
|
+
import type { ContentProviderNavigationOptions, ContentProviderQuery } from '../../public/provider-query';
|
|
14
|
+
export declare const PROVIDER_QUERY_VERSION: 1;
|
|
15
|
+
/**
|
|
16
|
+
* Lower builder params into the wire envelope. This is the single place the
|
|
17
|
+
* builder → plan translation happens before the provider boundary; providers
|
|
18
|
+
* receive only the closed, JSON-pure plan.
|
|
19
|
+
*/
|
|
20
|
+
export declare const toContentProviderQuery: (params: ContentQueryBuilderParams) => ContentProviderQuery;
|
|
21
|
+
/**
|
|
22
|
+
* Split builder params into the navigation wire pair (CS-5): the query plan
|
|
23
|
+
* (collection + user filter/sort) plus the navigation-only options
|
|
24
|
+
* (`fields` = `only` ∪ `navigationFields`, `canonical`, and the raw
|
|
25
|
+
* `resolveLocale`). The nav-only keys are stripped before lowering so they do
|
|
26
|
+
* not leak into the plan. Pure — the single navigation builder-params → wire
|
|
27
|
+
* seam, usable by providers and their conformance suites.
|
|
28
|
+
*/
|
|
29
|
+
export declare const toContentProviderNavigationQuery: (params: ContentQueryBuilderParams) => {
|
|
30
|
+
query: ContentProviderQuery;
|
|
31
|
+
options: ContentProviderNavigationOptions;
|
|
32
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { lowerQueryPlan } from "../../core/query/lower";
|
|
2
|
+
export const PROVIDER_QUERY_VERSION = 1;
|
|
3
|
+
export const toContentProviderQuery = (params) => ({
|
|
4
|
+
v: PROVIDER_QUERY_VERSION,
|
|
5
|
+
collection: params.collection ?? null,
|
|
6
|
+
plan: lowerQueryPlan(params)
|
|
7
|
+
});
|
|
8
|
+
export const toContentProviderNavigationQuery = (params) => {
|
|
9
|
+
const fields = [
|
|
10
|
+
...Array.isArray(params.only) ? params.only.map(String) : [],
|
|
11
|
+
...Array.isArray(params.navigationFields) ? params.navigationFields.map(String) : []
|
|
12
|
+
];
|
|
13
|
+
const canonical = params.canonical === true;
|
|
14
|
+
const resolveLocale = params.resolveLocale;
|
|
15
|
+
const planParams = { ...params };
|
|
16
|
+
delete planParams.only;
|
|
17
|
+
delete planParams.navigationFields;
|
|
18
|
+
delete planParams.canonical;
|
|
19
|
+
return {
|
|
20
|
+
query: toContentProviderQuery(planParams),
|
|
21
|
+
options: {
|
|
22
|
+
...fields.length ? { fields } : {},
|
|
23
|
+
...canonical ? { canonical: true } : {},
|
|
24
|
+
...resolveLocale ? { resolveLocale } : {}
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
};
|
|
@@ -1,8 +1,21 @@
|
|
|
1
1
|
import type { H3Event } from 'h3';
|
|
2
|
-
import type {
|
|
3
|
-
import type { ParsedContent } from '../../types/content';
|
|
2
|
+
import type { ContentDocumentResolution, ParsedContent } from '../../types/content';
|
|
4
3
|
import type { ContentQueryResponse } from '../../types/api';
|
|
5
|
-
import type { CollectionQueryBuilder, ContentQueryBuilderParams, ContentQueryRequest, ResolveContentReferenceOptions } from '../../types/query';
|
|
4
|
+
import type { CollectionQueryBuilder, ContentCollectionMap, ContentQueryBuilderParams, ContentQueryRequest, ResolveContentReferenceOptions } from '../../types/query';
|
|
5
|
+
import { type ContentProviderQuery } from '../../public/provider-query';
|
|
6
|
+
export { toContentProviderNavigationQuery as createProviderNavigationQuery } from '../../public/provider-query';
|
|
7
|
+
/**
|
|
8
|
+
* Build the provider wire query (CS-5) from builder params: reject
|
|
9
|
+
* globally-invalid operators and malformed `$options` up front (so callers see
|
|
10
|
+
* a clean typed error rather than a raw lowering `TypeError`), apply the shared
|
|
11
|
+
* content-query normalization (default sort, locale injection, `fallback: true`
|
|
12
|
+
* → chain expansion), then lower to a JSON-pure `ContentQueryPlan`.
|
|
13
|
+
*
|
|
14
|
+
* This is the single builder-params → plan seam before the provider boundary.
|
|
15
|
+
* Provider-specific policy (draft hiding, limit clamps, regex rejection) lives
|
|
16
|
+
* inside each provider, applied to the plan it receives.
|
|
17
|
+
*/
|
|
18
|
+
export declare const createProviderQuery: (params: ContentQueryBuilderParams) => ContentProviderQuery;
|
|
6
19
|
export declare const normalizeProviderQueryResult: <T>(response: ContentQueryResponse<T>) => T[];
|
|
7
20
|
export declare const normalizeProviderQueryResponse: <T>(params: ContentQueryBuilderParams, response: unknown, providerName?: string) => ContentQueryResponse<T>;
|
|
8
21
|
export declare const resolveProviderContentVariants: (event: H3Event, identity: string, options: ResolveContentReferenceOptions) => Promise<{
|
|
@@ -18,13 +31,9 @@ export declare const resolveProviderContentVariants: (event: H3Event, identity:
|
|
|
18
31
|
fallback: boolean;
|
|
19
32
|
} | null>;
|
|
20
33
|
export declare const createServerProviderQueryFetch: <T = ParsedContent>(event: H3Event) => (query: ContentQueryRequest) => Promise<ContentQueryResponse<T>>;
|
|
21
|
-
export declare const createServerContentQuery: <T = ParsedContent>(event: H3Event, query?: string | ContentQueryBuilderParams, ...pathParts: string[]) => import("
|
|
34
|
+
export declare const createServerContentQuery: <T = ParsedContent>(event: H3Event, query?: string | ContentQueryBuilderParams, ...pathParts: string[]) => import("../../types/query").ContentQueryBuilder<T>;
|
|
22
35
|
export declare function serverQueryCollection<K extends keyof ContentCollectionMap & string>(event: H3Event, collection: K): CollectionQueryBuilder<ContentCollectionMap[K]>;
|
|
23
36
|
export declare function serverQueryCollection<T = ParsedContent>(event: H3Event, collection: string): CollectionQueryBuilder<T>;
|
|
24
37
|
export declare const resolveContentReference: <T = ParsedContent>(event: H3Event, reference: string, options?: ResolveContentReferenceOptions) => Promise<(T & {
|
|
25
|
-
|
|
26
|
-
_resolvedLocale?: string;
|
|
27
|
-
_fallback?: boolean;
|
|
28
|
-
_availableLocales?: string[];
|
|
29
|
-
_variantPaths?: Record<string, string>;
|
|
38
|
+
resolved?: ContentDocumentResolution;
|
|
30
39
|
}) | null>;
|
|
@@ -1,10 +1,35 @@
|
|
|
1
1
|
import { joinURL, withLeadingSlash } from "ufo";
|
|
2
2
|
import { createQuery, wrapQueryBuilder } from "../../core/query/builder";
|
|
3
3
|
import { normalizeContentQueryParams } from "../../core/query/params";
|
|
4
|
+
import { containsStandaloneRegexOptions, findUnsupportedQueryOperator } from "../../core/query/operators";
|
|
4
5
|
import { normalizeI18nConfig, resolveRuntimeCollectionI18nConfig } from "../../features/localization/config";
|
|
6
|
+
import { sortLocalesCanonically } from "../../core/content/locale";
|
|
5
7
|
import { normalizeReferenceValue } from "../../core/references/resolve";
|
|
6
8
|
import { getContentRuntimeConfig } from "./runtime-config.js";
|
|
7
9
|
import { createContentProviderError } from "../../public/provider-errors";
|
|
10
|
+
import { toContentProviderQuery } from "../../public/provider-query";
|
|
11
|
+
export { toContentProviderNavigationQuery as createProviderNavigationQuery } from "../../public/provider-query";
|
|
12
|
+
export const createProviderQuery = (params) => {
|
|
13
|
+
const unsupported = findUnsupportedQueryOperator(params.where);
|
|
14
|
+
if (unsupported) {
|
|
15
|
+
throw createContentProviderError("unsupported_query_operator", `Unsupported query operator: ${unsupported}`, {
|
|
16
|
+
operator: unsupported
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
if (containsStandaloneRegexOptions(params.where)) {
|
|
20
|
+
throw createContentProviderError("unsupported_query_shape", "Query operator $options requires $regex.", {
|
|
21
|
+
operator: "$options"
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
const config = getContentRuntimeConfig().content || {};
|
|
25
|
+
const normalized = normalizeContentQueryParams(params, {
|
|
26
|
+
collectionI18n: params.collection ? config.collections?.[params.collection]?.i18n : void 0,
|
|
27
|
+
defaultLocale: config.defaultLocale,
|
|
28
|
+
localeFallback: config.localeFallback,
|
|
29
|
+
includeDraftFilter: false
|
|
30
|
+
});
|
|
31
|
+
return toContentProviderQuery(normalized);
|
|
32
|
+
};
|
|
8
33
|
const isObject = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
9
34
|
const isProviderFindResponse = (response) => isObject(response) && Array.isArray(response.result) && typeof response.skip === "number" && typeof response.limit === "number" && typeof response.total === "number";
|
|
10
35
|
export const normalizeProviderQueryResult = (response) => {
|
|
@@ -55,7 +80,7 @@ const identityMatchesDocument = (document, identity) => {
|
|
|
55
80
|
if (!normalizedIdentity) {
|
|
56
81
|
return false;
|
|
57
82
|
}
|
|
58
|
-
return [document.
|
|
83
|
+
return [document.canonicalKey, document.path, document.ref].filter((value) => typeof value === "string").some((value) => normalizeReferenceValue(value) === normalizedIdentity);
|
|
59
84
|
};
|
|
60
85
|
export const resolveProviderContentVariants = async (event, identity, options) => {
|
|
61
86
|
if (!options.collection) {
|
|
@@ -77,38 +102,43 @@ export const resolveProviderContentVariants = async (event, identity, options) =
|
|
|
77
102
|
const provider = await getContentProvider(event);
|
|
78
103
|
const baseQuery = {
|
|
79
104
|
collection: options.collection,
|
|
80
|
-
only: ["
|
|
105
|
+
only: ["path", "canonicalKey", "locale", "ref", "title", "description", "body"]
|
|
81
106
|
};
|
|
82
107
|
const documents = localesToQuery.length ? (await Promise.all(
|
|
83
|
-
localesToQuery.map(
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
)).flat() : normalizeProviderQueryResult(normalizeProviderQueryResponse(baseQuery, await provider.query(event, baseQuery), provider.name));
|
|
108
|
+
localesToQuery.map(async (locale) => {
|
|
109
|
+
const localeQuery = { ...baseQuery, resolveLocale: { locale, exact: true } };
|
|
110
|
+
return normalizeProviderQueryResult(
|
|
111
|
+
normalizeProviderQueryResponse(
|
|
112
|
+
localeQuery,
|
|
113
|
+
await provider.query(event, createProviderQuery(localeQuery)),
|
|
114
|
+
provider.name
|
|
115
|
+
)
|
|
116
|
+
);
|
|
117
|
+
})
|
|
118
|
+
)).flat() : normalizeProviderQueryResult(normalizeProviderQueryResponse(baseQuery, await provider.query(event, createProviderQuery(baseQuery)), provider.name));
|
|
95
119
|
const matched = documents.find((document) => identityMatchesDocument(document, normalizedReference));
|
|
96
|
-
const canonicalKey = matched?.
|
|
120
|
+
const canonicalKey = matched?.canonicalKey;
|
|
97
121
|
if (!canonicalKey) {
|
|
98
122
|
return null;
|
|
99
123
|
}
|
|
100
|
-
const variants = documents.filter((document) => document.
|
|
124
|
+
const variants = documents.filter((document) => document.canonicalKey === canonicalKey);
|
|
101
125
|
if (!variants.length) {
|
|
102
126
|
return null;
|
|
103
127
|
}
|
|
104
|
-
const selectByLocale = (locale) => locale ? variants.find((document) => document.
|
|
128
|
+
const selectByLocale = (locale) => locale ? variants.find((document) => document.locale === locale) : void 0;
|
|
105
129
|
const selected = selectByLocale(options.locale) || (!options.exact ? fallbackLocales.map(selectByLocale).find(Boolean) : void 0) || (!options.exact ? selectByLocale(collectionI18n?.defaultLocale || runtimeContent.defaultLocale) : void 0) || (!options.exact ? variants[0] : void 0);
|
|
106
130
|
if (!selected) {
|
|
107
131
|
return null;
|
|
108
132
|
}
|
|
109
|
-
const availableLocales =
|
|
133
|
+
const availableLocales = sortLocalesCanonically(
|
|
134
|
+
Array.from(new Set(variants.map((document) => document.locale).filter(Boolean))),
|
|
135
|
+
{
|
|
136
|
+
defaultLocale: collectionI18n?.defaultLocale || runtimeContent.defaultLocale,
|
|
137
|
+
locales: collectionI18n?.locales
|
|
138
|
+
}
|
|
139
|
+
);
|
|
110
140
|
const variantPaths = Object.fromEntries(
|
|
111
|
-
variants.filter((document) => document.
|
|
141
|
+
variants.filter((document) => document.locale && document.path).map((document) => [document.locale, document.path])
|
|
112
142
|
);
|
|
113
143
|
return {
|
|
114
144
|
canonicalKey,
|
|
@@ -117,16 +147,17 @@ export const resolveProviderContentVariants = async (event, identity, options) =
|
|
|
117
147
|
availableLocales,
|
|
118
148
|
variantPaths,
|
|
119
149
|
requestedLocale: options.locale,
|
|
120
|
-
resolvedLocale: selected.
|
|
121
|
-
fallback: Boolean(options.locale && selected.
|
|
150
|
+
resolvedLocale: selected.locale,
|
|
151
|
+
fallback: Boolean(options.locale && selected.locale && selected.locale !== options.locale)
|
|
122
152
|
};
|
|
123
153
|
};
|
|
124
154
|
export const createServerProviderQueryFetch = (event) => {
|
|
125
155
|
return async (query) => {
|
|
126
156
|
const { getContentProvider } = await import("./providers/index.js");
|
|
127
157
|
const provider = await getContentProvider(event);
|
|
128
|
-
const
|
|
129
|
-
|
|
158
|
+
const params = query.params();
|
|
159
|
+
const response = await provider.query(event, createProviderQuery(params));
|
|
160
|
+
return normalizeProviderQueryResponse(params, response, provider.name);
|
|
130
161
|
};
|
|
131
162
|
};
|
|
132
163
|
const getServerCollectionI18n = (collection) => {
|
|
@@ -164,10 +195,13 @@ export const resolveContentReference = async (event, reference, options = {}) =>
|
|
|
164
195
|
}
|
|
165
196
|
return {
|
|
166
197
|
...resolved.selected,
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
198
|
+
resolved: {
|
|
199
|
+
...resolved.selected.resolved || {},
|
|
200
|
+
requestedLocale: resolved.requestedLocale,
|
|
201
|
+
locale: resolved.resolvedLocale,
|
|
202
|
+
fallback: resolved.fallback,
|
|
203
|
+
availableLocales: resolved.availableLocales,
|
|
204
|
+
variantPaths: resolved.variantPaths
|
|
205
|
+
}
|
|
172
206
|
};
|
|
173
207
|
};
|