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.
@@ -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 source = value[FIMO_SOURCE];
133
- const { value: liveContent, ref } = useFimoLiveValue(value.content);
134
- return (_jsx("div", { ref: ref, ...props, "data-fimo-source": source, "data-fimo-richtext": "", children: renderNode(liveContent, components, 0) }));
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 ('i18n' in definition || 'localized' in definition) {
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}": field-level locale settings ("${key}") are not supported.`,
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fimo",
3
- "version": "0.9.0",
3
+ "version": "0.10.0-staging.1",
4
4
  "description": "Fimo CLI - create, deploy, and manage Fimo projects",
5
5
  "bin": {
6
6
  "fimo": "dist/cli/index.js"
package/release.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "source": "npm",
3
- "apiUrl": "https://api.fimo.ai",
4
- "webUrl": "https://fimo.ai"
3
+ "apiUrl": "https://api.staging.fimo.team",
4
+ "webUrl": "https://staging.fimo.team"
5
5
  }
@@ -21,7 +21,7 @@
21
21
  "cmdk": "^1.1.1",
22
22
  "date-fns": "^4.1.0",
23
23
  "embla-carousel-react": "^8.6.0",
24
- "fimo": "0.9.0",
24
+ "fimo": "0.10.0-staging.1",
25
25
  "input-otp": "^1.4.2",
26
26
  "isbot": "^5",
27
27
  "lucide-react": "^0.577.0",