fimo 0.6.0-experimental.2 → 0.6.0-staging.2

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.
@@ -11,7 +11,7 @@
11
11
  // AUTO-GENERATED ⚠️ – do not edit by hand
12
12
  import { <% if (!model.isSingleton) { %>useInfiniteQuery, <% } %>useSuspenseQuery, useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
13
13
  <% if (!model.isSingleton) { -%>
14
- import type { InfiniteData, UseInfiniteQueryResult, UseQueryResult, UseSuspenseQueryResult } from "@tanstack/react-query";
14
+ import type { InfiniteData, UseInfiniteQueryResult, UseQueryResult } from "@tanstack/react-query";
15
15
  <% } -%>
16
16
  import { FimoString, FimoMedia, FimoBoolean, FimoRichText, useLocale<% if (!model.isSingleton) { %>, parseCollectionResponse<% } %> } from "fimo/ui";
17
17
  // @ts-ignore - virtual module provided by Fimo's Vite plugin
@@ -36,35 +36,16 @@ export type { <%= model.pascal %>, <%= model.pascal %>Fields, <%= model.pascal %
36
36
  * Wraps raw API data with Fimo types for source tracking
37
37
  */
38
38
  export function wrapWithSource(entry: Record<string, any>): <%= model.pascal %> {
39
- <% if (!model.isSingleton) { -%>
40
- const documentId = entry.documentId;
41
- const locale = entry.locale;
42
- const sourcePrefix = `<%= model.pascal %>.v2:${documentId}:${encodeURIComponent(locale)}`;
43
- <% } else { -%>
44
39
  const id = entry.id;
45
- const documentId = entry.documentId;
46
- const locale = entry.locale ?? defaultLocale();
47
- const usesV2Identity = typeof id !== "string";
48
- const sourcePrefix = usesV2Identity
49
- ? `<%= model.pascal %>.v2:${documentId}:${encodeURIComponent(locale)}`
50
- : `<%= model.pascal %>.${id}`;
51
- <% } -%>
40
+ const sourcePrefix = `<%= model.pascal %>.${id}`;
52
41
  const entryFimo = entry.__fimo && typeof entry.__fimo === "object" ? entry.__fimo : {};
53
42
 
54
43
  return {
55
- <% if (!model.isSingleton) { -%>
56
- documentId,
57
- <% } else { -%>
58
- ...(typeof id === "string" ? { id } : {}),
59
- documentId,
60
- <% } -%>
44
+ id,
45
+ documentId: entry.documentId,
61
46
  slug: entry.slug != null ? new FimoString(entry.slug, `${sourcePrefix}.slug`) : entry.slug,
62
- <% if (!model.isSingleton) { -%>
63
- locale,
64
- <% } else if (model.localized) { -%>
65
- locale,
66
- <% } else { -%>
67
- ...(usesV2Identity ? { locale } : {}),
47
+ <% if (model.localized) { -%>
48
+ locale: entry.locale,
68
49
  <% } -%>
69
50
  createdAt: entry.createdAt,
70
51
  updatedAt: entry.updatedAt,
@@ -120,11 +101,11 @@ if (model.fields) {
120
101
  const wrapper = field.target === model.uid ? 'wrapWithSource' : `wrap${field.targetPascal}WithSource`;
121
102
  if (field.many) {
122
103
  -%>
123
- <%= key %>: Array.isArray(entry.<%= key %>) ? entry.<%= key %>.map((value: any) => isPopulatedEntry(value) ? <%= wrapper %>(value) : value) : entry.<%= key %>,
104
+ <%= key %>: Array.isArray(entry.<%= key %>) ? entry.<%= key %>.map((value: any) => value != null && typeof value === "object" && typeof value.id === "string" ? <%= wrapper %>(value) : value) : entry.<%= key %>,
124
105
  <%
125
106
  } else {
126
107
  -%>
127
- <%= key %>: isPopulatedEntry(entry.<%= key %>) ? <%= wrapper %>(entry.<%= key %>) : entry.<%= key %>,
108
+ <%= key %>: entry.<%= key %> != null && typeof entry.<%= key %> === "object" && typeof entry.<%= key %>.id === "string" ? <%= wrapper %>(entry.<%= key %>) : entry.<%= key %>,
128
109
  <%
129
110
  }
130
111
  break;
@@ -140,23 +121,6 @@ if (model.fields) {
140
121
  } as <%= model.pascal %>;
141
122
  }
142
123
 
143
- interface PopulatedEntryRecord extends Record<string, unknown> {
144
- documentId: string;
145
- __fimo: { contentType: string };
146
- }
147
-
148
- function isPopulatedEntry(value: unknown): value is PopulatedEntryRecord {
149
- if (value == null || typeof value !== "object") {
150
- return false;
151
- }
152
- const entry = value as Record<string, unknown>;
153
- const fimo = entry.__fimo;
154
- return typeof entry.documentId === "string"
155
- && fimo != null
156
- && typeof fimo === "object"
157
- && typeof (fimo as Record<string, unknown>).contentType === "string";
158
- }
159
-
160
124
  <%
161
125
  const hasPolymorphicReferences = model.fields && Object.values(model.fields).some((field) => field.type === 'reference' && Array.isArray(field.targetRefs) && field.targetRefs.length > 0);
162
126
  if (hasPolymorphicReferences) {
@@ -168,9 +132,7 @@ if (hasPolymorphicReferences) {
168
132
  * (unpopulated) values pass through untouched.
169
133
  */
170
134
  function wrapPolymorphic(value: any, wrappers: Record<string, (entry: Record<string, any>) => any>): any {
171
- if (!isPopulatedEntry(value)) {
172
- return value;
173
- }
135
+ if (value == null || typeof value !== "object" || typeof value.id !== "string") return value;
174
136
  const contentType = value.__fimo && typeof value.__fimo.contentType === "string" ? value.__fimo.contentType : null;
175
137
  const wrapper = contentType ? wrappers[contentType] : undefined;
176
138
  if (!wrapper) return value;
@@ -210,12 +172,8 @@ function readLocale(
210
172
  ownerUsesLocale: boolean,
211
173
  fallbackLocale = defaultLocale()
212
174
  ): string | undefined {
213
- <% if (!model.isSingleton) { -%>
214
- return options.locale ?? fallbackLocale;
215
- <% } else { -%>
216
175
  const populatesLocalizedTarget = populateFields(options.populate).some((field) => LOCALIZED_REFERENCE_FIELDS.has(field));
217
176
  return ownerUsesLocale || populatesLocalizedTarget ? options.locale ?? fallbackLocale : undefined;
218
- <% } -%>
219
177
  }
220
178
 
221
179
  function fimoHeaders(extra?: Record<string, string>): Record<string, string> {
@@ -291,11 +249,11 @@ export type InfiniteListResult<TItem> = UseInfiniteQueryResult<
291
249
  readonly isLoadingMore: boolean;
292
250
  };
293
251
 
294
- export async function getByDocumentId<TPopulate extends <%= model.pascal %>Populate | undefined = undefined>(
295
- documentId: string,
252
+ export async function getById<TPopulate extends <%= model.pascal %>Populate | undefined = undefined>(
253
+ id: string,
296
254
  options: { locale?: string; populate?: TPopulate; localeFallbacks?: boolean } = {}
297
255
  ): Promise<<%= model.pascal %>Result<undefined, TPopulate>> {
298
- const res = await fetch(`${base}${withReadOptions(`/v2/entries/<%= model.uid %>/${documentId}`, options)}`, { headers: fimoHeaders() });
256
+ const res = await fetch(`${base}${withReadOptions(`/entries/<%= model.uid %>/${id}`, options, false)}`, { headers: fimoHeaders() });
299
257
  if (!res.ok) throw new Error(await res.text());
300
258
  const data = await res.json();
301
259
  return wrapWithSource(data.data) as <%= model.pascal %>Result<undefined, TPopulate>;
@@ -305,7 +263,7 @@ export async function getBySlug<TPopulate extends <%= model.pascal %>Populate |
305
263
  slug: string,
306
264
  options: { locale?: string; populate?: TPopulate; localeFallbacks?: boolean } = {}
307
265
  ): Promise<<%= model.pascal %>Result<undefined, TPopulate> | null> {
308
- const res = await fetch(`${base}${withReadOptions(`/v2/entries/<%= model.uid %>/slug/${encodeURIComponent(slug)}`, options)}`, { headers: fimoHeaders() });
266
+ const res = await fetch(`${base}${withReadOptions(`/entries/<%= model.uid %>/slug/${encodeURIComponent(slug)}`, options)}`, { headers: fimoHeaders() });
309
267
  if (res.status === 404) return null;
310
268
  if (!res.ok) throw new Error(await res.text());
311
269
  const data = await res.json();
@@ -317,7 +275,7 @@ export async function getByField<TPopulate extends <%= model.pascal %>Populate |
317
275
  value: string,
318
276
  options: { locale?: string; populate?: TPopulate; localeFallbacks?: boolean } = {}
319
277
  ): Promise<<%= model.pascal %>Result<undefined, TPopulate> | null> {
320
- const res = await fetch(`${base}${withReadOptions(`/v2/entries/<%= model.uid %>/field/${encodeURIComponent(fieldName)}/${encodeURIComponent(value)}`, options)}`, { headers: fimoHeaders() });
278
+ const res = await fetch(`${base}${withReadOptions(`/entries/<%= model.uid %>/field/${encodeURIComponent(fieldName)}/${encodeURIComponent(value)}`, options)}`, { headers: fimoHeaders() });
321
279
  if (res.status === 404) return null;
322
280
  if (!res.ok) throw new Error(await res.text());
323
281
  const data = await res.json();
@@ -363,7 +321,7 @@ export async function list<
363
321
  TPopulate extends <%= model.pascal %>Populate | undefined = undefined,
364
322
  >(params: <%= model.pascal %>Query<TFields, TPopulate> = {} as <%= model.pascal %>Query<TFields, TPopulate>): Promise<CollectionPage<<%= model.pascal %>Result<TFields, TPopulate>>> {
365
323
  const qs = toQueryString(params);
366
- const res = await fetch(`${base}/v2/entries/<%= model.uid %>${qs ? "?" + qs : ""}`, { headers: fimoHeaders() });
324
+ const res = await fetch(`${base}/entries/<%= model.uid %>${qs ? "?" + qs : ""}`, { headers: fimoHeaders() });
367
325
  if (!res.ok) throw new Error(await res.text());
368
326
  const data = parseCollectionResponse(await res.json());
369
327
  const items = data.data.map(wrapWithSource) as <%= model.pascal %>Result<TFields, TPopulate>[];
@@ -385,7 +343,7 @@ export async function get<
385
343
  }
386
344
 
387
345
  export async function create(payload: <%= model.pascal %>Input): Promise<<%= model.pascal %>> {
388
- const res = await fetch(`${base}/v2/entries/<%= model.uid %>`, {
346
+ const res = await fetch(`${base}/entries/<%= model.uid %>`, {
389
347
  method: "POST",
390
348
  headers: fimoHeaders({ "Content-Type": "application/json" }),
391
349
  body: JSON.stringify(splitWritePayload(payload))
@@ -395,22 +353,19 @@ export async function create(payload: <%= model.pascal %>Input): Promise<<%= mod
395
353
  return wrapWithSource(data.data);
396
354
  }
397
355
 
398
- export async function update(documentId: string, payload: Partial<<%= model.pascal %>Input>): Promise<<%= model.pascal %>> {
399
- const write = splitWritePayload(payload) as { data: Record<string, unknown>; locale?: string };
400
- const url = withReadOptions(`/v2/entries/<%= model.uid %>/${documentId}`, { locale: write.locale });
401
- const res = await fetch(`${base}${url}`, {
356
+ export async function update(id: string, payload: Partial<<%= model.pascal %>Input>): Promise<<%= model.pascal %>> {
357
+ const res = await fetch(`${base}/entries/<%= model.uid %>/${id}`, {
402
358
  method: "PUT",
403
359
  headers: fimoHeaders({ "Content-Type": "application/json" }),
404
- body: JSON.stringify({ data: write.data })
360
+ body: JSON.stringify(splitWritePayload(payload))
405
361
  });
406
362
  if (!res.ok) throw new Error(await res.text());
407
363
  const data = await res.json();
408
364
  return wrapWithSource(data.data);
409
365
  }
410
366
 
411
- export async function remove(documentId: string, options: { locale?: string } = {}): Promise<void> {
412
- const url = withReadOptions(`/v2/entries/<%= model.uid %>/${documentId}`, options);
413
- const res = await fetch(`${base}${url}`, { method: "DELETE", headers: fimoHeaders() });
367
+ export async function remove(id: string): Promise<void> {
368
+ const res = await fetch(`${base}/entries/<%= model.uid %>/${id}`, { method: "DELETE", headers: fimoHeaders() });
414
369
  if (!res.ok) throw new Error(await res.text());
415
370
  }
416
371
  <% } else { -%>
@@ -444,7 +399,7 @@ export async function update(payload: Partial<<%= model.pascal %>Input>): Promis
444
399
  <% if (!model.isSingleton) { -%>
445
400
  const qk = {
446
401
  root : ["<%= model.pascal %>"] as const,
447
- byDocumentId: <TPopulate extends <%= model.pascal %>Populate | undefined = undefined>(documentId: string, options: { locale?: string; populate?: TPopulate; localeFallbacks?: boolean } = {}) => ["<%= model.pascal %>", "document", documentId, options.locale, options.populate] as const,
402
+ byId : <TPopulate extends <%= model.pascal %>Populate | undefined = undefined>(id: string, options: { locale?: string; populate?: TPopulate; localeFallbacks?: boolean } = {}) => ["<%= model.pascal %>", id, options.locale, options.populate] as const,
448
403
  bySlug : <TPopulate extends <%= model.pascal %>Populate | undefined = undefined>(slug: string, options: { locale?: string; populate?: TPopulate; localeFallbacks?: boolean } = {}) => ["<%= model.pascal %>", "slug", slug, options.locale, options.populate] as const,
449
404
  byField : <TPopulate extends <%= model.pascal %>Populate | undefined = undefined>(field: string, value: string, options: { locale?: string; populate?: TPopulate; localeFallbacks?: boolean } = {}) => ["<%= model.pascal %>", field, value, options.locale, options.populate] as const,
450
405
  list : (params: <%= model.pascal %>Query) => ["<%= model.pascal %>", params] as const,
@@ -454,10 +409,10 @@ const qk = {
454
409
  >(params: InfiniteListQuery<TFields, TPopulate>) => ["<%= model.pascal %>", "infinite", params] as const
455
410
  };
456
411
 
457
- export function useGetByDocumentId<TPopulate extends <%= model.pascal %>Populate | undefined = undefined>(documentId: string, options: { locale?: string; populate?: TPopulate; localeFallbacks?: boolean } = {}): UseQueryResult<<%= model.pascal %>Result<undefined, TPopulate>, Error> {
458
- const locale = useQueryLocale(options.locale);
412
+ export function useGetById<TPopulate extends <%= model.pascal %>Populate | undefined = undefined>(id: string, options: { locale?: string; populate?: TPopulate; localeFallbacks?: boolean } = {}) {
413
+ const locale = readLocale(options, false, useQueryLocale(options.locale));
459
414
  const localizedOptions = { ...options, locale };
460
- return useQuery<<%= model.pascal %>Result<undefined, TPopulate>, Error>({ queryKey: qk.byDocumentId(documentId, localizedOptions), queryFn: () => getByDocumentId(documentId, localizedOptions) });
415
+ return useQuery<<%= model.pascal %>Result<undefined, TPopulate>, Error>({ queryKey: qk.byId(id, localizedOptions), queryFn: () => getById(id, localizedOptions) });
461
416
  }
462
417
 
463
418
  export function useGetBySlug<TPopulate extends <%= model.pascal %>Populate | undefined = undefined>(slug: string, options: { locale?: string; populate?: TPopulate; localeFallbacks?: boolean } = {}) {
@@ -520,10 +475,10 @@ export function useInfiniteList<
520
475
  };
521
476
  }
522
477
 
523
- export function useSuspenseGetByDocumentId<TPopulate extends <%= model.pascal %>Populate | undefined = undefined>(documentId: string, options: { locale?: string; populate?: TPopulate; localeFallbacks?: boolean } = {}): UseSuspenseQueryResult<<%= model.pascal %>Result<undefined, TPopulate>, Error> {
524
- const locale = useQueryLocale(options.locale);
478
+ export function useSuspenseGetById<TPopulate extends <%= model.pascal %>Populate | undefined = undefined>(id: string, options: { locale?: string; populate?: TPopulate; localeFallbacks?: boolean } = {}) {
479
+ const locale = readLocale(options, false, useQueryLocale(options.locale));
525
480
  const localizedOptions = { ...options, locale };
526
- return useSuspenseQuery<<%= model.pascal %>Result<undefined, TPopulate>, Error>({ queryKey: qk.byDocumentId(documentId, localizedOptions), queryFn: () => getByDocumentId(documentId, localizedOptions) });
481
+ return useSuspenseQuery<<%= model.pascal %>Result<undefined, TPopulate>, Error>({ queryKey: qk.byId(id, localizedOptions), queryFn: () => getById(id, localizedOptions) });
527
482
  }
528
483
 
529
484
  export function useSuspenseGetBySlug<TPopulate extends <%= model.pascal %>Populate | undefined = undefined>(slug: string, options: { locale?: string; populate?: TPopulate; localeFallbacks?: boolean } = {}) {
@@ -561,22 +516,22 @@ export function useCreate() {
561
516
 
562
517
  export function useUpdate() {
563
518
  const qc = useQueryClient();
564
- return useMutation<<%= model.pascal %>, Error, { documentId: string; locale?: string } & Partial<<%= model.pascal %>Input>>({
565
- mutationFn : ({ documentId, ...patch }) => update(documentId, patch),
519
+ return useMutation<<%= model.pascal %>, Error, { id: string } & Partial<<%= model.pascal %>Input>>({
520
+ mutationFn : ({ id, ...patch }) => update(id, patch),
566
521
  onSuccess : (_data, vars) => {
567
522
  qc.invalidateQueries({ queryKey: qk.root });
568
- qc.invalidateQueries({ queryKey: qk.byDocumentId(vars.documentId, { locale: vars.locale ?? defaultLocale() }) });
523
+ qc.invalidateQueries({ queryKey: qk.byId(vars.id) });
569
524
  }
570
525
  });
571
526
  }
572
527
 
573
528
  export function useRemove() {
574
529
  const qc = useQueryClient();
575
- return useMutation<void, Error, { documentId: string; locale?: string }>({
576
- mutationFn : ({ documentId, locale }) => remove(documentId, { locale }),
577
- onSuccess : (_data, { documentId, locale }) => {
530
+ return useMutation<void, Error, string>({
531
+ mutationFn : remove,
532
+ onSuccess : (_data, id) => {
578
533
  qc.invalidateQueries({ queryKey: qk.root });
579
- qc.removeQueries({ queryKey: qk.byDocumentId(documentId, { locale: locale ?? defaultLocale() }), exact: false });
534
+ qc.removeQueries({ queryKey: ["<%= model.pascal %>", id], exact: false });
580
535
  }
581
536
  });
582
537
  }
@@ -614,7 +569,7 @@ export function useUpdate() {
614
569
  export default {
615
570
  <% if (!model.isSingleton) { -%>
616
571
  /* async helpers */
617
- getByDocumentId,
572
+ getById,
618
573
  getBySlug,
619
574
  getByField,
620
575
  list,
@@ -624,13 +579,13 @@ export default {
624
579
  remove,
625
580
 
626
581
  /* hooks */
627
- useGetByDocumentId,
582
+ useGetById,
628
583
  useGetBySlug,
629
584
  useGetByField,
630
585
  useList,
631
586
  useInfiniteList,
632
587
  useGet,
633
- useSuspenseGetByDocumentId,
588
+ useSuspenseGetById,
634
589
  useSuspenseGet,
635
590
  useSuspenseGetByField,
636
591
  useSuspenseGetBySlug,
@@ -32,15 +32,11 @@ export interface <%= model.pascal %>FimoMeta {
32
32
  }
33
33
 
34
34
  export interface <%= model.pascal %> extends WithReferences<<%= model.pascal %>References> {
35
- <% if (model.isSingleton) { -%>
36
- id?: string;
37
- <% } -%>
35
+ id: string;
38
36
  documentId: string;
39
37
  slug: FimoString;
40
- <% if (!model.isSingleton || model.localized) { -%>
38
+ <% if (model.localized) { -%>
41
39
  locale: string;
42
- <% } else { -%>
43
- locale?: string;
44
40
  <% } -%>
45
41
  createdAt: string;
46
42
  updatedAt: string;
@@ -191,9 +191,10 @@ Import from the public schema module, e.g. `import BlogPost from '@/schemas/Blog
191
191
 
192
192
  ```ts
193
193
  interface BlogPost {
194
+ id: string;
194
195
  documentId: string;
195
196
  slug: FimoString;
196
- locale: string;
197
+ locale: string; // localized schemas only; omitted when i18n.enabled is false
197
198
  createdAt: string;
198
199
  updatedAt: string;
199
200
  __fimo: {
@@ -218,7 +219,7 @@ When a project has multiple configured locales, create and update each localized
218
219
 
219
220
  For shared content, set `i18n: { "enabled": false }` on the schema and create each entry once. Shared entries:
220
221
 
221
- - expose the effective request locale in collection v2 responses;
222
+ - have no public `locale` property;
222
223
  - are returned in every locale context without duplication;
223
224
  - ignore locale on owner reads and writes;
224
225
  - still use the active/requested locale when a populated reference targets a localized schema.
@@ -246,17 +247,17 @@ Filtering on polymorphic fields is not supported yet.
246
247
 
247
248
  ```ts
248
249
  // low-level fetch helpers
249
- getByDocumentId<TPopulate extends BlogPostPopulate | undefined>(documentId: string, options?: { locale?: string; populate?: TPopulate }): Promise<BlogPostResult<undefined, TPopulate>>
250
+ getById<TPopulate extends BlogPostPopulate | undefined>(id: string, options?: { populate?: TPopulate }): Promise<BlogPostResult<undefined, TPopulate>>
250
251
  getBySlug<TPopulate extends BlogPostPopulate | undefined>(slug: string, options?: { populate?: TPopulate }): Promise<BlogPostResult<undefined, TPopulate> | null>
251
252
  getByField<TPopulate extends BlogPostPopulate | undefined>(fieldName: string, value: string, options?: { populate?: TPopulate }): Promise<BlogPostResult<undefined, TPopulate> | null>
252
253
  list<TFields extends BlogPostFields | undefined, TPopulate extends BlogPostPopulate | undefined>(params?: BlogPostQuery<TFields, TPopulate>): Promise<CollectionPage<BlogPostResult<TFields, TPopulate>>>
253
254
  get<TFields extends BlogPostFields | undefined, TPopulate extends BlogPostPopulate | undefined>(params?: BlogPostQuery<TFields, TPopulate>): Promise<BlogPostResult<TFields, TPopulate>[]>
254
255
  create(payload: BlogPostInput): Promise<BlogPost>
255
- update(documentId: string, payload: Partial<BlogPostInput>): Promise<BlogPost>
256
- remove(documentId: string, options?: { locale?: string }): Promise<void>
256
+ update(id: string, payload: Partial<BlogPostInput>): Promise<BlogPost>
257
+ remove(id: string): Promise<void>
257
258
 
258
259
  // react-query hooks
259
- useGetByDocumentId(documentId, { locale?, populate? }) // → { data: BlogPostResult<undefined, TPopulate> | undefined, isLoading, ... }
260
+ useGetById(id, { populate? }) // → { data: BlogPostResult<undefined, TPopulate> | undefined, isLoading, ... }
260
261
  useGetBySlug(slug, { populate? }) // → { data: BlogPostResult<undefined, TPopulate> | null | undefined, ... } — ideal for /:slug detail routes
261
262
  useGetByField(fieldName, value, { populate? })
262
263
  useList<TFields, TPopulate>(params?) // → { data: CollectionPage<BlogPostResult<TFields, TPopulate>> | undefined, ... }
@@ -265,7 +266,7 @@ useGet<TFields, TPopulate>(params?) // → legacy array-shaped { data:
265
266
  useCreate() / useUpdate() / useRemove()
266
267
 
267
268
  // Suspense variants (same signatures, throw to a <Suspense> boundary instead of returning isLoading)
268
- useSuspenseGetByDocumentId(documentId) / useSuspenseGetBySlug(slug) / useSuspenseGetByField(fieldName, value) / useSuspenseGet(params?)
269
+ useSuspenseGetById(id) / useSuspenseGetBySlug(slug) / useSuspenseGetByField(fieldName, value) / useSuspenseGet(params?)
269
270
  ```
270
271
 
271
272
  Write inputs contain plain JSON values. Read models contain Fimo wrapper values for source tracking, so use `BlogPostInput` rather than sending a `BlogPost` back to `create` or `update`.
@@ -278,7 +279,7 @@ update(payload: Partial<SettingsInput>): Promise<Settings>
278
279
  useGet(options?) / useSuspenseGet(options?) / useUpdate()
279
280
  ```
280
281
 
281
- Singleton clients do not expose `create`, `remove`, `getByDocumentId`, or list queries. Localized singletons have one variant per locale; non-localized singletons have one locale-free row.
282
+ Singleton clients do not expose `create`, `remove`, `getById`, or list queries. Localized singletons have one variant per locale; non-localized singletons have one locale-free row.
282
283
 
283
284
  Choose the collection interface from the UI behavior. Use `useList` when the UI controls a page, and read pagination state from `pageInfo`:
284
285
 
@@ -337,7 +338,7 @@ Operators: scalar equality, `$eq`, `$ne`, `$gt`, `$gte`, `$lt`, `$lte`, `$in`, `
337
338
  Reference field values are reference objects, but reference filters use the target `documentId` string, for example `where: { author: "750e..." }`; for to-many references that means "contains this target document".
338
339
  For to-many references, `$eq` and `$contains` mean membership, `$in` means any listed document is present, `$ne` and `$nin` mean none are present, and `$null: true` means empty or missing. Reference fields cannot be sorted.
339
340
 
340
- Use `fields` to keep list payloads small. The v2 API always keeps `documentId` and `locale`, and returns only the requested fields beyond that:
341
+ Use `fields` to keep list payloads small. The API always keeps `id`, and returns only the requested fields beyond that:
341
342
 
342
343
  ```tsx
343
344
  const { data: summaries = [] } = BlogPost.useGet({
@@ -345,7 +346,7 @@ const { data: summaries = [] } = BlogPost.useGet({
345
346
  sort: '-publishedAt',
346
347
  limit: 12,
347
348
  });
348
- // summaries: Array<Pick<BlogPost, 'documentId' | 'locale' | 'slug' | 'title' | 'excerpt' | 'coverImage'>>
349
+ // summaries: Array<Pick<BlogPost, 'id' | 'slug' | 'title' | 'excerpt' | 'coverImage'>>
349
350
  ```
350
351
 
351
352
  Use `populate` to embed reference targets in read results:
@@ -433,7 +434,7 @@ export function BlogList() {
433
434
  return (
434
435
  <ul>
435
436
  {page.items.map((post) => (
436
- <li key={`${post.documentId}:${post.locale}`}>
437
+ <li key={post.id}>
437
438
  <Text value={post.title} as="h2" />
438
439
  <Image value={post.coverImage} width={800} height={400} fit="cover" />
439
440
  <RichText value={post.body} className="prose" />
@@ -450,9 +451,9 @@ For the `<Text>` / `<RichText>` / `<Image>` / `<Date>` components and the rules
450
451
  ## Read path (published app, no auth)
451
452
 
452
453
  ```ts
453
- const res = await fetch(`${import.meta.env.VITE_API_URL}/v2/entries/<typeName>?locale=en&fields=slug,title&limit=12`);
454
+ const res = await fetch(`${import.meta.env.VITE_API_URL}/entries/<typeName>?fields=slug,title&limit=12`);
454
455
  const { data, meta } = await res.json();
455
- // data: Entry[] — fields flattened at top level (documentId, locale, slug, title, ...)
456
+ // data: Entry[] — fields flattened at top level (id, slug, title, ...)
456
457
  // meta: { limit, offset, total, hasMore }
457
458
  ```
458
459
 
@@ -43,9 +43,9 @@ fimo entries create <TypeName> --body '<json>'
43
43
  fimo entries create <TypeName> --locale es --document-id <documentId> --body '<json>'
44
44
  fimo entries list <TypeName> [--limit N] [--offset N] [--search Q] [--where JSON] [--sort F] [--fields FIELDS] [--populate FIELDS]
45
45
  fimo entries list <TypeName> --locale es
46
- fimo entries get <TypeName> <documentId> --locale es
47
- fimo entries update <TypeName> <documentId> --locale es --body '<json>'
48
- fimo entries delete <TypeName> <documentId> --locale es
46
+ fimo entries get <TypeName> <id>
47
+ fimo entries update <TypeName> <id> --locale es --body '<json>'
48
+ fimo entries delete <TypeName> <id>
49
49
  ```
50
50
 
51
51
  `--body` is a **required** option on `create` and `update`. Its JSON shape (where `slug` goes, how `media` fields look, Tiptap richtext format) lives in `fimo/references/content.md`. **Always read that first before constructing an entry payload — slug must be inside `data`, media has a specific shape, richtext must be Tiptap JSONContent.**
@@ -66,7 +66,7 @@ Use the canonical read query flags: `--search`, `--sort`, `--where`, `--limit`,
66
66
  `--where` is a JSON object keyed by schema field name. Simple values mean equality and stay typed inside the JSON (`{"featured":true}`, `{"category":"react"}`, `{"rank":{"$gte":3}}`); operator objects support `$eq`, `$ne`, `$gt`, `$gte`, `$lt`, `$lte`, `$in`, `$nin`, `$contains`, `$startsWith`, and `$null`, subject to the field type. Public Fimo-owned metadata lives under `__fimo`; currently `__fimo.contentType` is filterable.
67
67
 
68
68
  Reference filters take the target `documentId` string even though stored values are objects (`{"author":"750e..."}`). On a to-many field, `$eq` and `$contains` mean membership, `$in` means any listed document is present, `$ne` and `$nin` mean none are present, and `$null: true` means empty or missing. Reference fields cannot be sorted; use `--sort field` / `--sort -field` on scalar fields.
69
- `--fields` is a comma-separated projection for list payloads. The v2 API always keeps `documentId` and `locale`; pass only the other fields your view needs, such as `slug,title,excerpt,coverImage`.
69
+ `--fields` is a comma-separated projection for list payloads. The API always keeps `id`; pass only the fields your view needs, such as `slug,title,excerpt,coverImage`.
70
70
 
71
71
  `--populate` is a comma-separated list of reference fields to embed. Without it, reference fields return reference objects like `{ "documentId": "..." }`; with `--populate author,contributors`, those fields return the target entry objects for the requested locale. Only reference fields can be populated (scalar fields 400), and populate never selects which target fields come back. A populated target missing in the requested locale resolves to null unless you pass `localeFallbacks=true`, which falls back to the best available locale variant, marked by its `locale` field. Limits: 200 references per to-many write, 500 distinct populated documents per field per request (400 past either).
72
72
 
@@ -95,11 +95,11 @@ Do not add `localized` or field-level `i18n` to reference fields. The reference
95
95
 
96
96
  ## Localized and shared content
97
97
 
98
- Schemas are localized by default. Omit `--locale` for default-locale creates and lists. `entries get`, `entries update`, and `entries delete` require `--locale` because collection entry identity is always `documentId + locale`.
98
+ Schemas are localized by default. Omit `--locale` for default-locale entries. Pass `--locale <locale>` when creating, listing, reading, or updating a specific non-default locale.
99
99
 
100
100
  When creating a localized variant of an existing entry, pass the source entry's `documentId` with `--document-id`. Keep projects single-locale unless the user asks for multilingual or localized output; when multiple locales are configured, create and update every locale explicitly.
101
101
 
102
- For content shared across locales, define `"i18n": { "enabled": false }` at the schema root and create each entry once. Do not pass `--document-id` to manufacture locale variants. V2 shared entry responses expose the effective request locale even though storage still has one locale-free row. No other `i18n` options and no field-level localization settings are supported.
102
+ For content shared across locales, define `"i18n": { "enabled": false }` at the schema root and create each entry once. Do not pass `--document-id` to manufacture locale variants. Shared entry responses omit `locale`; a read locale is only used to resolve populated references that target localized schemas. No other `i18n` options and no field-level localization settings are supported.
103
103
 
104
104
  Use `"isSingleton": true` for a type with exactly one logical document. Generated singleton clients expose `get`/`update` and their React Query hooks, not collection create/remove APIs.
105
105
 
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "bundled": true,
3
3
  "bundler": "esbuild",
4
- "bundledAt": "2026-07-14T21:53:17.245Z",
5
- "cliVersion": "0.5.0",
4
+ "bundledAt": "2026-07-15T05:03:55.292Z",
5
+ "cliVersion": "0.6.0",
6
6
  "external": [
7
7
  "oxc-parser",
8
8
  "fsevents"
package/dist/cli/index.js CHANGED
@@ -20634,39 +20634,33 @@ var init_api = __esm({
20634
20634
  // ── Tenant API: Entries ──
20635
20635
  async listEntries(projectId, typeName, params) {
20636
20636
  const query = params ? `?${new URLSearchParams(params).toString()}` : "";
20637
- return this.request(this.tenantPath(projectId, `/v2/entries/${typeName}${query}`));
20637
+ return this.request(this.tenantPath(projectId, `/entries/${typeName}${query}`));
20638
20638
  }
20639
- async getEntry(projectId, typeName, documentId, locale) {
20640
- const query = new URLSearchParams({ locale }).toString();
20639
+ async getEntry(projectId, typeName, id, params) {
20640
+ const query = params ? `?${new URLSearchParams(params).toString()}` : "";
20641
20641
  const body = await this.request(
20642
- this.tenantPath(projectId, `/v2/entries/${typeName}/${documentId}?${query}`)
20642
+ this.tenantPath(projectId, `/entries/${typeName}/${id}${query}`)
20643
20643
  );
20644
20644
  return body.data;
20645
20645
  }
20646
20646
  async createEntry(projectId, typeName, data2) {
20647
- const body = await this.request(this.tenantPath(projectId, `/v2/entries/${typeName}`), {
20647
+ const body = await this.request(this.tenantPath(projectId, `/entries/${typeName}`), {
20648
20648
  method: "POST",
20649
20649
  body: JSON.stringify(data2)
20650
20650
  });
20651
20651
  return body.data;
20652
20652
  }
20653
- async updateEntry(projectId, typeName, documentId, locale, data2) {
20654
- const query = new URLSearchParams({ locale }).toString();
20655
- const body = await this.request(
20656
- this.tenantPath(projectId, `/v2/entries/${typeName}/${documentId}?${query}`),
20657
- {
20658
- method: "PUT",
20659
- body: JSON.stringify(data2)
20660
- }
20661
- );
20653
+ async updateEntry(projectId, typeName, id, data2) {
20654
+ const body = await this.request(this.tenantPath(projectId, `/entries/${typeName}/${id}`), {
20655
+ method: "PUT",
20656
+ body: JSON.stringify(data2)
20657
+ });
20662
20658
  return body.data;
20663
20659
  }
20664
- async deleteEntry(projectId, typeName, documentId, locale) {
20665
- const query = new URLSearchParams({ locale }).toString();
20666
- const body = await this.request(
20667
- this.tenantPath(projectId, `/v2/entries/${typeName}/${documentId}?${query}`),
20668
- { method: "DELETE" }
20669
- );
20660
+ async deleteEntry(projectId, typeName, id) {
20661
+ const body = await this.request(this.tenantPath(projectId, `/entries/${typeName}/${id}`), {
20662
+ method: "DELETE"
20663
+ });
20670
20664
  return body.data;
20671
20665
  }
20672
20666
  // ── Tenant API: Assets ──
@@ -44413,7 +44407,7 @@ var init_payment_method_dto = __esm({
44413
44407
  });
44414
44408
 
44415
44409
  // ../../packages/api-contracts/dist/esm/dtos/content.dto.js
44416
- var FieldDefinitionSchema, ContentTypeI18nSchema, ContentTypeDTOSchema, ContentTypeDTO, SchemaDTOSchema, SchemaDTO, EntryDTOSchema, EntryDTO, EntryV2DTOSchema, EntryV2DTO, PaginatedEntriesDTOSchema, PaginatedEntriesDTO, PaginatedEntriesV2DTOSchema, PaginatedEntriesV2DTO, EntryCountDTOSchema, EntryCountDTO, EntryCountsDTOSchema, EntryCountsDTO, ContentTypeResponseSchema, ContentTypeListResponseSchema, SchemaResponseSchema, EntryResponseSchema, EntryV2ResponseSchema, EntryListResponseSchema, EntryV2ListResponseSchema;
44410
+ var FieldDefinitionSchema, ContentTypeI18nSchema, ContentTypeDTOSchema, ContentTypeDTO, SchemaDTOSchema, SchemaDTO, EntryDTOSchema, EntryDTO, PaginatedEntriesDTOSchema, PaginatedEntriesDTO, EntryCountDTOSchema, EntryCountDTO, EntryCountsDTOSchema, EntryCountsDTO, ContentTypeResponseSchema, ContentTypeListResponseSchema, SchemaResponseSchema, EntryResponseSchema, EntryListResponseSchema;
44417
44411
  var init_content_dto = __esm({
44418
44412
  "../../packages/api-contracts/dist/esm/dtos/content.dto.js"() {
44419
44413
  "use strict";
@@ -44455,18 +44449,6 @@ var init_content_dto = __esm({
44455
44449
  })
44456
44450
  }).passthrough();
44457
44451
  EntryDTO = createDTO(EntryDTOSchema);
44458
- EntryV2DTOSchema = external_exports.object({
44459
- id: external_exports.never().optional(),
44460
- documentId: external_exports.string(),
44461
- slug: external_exports.string(),
44462
- locale: external_exports.string(),
44463
- createdAt: external_exports.string(),
44464
- updatedAt: external_exports.string(),
44465
- __fimo: external_exports.object({
44466
- contentType: external_exports.string()
44467
- })
44468
- }).passthrough();
44469
- EntryV2DTO = createDTO(EntryV2DTOSchema);
44470
44452
  PaginatedEntriesDTOSchema = external_exports.object({
44471
44453
  data: external_exports.array(EntryDTOSchema),
44472
44454
  meta: external_exports.object({
@@ -44477,10 +44459,6 @@ var init_content_dto = __esm({
44477
44459
  })
44478
44460
  });
44479
44461
  PaginatedEntriesDTO = createDTO(PaginatedEntriesDTOSchema);
44480
- PaginatedEntriesV2DTOSchema = PaginatedEntriesDTOSchema.extend({
44481
- data: external_exports.array(EntryV2DTOSchema)
44482
- });
44483
- PaginatedEntriesV2DTO = createDTO(PaginatedEntriesV2DTOSchema);
44484
44462
  EntryCountDTOSchema = external_exports.object({
44485
44463
  contentType: external_exports.string(),
44486
44464
  count: external_exports.number()
@@ -44494,9 +44472,7 @@ var init_content_dto = __esm({
44494
44472
  ContentTypeListResponseSchema = createResponseSchema(external_exports.array(ContentTypeDTOSchema));
44495
44473
  SchemaResponseSchema = createResponseSchema(SchemaDTOSchema);
44496
44474
  EntryResponseSchema = createResponseSchema(EntryDTOSchema);
44497
- EntryV2ResponseSchema = createResponseSchema(EntryV2DTOSchema);
44498
44475
  EntryListResponseSchema = createResponseSchema(external_exports.array(EntryDTOSchema));
44499
- EntryV2ListResponseSchema = createResponseSchema(external_exports.array(EntryV2DTOSchema));
44500
44476
  }
44501
44477
  });
44502
44478
 
@@ -106376,10 +106352,11 @@ async function entriesListCommand(typeName, options, cmd) {
106376
106352
  ui.result({ command: "entries list", data: result, render: /* @__PURE__ */ __name(() => renderPrettyJson5(result), "render") });
106377
106353
  }
106378
106354
  __name(entriesListCommand, "entriesListCommand");
106379
- async function entriesGetCommand(typeName, documentId, options, cmd) {
106355
+ async function entriesGetCommand(typeName, id, options, cmd) {
106380
106356
  const { ctx, api } = await bootstrapProjectCommand(options, cmd);
106381
106357
  await requireOperation("cms.get", { projectId: ctx.projectId, env: ctx.env });
106382
- const result = await api.getEntry(ctx.projectId, typeName, documentId, options.locale);
106358
+ const params = options.locale ? { locale: options.locale } : void 0;
106359
+ const result = await api.getEntry(ctx.projectId, typeName, id, params);
106383
106360
  ui.result({ command: "entries get", data: result, render: /* @__PURE__ */ __name(() => renderPrettyJson5(result), "render") });
106384
106361
  }
106385
106362
  __name(entriesGetCommand, "entriesGetCommand");
@@ -106394,18 +106371,21 @@ async function entriesCreateCommand(typeName, options, cmd) {
106394
106371
  ui.result({ command: "entries create", data: result, render: /* @__PURE__ */ __name(() => renderPrettyJson5(result), "render") });
106395
106372
  }
106396
106373
  __name(entriesCreateCommand, "entriesCreateCommand");
106397
- async function entriesUpdateCommand(typeName, documentId, options, cmd) {
106374
+ async function entriesUpdateCommand(typeName, id, options, cmd) {
106398
106375
  const { ctx, api } = await bootstrapProjectCommand(options, cmd, { refuseReadOnly: true });
106399
106376
  await requireOperation("cms.update", { projectId: ctx.projectId, env: ctx.env });
106400
- const data2 = parseJsonObject(options.body);
106401
- const result = await api.updateEntry(ctx.projectId, typeName, documentId, options.locale, data2);
106377
+ const data2 = addDefinedMetadata(parseJsonObject(options.body), {
106378
+ locale: options.locale,
106379
+ documentId: options.documentId
106380
+ });
106381
+ const result = await api.updateEntry(ctx.projectId, typeName, id, data2);
106402
106382
  ui.result({ command: "entries update", data: result, render: /* @__PURE__ */ __name(() => renderPrettyJson5(result), "render") });
106403
106383
  }
106404
106384
  __name(entriesUpdateCommand, "entriesUpdateCommand");
106405
- async function entriesDeleteCommand(typeName, documentId, options, cmd) {
106385
+ async function entriesDeleteCommand(typeName, id, options, cmd) {
106406
106386
  const { ctx, api } = await bootstrapProjectCommand(options, cmd, { refuseReadOnly: true });
106407
106387
  await requireOperation("cms.delete", { projectId: ctx.projectId, env: ctx.env });
106408
- const result = await api.deleteEntry(ctx.projectId, typeName, documentId, options.locale);
106388
+ const result = await api.deleteEntry(ctx.projectId, typeName, id);
106409
106389
  ui.result({ command: "entries delete", data: result, render: /* @__PURE__ */ __name(() => renderPrettyJson5(result), "render") });
106410
106390
  }
106411
106391
  __name(entriesDeleteCommand, "entriesDeleteCommand");
@@ -110358,10 +110338,10 @@ schemas2.command("push").description("Push schema JSON files to the API (create
110358
110338
  schemas2.command("delete").description("Delete a schema by type name").argument("<typeName>", "Content type name").option("-C, --cwd <dir>", "Project directory").action(schemaDeleteCommand);
110359
110339
  var entries = program.command("entries").description("Manage content entries");
110360
110340
  entries.command("list").description("List entries of a content type").argument("<typeName>", "Content type name").option("-C, --cwd <dir>", "Project directory").option("--limit <n>", "Max entries to return").option("--offset <n>", "Offset for pagination").option("--search <query>", "Search query").option("--where <json>", `JSON filter object, e.g. '{"featured":true}'`).option("--sort <field>", "Sort field, prefix with - for descending").option("--fields <fields>", "Comma-separated fields to return, e.g. slug,title,excerpt").option("--populate <fields>", "Comma-separated reference fields to populate, e.g. author,contributors").option("--locale <locale>", "Locale to list (default en)").option("--sort-by <field>", "Sort field").option("--sort-direction <dir>", "Sort direction (asc|desc)").action(entriesListCommand);
110361
- entries.command("get").description("Get a single entry").argument("<typeName>", "Content type name").argument("<documentId>", "Document ID").option("-C, --cwd <dir>", "Project directory").requiredOption("--locale <locale>", "Entry locale").action(entriesGetCommand);
110341
+ entries.command("get").description("Get a single entry").argument("<typeName>", "Content type name").argument("<id>", "Entry ID").option("-C, --cwd <dir>", "Project directory").option("--locale <locale>", "Locale to read (default en)").action(entriesGetCommand);
110362
110342
  entries.command("create").description("Create a new entry").argument("<typeName>", "Content type name").option("-C, --cwd <dir>", "Project directory").requiredOption("--body <json>", "Entry JSON body (slug + data)").option("--locale <locale>", "Entry locale (default en)").option("--document-id <id>", "Document ID shared by localized variants").action(entriesCreateCommand);
110363
- entries.command("update").description("Update an existing entry").argument("<typeName>", "Content type name").argument("<documentId>", "Document ID").option("-C, --cwd <dir>", "Project directory").requiredOption("--body <json>", "Updated entry JSON body").requiredOption("--locale <locale>", "Entry locale").action(entriesUpdateCommand);
110364
- entries.command("delete").description("Delete an entry").argument("<typeName>", "Content type name").argument("<documentId>", "Document ID").option("-C, --cwd <dir>", "Project directory").requiredOption("--locale <locale>", "Entry locale").action(entriesDeleteCommand);
110343
+ entries.command("update").description("Update an existing entry").argument("<typeName>", "Content type name").argument("<id>", "Entry ID").option("-C, --cwd <dir>", "Project directory").requiredOption("--body <json>", "Updated entry JSON body").option("--locale <locale>", "Entry locale").option("--document-id <id>", "Document ID shared by localized variants").action(entriesUpdateCommand);
110344
+ entries.command("delete").description("Delete an entry").argument("<typeName>", "Content type name").argument("<id>", "Entry ID").option("-C, --cwd <dir>", "Project directory").action(entriesDeleteCommand);
110365
110345
  var assets2 = program.command("assets").description("Manage media assets");
110366
110346
  assets2.command("list").description("List assets").option("-C, --cwd <dir>", "Project directory").option("--parent-id <id>", "Filter by parent folder").option(
110367
110347
  "--search <query>",
@@ -71,7 +71,7 @@ export async function resolveMetaEntries(url) {
71
71
  return;
72
72
  }
73
73
  const { schema, queryField } = paramInfo;
74
- const entryUrl = new URL(`${base}/v2/entries/${schema}/field/${encodeURIComponent(queryField)}/${encodeURIComponent(value)}`);
74
+ const entryUrl = new URL(`${base}/entries/${schema}/field/${encodeURIComponent(queryField)}/${encodeURIComponent(value)}`);
75
75
  entryUrl.searchParams.set('locale', localeResolution.locale);
76
76
  const res = await fetch(entryUrl);
77
77
  if (res.ok) {
@@ -1,7 +1,6 @@
1
1
  type FieldData = Record<string, string>;
2
2
  interface RecordData {
3
3
  id: string;
4
- locale?: string;
5
4
  data: FieldData;
6
5
  visible: boolean;
7
6
  }
@@ -1 +1 @@
1
- {"version":3,"file":"retrieve-data-sources.d.ts","sourceRoot":"","sources":["../../../../src/runtime/content/utils/retrieve-data-sources.ts"],"names":[],"mappings":"AACA,KAAK,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAExC,UAAU,UAAU;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;AAgD9D;;;;GAIG;AACH,wBAAgB,0BAA0B,IAAI,kBAAkB,CAwD/D"}
1
+ {"version":3,"file":"retrieve-data-sources.d.ts","sourceRoot":"","sources":["../../../../src/runtime/content/utils/retrieve-data-sources.ts"],"names":[],"mappings":"AACA,KAAK,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAExC,UAAU,UAAU;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;AA8B9D;;;;GAIG;AACH,wBAAgB,0BAA0B,IAAI,kBAAkB,CAiD/D"}
@@ -1,19 +1,3 @@
1
- function parseRecordIdentity(token) {
2
- if (!token.startsWith('v2:')) {
3
- return { id: token };
4
- }
5
- const [version, documentId, encodedLocale, ...rest] = token.split(':');
6
- if (version !== 'v2' || !documentId || !encodedLocale || rest.length > 0) {
7
- return null;
8
- }
9
- try {
10
- const locale = decodeURIComponent(encodedLocale);
11
- return locale ? { id: documentId, locale } : null;
12
- }
13
- catch {
14
- return null;
15
- }
16
- }
17
1
  /**
18
2
  * Checks if an element is genuinely visible to the user within the viewport.
19
3
  * @param el The element to check.
@@ -54,13 +38,7 @@ export function retrieveVisibleDataSources() {
54
38
  const parts = source.split('.');
55
39
  // Expects the format "SchemaName.id.fieldName"
56
40
  if (parts.length === 3) {
57
- const [schemaName, identityToken, fieldName] = parts;
58
- const identity = parseRecordIdentity(identityToken);
59
- if (!identity) {
60
- return;
61
- }
62
- const { id, locale } = identity;
63
- const recordKey = JSON.stringify([id, locale ?? null]);
41
+ const [schemaName, id, fieldName] = parts;
64
42
  // Skip __translations
65
43
  if (schemaName === '__translations') {
66
44
  return;
@@ -70,17 +48,16 @@ export function retrieveVisibleDataSources() {
70
48
  tempGroupedData[schemaName] = {};
71
49
  }
72
50
  // Ensure the record (by ID) exists for this schema
73
- if (!tempGroupedData[schemaName][recordKey]) {
74
- tempGroupedData[schemaName][recordKey] = {
51
+ if (!tempGroupedData[schemaName][id]) {
52
+ tempGroupedData[schemaName][id] = {
75
53
  id: id,
76
- ...(locale ? { locale } : {}),
77
54
  data: {},
78
55
  visible: isElementVisible(el),
79
56
  };
80
57
  }
81
58
  // Add the field and its text content to the record
82
59
  if (el.textContent) {
83
- tempGroupedData[schemaName][recordKey].data[fieldName] = el.textContent.trim();
60
+ tempGroupedData[schemaName][id].data[fieldName] = el.textContent.trim();
84
61
  }
85
62
  }
86
63
  });
@@ -35,7 +35,7 @@ function resolveApiBaseUrl(rootDir) {
35
35
  return readEnvValue(rootDir, 'VITE_API_URL') ?? readEnvValue(rootDir, 'VITE_API_URL_DEV');
36
36
  }
37
37
  async function fetchEntries(baseUrl, schema, rootDir, locale) {
38
- const url = new URL(`${baseUrl.replace(/\/$/, '')}/v2/entries/${schema}`);
38
+ const url = new URL(`${baseUrl.replace(/\/$/, '')}/entries/${schema}`);
39
39
  url.searchParams.set('locale', locale);
40
40
  if (isValidationBuild) {
41
41
  url.searchParams.set('limit', '1');
@@ -42,6 +42,7 @@ export type ManyReferenceOps = {
42
42
  };
43
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;
44
44
  type BaseTopLevelWhere = {
45
+ id?: string | StringOps;
45
46
  documentId?: string | StringOps;
46
47
  slug?: string | StringOps;
47
48
  createdAt?: string | DateOps;
@@ -65,12 +66,9 @@ export type Fields<T> = Field<T> | readonly Field<T>[];
65
66
  type SelectedField<TField> = TField extends `__fimo.${string}` ? '__fimo' : TField;
66
67
  type SelectedFields<TFields> = TFields extends readonly (infer K)[] ? SelectedField<K> : SelectedField<TFields>;
67
68
  type ListItem<TValue> = TValue extends readonly (infer K)[] ? K : TValue;
68
- type EntryIdentityField<T> = Extract<'documentId' | 'locale', keyof T>;
69
69
  export type Projected<T extends {
70
- documentId: string;
71
- }, TFields extends Fields<T> | undefined> = [TFields] extends [
72
- undefined
73
- ] ? T : Pick<T, EntryIdentityField<T> | Extract<SelectedFields<TFields>, keyof T>>;
70
+ id: string;
71
+ }, TFields extends Fields<T> | undefined> = [TFields] extends [undefined] ? T : Pick<T, Extract<'id' | SelectedFields<TFields>, keyof T>>;
74
72
  export declare const FIMO_REFERENCES: unique symbol;
75
73
  export interface WithReferences<TReferences> {
76
74
  readonly [FIMO_REFERENCES]?: TReferences;
@@ -80,20 +78,20 @@ export type ReferenceField<TEntry> = Extract<keyof ReferenceMap<TEntry>, string>
80
78
  export type Populate<TEntry> = ReferenceField<TEntry> | readonly ReferenceField<TEntry>[];
81
79
  type PopulatedKeys<TEntry, TPopulate> = Extract<ListItem<TPopulate>, keyof ReferenceMap<TEntry> & keyof TEntry>;
82
80
  export type Populated<TEntry extends {
83
- documentId: string;
84
- }, TPopulate extends Populate<TEntry>> = Pick<TEntry, EntryIdentityField<TEntry>> & Omit<TEntry, PopulatedKeys<TEntry, TPopulate>> & {
81
+ id: string;
82
+ }, TPopulate extends Populate<TEntry>> = Pick<TEntry, 'id'> & Omit<TEntry, PopulatedKeys<TEntry, TPopulate>> & {
85
83
  [K in PopulatedKeys<TEntry, TPopulate>]: ReferenceMap<TEntry>[K];
86
84
  };
87
85
  export type PopulatedResult<TEntry extends {
88
- documentId: string;
86
+ id: string;
89
87
  }, TPopulate extends Populate<TEntry> | undefined> = [
90
88
  TPopulate
91
89
  ] extends [undefined] ? TEntry : Populated<TEntry, NonNullable<TPopulate>>;
92
90
  export type ProjectedWithPopulate<T extends {
93
- documentId: string;
94
- }, TFields extends string | readonly string[] | undefined, TPopulate extends string | readonly string[] | undefined> = [TFields] extends [undefined] ? T : Pick<T, EntryIdentityField<T> | Extract<SelectedFields<TFields> | ListItem<NonNullable<TPopulate>>, keyof T>>;
91
+ id: string;
92
+ }, TFields extends string | readonly string[] | undefined, TPopulate extends string | readonly string[] | undefined> = [TFields] extends [undefined] ? T : Pick<T, Extract<'id' | SelectedFields<TFields> | ListItem<NonNullable<TPopulate>>, keyof T>>;
95
93
  export type Query<T extends {
96
- documentId: string;
94
+ id: string;
97
95
  }, TFields extends Fields<T> | undefined = Fields<T> | undefined, TPopulate extends string | readonly string[] | undefined = string | readonly string[] | undefined> = {
98
96
  where?: Where<T>;
99
97
  locale?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../../../src/runtime/primitives/lib/query.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../../../src/runtime/primitives/lib/query.ts"],"names":[],"mappings":"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"}
@@ -12,9 +12,9 @@ describe('fimo/ui public type surface', () => {
12
12
  expectTypeOf().toEqualTypeOf();
13
13
  const localizedWhere = { locale: 'en' };
14
14
  expectTypeOf(localizedWhere).toEqualTypeOf();
15
- // @ts-expect-error row IDs are not part of the v2 public entry contract.
16
- const rowIdWhere = { id: '550e8400-e29b-41d4-a716-446655440000' };
17
- expectTypeOf(rowIdWhere).toEqualTypeOf();
15
+ // @ts-expect-error locale is not a filter on non-localized generated entry types.
16
+ const sharedWhere = { locale: 'en' };
17
+ expectTypeOf(sharedWhere).toEqualTypeOf();
18
18
  });
19
19
  it('supports the reference populate pattern emitted into generated schemas', () => {
20
20
  const query = {
@@ -37,8 +37,6 @@ describe('syncSchemas', () => {
37
37
  const post = readFileSync(join(scratch, 'src/schemas/Post.ts'), 'utf-8');
38
38
  const postTypes = readFileSync(join(scratch, 'src/schemas/Post.types.ts'), 'utf-8');
39
39
  expect(post).toContain('import { wrapWithSource as wrapAuthorWithSource } from "./Author";');
40
- expect(post).toContain('isPopulatedEntry(value) ? wrapAuthorWithSource(value) : value');
41
- expect(post).toContain('function isPopulatedEntry(value: unknown): value is PopulatedEntryRecord');
42
40
  expect(post).toContain('import type { Post, PostInput, PostPopulate, PostResult, PostFields, PostQuery } from "./Post.types";');
43
41
  expect(post).toContain('from "./Post.types";');
44
42
  expect(post).not.toContain('import type { Author } from "./Author";');
@@ -49,14 +47,9 @@ describe('syncSchemas', () => {
49
47
  expect(post).toContain('wrapAuthorWithSource(value)');
50
48
  expect(post).toContain('wrapWithSource(value)');
51
49
  expect(post).toContain('export async function create(payload: PostInput): Promise<Post>');
52
- expect(post).toContain('export async function getByDocumentId');
53
- expect(post).toContain('/v2/entries/Post/');
54
50
  expect(post).toContain('return wrapWithSource(data.data);');
55
51
  expect(postTypes).toContain('import type { Author } from "./Author.types";');
56
52
  expect(postTypes).toContain('export interface Post extends WithReferences<PostReferences>');
57
- expect(postTypes).not.toContain(' id: string;');
58
- expect(postTypes).toContain(' documentId: string;');
59
- expect(postTypes).toContain(' locale: string;');
60
53
  expect(postTypes).toContain('type FimoReference');
61
54
  expect(postTypes).toContain('author: FimoReference | null;');
62
55
  expect(postTypes).toContain('contributors: FimoReference[];');
@@ -95,15 +88,15 @@ describe('syncSchemas', () => {
95
88
  const settings = readFileSync(join(scratch, 'src/schemas/Settings.ts'), 'utf-8');
96
89
  const settingsTypes = readFileSync(join(scratch, 'src/schemas/Settings.types.ts'), 'utf-8');
97
90
  const homepageTypes = readFileSync(join(scratch, 'src/schemas/Homepage.types.ts'), 'utf-8');
98
- expect(settingsTypes).toContain('locale: string;');
91
+ expect(settingsTypes).not.toContain('locale: string;');
99
92
  expect(settingsTypes).not.toContain('locale?: string;');
100
93
  expect(homepageTypes).toContain('locale: string;');
101
94
  expect(settings).toContain('const LOCALIZED_CONTENT = false;');
102
95
  expect(settings).toContain('const LOCALIZED_REFERENCE_FIELDS = new Set<string>(["homepage"]);');
103
- expect(settings).toContain(' locale,');
96
+ expect(settings).not.toContain(' locale: entry.locale,');
104
97
  expect(settings).toContain('readLocale(params, LOCALIZED_CONTENT, useQueryLocale(params.locale))');
105
98
  expect(settings.match(/readLocale\(params, LOCALIZED_CONTENT, useQueryLocale\(params\.locale\)\)/g)?.length).toBe(4);
106
- expect(settings.match(/const locale = useQueryLocale\(options\.locale\);/g)?.length).toBe(2);
99
+ expect(settings.match(/readLocale\(options, false, useQueryLocale\(options\.locale\)\)/g)?.length).toBe(2);
107
100
  });
108
101
  it('generates singleton document APIs without collection mutations', () => {
109
102
  writeSchema('Settings', {
@@ -117,10 +110,6 @@ describe('syncSchemas', () => {
117
110
  const settings = readFileSync(join(scratch, 'src/schemas/Settings.ts'), 'utf-8');
118
111
  const settingsTypes = readFileSync(join(scratch, 'src/schemas/Settings.types.ts'), 'utf-8');
119
112
  expect(settings).toContain('fetch(`${base}${withReadOptions(`/documents/Settings`, options)}`');
120
- expect(settings).toContain('const usesV2Identity = typeof id !== "string";');
121
- expect(settings).toContain('`Settings.v2:${documentId}:${encodeURIComponent(locale)}`');
122
- expect(settingsTypes).toContain('id?: string;');
123
- expect(settingsTypes).toContain('locale?: string;');
124
113
  expect(settings).toContain('export async function update(payload: Partial<SettingsInput>)');
125
114
  expect(settings).toContain('export function useSuspenseGet');
126
115
  expect(settings).not.toContain('export async function create(');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fimo",
3
- "version": "0.6.0-experimental.2",
3
+ "version": "0.6.0-staging.2",
4
4
  "description": "Fimo CLI - create, deploy, and manage Fimo projects",
5
5
  "bin": {
6
6
  "fimo": "dist/cli/index.js"
@@ -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.6.0-experimental.2",
24
+ "fimo": "0.6.0-staging.2",
25
25
  "input-otp": "^1.4.2",
26
26
  "isbot": "^5",
27
27
  "lucide-react": "^0.577.0",