@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
|
@@ -39,7 +39,7 @@ const rememberSearchRecords = (cacheKey, records) => {
|
|
|
39
39
|
}
|
|
40
40
|
};
|
|
41
41
|
const mergeSearchFilter = (filterQuery, locale) => {
|
|
42
|
-
const localeFilter = locale ? {
|
|
42
|
+
const localeFilter = locale ? { locale } : void 0;
|
|
43
43
|
if (filterQuery && localeFilter) {
|
|
44
44
|
return { $and: [filterQuery, localeFilter] };
|
|
45
45
|
}
|
|
@@ -50,7 +50,7 @@ export async function serverSearchContent(event, filterQuery, locale, collection
|
|
|
50
50
|
const collections = resolveSearchCollections(runtimeConfig.content, collectionsOverride);
|
|
51
51
|
const results = await Promise.all(collections.map(async (collection) => {
|
|
52
52
|
const loadPages = async (queryLocale) => {
|
|
53
|
-
const query = serverQueryCollection(event, collection).select("
|
|
53
|
+
const query = serverQueryCollection(event, collection).select("path", "locale", "title", "description", "body");
|
|
54
54
|
const mergedFilter = mergeSearchFilter(filterQuery, queryLocale);
|
|
55
55
|
if (mergedFilter) {
|
|
56
56
|
return await query.where(mergedFilter).find();
|
|
@@ -84,7 +84,7 @@ const toSearchRecord = (section) => {
|
|
|
84
84
|
content: section.content,
|
|
85
85
|
headings: section.titles,
|
|
86
86
|
anchor: anchor || void 0,
|
|
87
|
-
locale: typeof section.
|
|
87
|
+
locale: typeof section.locale === "string" ? section.locale : void 0
|
|
88
88
|
};
|
|
89
89
|
};
|
|
90
90
|
const buildProviderSearchSections = async (event, collections, provider, opts) => {
|
|
@@ -92,7 +92,7 @@ const buildProviderSearchSections = async (event, collections, provider, opts) =
|
|
|
92
92
|
const sections = await Promise.all(collections.map(async (collection) => {
|
|
93
93
|
const loadCollectionLocale = async (locale) => (await provider.searchSections(event, collection, {
|
|
94
94
|
ignoredTags: opts.ignoredTags || [],
|
|
95
|
-
extraFields: unique(["
|
|
95
|
+
extraFields: unique(["locale", ...opts.extraFields || []]),
|
|
96
96
|
filterQuery: opts.filterQuery,
|
|
97
97
|
locale
|
|
98
98
|
})).map((section) => ({
|
|
@@ -6,11 +6,11 @@ import { serverQueryCollection } from "./storage.js";
|
|
|
6
6
|
import { contentConfig } from "./storage-access.js";
|
|
7
7
|
import { resolveCollectionI18n } from "../../features/localization/path";
|
|
8
8
|
const sitemapPageFields = [
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"
|
|
9
|
+
"path",
|
|
10
|
+
"file",
|
|
11
|
+
"locale",
|
|
12
|
+
"draft",
|
|
13
|
+
"canonicalKey",
|
|
14
14
|
"sitemap",
|
|
15
15
|
"image",
|
|
16
16
|
"seo",
|
|
@@ -1 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
import type { H3Event } from 'h3';
|
|
2
|
+
import { cacheParsedStorage, cacheStorage, contentConfig, contentIgnorePredicate, getSourceContentIds, resolveStorageId, sourceStorage } from '../../integrations/nitro/storage';
|
|
3
|
+
export declare const getContentsIds: (event: H3Event, prefix?: string) => Promise<string[]>;
|
|
4
|
+
export { cacheParsedStorage, cacheStorage, contentConfig, contentIgnorePredicate, getSourceContentIds, resolveStorageId, sourceStorage };
|
|
@@ -1,9 +1,34 @@
|
|
|
1
|
-
|
|
1
|
+
import { splitInlineLocaleVariantId } from "../../core/content/locale";
|
|
2
|
+
import {
|
|
2
3
|
cacheParsedStorage,
|
|
3
4
|
cacheStorage,
|
|
4
5
|
contentConfig,
|
|
5
6
|
contentIgnorePredicate,
|
|
6
|
-
getContentsIds,
|
|
7
|
+
getContentsIds as getStorageContentsIds,
|
|
8
|
+
getSourceContentIds,
|
|
7
9
|
resolveStorageId,
|
|
8
10
|
sourceStorage
|
|
9
11
|
} from "../../integrations/nitro/storage";
|
|
12
|
+
import { getProcessDocuments, usesProcessSnapshot } from "../../storage/snapshot-runtime";
|
|
13
|
+
export const getContentsIds = async (event, prefix) => {
|
|
14
|
+
if (!usesProcessSnapshot) {
|
|
15
|
+
return getStorageContentsIds(event, prefix);
|
|
16
|
+
}
|
|
17
|
+
const ids = /* @__PURE__ */ new Set();
|
|
18
|
+
for (const document of await getProcessDocuments(event)) {
|
|
19
|
+
const { sourceId } = splitInlineLocaleVariantId(document.id);
|
|
20
|
+
if (!prefix || sourceId.startsWith(prefix)) {
|
|
21
|
+
ids.add(sourceId);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return [...ids];
|
|
25
|
+
};
|
|
26
|
+
export {
|
|
27
|
+
cacheParsedStorage,
|
|
28
|
+
cacheStorage,
|
|
29
|
+
contentConfig,
|
|
30
|
+
contentIgnorePredicate,
|
|
31
|
+
getSourceContentIds,
|
|
32
|
+
resolveStorageId,
|
|
33
|
+
sourceStorage
|
|
34
|
+
};
|
|
@@ -6,5 +6,5 @@ export declare function loadComponents(node: ParsedContent['body'] | {
|
|
|
6
6
|
props?: Record<string, unknown>;
|
|
7
7
|
children?: Array<ParsedContent['body']>;
|
|
8
8
|
} | null, tags: Record<string, string>): [string, unknown][];
|
|
9
|
-
declare const _default: import("../../types").ContentTransformer;
|
|
9
|
+
declare const _default: import("../../types/content").ContentTransformer;
|
|
10
10
|
export default _default;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { H3Event } from 'h3';
|
|
2
|
-
import type { ParsedContent } from '../types/content';
|
|
2
|
+
import type { ContentDocumentResolution, ParsedContent } from '../types/content';
|
|
3
3
|
import type { ContentCollectionMap, ContentLocaleEntry, ContentQueryBuilderParams, ContentQueryFetcher, CollectionQueryBuilder, ResolveContentReferenceOptions } from '../types/query';
|
|
4
4
|
export declare const createServerQueryFetch: <T = ParsedContent>(event: H3Event) => ContentQueryFetcher<T>;
|
|
5
5
|
/**
|
|
@@ -19,11 +19,7 @@ export declare const createServerQueryFetch: <T = ParsedContent>(event: H3Event)
|
|
|
19
19
|
* ```
|
|
20
20
|
*/
|
|
21
21
|
export declare const resolveContentReference: <T = ParsedContent>(event: H3Event, reference: string, options?: ResolveContentReferenceOptions) => Promise<(T & {
|
|
22
|
-
|
|
23
|
-
_resolvedLocale?: string;
|
|
24
|
-
_fallback?: boolean;
|
|
25
|
-
_availableLocales?: string[];
|
|
26
|
-
_variantPaths?: Record<string, string>;
|
|
22
|
+
resolved?: ContentDocumentResolution;
|
|
27
23
|
}) | null>;
|
|
28
24
|
export declare const createServerContentQuery: <T = ParsedContent>(event: H3Event, query?: string | ContentQueryBuilderParams, ...pathParts: string[]) => import("../types/query").ContentQueryBuilder<T>;
|
|
29
25
|
export declare function serverQueryCollection<K extends keyof ContentCollectionMap & string>(event: H3Event, collection: K): CollectionQueryBuilder<ContentCollectionMap[K]>;
|
package/dist/storage/content.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { joinURL, withLeadingSlash } from "ufo";
|
|
2
2
|
import { createQuery, wrapQueryBuilder } from "../core/query/builder";
|
|
3
3
|
import { resolveGraphCanonicalKey, resolveGraphCollectionLocales, resolveGraphVariant } from "../core/content/graph";
|
|
4
|
+
import { sortLocalesCanonically } from "../core/content/locale";
|
|
4
5
|
import { normalizeReferenceValue } from "../core/references/resolve";
|
|
5
6
|
import { executeQueryPlan } from "../core/query/execute";
|
|
6
7
|
import { lowerQueryPlan } from "../core/query/lower";
|
|
@@ -27,7 +28,7 @@ export const resolveContentReference = async (event, reference, options = {}) =>
|
|
|
27
28
|
if (!canonicalId) {
|
|
28
29
|
return null;
|
|
29
30
|
}
|
|
30
|
-
const variants = Object.values(graph.byCanonical[canonicalId] || {}).map((entry) => entry.document).filter((document) => !options.collection || document.
|
|
31
|
+
const variants = Object.values(graph.byCanonical[canonicalId] || {}).map((entry) => entry.document).filter((document) => !options.collection || document.collection === options.collection);
|
|
31
32
|
if (!variants.length) {
|
|
32
33
|
return null;
|
|
33
34
|
}
|
|
@@ -41,17 +42,27 @@ export const resolveContentReference = async (event, reference, options = {}) =>
|
|
|
41
42
|
if (!resolved || !resolvedVariant) {
|
|
42
43
|
return null;
|
|
43
44
|
}
|
|
44
|
-
const
|
|
45
|
+
const collectionI18n = getServerCollectionI18n(options.collection);
|
|
46
|
+
const availableLocales = sortLocalesCanonically(
|
|
47
|
+
Array.from(new Set(variants.map((document) => document.locale).filter(Boolean))),
|
|
48
|
+
{
|
|
49
|
+
defaultLocale: collectionI18n?.defaultLocale || config.defaultLocale,
|
|
50
|
+
locales: collectionI18n?.locales
|
|
51
|
+
}
|
|
52
|
+
);
|
|
45
53
|
const variantPaths = Object.fromEntries(
|
|
46
|
-
variants.filter((document) => document.
|
|
54
|
+
variants.filter((document) => document.locale && document.path).map((document) => [document.locale, document.path])
|
|
47
55
|
);
|
|
48
56
|
return {
|
|
49
57
|
...resolved,
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
58
|
+
resolved: {
|
|
59
|
+
...resolved.resolved || {},
|
|
60
|
+
requestedLocale: resolvedVariant.requestedLocale,
|
|
61
|
+
locale: resolvedVariant.resolvedLocale,
|
|
62
|
+
fallback: resolvedVariant.fallback,
|
|
63
|
+
availableLocales,
|
|
64
|
+
variantPaths
|
|
65
|
+
}
|
|
55
66
|
};
|
|
56
67
|
};
|
|
57
68
|
const getServerCollectionI18n = (collection) => {
|
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import type { H3Event } from 'h3';
|
|
2
|
-
import type { ParsedContent } from '../types/content';
|
|
2
|
+
import type { MissingDocument, ParsedContent } from '../types/content';
|
|
3
3
|
export declare function chunksFromArray<T>(arr: T[], n: number): Generator<T[], void>;
|
|
4
|
+
/**
|
|
5
|
+
* Load every locale variant for a single content id.
|
|
6
|
+
*
|
|
7
|
+
* Cache strategy:
|
|
8
|
+
* 1. Dev/prerender validate source metadata before reusing an artifact.
|
|
9
|
+
* 2. Concurrent misses for the same `(storageId, hash)` share one parse.
|
|
10
|
+
*/
|
|
11
|
+
export declare const loadContentVariants: (event: H3Event, id: string) => Promise<Array<ParsedContent | MissingDocument>>;
|
|
4
12
|
export declare const getContentsList: (event: H3Event, prefix?: string) => Promise<ParsedContent[]>;
|
|
5
13
|
export declare const getContent: (event: H3Event, id: string) => Promise<ParsedContent>;
|
package/dist/storage/contents.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { hash as ohash } from "ohash";
|
|
2
|
+
import { isRealDocument } from "../core/content/document";
|
|
2
3
|
import { splitInlineLocaleVariantId } from "../core/content/locale";
|
|
3
4
|
import { memoizeRuntimeValue } from "../integrations/nitro/context";
|
|
4
5
|
import { parseContentVariants } from "../integrations/nitro/ingest";
|
|
5
6
|
import { cacheStoreFor, getCachedContents, setCachedContents } from "./cache.js";
|
|
6
7
|
import { contentConfig, contentIgnorePredicate, getContentStorageRuntime, getContentsIds, resolveStorageId } from "./driver.js";
|
|
8
|
+
import { getProcessDocuments, usesProcessSnapshot } from "./snapshot-runtime.js";
|
|
7
9
|
import { validateContentGraph } from "./validation.js";
|
|
8
|
-
const isProduction = process.env.NODE_ENV === "production";
|
|
9
10
|
const isPrerendering = import.meta.prerender;
|
|
10
11
|
const shouldValidateAtRuntime = import.meta.dev || isPrerendering;
|
|
11
12
|
const isContentCacheArtifact = (value) => {
|
|
@@ -16,23 +17,22 @@ export function* chunksFromArray(arr, n) {
|
|
|
16
17
|
yield arr.slice(i, i + n);
|
|
17
18
|
}
|
|
18
19
|
}
|
|
19
|
-
const loadContentVariants = async (event, id) => {
|
|
20
|
+
export const loadContentVariants = async (event, id) => {
|
|
20
21
|
const runtime = getContentStorageRuntime(event);
|
|
21
22
|
const config = contentConfig();
|
|
22
23
|
const { sourceId: contentId } = splitInlineLocaleVariantId(id);
|
|
23
24
|
if (!contentIgnorePredicate(contentId)) {
|
|
24
|
-
return [{
|
|
25
|
+
return [{ id: contentId, body: null, missing: true }];
|
|
25
26
|
}
|
|
26
27
|
const storageId = await resolveStorageId(event, contentId);
|
|
27
28
|
const cachedValue = await runtime.parsedCache.getItem(storageId);
|
|
28
29
|
const cached = isContentCacheArtifact(cachedValue) ? cachedValue : null;
|
|
29
|
-
|
|
30
|
-
|
|
30
|
+
const body = await runtime.source.getItem(storageId);
|
|
31
|
+
if (body === null) {
|
|
32
|
+
return [{ id: contentId, body: null, missing: true }];
|
|
31
33
|
}
|
|
32
|
-
const meta = await runtime.source.getMeta(storageId);
|
|
33
34
|
const hash = ohash({
|
|
34
|
-
|
|
35
|
-
size: meta.size || 0,
|
|
35
|
+
body: ohash(body),
|
|
36
36
|
version: runtime.config.cacheVersion,
|
|
37
37
|
integrity: runtime.config.cacheIntegrity,
|
|
38
38
|
collections: runtime.config.collections,
|
|
@@ -46,10 +46,6 @@ const loadContentVariants = async (event, id) => {
|
|
|
46
46
|
return cached.parsed;
|
|
47
47
|
}
|
|
48
48
|
return cacheStoreFor(event).inflightContents.run(`${storageId}${hash}`, async () => {
|
|
49
|
-
const body = await runtime.source.getItem(storageId);
|
|
50
|
-
if (body === null) {
|
|
51
|
-
return [{ _id: contentId, body: null }];
|
|
52
|
-
}
|
|
53
49
|
const parsed = await parseContentVariants(contentId, body, config, { validate: true });
|
|
54
50
|
try {
|
|
55
51
|
await runtime.parsedCache.setItem(storageId, { parsed, hash });
|
|
@@ -68,7 +64,7 @@ const loadContents = async (event, prefix) => {
|
|
|
68
64
|
const result = await Promise.all(chunk.map((key) => loadContentVariants(event, key)));
|
|
69
65
|
contents.push(...result.flat());
|
|
70
66
|
}
|
|
71
|
-
const filtered = contents.filter((document) => document
|
|
67
|
+
const filtered = contents.filter(isRealDocument).filter((document) => document.path);
|
|
72
68
|
if (shouldValidateAtRuntime) {
|
|
73
69
|
const outcome = validateContentGraph(filtered, contentConfig());
|
|
74
70
|
if (!outcome.ok) {
|
|
@@ -77,7 +73,20 @@ const loadContents = async (event, prefix) => {
|
|
|
77
73
|
}
|
|
78
74
|
return filtered;
|
|
79
75
|
};
|
|
76
|
+
const snapshotDocumentsFor = async (event, prefix) => {
|
|
77
|
+
const documents = await getProcessDocuments(event);
|
|
78
|
+
if (!prefix) {
|
|
79
|
+
return documents;
|
|
80
|
+
}
|
|
81
|
+
return documents.filter((document) => {
|
|
82
|
+
const { sourceId } = splitInlineLocaleVariantId(document.id);
|
|
83
|
+
return sourceId.startsWith(prefix);
|
|
84
|
+
});
|
|
85
|
+
};
|
|
80
86
|
export const getContentsList = (event, prefix) => {
|
|
87
|
+
if (usesProcessSnapshot) {
|
|
88
|
+
return snapshotDocumentsFor(event, prefix);
|
|
89
|
+
}
|
|
81
90
|
const runtime = getContentStorageRuntime(event);
|
|
82
91
|
const cacheKey = JSON.stringify({
|
|
83
92
|
prefix,
|
|
@@ -90,25 +99,23 @@ export const getContentsList = (event, prefix) => {
|
|
|
90
99
|
});
|
|
91
100
|
return memoizeRuntimeValue(event, `contents:${cacheKey}`, async () => {
|
|
92
101
|
const cached = getCachedContents(event, cacheKey);
|
|
93
|
-
if (
|
|
102
|
+
if (cached?.length) {
|
|
94
103
|
return cached;
|
|
95
104
|
}
|
|
96
105
|
return await cacheStoreFor(event).inflightContentsList.run(cacheKey, async () => {
|
|
97
106
|
const result = await loadContents(event, prefix);
|
|
98
|
-
|
|
99
|
-
setCachedContents(event, cacheKey, result);
|
|
100
|
-
}
|
|
107
|
+
setCachedContents(event, cacheKey, result);
|
|
101
108
|
return result;
|
|
102
109
|
});
|
|
103
110
|
});
|
|
104
111
|
};
|
|
105
112
|
export const getContent = async (event, id) => {
|
|
106
113
|
const { sourceId, locale } = splitInlineLocaleVariantId(id);
|
|
107
|
-
const parsed = await loadContentVariants(event, sourceId);
|
|
114
|
+
const parsed = usesProcessSnapshot ? (await getProcessDocuments(event)).filter((document) => splitInlineLocaleVariantId(document.id).sourceId === sourceId) : (await loadContentVariants(event, sourceId)).filter(isRealDocument);
|
|
108
115
|
if (!locale) {
|
|
109
116
|
return parsed[0];
|
|
110
117
|
}
|
|
111
|
-
const match = parsed.find((document) => document.
|
|
118
|
+
const match = parsed.find((document) => document.locale === locale);
|
|
112
119
|
if (!match) {
|
|
113
120
|
console.warn(`[content] Locale variant "${locale}" not found for "${sourceId}", falling back to default`);
|
|
114
121
|
}
|
package/dist/storage/driver.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { H3Event } from 'h3';
|
|
2
2
|
import type { Storage, StorageValue } from 'unstorage';
|
|
3
|
-
import { sourceStorage, cacheStorage, cacheParsedStorage, contentConfig, contentIgnorePredicate, getContentsIds, resolveStorageId } from '../integrations/nitro/storage';
|
|
3
|
+
import { sourceStorage, cacheStorage, cacheParsedStorage, contentConfig, contentIgnorePredicate, getContentsIds, getSourceContentIds, resolveStorageId } from '../integrations/nitro/storage';
|
|
4
4
|
export interface ContentSourceDriver {
|
|
5
5
|
getKeys: (prefix?: string) => Promise<string[]>;
|
|
6
6
|
getItem: (key: string) => Promise<StorageValue | null>;
|
|
@@ -25,4 +25,4 @@ export interface ContentStorageRuntime {
|
|
|
25
25
|
now: () => Date;
|
|
26
26
|
}
|
|
27
27
|
export declare const getContentStorageRuntime: (event: H3Event) => ContentStorageRuntime;
|
|
28
|
-
export { cacheParsedStorage, cacheStorage, contentConfig, contentIgnorePredicate, getContentsIds, resolveStorageId, sourceStorage };
|
|
28
|
+
export { cacheParsedStorage, cacheStorage, contentConfig, contentIgnorePredicate, getContentsIds, getSourceContentIds, resolveStorageId, sourceStorage };
|
package/dist/storage/driver.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { sourceStorage, cacheStorage, cacheParsedStorage, contentConfig, contentIgnorePredicate, getContentsIds, resolveStorageId } from "../integrations/nitro/storage";
|
|
1
|
+
import { sourceStorage, cacheStorage, cacheParsedStorage, contentConfig, contentIgnorePredicate, getContentsIds, getSourceContentIds, resolveStorageId } from "../integrations/nitro/storage";
|
|
2
2
|
import { getContentRuntimeContext } from "../integrations/nitro/context";
|
|
3
3
|
export const getContentStorageRuntime = (event) => {
|
|
4
4
|
const runtime = getContentRuntimeContext(event);
|
|
@@ -17,6 +17,7 @@ export {
|
|
|
17
17
|
contentConfig,
|
|
18
18
|
contentIgnorePredicate,
|
|
19
19
|
getContentsIds,
|
|
20
|
+
getSourceContentIds,
|
|
20
21
|
resolveStorageId,
|
|
21
22
|
sourceStorage
|
|
22
23
|
};
|
package/dist/storage/graph.js
CHANGED
|
@@ -2,7 +2,11 @@ import { buildContentGraph } from "../core/content/graph";
|
|
|
2
2
|
import { memoizeRuntimeValue } from "../integrations/nitro/context";
|
|
3
3
|
import { contentConfig } from "./driver.js";
|
|
4
4
|
import { getContentsList } from "./contents.js";
|
|
5
|
+
import { getProcessGraph, usesProcessSnapshot } from "./snapshot-runtime.js";
|
|
5
6
|
export const getContentGraph = async (event) => {
|
|
7
|
+
if (usesProcessSnapshot) {
|
|
8
|
+
return getProcessGraph(event);
|
|
9
|
+
}
|
|
6
10
|
return await memoizeRuntimeValue(event, "graph", async () => {
|
|
7
11
|
const config = contentConfig();
|
|
8
12
|
const contents = await getContentsList(event);
|
package/dist/storage/manifest.js
CHANGED
|
@@ -31,6 +31,7 @@ export async function resolveVariant(event, canonicalKey, requestedLocale, optio
|
|
|
31
31
|
const config = getContentRuntimeConfig().content;
|
|
32
32
|
return resolveGraphVariant(await getContentGraph(event), canonicalKey, requestedLocale, {
|
|
33
33
|
defaultLocale: config.defaultLocale,
|
|
34
|
+
locales: config.locales,
|
|
34
35
|
fallback: options.fallback,
|
|
35
36
|
exact: options.exact,
|
|
36
37
|
localeFallback: config.localeFallback
|
|
@@ -40,6 +41,7 @@ export async function resolveRouteVariant(event, routePath, requestedLocale, opt
|
|
|
40
41
|
const config = getContentRuntimeConfig().content;
|
|
41
42
|
return resolveGraphRouteVariant(await getContentGraph(event), routePath, requestedLocale, {
|
|
42
43
|
defaultLocale: config.defaultLocale,
|
|
44
|
+
locales: config.locales,
|
|
43
45
|
fallback: options.fallback,
|
|
44
46
|
exact: options.exact,
|
|
45
47
|
localeFallback: config.localeFallback
|
|
@@ -56,7 +58,7 @@ export async function getIndexedContentsList(event, query) {
|
|
|
56
58
|
return await getContentsList(event);
|
|
57
59
|
}
|
|
58
60
|
const params = query.params();
|
|
59
|
-
const paths = collectQueryWhere(params?.where, (where) => typeof where.
|
|
61
|
+
const paths = collectQueryWhere(params?.where, (where) => typeof where.path !== "undefined").map((where) => where.path).filter((path) => typeof path === "string" || path instanceof RegExp);
|
|
60
62
|
const graph = await getContentGraph(event);
|
|
61
63
|
if (!paths.length && !params?.collection) {
|
|
62
64
|
return graph.documents;
|
|
@@ -17,7 +17,7 @@ const isConfiguredQuickLink = (href) => {
|
|
|
17
17
|
return Boolean(links?.[namespace]?.[key]);
|
|
18
18
|
};
|
|
19
19
|
const resolveDocumentRefLinks = async (event, content, requestedLocale) => {
|
|
20
|
-
if (!content || content.
|
|
20
|
+
if (!content || content.type !== "markdown" || !content.body) {
|
|
21
21
|
return void 0;
|
|
22
22
|
}
|
|
23
23
|
const hrefs = collectMarkdownRefLinks(content.body);
|
|
@@ -35,19 +35,19 @@ const resolveDocumentRefLinks = async (event, content, requestedLocale) => {
|
|
|
35
35
|
return [href, href];
|
|
36
36
|
}
|
|
37
37
|
if (import.meta.dev) {
|
|
38
|
-
console.warn(`[content] Could not resolve markdown ref "${href}" in "${content.
|
|
38
|
+
console.warn(`[content] Could not resolve markdown ref "${href}" in "${content.file?.path || content.id}"`);
|
|
39
39
|
}
|
|
40
40
|
return [href, href];
|
|
41
41
|
}
|
|
42
42
|
const variant = await resolveVariant(event, canonicalKey, requestedLocale);
|
|
43
43
|
if (!variant?.path) {
|
|
44
44
|
if (import.meta.dev) {
|
|
45
|
-
console.warn(`[content] Could not resolve markdown ref "${href}" in "${content.
|
|
45
|
+
console.warn(`[content] Could not resolve markdown ref "${href}" in "${content.file?.path || content.id}"`);
|
|
46
46
|
}
|
|
47
47
|
return [href, href];
|
|
48
48
|
}
|
|
49
49
|
if (import.meta.dev && requestedLocale && variant.resolvedLocale && variant.resolvedLocale !== requestedLocale) {
|
|
50
|
-
console.warn(`[content] Markdown ref "${href}" in "${content.
|
|
50
|
+
console.warn(`[content] Markdown ref "${href}" in "${content.file?.path || content.id}" fell back from locale "${requestedLocale}" to "${variant.resolvedLocale}"`);
|
|
51
51
|
}
|
|
52
52
|
const routeLocale = variant.fallback && requestedLocale ? requestedLocale : variant.resolvedLocale;
|
|
53
53
|
return [href, `${projectContentPathToLocale(variant.path, routeLocale, contentConfig().defaultLocale)}${parsed.hash}`];
|
|
@@ -63,9 +63,13 @@ export const withResolvedRefs = async (event, content, requestedLocale) => {
|
|
|
63
63
|
if (!resolvedRefs) {
|
|
64
64
|
return content;
|
|
65
65
|
}
|
|
66
|
+
const existingResolution = content.resolved;
|
|
66
67
|
return {
|
|
67
68
|
...content,
|
|
68
|
-
|
|
69
|
+
resolved: {
|
|
70
|
+
...existingResolution || {},
|
|
71
|
+
resolvedRefs
|
|
72
|
+
}
|
|
69
73
|
};
|
|
70
74
|
};
|
|
71
75
|
export const withResolvedRefsList = async (event, items, requestedLocale) => {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './snapshot-runtime.js'
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { H3Event } from 'h3';
|
|
2
|
+
import type { ParsedContent } from '../types/content';
|
|
3
|
+
import type { ContentGraph } from '../core/content/graph';
|
|
4
|
+
/**
|
|
5
|
+
* Single source of truth for "serve from the process-scoped snapshot".
|
|
6
|
+
* Prerender must stay on the request-scoped dev path — it is the phase that
|
|
7
|
+
* produces the snapshot in the first place.
|
|
8
|
+
*/
|
|
9
|
+
export declare const usesProcessSnapshot: boolean;
|
|
10
|
+
export declare const getProcessGraph: (event: H3Event) => Promise<ContentGraph>;
|
|
11
|
+
export declare const getProcessDocuments: (event: H3Event) => Promise<ParsedContent[]>;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { buildContentGraph } from "../core/content/graph";
|
|
2
|
+
import { isContentSnapshot } from "../core/content/snapshot";
|
|
3
|
+
import { cacheStorage, contentConfig } from "./driver.js";
|
|
4
|
+
export const usesProcessSnapshot = process.env.NODE_ENV === "production" && !import.meta.prerender;
|
|
5
|
+
let state = null;
|
|
6
|
+
export const getProcessGraph = async (event) => {
|
|
7
|
+
const snapshotState = await getProcessSnapshotState(event);
|
|
8
|
+
return snapshotState.graph;
|
|
9
|
+
};
|
|
10
|
+
export const getProcessDocuments = async (event) => {
|
|
11
|
+
const snapshotState = await getProcessSnapshotState(event);
|
|
12
|
+
return snapshotState.documents;
|
|
13
|
+
};
|
|
14
|
+
const getProcessSnapshotState = (event) => {
|
|
15
|
+
const config = contentConfig();
|
|
16
|
+
const integrity = config.cacheIntegrity;
|
|
17
|
+
if (state && state.integrity === integrity) {
|
|
18
|
+
return state.promise;
|
|
19
|
+
}
|
|
20
|
+
const promise = loadSnapshotState(event, integrity);
|
|
21
|
+
promise.catch(() => {
|
|
22
|
+
if (state?.promise === promise) {
|
|
23
|
+
state = null;
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
state = { integrity, promise };
|
|
27
|
+
return promise;
|
|
28
|
+
};
|
|
29
|
+
const loadSnapshotState = async (event, integrity) => {
|
|
30
|
+
const raw = await cacheStorage(event).getItem("snapshot.json");
|
|
31
|
+
if (!isContentSnapshot(raw)) {
|
|
32
|
+
throw new Error("[content] production snapshot missing or invalid \u2014 the site was built without a content snapshot. Rebuild with this package version.");
|
|
33
|
+
}
|
|
34
|
+
if (raw.integrity !== integrity) {
|
|
35
|
+
throw new Error(`[content] snapshot integrity mismatch (built: ${raw.integrity}, runtime: ${integrity}) \u2014 stale build artifact.`);
|
|
36
|
+
}
|
|
37
|
+
const config = contentConfig();
|
|
38
|
+
const graph = buildContentGraph(raw.documents, {
|
|
39
|
+
locales: config.locales,
|
|
40
|
+
defaultLocale: config.defaultLocale
|
|
41
|
+
});
|
|
42
|
+
return {
|
|
43
|
+
graph,
|
|
44
|
+
documents: raw.documents
|
|
45
|
+
};
|
|
46
|
+
};
|
|
@@ -16,7 +16,7 @@ export declare const getCanonicalContentId: (document: ParsedContent, locales?:
|
|
|
16
16
|
* - Strict collections (default): schema errors produce a `SCHEMA_VALIDATION_FAILED`
|
|
17
17
|
* failure.
|
|
18
18
|
*
|
|
19
|
-
* Also chains into `validateNavigationDocument` for `
|
|
19
|
+
* Also chains into `validateNavigationDocument` for `navigationFile: true` files,
|
|
20
20
|
* which can fail with `INVALID_NAVIGATION_YAML`.
|
|
21
21
|
*/
|
|
22
22
|
export declare const validateCollectionDocument: (document: ParsedContent, collections?: Record<string, ContentCollectionConfig>) => Result<ParsedContent, ContentError>;
|