fimo 0.7.0-experimental.2 → 0.7.0-staging.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. package/README.md +1 -1
  2. package/assets/skills/fimo-cli/references/domains.md +1 -1
  3. package/assets/skills/fimo-studio/references/custom-domains.md +1 -1
  4. package/dist/build/vite/index.d.ts.map +1 -0
  5. package/dist/build/vite/plugins/content-sync.d.ts.map +1 -0
  6. package/dist/build/vite/plugins/content-sync.test.d.ts +2 -0
  7. package/dist/build/vite/plugins/content-sync.test.d.ts.map +1 -0
  8. package/dist/build/vite/plugins/content-sync.test.js +64 -0
  9. package/dist/build/vite/plugins/data-id.d.ts.map +1 -0
  10. package/dist/build/vite/plugins/fimo-config.d.ts.map +1 -0
  11. package/dist/build/vite/plugins/fimo-config.test.d.ts +2 -0
  12. package/dist/build/vite/plugins/fimo-config.test.d.ts.map +1 -0
  13. package/dist/build/vite/plugins/fimo-config.test.js +46 -0
  14. package/dist/build/vite/plugins/overlay.d.ts.map +1 -0
  15. package/dist/build/vite/plugins/robots.d.ts.map +1 -0
  16. package/dist/build/vite/plugins/seo.d.ts.map +1 -0
  17. package/dist/build/vite/plugins/server-config.d.ts.map +1 -0
  18. package/dist/build/vite/plugins/sitemap.d.ts.map +1 -0
  19. package/dist/build/vite/plugins/translations.d.ts.map +1 -0
  20. package/dist/build/vite/plugins/translations.test.d.ts +2 -0
  21. package/dist/build/vite/plugins/translations.test.d.ts.map +1 -0
  22. package/dist/build/vite/plugins/translations.test.js +266 -0
  23. package/dist/cli/bundle.json +2 -3
  24. package/dist/cli/index.js +110670 -1196
  25. package/dist/runtime/app/FimoProviders.d.ts.map +1 -0
  26. package/dist/runtime/app/FimoScripts.d.ts.map +1 -0
  27. package/dist/runtime/app/index.d.ts.map +1 -0
  28. package/dist/runtime/app/prefetch.d.ts.map +1 -0
  29. package/dist/runtime/content/DataSourcesProvider.d.ts.map +1 -0
  30. package/dist/runtime/content/RefreshContentProvider.d.ts.map +1 -0
  31. package/dist/runtime/content/RefreshContentProvider.test.d.ts +2 -0
  32. package/dist/runtime/content/RefreshContentProvider.test.d.ts.map +1 -0
  33. package/dist/runtime/content/RefreshContentProvider.test.js +33 -0
  34. package/dist/runtime/content/parseCollectionResponse.d.ts.map +1 -0
  35. package/dist/runtime/content/parseCollectionResponse.test.d.ts +2 -0
  36. package/dist/runtime/content/parseCollectionResponse.test.d.ts.map +1 -0
  37. package/dist/runtime/content/parseCollectionResponse.test.js +20 -0
  38. package/dist/runtime/content/utils/retrieve-data-sources.d.ts.map +1 -0
  39. package/dist/runtime/core/AppErrorBoundary.d.ts.map +1 -0
  40. package/dist/runtime/core/ViteLifecycles.d.ts.map +1 -0
  41. package/dist/runtime/i18n/FimoLocaleContext.d.ts.map +1 -0
  42. package/dist/runtime/i18n/locale.d.ts.map +1 -0
  43. package/dist/runtime/i18n/locale.test.d.ts +2 -0
  44. package/dist/runtime/i18n/locale.test.d.ts.map +1 -0
  45. package/dist/runtime/i18n/locale.test.js +58 -0
  46. package/dist/runtime/iframe/ConsoleErrorProvider.d.ts.map +1 -0
  47. package/dist/runtime/iframe/ScreenshotProvider.d.ts.map +1 -0
  48. package/dist/runtime/iframe/runtime/overlay-hmr.d.ts.map +1 -0
  49. package/dist/runtime/iframe/runtime/overlay-runtime.d.ts.map +1 -0
  50. package/dist/runtime/index.d.ts +0 -3
  51. package/dist/runtime/index.d.ts.map +1 -0
  52. package/dist/runtime/index.js +0 -2
  53. package/dist/runtime/paths/get-fimo-paths.d.ts.map +1 -0
  54. package/dist/runtime/paths/get-fimo-paths.test.d.ts +2 -0
  55. package/dist/runtime/paths/get-fimo-paths.test.d.ts.map +1 -0
  56. package/dist/runtime/paths/get-fimo-paths.test.js +69 -0
  57. package/dist/runtime/paths/index.d.ts.map +1 -0
  58. package/dist/runtime/paths/types.d.ts.map +1 -0
  59. package/dist/runtime/primitives/components/Boolean.d.ts.map +1 -0
  60. package/dist/runtime/primitives/components/Date.d.ts.map +1 -0
  61. package/dist/runtime/primitives/components/Image.d.ts.map +1 -0
  62. package/dist/runtime/primitives/components/RichText.d.ts.map +1 -0
  63. package/dist/runtime/primitives/components/StaticImage.d.ts.map +1 -0
  64. package/dist/runtime/primitives/components/Text.d.ts.map +1 -0
  65. package/dist/runtime/primitives/components/Video.d.ts.map +1 -0
  66. package/dist/runtime/primitives/components/index.d.ts.map +1 -0
  67. package/dist/runtime/primitives/index.d.ts.map +1 -0
  68. package/dist/runtime/primitives/lib/image-optimization.d.ts.map +1 -0
  69. package/dist/runtime/primitives/lib/index.d.ts.map +1 -0
  70. package/dist/runtime/primitives/lib/primitives.d.ts.map +1 -0
  71. package/dist/runtime/primitives/lib/query.d.ts.map +1 -0
  72. package/dist/runtime/primitives/lib/template.d.ts.map +1 -0
  73. package/dist/runtime/primitives/lib/useFimoLiveValue.d.ts.map +1 -0
  74. package/dist/runtime/primitives/public-surface.test.d.ts +2 -0
  75. package/dist/runtime/primitives/public-surface.test.d.ts.map +1 -0
  76. package/dist/runtime/primitives/public-surface.test.js +49 -0
  77. package/dist/runtime/primitives/translations.d.ts.map +1 -0
  78. package/dist/runtime/react-router/index.d.ts.map +1 -0
  79. package/dist/runtime/react-router/navigation-utils.d.ts.map +1 -0
  80. package/dist/runtime/react-router/navigation.d.ts.map +1 -0
  81. package/dist/runtime/react-router/navigation.test.d.ts +2 -0
  82. package/dist/runtime/react-router/navigation.test.d.ts.map +1 -0
  83. package/dist/runtime/react-router/navigation.test.js +35 -0
  84. package/dist/runtime/react-router/routes.d.ts.map +1 -0
  85. package/dist/runtime/react-router/routes.test.d.ts +2 -0
  86. package/dist/runtime/react-router/routes.test.d.ts.map +1 -0
  87. package/dist/runtime/react-router/routes.test.js +67 -0
  88. package/dist/runtime/routing/AppResetScrollOnNavigate.d.ts.map +1 -0
  89. package/dist/runtime/routing/AppRoutesProvider.d.ts.map +1 -0
  90. package/dist/runtime/seo/buildSeoForPath.d.ts.map +1 -0
  91. package/dist/runtime/seo/htmlProps.d.ts.map +1 -0
  92. package/dist/runtime/seo/index.d.ts.map +1 -0
  93. package/dist/runtime/seo/resolver.d.ts.map +1 -0
  94. package/dist/runtime/shared/fimo-config.server.d.ts.map +1 -0
  95. package/dist/runtime/shared/fimo-config.types.d.ts.map +1 -0
  96. package/dist/runtime/t/OptionalTracking.d.ts.map +1 -0
  97. package/dist/runtime/t/OptionalTracking.test.d.ts +2 -0
  98. package/dist/runtime/t/OptionalTracking.test.d.ts.map +1 -0
  99. package/dist/runtime/t/OptionalTracking.test.js +11 -0
  100. package/dist/runtime/t/Pageview.d.ts.map +1 -0
  101. package/dist/runtime/templates.d.ts.map +1 -0
  102. package/dist/scripts/generated-types.test.js +212 -0
  103. package/dist/scripts/lint-translation-keys.test.d.ts +1 -0
  104. package/dist/scripts/lint-translation-keys.test.js +16 -0
  105. package/dist/scripts/sync-schemas.test.d.ts +1 -0
  106. package/dist/scripts/sync-schemas.test.js +144 -0
  107. package/dist/scripts/validate-route-metadata.test.d.ts +1 -0
  108. package/dist/scripts/validate-route-metadata.test.js +116 -0
  109. package/dist/scripts/validate-schemas.test.d.ts +1 -0
  110. package/dist/scripts/validate-schemas.test.js +263 -0
  111. package/package.json +13 -31
  112. package/scripts/add-ext.mjs +47 -0
  113. package/scripts/bump-version.mjs +58 -0
  114. package/scripts/bundle-cli.mjs +123 -0
  115. package/scripts/install-cli.mjs +36 -0
  116. package/scripts/lib/channels.mjs +70 -0
  117. package/scripts/lib/dev-release-state.mjs +44 -0
  118. package/scripts/lib/dev-release-state.test.ts +36 -0
  119. package/scripts/lib/postinstall-onboarding.test.ts +82 -0
  120. package/scripts/lib/release-core.mjs +225 -0
  121. package/scripts/lib/release-core.test.ts +147 -0
  122. package/scripts/migration-qa-gate.test.ts +155 -0
  123. package/scripts/publish-npm.mjs +180 -0
  124. package/templates/react-router/package.json +1 -1
  125. package/templates/react-router/src/pages/Index.tsx +1 -1
  126. package/dist/runtime/content/client/createContentClient.d.ts +0 -5
  127. package/dist/runtime/content/client/createContentClient.js +0 -300
  128. package/dist/runtime/content/client/createSingletonClient.d.ts +0 -5
  129. package/dist/runtime/content/client/createSingletonClient.js +0 -108
  130. package/dist/runtime/content/client/internal.d.ts +0 -44
  131. package/dist/runtime/content/client/internal.js +0 -236
  132. package/dist/runtime/content/client/types.d.ts +0 -136
  133. package/dist/runtime/content/client/useQueryLocale.d.ts +0 -2
  134. package/dist/runtime/content/client/useQueryLocale.js +0 -6
  135. /package/dist/{runtime/content/client/types.js → scripts/generated-types.test.d.ts} +0 -0
@@ -1,108 +0,0 @@
1
- import { useMutation, useQuery, useQueryClient, useSuspenseQuery } from '@tanstack/react-query';
2
- import { apiBase, buildReadPath, fimoHeaders, interpretSchema, readSingletonLocale, referenceTargetUids, resolveClientHandle, splitWritePayload, validateReferences, withMutationLocale, wrapEntry, } from './internal.js';
3
- import { useQueryLocale } from './useQueryLocale.js';
4
- export function createSingletonClient(config) {
5
- const references = config.references ?? {};
6
- const info = interpretSchema(config.schema);
7
- if (!info.isSingleton) {
8
- throw new Error(`Schema "${info.uid}" is a collection — use createContentClient instead.`);
9
- }
10
- validateReferences(info, references);
11
- const meta = { uid: info.uid, pascal: info.pascal, localized: info.localized };
12
- const self = { wrapWithSource, meta };
13
- const resolve = (uid) => uid === info.uid ? self : resolveClientHandle(references[uid]);
14
- // Which reference fields point at a localized schema decides whether a
15
- // non-localized singleton read must still send a locale. Target metas live
16
- // on other modules in a possibly-cyclic graph, so this is derived lazily on
17
- // first request, never at module init.
18
- let localizedReferenceFields = null;
19
- function getLocalizedReferenceFields() {
20
- if (localizedReferenceFields) {
21
- return localizedReferenceFields;
22
- }
23
- const fields = new Set();
24
- for (const [key, field] of info.fields) {
25
- if (field.type !== 'reference') {
26
- continue;
27
- }
28
- const localizedTarget = referenceTargetUids(field).some((uid) => resolve(uid)?.meta?.localized !== false);
29
- if (localizedTarget) {
30
- fields.add(key);
31
- }
32
- }
33
- localizedReferenceFields = fields;
34
- return fields;
35
- }
36
- function wrapWithSource(entry) {
37
- return wrapEntry(info, entry, { alwaysIncludeLocale: info.localized, resolve });
38
- }
39
- function readLocale(options, fallbackLocale) {
40
- return fallbackLocale === undefined
41
- ? readSingletonLocale(options, info.localized, getLocalizedReferenceFields())
42
- : readSingletonLocale(options, info.localized, getLocalizedReferenceFields(), fallbackLocale);
43
- }
44
- function readPath(url, options) {
45
- return buildReadPath(url, readLocale(options), options.populate, options.localeFallbacks);
46
- }
47
- async function get(options = {}) {
48
- const res = await fetch(`${apiBase()}${readPath(`/documents/${info.uid}`, options)}`, {
49
- headers: fimoHeaders(),
50
- });
51
- if (!res.ok) {
52
- throw new Error(await res.text());
53
- }
54
- const data = await res.json();
55
- return wrapWithSource(data.data);
56
- }
57
- async function update(payload) {
58
- const write = splitWritePayload(payload);
59
- const url = buildReadPath(`/documents/${info.uid}`, readLocale({ locale: write.locale }), undefined);
60
- const res = await fetch(`${apiBase()}${url}`, {
61
- method: 'PUT',
62
- headers: fimoHeaders({ 'Content-Type': 'application/json' }),
63
- body: JSON.stringify({ data: write.data }),
64
- });
65
- if (!res.ok) {
66
- throw new Error(await res.text());
67
- }
68
- const data = await res.json();
69
- return wrapWithSource(data.data);
70
- }
71
- const qk = {
72
- root: [info.pascal],
73
- document: (options = {}) => [info.pascal, 'document', options.locale, options.populate],
74
- };
75
- function useGet(options = {}) {
76
- const locale = readLocale(options, useQueryLocale(options.locale));
77
- const localizedOptions = { ...options, locale };
78
- return useQuery({
79
- queryKey: qk.document(localizedOptions),
80
- queryFn: () => get(localizedOptions),
81
- });
82
- }
83
- function useSuspenseGet(options = {}) {
84
- const locale = readLocale(options, useQueryLocale(options.locale));
85
- const localizedOptions = { ...options, locale };
86
- return useSuspenseQuery({
87
- queryKey: qk.document(localizedOptions),
88
- queryFn: () => get(localizedOptions),
89
- });
90
- }
91
- function useUpdate() {
92
- const qc = useQueryClient();
93
- const activeLocale = useQueryLocale();
94
- return useMutation({
95
- mutationFn: (payload) => update(withMutationLocale(payload, activeLocale)),
96
- onSuccess: () => qc.invalidateQueries({ queryKey: qk.root }),
97
- });
98
- }
99
- return {
100
- meta,
101
- wrapWithSource,
102
- get,
103
- update,
104
- useGet,
105
- useSuspenseGet,
106
- useUpdate,
107
- };
108
- }
@@ -1,44 +0,0 @@
1
- import type { ContentClientHandle, ContentModuleRef, ContentSchema, ContentSchemaField } from './types.js';
2
- export interface InterpretedSchema {
3
- uid: string;
4
- pascal: string;
5
- localized: boolean;
6
- isSingleton: boolean;
7
- fields: ReadonlyArray<readonly [string, ContentSchemaField]>;
8
- }
9
- export declare function interpretSchema(schema: ContentSchema): InterpretedSchema;
10
- export declare function referenceTargetUids(field: ContentSchemaField): readonly string[];
11
- export declare function validateReferences(info: InterpretedSchema, references: Readonly<Record<string, ContentModuleRef>>): void;
12
- export declare function apiBase(): string;
13
- export declare function defaultLocale(): string;
14
- export declare function fimoHeaders(extra?: Record<string, string>): Record<string, string>;
15
- interface LocaleReadOptions {
16
- locale?: string;
17
- populate?: string | readonly string[];
18
- }
19
- export declare function readCollectionLocale(options: LocaleReadOptions, fallbackLocale?: string): string;
20
- export declare function readSingletonLocale(options: LocaleReadOptions, ownerUsesLocale: boolean, localizedReferenceFields: ReadonlySet<string>, fallbackLocale?: string): string | undefined;
21
- export declare function buildReadPath(url: string, locale: string | undefined, populate: string | readonly string[] | undefined, localeFallbacks?: boolean): string;
22
- export declare function splitWritePayload(payload: Record<string, unknown>): {
23
- data: Record<string, unknown>;
24
- locale?: string;
25
- documentId?: string;
26
- };
27
- export declare function withMutationLocale<T extends object>(payload: T, activeLocale: string): T & {
28
- locale: string;
29
- };
30
- type ReferenceResolver = (uid: string) => ContentClientHandle | undefined;
31
- /**
32
- * A reference is either a client or a module namespace whose default export
33
- * is the client. Only ever called at request time — unwrapping a namespace's
34
- * `default` mid-cycle would read an uninitialized binding. A namespace can
35
- * plausibly carry BOTH a re-exported wrapWithSource and a default client, so
36
- * prefer whichever shape carries meta — the locale rules depend on it.
37
- */
38
- export declare function resolveClientHandle(ref: ContentModuleRef | undefined): ContentClientHandle | undefined;
39
- export declare function wrapEntry(info: InterpretedSchema, entry: Record<string, any>, options: {
40
- alwaysIncludeLocale: boolean;
41
- resolve: ReferenceResolver;
42
- }): Record<string, unknown>;
43
- export {};
44
- //# sourceMappingURL=internal.d.ts.map
@@ -1,236 +0,0 @@
1
- import { pascalCase } from 'change-case';
2
- // @ts-ignore - virtual module provided by fimoConfigPlugin in fimo/vite
3
- import fimoConfig from 'virtual:fimo-config';
4
- import { FimoBoolean, FimoMedia, FimoRichText, FimoString } from '../../primitives/lib/primitives.js';
5
- export function interpretSchema(schema) {
6
- if (!schema || typeof schema.uid !== 'string' || schema.uid.length === 0) {
7
- throw new Error('Content schema is missing a "uid".');
8
- }
9
- return {
10
- uid: schema.uid,
11
- pascal: pascalCase(schema.uid),
12
- localized: schema.i18n?.enabled !== false,
13
- isSingleton: schema.isSingleton ?? false,
14
- // Codegen tolerates malformed field values (null, arrays, primitives) by
15
- // treating them as untyped passthrough fields — mirror that.
16
- fields: Object.entries(schema.fields ?? {}).map(([key, value]) => [key, value && typeof value === 'object' && !Array.isArray(value) ? value : {}]),
17
- };
18
- }
19
- // Codegen treats an empty or non-string-bearing `targets` array as absent and
20
- // falls back to the monomorphic `target` — mirror that normalization so the
21
- // polymorphic/fixed decision, validation, and the singleton locale rule agree.
22
- function polymorphicTargetUids(field) {
23
- if (!Array.isArray(field.targets)) {
24
- return undefined;
25
- }
26
- const targets = field.targets.filter((uid) => typeof uid === 'string');
27
- return targets.length > 0 ? targets : undefined;
28
- }
29
- export function referenceTargetUids(field) {
30
- return polymorphicTargetUids(field) ?? (field.target ? [field.target] : []);
31
- }
32
- export function validateReferences(info, references) {
33
- for (const [key, field] of info.fields) {
34
- if (field.type !== 'reference') {
35
- continue;
36
- }
37
- for (const uid of referenceTargetUids(field)) {
38
- if (uid !== info.uid && !(uid in references)) {
39
- throw new Error(`Schema "${info.uid}" field "${key}" references "${uid}", but "${uid}" is missing from the client's references map.`);
40
- }
41
- }
42
- }
43
- }
44
- export function apiBase() {
45
- // @ts-ignore - import.meta.env is a Vite feature, replaced at build time for both client and SSR
46
- return import.meta.env.VITE_API_URL;
47
- }
48
- export function defaultLocale() {
49
- return fimoConfig.i18n?.defaultLocale ?? 'en';
50
- }
51
- export function fimoHeaders(extra) {
52
- const h = { ...extra };
53
- // @ts-ignore - import.meta.env is a Vite feature
54
- const branch = import.meta.env.VITE_FIMO_BRANCH;
55
- if (branch) {
56
- h['X-Fimo-Branch'] = branch;
57
- }
58
- return h;
59
- }
60
- function populateFields(populate) {
61
- if (populate == null) {
62
- return [];
63
- }
64
- return typeof populate === 'string' ? [populate] : [...populate];
65
- }
66
- export function readCollectionLocale(options, fallbackLocale = defaultLocale()) {
67
- return options.locale ?? fallbackLocale;
68
- }
69
- export function readSingletonLocale(options, ownerUsesLocale, localizedReferenceFields, fallbackLocale = defaultLocale()) {
70
- const populatesLocalizedTarget = populateFields(options.populate).some((field) => localizedReferenceFields.has(field));
71
- return ownerUsesLocale || populatesLocalizedTarget ? (options.locale ?? fallbackLocale) : undefined;
72
- }
73
- export function buildReadPath(url, locale, populate, localeFallbacks) {
74
- const u = new URL(url, 'http://fimo.local');
75
- if (locale) {
76
- u.searchParams.set('locale', locale);
77
- }
78
- if (populate != null) {
79
- u.searchParams.set('populate', typeof populate === 'string' ? populate : populate.join(','));
80
- }
81
- if (localeFallbacks) {
82
- u.searchParams.set('localeFallbacks', 'true');
83
- }
84
- return `${u.pathname}${u.search}`;
85
- }
86
- export function splitWritePayload(payload) {
87
- const { id, entryId, documentId, locale, createdAt, updatedAt, ...data } = payload;
88
- delete data.__fimo;
89
- void id;
90
- void entryId;
91
- void createdAt;
92
- void updatedAt;
93
- return {
94
- data,
95
- ...(typeof locale === 'string' && locale.length > 0 ? { locale } : {}),
96
- ...(typeof documentId === 'string' && documentId.length > 0 ? { documentId } : {}),
97
- };
98
- }
99
- export function withMutationLocale(payload, activeLocale) {
100
- const locale = payload.locale;
101
- return { ...payload, locale: locale ?? activeLocale };
102
- }
103
- function isPopulatedEntry(value) {
104
- if (value == null || typeof value !== 'object') {
105
- return false;
106
- }
107
- const entry = value;
108
- const fimo = entry.__fimo;
109
- return (typeof entry.id === 'string' &&
110
- fimo != null &&
111
- typeof fimo === 'object' &&
112
- typeof fimo.contentType === 'string');
113
- }
114
- function asClientHandle(candidate) {
115
- if (candidate == null || typeof candidate !== 'object') {
116
- return undefined;
117
- }
118
- const handle = candidate;
119
- return typeof handle.wrapWithSource === 'function' ? handle : undefined;
120
- }
121
- /**
122
- * A reference is either a client or a module namespace whose default export
123
- * is the client. Only ever called at request time — unwrapping a namespace's
124
- * `default` mid-cycle would read an uninitialized binding. A namespace can
125
- * plausibly carry BOTH a re-exported wrapWithSource and a default client, so
126
- * prefer whichever shape carries meta — the locale rules depend on it.
127
- */
128
- export function resolveClientHandle(ref) {
129
- if (ref == null) {
130
- return undefined;
131
- }
132
- const direct = asClientHandle(ref);
133
- const viaDefault = asClientHandle(ref.default);
134
- if (viaDefault?.meta) {
135
- return viaDefault;
136
- }
137
- if (direct?.meta) {
138
- return direct;
139
- }
140
- return direct ?? viaDefault;
141
- }
142
- function unresolvableReference(uid) {
143
- // The template's equivalent was a compile-time import error; degrading to
144
- // silently unwrapped values would kill inline editing invisibly instead.
145
- return new Error(`Cannot wrap populated reference to "${uid}": its module did not resolve to a content client.`);
146
- }
147
- /**
148
- * Populated polymorphic entries carry their type marker; the wrapper picks
149
- * the right per-type wrapping and stamps a top-level $type so the generated
150
- * union narrows in a switch. Raw (unpopulated) values and types outside the
151
- * field's declared targets pass through untouched.
152
- */
153
- function wrapPolymorphic(value, targetUids, resolve) {
154
- if (!isPopulatedEntry(value)) {
155
- return value;
156
- }
157
- const contentType = typeof value.__fimo.contentType === 'string' ? value.__fimo.contentType : null;
158
- if (!contentType || !targetUids.includes(contentType)) {
159
- return value;
160
- }
161
- const target = resolve(contentType);
162
- if (!target) {
163
- throw unresolvableReference(contentType);
164
- }
165
- const wrapped = target.wrapWithSource(value);
166
- wrapped.$type = contentType;
167
- return wrapped;
168
- }
169
- function wrapReference(value, uid, resolve) {
170
- if (!isPopulatedEntry(value)) {
171
- return value;
172
- }
173
- const target = resolve(uid);
174
- if (!target) {
175
- throw unresolvableReference(uid);
176
- }
177
- return target.wrapWithSource(value);
178
- }
179
- function wrapField(field, value, source, resolve) {
180
- switch (field.type) {
181
- case 'string':
182
- return value != null ? new FimoString(value, source) : value;
183
- case 'richtext':
184
- return value != null ? new FimoRichText(value, source) : value;
185
- case 'boolean':
186
- return value != null ? new FimoBoolean(value, source) : value;
187
- case 'media':
188
- if (field.multiple) {
189
- return (value?.map((m, i) => new FimoMedia(m, `${source}[${i}]`)) ?? value);
190
- }
191
- return value != null ? new FimoMedia(value, source) : value;
192
- case 'reference': {
193
- const polymorphic = polymorphicTargetUids(field);
194
- if (polymorphic) {
195
- if (field.many) {
196
- return Array.isArray(value) ? value.map((item) => wrapPolymorphic(item, polymorphic, resolve)) : value;
197
- }
198
- return wrapPolymorphic(value, polymorphic, resolve);
199
- }
200
- const uid = field.target;
201
- if (!uid) {
202
- return value;
203
- }
204
- if (field.many) {
205
- return Array.isArray(value) ? value.map((item) => wrapReference(item, uid, resolve)) : value;
206
- }
207
- return wrapReference(value, uid, resolve);
208
- }
209
- default:
210
- return value;
211
- }
212
- }
213
- export function wrapEntry(info, entry, options) {
214
- const id = entry.id;
215
- const entryId = entry.entryId;
216
- const documentId = entry.documentId ?? id;
217
- const locale = entry.locale ?? defaultLocale();
218
- const sourcePrefix = `${info.pascal}.id:${id}:${encodeURIComponent(locale)}`;
219
- const entryFimo = entry.__fimo && typeof entry.__fimo === 'object' ? entry.__fimo : {};
220
- const wrapped = {
221
- id,
222
- entryId,
223
- documentId,
224
- slug: entry.slug != null ? new FimoString(entry.slug, `${sourcePrefix}.slug`) : entry.slug,
225
- ...(options.alwaysIncludeLocale || entry.locale ? { locale } : {}),
226
- createdAt: entry.createdAt,
227
- updatedAt: entry.updatedAt,
228
- __fimo: {
229
- contentType: typeof entryFimo.contentType === 'string' ? entryFimo.contentType : info.uid,
230
- },
231
- };
232
- for (const [key, field] of info.fields) {
233
- wrapped[key] = wrapField(field, entry[key], `${sourcePrefix}.${key}`, options.resolve);
234
- }
235
- return wrapped;
236
- }
@@ -1,136 +0,0 @@
1
- import type { InfiniteData, UseInfiniteQueryResult, UseMutationResult, UseQueryResult, UseSuspenseQueryResult } from '@tanstack/react-query';
2
- import type { Fields, Populate, PopulatedResult, ProjectedWithPopulate, Query } from '../../primitives/lib/query.js';
3
- /**
4
- * Result shape of a read: the entity with populated references applied and
5
- * field projection narrowed — the runtime equivalent of the generated
6
- * `{Uid}Result` alias.
7
- */
8
- export type ContentResult<T extends {
9
- id: string;
10
- }, TFields extends Fields<T> | undefined = undefined, TPopulate extends Populate<T> | undefined = undefined> = ProjectedWithPopulate<PopulatedResult<T, TPopulate> & {
11
- id: string;
12
- }, TFields, TPopulate>;
13
- /**
14
- * The schema definition as written in `src/schemas/<uid>.json`. The factory
15
- * interprets it directly — the schema is the descriptor, so generated code
16
- * never transcribes field shapes into a second format that could drift.
17
- */
18
- export interface ContentSchemaField {
19
- type?: string;
20
- required?: boolean;
21
- /** Media fields: multiple assets. */
22
- multiple?: boolean;
23
- /** Reference fields: to-many. */
24
- many?: boolean;
25
- /** Reference fields: target schema uid (may be this schema's own uid). */
26
- target?: string;
27
- /** Polymorphic reference fields: allowed target schema uids. */
28
- targets?: readonly string[];
29
- }
30
- export interface ContentSchema {
31
- uid: string;
32
- name?: string;
33
- isSingleton?: boolean;
34
- i18n?: {
35
- enabled?: boolean;
36
- };
37
- fields?: Readonly<Record<string, ContentSchemaField>>;
38
- }
39
- export interface ContentModuleMeta {
40
- readonly uid: string;
41
- readonly pascal: string;
42
- readonly localized: boolean;
43
- }
44
- export interface ContentClientHandle {
45
- wrapWithSource: (entry: Record<string, any>) => unknown;
46
- meta: ContentModuleMeta;
47
- }
48
- /**
49
- * A cross-referenced generated module — either a client directly, or a module
50
- * namespace whose default export is the client. Generated modules for schemas
51
- * that reference each other form ESM cycles, so the factory only reads
52
- * properties off a ref lazily at request time, never while the client is
53
- * being constructed — a namespace import is safe to pass here even mid-cycle.
54
- */
55
- export type ContentModuleRef = ContentClientHandle | {
56
- default: ContentClientHandle;
57
- };
58
- export interface ContentClientConfig {
59
- schema: ContentSchema;
60
- /**
61
- * Every OTHER schema module this schema references, keyed by uid —
62
- * `references: { Author, Video }` with namespace imports. Self-references
63
- * resolve internally and never appear here.
64
- */
65
- references?: Readonly<Record<string, ContentModuleRef>>;
66
- }
67
- export interface ContentReadOptions<TPopulate> {
68
- locale?: string;
69
- populate?: TPopulate;
70
- localeFallbacks?: boolean;
71
- }
72
- export interface CollectionPageInfo {
73
- readonly limit: number;
74
- readonly offset: number;
75
- readonly total: number;
76
- readonly hasMore: boolean;
77
- readonly nextOffset: number | null;
78
- }
79
- export interface CollectionPage<TItem> {
80
- readonly items: TItem[];
81
- readonly pageInfo: CollectionPageInfo;
82
- }
83
- export type InfiniteListResult<TItem> = UseInfiniteQueryResult<InfiniteData<CollectionPage<TItem>>, Error> & {
84
- readonly items: TItem[];
85
- readonly total: number;
86
- readonly hasMore: boolean;
87
- readonly loadMore: () => ReturnType<UseInfiniteQueryResult<InfiniteData<CollectionPage<TItem>>, Error>['fetchNextPage']>;
88
- readonly isLoadingMore: boolean;
89
- };
90
- export interface CollectionContentClient<T extends {
91
- id: string;
92
- }, TInput> {
93
- readonly meta: ContentModuleMeta;
94
- wrapWithSource(entry: Record<string, any>): T;
95
- getById<TPopulate extends Populate<T> | undefined = undefined>(id: string, options?: ContentReadOptions<TPopulate>): Promise<ContentResult<T, undefined, TPopulate>>;
96
- getBySlug<TPopulate extends Populate<T> | undefined = undefined>(slug: string, options?: ContentReadOptions<TPopulate>): Promise<ContentResult<T, undefined, TPopulate> | null>;
97
- getByField<TPopulate extends Populate<T> | undefined = undefined>(fieldName: string, value: string, options?: ContentReadOptions<TPopulate>): Promise<ContentResult<T, undefined, TPopulate> | null>;
98
- list<TFields extends Fields<T> | undefined = undefined, TPopulate extends Populate<T> | undefined = undefined>(params?: Query<T, TFields, TPopulate>): Promise<CollectionPage<ContentResult<T, TFields, TPopulate>>>;
99
- get<TFields extends Fields<T> | undefined = undefined, TPopulate extends Populate<T> | undefined = undefined>(params?: Query<T, TFields, TPopulate>): Promise<ContentResult<T, TFields, TPopulate>[]>;
100
- create(payload: TInput): Promise<T>;
101
- update(id: string, payload: Partial<TInput>): Promise<T>;
102
- remove(id: string, options?: {
103
- locale?: string;
104
- }): Promise<void>;
105
- useGetById<TPopulate extends Populate<T> | undefined = undefined>(id: string, options?: ContentReadOptions<TPopulate>): UseQueryResult<ContentResult<T, undefined, TPopulate>, Error>;
106
- useGetBySlug<TPopulate extends Populate<T> | undefined = undefined>(slug: string, options?: ContentReadOptions<TPopulate>): UseQueryResult<ContentResult<T, undefined, TPopulate> | null, Error>;
107
- useGetByField<TPopulate extends Populate<T> | undefined = undefined>(fieldName: string, value: string, options?: ContentReadOptions<TPopulate>): UseQueryResult<ContentResult<T, undefined, TPopulate> | null, Error>;
108
- useGet<TFields extends Fields<T> | undefined = undefined, TPopulate extends Populate<T> | undefined = undefined>(params?: Query<T, TFields, TPopulate>): UseQueryResult<ContentResult<T, TFields, TPopulate>[], Error>;
109
- useList<TFields extends Fields<T> | undefined = undefined, TPopulate extends Populate<T> | undefined = undefined>(params?: Query<T, TFields, TPopulate>): UseQueryResult<CollectionPage<ContentResult<T, TFields, TPopulate>>, Error>;
110
- useInfiniteList<TFields extends Fields<T> | undefined = undefined, TPopulate extends Populate<T> | undefined = undefined>(params?: Omit<Query<T, TFields, TPopulate>, 'offset'>): InfiniteListResult<ContentResult<T, TFields, TPopulate>>;
111
- useSuspenseGetById<TPopulate extends Populate<T> | undefined = undefined>(id: string, options?: ContentReadOptions<TPopulate>): UseSuspenseQueryResult<ContentResult<T, undefined, TPopulate>, Error>;
112
- useSuspenseGetBySlug<TPopulate extends Populate<T> | undefined = undefined>(slug: string, options?: ContentReadOptions<TPopulate>): UseSuspenseQueryResult<ContentResult<T, undefined, TPopulate> | null, Error>;
113
- useSuspenseGetByField<TPopulate extends Populate<T> | undefined = undefined>(fieldName: string, value: string, options?: ContentReadOptions<TPopulate>): UseSuspenseQueryResult<ContentResult<T, undefined, TPopulate> | null, Error>;
114
- useSuspenseGet<TFields extends Fields<T> | undefined = undefined, TPopulate extends Populate<T> | undefined = undefined>(params?: Query<T, TFields, TPopulate>): UseSuspenseQueryResult<ContentResult<T, TFields, TPopulate>[], Error>;
115
- useCreate(): UseMutationResult<T, Error, TInput>;
116
- useUpdate(): UseMutationResult<T, Error, {
117
- id: string;
118
- locale?: string;
119
- } & Partial<TInput>>;
120
- useRemove(): UseMutationResult<void, Error, string | {
121
- id: string;
122
- locale?: string;
123
- }>;
124
- }
125
- export interface SingletonContentClient<T extends {
126
- id: string;
127
- }, TInput> {
128
- readonly meta: ContentModuleMeta;
129
- wrapWithSource(entry: Record<string, any>): T;
130
- get<TPopulate extends Populate<T> | undefined = undefined>(options?: ContentReadOptions<TPopulate>): Promise<ContentResult<T, undefined, TPopulate>>;
131
- update(payload: Partial<TInput>): Promise<T>;
132
- useGet<TPopulate extends Populate<T> | undefined = undefined>(options?: ContentReadOptions<TPopulate>): UseQueryResult<ContentResult<T, undefined, TPopulate>, Error>;
133
- useSuspenseGet<TPopulate extends Populate<T> | undefined = undefined>(options?: ContentReadOptions<TPopulate>): UseSuspenseQueryResult<ContentResult<T, undefined, TPopulate>, Error>;
134
- useUpdate(): UseMutationResult<T, Error, Partial<TInput>>;
135
- }
136
- //# sourceMappingURL=types.d.ts.map
@@ -1,2 +0,0 @@
1
- export declare function useQueryLocale(locale?: string): string;
2
- //# sourceMappingURL=useQueryLocale.d.ts.map
@@ -1,6 +0,0 @@
1
- import { useLocale } from '../../i18n/FimoLocaleContext.js';
2
- import { defaultLocale } from './internal.js';
3
- export function useQueryLocale(locale) {
4
- const activeLocale = useLocale().locale;
5
- return locale ?? activeLocale ?? defaultLocale();
6
- }