fimo 0.9.0 → 0.10.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.
- package/assets/content-templates/types-template.eta +30 -3
- package/assets/skills/fimo-cli/references/content.md +76 -4
- package/assets/skills/fimo-cli/references/locales.md +2 -0
- package/assets/skills/fimo-cli/references/webhooks.md +4 -0
- package/assets/skills/fimo-code/references/content.md +62 -4
- package/assets/skills/fimo-studio/references/cms.md +13 -0
- package/assets/skills/fimo-studio/references/webhooks.md +1 -1
- package/dist/cli/bundle.json +1 -1
- package/dist/cli/index.js +14 -14
- package/dist/runtime/primitives/components/RichText.d.ts +2 -2
- package/dist/runtime/primitives/components/RichText.js +5 -3
- package/dist/runtime/primitives/lib/query.d.ts +1 -1
- package/dist/scripts/validate-schemas.js +32 -4
- package/package.json +1 -1
- package/release.json +2 -2
- package/templates/react-router/package.json +1 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { type ComponentPropsWithoutRef } from 'react';
|
|
2
2
|
import { type FimoRichText, type FimoRichTextComponents } from '../lib/index.js';
|
|
3
3
|
type RichTextProps = {
|
|
4
|
-
value: FimoRichText;
|
|
4
|
+
value: FimoRichText | null | undefined;
|
|
5
5
|
components?: FimoRichTextComponents;
|
|
6
6
|
} & Omit<ComponentPropsWithoutRef<'div'>, 'children'>;
|
|
7
|
-
export declare function RichText({ value, components, ...props }: RichTextProps): import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
export declare function RichText({ value, components, ...props }: RichTextProps): import("react/jsx-runtime").JSX.Element | null;
|
|
8
8
|
export {};
|
|
9
9
|
//# sourceMappingURL=RichText.d.ts.map
|
|
@@ -129,7 +129,9 @@ function renderNode(node, components, key) {
|
|
|
129
129
|
return _jsx(Fragment, { children: children }, key);
|
|
130
130
|
}
|
|
131
131
|
export function RichText({ value, components, ...props }) {
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
|
|
132
|
+
const { value: liveContent, ref } = useFimoLiveValue(value?.content ?? null);
|
|
133
|
+
if (!value || !liveContent) {
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
return (_jsx("div", { ref: ref, ...props, "data-fimo-source": value[FIMO_SOURCE], "data-fimo-richtext": "", children: renderNode(liveContent, components, 0) }));
|
|
135
137
|
}
|
|
@@ -40,7 +40,7 @@ export type ManyReferenceOps = {
|
|
|
40
40
|
$contains?: string;
|
|
41
41
|
$null?: boolean;
|
|
42
42
|
};
|
|
43
|
-
export type FilterFor<T> = [T] extends [FimoString | string] ? string | StringOps : [T] extends [FimoBoolean | boolean] ? boolean | BoolOps : [T] extends [FimoDate | Date] ? string | DateOps : [T] extends [number] ? number | NumberOps : [T] extends [FimoPolymorphicReference | null] ? never : [T] extends [FimoPolymorphicReference[]] ? never : [T] extends [FimoReference | null] ? string | null | ReferenceOps : [T] extends [FimoReference[]] ? string | ManyReferenceOps : [T] extends [FimoMedia | FimoMedia[]] ? NullOnlyOps : [T] extends [FimoRichText] ? string | StringOps : NullOnlyOps;
|
|
43
|
+
export type FilterFor<T> = [T] extends [FimoString | string] ? string | StringOps : [T] extends [FimoBoolean | boolean] ? boolean | BoolOps : [T] extends [FimoDate | Date] ? string | DateOps : [T] extends [number] ? number | NumberOps : [T] extends [FimoPolymorphicReference | null] ? never : [T] extends [FimoPolymorphicReference[]] ? never : [T] extends [FimoReference | null] ? string | null | ReferenceOps : [T] extends [FimoReference[]] ? string | ManyReferenceOps : [T] extends [FimoMedia | FimoMedia[]] ? NullOnlyOps : [NonNullable<T>] extends [FimoRichText] ? string | StringOps : NullOnlyOps;
|
|
44
44
|
type BaseTopLevelWhere = {
|
|
45
45
|
id?: string | StringOps;
|
|
46
46
|
entryId?: string | StringOps;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { existsSync, readFileSync, readdirSync } from 'node:fs';
|
|
2
2
|
import { basename, join, resolve } from 'node:path';
|
|
3
|
-
import { CONTENT_FIELD_NAME_PATTERN, CONTENT_FIELD_NAME_PATTERN_DESCRIPTION, CONTENT_TYPE_NAME_PATTERN, CONTENT_TYPE_NAME_PATTERN_DESCRIPTION, ContentFieldDefinitionSchema, FieldTypeSchema, MAX_STRUCTURED_CONTENT_DEPTH, RESERVED_CONTENT_FIELD_NAMES, walkContentFields, } from '@fimo/api-contracts';
|
|
3
|
+
import { CONTENT_FIELD_NAME_PATTERN, CONTENT_FIELD_NAME_PATTERN_DESCRIPTION, CONTENT_TYPE_NAME_PATTERN, CONTENT_TYPE_NAME_PATTERN_DESCRIPTION, ContentFieldDefinitionSchema, FieldTypeSchema, MAX_STRUCTURED_CONTENT_DEPTH, RESERVED_CONTENT_FIELD_NAMES, collectConditionProblems, walkContentFields, } from '@fimo/api-contracts';
|
|
4
4
|
/**
|
|
5
5
|
* Validate `src/schemas/*.json` locally against the same rules the API's
|
|
6
6
|
* schema validator enforces (field types, reserved field names, required
|
|
@@ -127,6 +127,7 @@ export function validateSchemaFile(absolutePath, file, schemaUids = new Set()) {
|
|
|
127
127
|
});
|
|
128
128
|
return errors;
|
|
129
129
|
}
|
|
130
|
+
const parsedFields = {};
|
|
130
131
|
for (const [fieldName, definition] of Object.entries(fields)) {
|
|
131
132
|
if (!CONTENT_FIELD_NAME_PATTERN.test(fieldName)) {
|
|
132
133
|
errors.push({
|
|
@@ -161,14 +162,33 @@ export function validateSchemaFile(absolutePath, file, schemaUids = new Set()) {
|
|
|
161
162
|
file,
|
|
162
163
|
});
|
|
163
164
|
}
|
|
164
|
-
if ('
|
|
165
|
-
const key = 'i18n' in definition ? 'i18n' : 'localized';
|
|
165
|
+
if ('localized' in definition) {
|
|
166
166
|
errors.push({
|
|
167
167
|
rule: 'schemas/field-i18n',
|
|
168
|
-
message: `Field "${fieldName}":
|
|
168
|
+
message: `Field "${fieldName}": "localized" is not supported. Use "i18n": false to share one value across locales.`,
|
|
169
169
|
file,
|
|
170
170
|
});
|
|
171
171
|
}
|
|
172
|
+
// `i18n: false` shares one value across every locale of the document.
|
|
173
|
+
// Structured content follows the locale of the entry that carries it, so
|
|
174
|
+
// the flag has no row of its own to apply to there.
|
|
175
|
+
if ('i18n' in definition) {
|
|
176
|
+
const value = definition.i18n;
|
|
177
|
+
if (typeof value !== 'boolean') {
|
|
178
|
+
errors.push({
|
|
179
|
+
rule: 'schemas/field-i18n',
|
|
180
|
+
message: `Field "${fieldName}": "i18n" must be true or false.`,
|
|
181
|
+
file,
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
else if (type === 'blocks') {
|
|
185
|
+
errors.push({
|
|
186
|
+
rule: 'schemas/field-i18n',
|
|
187
|
+
message: `Field "${fieldName}": "i18n" is not supported on blocks fields.`,
|
|
188
|
+
file,
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
}
|
|
172
192
|
if (type === 'blocks') {
|
|
173
193
|
const parsed = ContentFieldDefinitionSchema.safeParse(definition);
|
|
174
194
|
if (!parsed.success) {
|
|
@@ -181,6 +201,7 @@ export function validateSchemaFile(absolutePath, file, schemaUids = new Set()) {
|
|
|
181
201
|
}
|
|
182
202
|
continue;
|
|
183
203
|
}
|
|
204
|
+
parsedFields[fieldName] = parsed.data;
|
|
184
205
|
walkContentFields({ [fieldName]: parsed.data }, ({ field, path, structuredDepth, insideStructuredContent }) => {
|
|
185
206
|
if (field.type === 'blocks' && structuredDepth >= MAX_STRUCTURED_CONTENT_DEPTH) {
|
|
186
207
|
errors.push({
|
|
@@ -210,6 +231,10 @@ export function validateSchemaFile(absolutePath, file, schemaUids = new Set()) {
|
|
|
210
231
|
});
|
|
211
232
|
continue;
|
|
212
233
|
}
|
|
234
|
+
const parsed = ContentFieldDefinitionSchema.safeParse(definition);
|
|
235
|
+
if (parsed.success) {
|
|
236
|
+
parsedFields[fieldName] = parsed.data;
|
|
237
|
+
}
|
|
213
238
|
if (type === 'reference') {
|
|
214
239
|
const { target, targets, many } = definition;
|
|
215
240
|
if (targets !== undefined && target !== undefined) {
|
|
@@ -281,5 +306,8 @@ export function validateSchemaFile(absolutePath, file, schemaUids = new Set()) {
|
|
|
281
306
|
}
|
|
282
307
|
}
|
|
283
308
|
}
|
|
309
|
+
for (const problem of collectConditionProblems(parsedFields)) {
|
|
310
|
+
errors.push({ rule: 'schemas/conditions', message: problem.message, file });
|
|
311
|
+
}
|
|
284
312
|
return errors;
|
|
285
313
|
}
|
package/package.json
CHANGED
package/release.json
CHANGED