fimo 0.4.1 → 0.5.0-experimental.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.
- package/assets/content-templates/hooks-template.eta +108 -9
- package/assets/skills/fimo/SKILL.md +1 -1
- package/assets/skills/fimo/references/content.md +39 -11
- package/dist/cli/bundle.json +2 -2
- package/dist/cli/index.js +37 -31
- package/dist/runtime/content/parseCollectionResponse.d.ts +11 -0
- package/dist/runtime/content/parseCollectionResponse.d.ts.map +1 -0
- package/dist/runtime/content/parseCollectionResponse.js +13 -0
- package/dist/runtime/content/parseCollectionResponse.test.d.ts +2 -0
- package/dist/runtime/content/parseCollectionResponse.test.d.ts.map +1 -0
- package/dist/runtime/content/parseCollectionResponse.test.js +20 -0
- package/dist/runtime/index.d.ts +2 -0
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/index.js +1 -0
- package/dist/scripts/generated-types.test.js +40 -0
- package/dist/scripts/sync-schemas.test.js +4 -1
- package/package.json +1 -1
- package/release.json +2 -2
- package/templates/react-router/package.json +1 -1
|
@@ -9,8 +9,11 @@
|
|
|
9
9
|
*/
|
|
10
10
|
%>
|
|
11
11
|
// AUTO-GENERATED ⚠️ – do not edit by hand
|
|
12
|
-
import { useSuspenseQuery, useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
|
|
13
|
-
|
|
12
|
+
import { <% if (!model.isSingleton) { %>useInfiniteQuery, <% } %>useSuspenseQuery, useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
|
|
13
|
+
<% if (!model.isSingleton) { -%>
|
|
14
|
+
import type { InfiniteData, UseInfiniteQueryResult, UseQueryResult } from "@tanstack/react-query";
|
|
15
|
+
<% } -%>
|
|
16
|
+
import { FimoString, FimoMedia, FimoBoolean, FimoRichText, useLocale<% if (!model.isSingleton) { %>, parseCollectionResponse<% } %> } from "fimo/ui";
|
|
14
17
|
// @ts-ignore - virtual module provided by Fimo's Vite plugin
|
|
15
18
|
import fimoConfig from "virtual:fimo-config";
|
|
16
19
|
import type { <%= model.pascal %>, <%= model.pascal %>Input, <%= model.pascal %>Populate, <%= model.pascal %>Result<% if (!model.isSingleton) { %>, <%= model.pascal %>Fields, <%= model.pascal %>Query<% } %> } from "./<%= model.pascal %>.types";
|
|
@@ -215,6 +218,37 @@ function splitWritePayload(payload: Partial<<%= model.pascal %>Input>): Record<s
|
|
|
215
218
|
}
|
|
216
219
|
|
|
217
220
|
<% if (!model.isSingleton) { -%>
|
|
221
|
+
export interface CollectionPageInfo {
|
|
222
|
+
readonly limit: number;
|
|
223
|
+
readonly offset: number;
|
|
224
|
+
readonly total: number;
|
|
225
|
+
readonly hasMore: boolean;
|
|
226
|
+
readonly nextOffset: number | null;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
export interface CollectionPage<TItem> {
|
|
230
|
+
readonly items: TItem[];
|
|
231
|
+
readonly pageInfo: CollectionPageInfo;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
export type InfiniteListQuery<
|
|
235
|
+
TFields extends <%= model.pascal %>Fields | undefined = undefined,
|
|
236
|
+
TPopulate extends <%= model.pascal %>Populate | undefined = undefined,
|
|
237
|
+
> = Omit<<%= model.pascal %>Query<TFields, TPopulate>, "offset">;
|
|
238
|
+
|
|
239
|
+
export type InfiniteListResult<TItem> = UseInfiniteQueryResult<
|
|
240
|
+
InfiniteData<CollectionPage<TItem>>,
|
|
241
|
+
Error
|
|
242
|
+
> & {
|
|
243
|
+
readonly items: TItem[];
|
|
244
|
+
readonly total: number;
|
|
245
|
+
readonly hasMore: boolean;
|
|
246
|
+
readonly loadMore: () => ReturnType<
|
|
247
|
+
UseInfiniteQueryResult<InfiniteData<CollectionPage<TItem>>, Error>["fetchNextPage"]
|
|
248
|
+
>;
|
|
249
|
+
readonly isLoadingMore: boolean;
|
|
250
|
+
};
|
|
251
|
+
|
|
218
252
|
export async function getById<TPopulate extends <%= model.pascal %>Populate | undefined = undefined>(
|
|
219
253
|
id: string,
|
|
220
254
|
options: { locale?: string; populate?: TPopulate; localeFallbacks?: boolean } = {}
|
|
@@ -282,15 +316,30 @@ function toQueryString<
|
|
|
282
316
|
return query.toString();
|
|
283
317
|
}
|
|
284
318
|
|
|
285
|
-
export async function
|
|
319
|
+
export async function list<
|
|
286
320
|
TFields extends <%= model.pascal %>Fields | undefined = undefined,
|
|
287
321
|
TPopulate extends <%= model.pascal %>Populate | undefined = undefined,
|
|
288
|
-
>(params: <%= model.pascal %>Query<TFields, TPopulate> = {} as <%= model.pascal %>Query<TFields, TPopulate>): Promise<<%= model.pascal %>Result<TFields, TPopulate
|
|
322
|
+
>(params: <%= model.pascal %>Query<TFields, TPopulate> = {} as <%= model.pascal %>Query<TFields, TPopulate>): Promise<CollectionPage<<%= model.pascal %>Result<TFields, TPopulate>>> {
|
|
289
323
|
const qs = toQueryString(params);
|
|
290
324
|
const res = await fetch(`${base}/entries/<%= model.uid %>${qs ? "?" + qs : ""}`, { headers: fimoHeaders() });
|
|
291
325
|
if (!res.ok) throw new Error(await res.text());
|
|
292
|
-
const data = await res.json();
|
|
293
|
-
|
|
326
|
+
const data = parseCollectionResponse(await res.json());
|
|
327
|
+
const items = data.data.map(wrapWithSource) as <%= model.pascal %>Result<TFields, TPopulate>[];
|
|
328
|
+
const pageInfo: CollectionPageInfo = {
|
|
329
|
+
limit: data.meta.limit,
|
|
330
|
+
offset: data.meta.offset,
|
|
331
|
+
total: data.meta.total,
|
|
332
|
+
hasMore: data.meta.hasMore,
|
|
333
|
+
nextOffset: data.meta.hasMore ? data.meta.offset + data.meta.limit : null,
|
|
334
|
+
};
|
|
335
|
+
return { items, pageInfo };
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
export async function get<
|
|
339
|
+
TFields extends <%= model.pascal %>Fields | undefined = undefined,
|
|
340
|
+
TPopulate extends <%= model.pascal %>Populate | undefined = undefined,
|
|
341
|
+
>(params: <%= model.pascal %>Query<TFields, TPopulate> = {} as <%= model.pascal %>Query<TFields, TPopulate>): Promise<<%= model.pascal %>Result<TFields, TPopulate>[]> {
|
|
342
|
+
return (await list(params)).items;
|
|
294
343
|
}
|
|
295
344
|
|
|
296
345
|
export async function create(payload: <%= model.pascal %>Input): Promise<<%= model.pascal %>> {
|
|
@@ -353,7 +402,11 @@ const qk = {
|
|
|
353
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,
|
|
354
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,
|
|
355
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,
|
|
356
|
-
list : (params: <%= model.pascal %>Query) => ["<%= model.pascal %>", params] as const
|
|
405
|
+
list : (params: <%= model.pascal %>Query) => ["<%= model.pascal %>", params] as const,
|
|
406
|
+
infiniteList: <
|
|
407
|
+
TFields extends <%= model.pascal %>Fields | undefined = undefined,
|
|
408
|
+
TPopulate extends <%= model.pascal %>Populate | undefined = undefined,
|
|
409
|
+
>(params: InfiniteListQuery<TFields, TPopulate>) => ["<%= model.pascal %>", "infinite", params] as const
|
|
357
410
|
};
|
|
358
411
|
|
|
359
412
|
export function useGetById<TPopulate extends <%= model.pascal %>Populate | undefined = undefined>(id: string, options: { locale?: string; populate?: TPopulate; localeFallbacks?: boolean } = {}) {
|
|
@@ -380,7 +433,46 @@ export function useGet<
|
|
|
380
433
|
>(params: <%= model.pascal %>Query<TFields, TPopulate> = {} as <%= model.pascal %>Query<TFields, TPopulate>) {
|
|
381
434
|
const locale = readLocale(params, LOCALIZED_CONTENT, useQueryLocale(params.locale));
|
|
382
435
|
const localizedParams = { ...params, locale };
|
|
383
|
-
return useQuery<<%= model.pascal %>Result<TFields, TPopulate
|
|
436
|
+
return useQuery<CollectionPage<<%= model.pascal %>Result<TFields, TPopulate>>, Error, <%= model.pascal %>Result<TFields, TPopulate>[]>({
|
|
437
|
+
queryKey: qk.list(localizedParams),
|
|
438
|
+
queryFn: () => list(localizedParams),
|
|
439
|
+
select: (page) => page.items,
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
export function useList<
|
|
444
|
+
TFields extends <%= model.pascal %>Fields | undefined = undefined,
|
|
445
|
+
TPopulate extends <%= model.pascal %>Populate | undefined = undefined,
|
|
446
|
+
>(params: <%= model.pascal %>Query<TFields, TPopulate> = {} as <%= model.pascal %>Query<TFields, TPopulate>): UseQueryResult<CollectionPage<<%= model.pascal %>Result<TFields, TPopulate>>, Error> {
|
|
447
|
+
const locale = readLocale(params, LOCALIZED_CONTENT, useQueryLocale(params.locale));
|
|
448
|
+
const localizedParams = { ...params, locale };
|
|
449
|
+
return useQuery<CollectionPage<<%= model.pascal %>Result<TFields, TPopulate>>, Error>({
|
|
450
|
+
queryKey: qk.list(localizedParams),
|
|
451
|
+
queryFn: () => list(localizedParams),
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
export function useInfiniteList<
|
|
456
|
+
TFields extends <%= model.pascal %>Fields | undefined = undefined,
|
|
457
|
+
TPopulate extends <%= model.pascal %>Populate | undefined = undefined,
|
|
458
|
+
>(params: InfiniteListQuery<TFields, TPopulate> = {} as InfiniteListQuery<TFields, TPopulate>): InfiniteListResult<<%= model.pascal %>Result<TFields, TPopulate>> {
|
|
459
|
+
const locale = readLocale(params, LOCALIZED_CONTENT, useQueryLocale(params.locale));
|
|
460
|
+
const localizedParams = { ...params, locale };
|
|
461
|
+
const query = useInfiniteQuery({
|
|
462
|
+
queryKey: qk.infiniteList(localizedParams),
|
|
463
|
+
queryFn: ({ pageParam }) => list({ ...localizedParams, offset: pageParam }),
|
|
464
|
+
initialPageParam: 0,
|
|
465
|
+
getNextPageParam: (lastPage) => lastPage.pageInfo.nextOffset ?? undefined,
|
|
466
|
+
});
|
|
467
|
+
|
|
468
|
+
return {
|
|
469
|
+
...query,
|
|
470
|
+
items: query.data?.pages.flatMap((page) => page.items) ?? [],
|
|
471
|
+
total: query.data?.pages[0]?.pageInfo.total ?? 0,
|
|
472
|
+
hasMore: query.hasNextPage,
|
|
473
|
+
loadMore: () => query.fetchNextPage(),
|
|
474
|
+
isLoadingMore: query.isFetchingNextPage,
|
|
475
|
+
};
|
|
384
476
|
}
|
|
385
477
|
|
|
386
478
|
export function useSuspenseGetById<TPopulate extends <%= model.pascal %>Populate | undefined = undefined>(id: string, options: { locale?: string; populate?: TPopulate; localeFallbacks?: boolean } = {}) {
|
|
@@ -407,7 +499,11 @@ export function useSuspenseGet<
|
|
|
407
499
|
>(params: <%= model.pascal %>Query<TFields, TPopulate> = {} as <%= model.pascal %>Query<TFields, TPopulate>) {
|
|
408
500
|
const locale = readLocale(params, LOCALIZED_CONTENT, useQueryLocale(params.locale));
|
|
409
501
|
const localizedParams = { ...params, locale };
|
|
410
|
-
return useSuspenseQuery<<%= model.pascal %>Result<TFields, TPopulate
|
|
502
|
+
return useSuspenseQuery<CollectionPage<<%= model.pascal %>Result<TFields, TPopulate>>, Error, <%= model.pascal %>Result<TFields, TPopulate>[]>({
|
|
503
|
+
queryKey: qk.list(localizedParams),
|
|
504
|
+
queryFn: () => list(localizedParams),
|
|
505
|
+
select: (page) => page.items,
|
|
506
|
+
});
|
|
411
507
|
}
|
|
412
508
|
|
|
413
509
|
export function useCreate() {
|
|
@@ -476,6 +572,7 @@ export default {
|
|
|
476
572
|
getById,
|
|
477
573
|
getBySlug,
|
|
478
574
|
getByField,
|
|
575
|
+
list,
|
|
479
576
|
get,
|
|
480
577
|
create,
|
|
481
578
|
update,
|
|
@@ -485,6 +582,8 @@ export default {
|
|
|
485
582
|
useGetById,
|
|
486
583
|
useGetBySlug,
|
|
487
584
|
useGetByField,
|
|
585
|
+
useList,
|
|
586
|
+
useInfiniteList,
|
|
488
587
|
useGet,
|
|
489
588
|
useSuspenseGetById,
|
|
490
589
|
useSuspenseGet,
|
|
@@ -20,7 +20,7 @@ For CLI commands and workflows (creating a project, pushing schemas/forms, deplo
|
|
|
20
20
|
|
|
21
21
|
This is the load-bearing rule for every code change. **Fimo's whole point is that content editors edit content in the dashboard, not in code.** Anything hardcoded breaks that.
|
|
22
22
|
|
|
23
|
-
- **Content** (posts, products, pages, lists, anything structured) → declare a schema, render with
|
|
23
|
+
- **Content** (posts, products, pages, lists, anything structured) → declare a schema, render collections with generated `useList()` or `useInfiniteList()` hooks + `fimo/ui` components. Use `useGet()` only for legacy fixed array queries. **Never** write `const posts = [...]` in JSX.
|
|
24
24
|
- **Strings** (labels, CTAs, headings, descriptions, any visible text) → wrap in `t('key')` and create the default-locale value with `fimo labels set`. Use `--locale <locale>` only when intentionally writing a non-default locale. **Never** write `<h1>Welcome</h1>` directly — write `<Text value={t('home.title')} as="h1" />`.
|
|
25
25
|
- **Media** (images, videos, files) → use `<Image>` / `<Video>` from `fimo/ui` for schema media, `<StaticImage>` for hard-coded URLs. **Never** use `<img src={...}>`.
|
|
26
26
|
- **Forms** → use the generated Zod schema + `submitX` helper from `@/forms/<name>`. Never hand-roll fetch or validation.
|
|
@@ -250,6 +250,7 @@ Filtering on polymorphic fields is not supported yet.
|
|
|
250
250
|
getById<TPopulate extends BlogPostPopulate | undefined>(id: string, options?: { populate?: TPopulate }): Promise<BlogPostResult<undefined, TPopulate>>
|
|
251
251
|
getBySlug<TPopulate extends BlogPostPopulate | undefined>(slug: string, options?: { populate?: TPopulate }): Promise<BlogPostResult<undefined, TPopulate> | null>
|
|
252
252
|
getByField<TPopulate extends BlogPostPopulate | undefined>(fieldName: string, value: string, options?: { populate?: TPopulate }): Promise<BlogPostResult<undefined, TPopulate> | null>
|
|
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
256
|
update(id: string, payload: Partial<BlogPostInput>): Promise<BlogPost>
|
|
@@ -259,7 +260,9 @@ remove(id: string): Promise<void>
|
|
|
259
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, ... }
|
|
264
|
+
useInfiniteList<TFields, TPopulate>(params?) // → { items, total, hasMore, loadMore, isLoadingMore, ... }
|
|
265
|
+
useGet<TFields, TPopulate>(params?) // → legacy array-shaped { data: BlogPostResult<TFields, TPopulate>[] | undefined, ... }
|
|
263
266
|
useCreate() / useUpdate() / useRemove()
|
|
264
267
|
|
|
265
268
|
// Suspense variants (same signatures, throw to a <Suspense> boundary instead of returning isLoading)
|
|
@@ -278,12 +281,37 @@ useGet(options?) / useSuspenseGet(options?) / useUpdate()
|
|
|
278
281
|
|
|
279
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.
|
|
280
283
|
|
|
281
|
-
|
|
284
|
+
Choose the collection interface from the UI behavior. Use `useList` when the UI controls a page, and read pagination state from `pageInfo`:
|
|
282
285
|
|
|
283
286
|
```tsx
|
|
284
|
-
const { data:
|
|
285
|
-
if (isLoading || !
|
|
286
|
-
|
|
287
|
+
const { data: page, isLoading } = BlogPost.useList({ sort: '-publishedAt', limit: 12, offset: 24 });
|
|
288
|
+
if (isLoading || !page) return null;
|
|
289
|
+
|
|
290
|
+
page.items.map((post) => /* ... */);
|
|
291
|
+
page.pageInfo; // { limit, offset, total, hasMore, nextOffset }
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
Use `useInfiniteList` for load-more and infinite-scroll views. It accumulates pages and exposes one typed `items` array, so UI code does not manage offsets or flatten pages:
|
|
295
|
+
|
|
296
|
+
```tsx
|
|
297
|
+
const {
|
|
298
|
+
items: posts,
|
|
299
|
+
hasMore,
|
|
300
|
+
loadMore,
|
|
301
|
+
isLoadingMore,
|
|
302
|
+
} = BlogPost.useInfiniteList({
|
|
303
|
+
sort: '-publishedAt',
|
|
304
|
+
limit: 12,
|
|
305
|
+
});
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
`get()` and `useGet()` remain available as legacy array-shaped helpers for small, deliberately bounded subsets:
|
|
309
|
+
|
|
310
|
+
```tsx
|
|
311
|
+
const { data: featured = [] } = BlogPost.useGet({
|
|
312
|
+
where: { featured: true },
|
|
313
|
+
limit: 3,
|
|
314
|
+
});
|
|
287
315
|
```
|
|
288
316
|
|
|
289
317
|
Query params supported: `limit` (1-100, default 20), `offset` (default 0), `search`, `sort`, `where`, `fields`, and `populate`. Use these canonical names in new code.
|
|
@@ -350,7 +378,7 @@ Do not type populated hook data as `BlogPost[]`: plain `BlogPost` keeps referenc
|
|
|
350
378
|
|
|
351
379
|
Populate is depth-one. It only works for reference fields; trying to populate a scalar field returns 400. To-many reference order is preserved.
|
|
352
380
|
|
|
353
|
-
|
|
381
|
+
`list()` and `useList()` surface pagination metadata as `pageInfo`. `useInfiniteList()` consumes `nextOffset` internally and exposes `hasMore` plus `loadMore()`.
|
|
354
382
|
|
|
355
383
|
## Fimo primitives (what the field values are)
|
|
356
384
|
|
|
@@ -397,15 +425,15 @@ class FimoBoolean {
|
|
|
397
425
|
## UI code pattern
|
|
398
426
|
|
|
399
427
|
```tsx
|
|
400
|
-
import {
|
|
428
|
+
import { useList } from '@/schemas/BlogPost';
|
|
401
429
|
import { Text, RichText, Image, Date } from 'fimo/ui';
|
|
402
430
|
|
|
403
431
|
export function BlogList() {
|
|
404
|
-
const { data:
|
|
405
|
-
if (isLoading || !
|
|
432
|
+
const { data: page, isLoading } = useList({ limit: 10 });
|
|
433
|
+
if (isLoading || !page) return null;
|
|
406
434
|
return (
|
|
407
435
|
<ul>
|
|
408
|
-
{
|
|
436
|
+
{page.items.map((post) => (
|
|
409
437
|
<li key={post.id}>
|
|
410
438
|
<Text value={post.title} as="h2" />
|
|
411
439
|
<Image value={post.coverImage} width={800} height={400} fit="cover" />
|
|
@@ -429,7 +457,7 @@ const { data, meta } = await res.json();
|
|
|
429
457
|
// meta: { limit, offset, total, hasMore }
|
|
430
458
|
```
|
|
431
459
|
|
|
432
|
-
Prefer the generated
|
|
460
|
+
Prefer the generated `useList` or `useInfiniteList` hooks from `@/schemas/{Uid}` over hand-rolled fetches. They preserve projected/populated item types, cache results, and expose the pagination state regular list UIs need. Use the raw endpoint only for lower-level integrations outside the generated client.
|
|
433
461
|
|
|
434
462
|
## Forms vs. schemas
|
|
435
463
|
|
package/dist/cli/bundle.json
CHANGED
package/dist/cli/index.js
CHANGED
|
@@ -4194,7 +4194,7 @@ var init_session_refresh = __esm({
|
|
|
4194
4194
|
}
|
|
4195
4195
|
});
|
|
4196
4196
|
|
|
4197
|
-
// ../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-
|
|
4197
|
+
// ../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-cal_da517a110fdd8af320b5bd05eef9033a/node_modules/@better-auth/core/dist/env/env-impl.mjs
|
|
4198
4198
|
function getEnvVar(key, fallback) {
|
|
4199
4199
|
if (typeof process !== "undefined" && process.env) return process.env[key] ?? fallback;
|
|
4200
4200
|
if (typeof Deno !== "undefined") return Deno.env.get(key) ?? fallback;
|
|
@@ -4203,7 +4203,7 @@ function getEnvVar(key, fallback) {
|
|
|
4203
4203
|
}
|
|
4204
4204
|
var _envShim, _getEnv, env, nodeENV, ENV;
|
|
4205
4205
|
var init_env_impl = __esm({
|
|
4206
|
-
"../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-
|
|
4206
|
+
"../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-cal_da517a110fdd8af320b5bd05eef9033a/node_modules/@better-auth/core/dist/env/env-impl.mjs"() {
|
|
4207
4207
|
_envShim = /* @__PURE__ */ Object.create(null);
|
|
4208
4208
|
_getEnv = /* @__PURE__ */ __name((useShim) => globalThis.process?.env || globalThis.Deno?.env.toObject() || globalThis.__env__ || (useShim ? _envShim : globalThis), "_getEnv");
|
|
4209
4209
|
env = new Proxy(_envShim, {
|
|
@@ -4257,7 +4257,7 @@ var init_env_impl = __esm({
|
|
|
4257
4257
|
}
|
|
4258
4258
|
});
|
|
4259
4259
|
|
|
4260
|
-
// ../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-
|
|
4260
|
+
// ../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-cal_da517a110fdd8af320b5bd05eef9033a/node_modules/@better-auth/core/dist/env/color-depth.mjs
|
|
4261
4261
|
function getColorDepth() {
|
|
4262
4262
|
if (getEnvVar("FORCE_COLOR") !== void 0) switch (getEnvVar("FORCE_COLOR")) {
|
|
4263
4263
|
case "":
|
|
@@ -4303,7 +4303,7 @@ function getColorDepth() {
|
|
|
4303
4303
|
}
|
|
4304
4304
|
var COLORS_2, COLORS_16, COLORS_256, COLORS_16m, TERM_ENVS, CI_ENVS_MAP, TERM_ENVS_REG_EXP;
|
|
4305
4305
|
var init_color_depth = __esm({
|
|
4306
|
-
"../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-
|
|
4306
|
+
"../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-cal_da517a110fdd8af320b5bd05eef9033a/node_modules/@better-auth/core/dist/env/color-depth.mjs"() {
|
|
4307
4307
|
init_env_impl();
|
|
4308
4308
|
COLORS_2 = 1;
|
|
4309
4309
|
COLORS_16 = 4;
|
|
@@ -4354,13 +4354,13 @@ var init_color_depth = __esm({
|
|
|
4354
4354
|
}
|
|
4355
4355
|
});
|
|
4356
4356
|
|
|
4357
|
-
// ../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-
|
|
4357
|
+
// ../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-cal_da517a110fdd8af320b5bd05eef9033a/node_modules/@better-auth/core/dist/env/logger.mjs
|
|
4358
4358
|
function shouldPublishLog(currentLogLevel, logLevel) {
|
|
4359
4359
|
return levels.indexOf(logLevel) >= levels.indexOf(currentLogLevel);
|
|
4360
4360
|
}
|
|
4361
4361
|
var TTY_COLORS, levels, levelColors, formatMessage, createLogger, logger;
|
|
4362
4362
|
var init_logger = __esm({
|
|
4363
|
-
"../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-
|
|
4363
|
+
"../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-cal_da517a110fdd8af320b5bd05eef9033a/node_modules/@better-auth/core/dist/env/logger.mjs"() {
|
|
4364
4364
|
init_color_depth();
|
|
4365
4365
|
TTY_COLORS = {
|
|
4366
4366
|
reset: "\x1B[0m",
|
|
@@ -4438,34 +4438,34 @@ var init_logger = __esm({
|
|
|
4438
4438
|
}
|
|
4439
4439
|
});
|
|
4440
4440
|
|
|
4441
|
-
// ../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-
|
|
4441
|
+
// ../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-cal_da517a110fdd8af320b5bd05eef9033a/node_modules/@better-auth/core/dist/env/index.mjs
|
|
4442
4442
|
var init_env = __esm({
|
|
4443
|
-
"../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-
|
|
4443
|
+
"../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-cal_da517a110fdd8af320b5bd05eef9033a/node_modules/@better-auth/core/dist/env/index.mjs"() {
|
|
4444
4444
|
init_env_impl();
|
|
4445
4445
|
init_color_depth();
|
|
4446
4446
|
init_logger();
|
|
4447
4447
|
}
|
|
4448
4448
|
});
|
|
4449
4449
|
|
|
4450
|
-
// ../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-
|
|
4450
|
+
// ../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-cal_da517a110fdd8af320b5bd05eef9033a/node_modules/@better-auth/core/dist/utils/error-codes.mjs
|
|
4451
4451
|
function defineErrorCodes(codes) {
|
|
4452
4452
|
return codes;
|
|
4453
4453
|
}
|
|
4454
4454
|
var init_error_codes = __esm({
|
|
4455
|
-
"../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-
|
|
4455
|
+
"../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-cal_da517a110fdd8af320b5bd05eef9033a/node_modules/@better-auth/core/dist/utils/error-codes.mjs"() {
|
|
4456
4456
|
__name(defineErrorCodes, "defineErrorCodes");
|
|
4457
4457
|
}
|
|
4458
4458
|
});
|
|
4459
4459
|
|
|
4460
|
-
// ../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-
|
|
4460
|
+
// ../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-cal_da517a110fdd8af320b5bd05eef9033a/node_modules/@better-auth/core/dist/utils/db.mjs
|
|
4461
4461
|
var init_db = __esm({
|
|
4462
|
-
"../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-
|
|
4462
|
+
"../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-cal_da517a110fdd8af320b5bd05eef9033a/node_modules/@better-auth/core/dist/utils/db.mjs"() {
|
|
4463
4463
|
}
|
|
4464
4464
|
});
|
|
4465
4465
|
|
|
4466
|
-
// ../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-
|
|
4466
|
+
// ../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-cal_da517a110fdd8af320b5bd05eef9033a/node_modules/@better-auth/core/dist/utils/deprecate.mjs
|
|
4467
4467
|
var init_deprecate = __esm({
|
|
4468
|
-
"../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-
|
|
4468
|
+
"../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-cal_da517a110fdd8af320b5bd05eef9033a/node_modules/@better-auth/core/dist/utils/deprecate.mjs"() {
|
|
4469
4469
|
}
|
|
4470
4470
|
});
|
|
4471
4471
|
|
|
@@ -4475,42 +4475,42 @@ var init_random = __esm({
|
|
|
4475
4475
|
}
|
|
4476
4476
|
});
|
|
4477
4477
|
|
|
4478
|
-
// ../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-
|
|
4478
|
+
// ../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-cal_da517a110fdd8af320b5bd05eef9033a/node_modules/@better-auth/core/dist/utils/id.mjs
|
|
4479
4479
|
var init_id = __esm({
|
|
4480
|
-
"../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-
|
|
4480
|
+
"../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-cal_da517a110fdd8af320b5bd05eef9033a/node_modules/@better-auth/core/dist/utils/id.mjs"() {
|
|
4481
4481
|
init_random();
|
|
4482
4482
|
}
|
|
4483
4483
|
});
|
|
4484
4484
|
|
|
4485
|
-
// ../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-
|
|
4485
|
+
// ../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-cal_da517a110fdd8af320b5bd05eef9033a/node_modules/@better-auth/core/dist/utils/ip.mjs
|
|
4486
4486
|
var init_ip = __esm({
|
|
4487
|
-
"../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-
|
|
4487
|
+
"../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-cal_da517a110fdd8af320b5bd05eef9033a/node_modules/@better-auth/core/dist/utils/ip.mjs"() {
|
|
4488
4488
|
}
|
|
4489
4489
|
});
|
|
4490
4490
|
|
|
4491
|
-
// ../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-
|
|
4491
|
+
// ../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-cal_da517a110fdd8af320b5bd05eef9033a/node_modules/@better-auth/core/dist/utils/json.mjs
|
|
4492
4492
|
var init_json = __esm({
|
|
4493
|
-
"../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-
|
|
4493
|
+
"../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-cal_da517a110fdd8af320b5bd05eef9033a/node_modules/@better-auth/core/dist/utils/json.mjs"() {
|
|
4494
4494
|
init_logger();
|
|
4495
4495
|
init_env();
|
|
4496
4496
|
}
|
|
4497
4497
|
});
|
|
4498
4498
|
|
|
4499
|
-
// ../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-
|
|
4499
|
+
// ../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-cal_da517a110fdd8af320b5bd05eef9033a/node_modules/@better-auth/core/dist/utils/string.mjs
|
|
4500
4500
|
var init_string = __esm({
|
|
4501
|
-
"../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-
|
|
4501
|
+
"../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-cal_da517a110fdd8af320b5bd05eef9033a/node_modules/@better-auth/core/dist/utils/string.mjs"() {
|
|
4502
4502
|
}
|
|
4503
4503
|
});
|
|
4504
4504
|
|
|
4505
|
-
// ../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-
|
|
4505
|
+
// ../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-cal_da517a110fdd8af320b5bd05eef9033a/node_modules/@better-auth/core/dist/utils/url.mjs
|
|
4506
4506
|
var init_url = __esm({
|
|
4507
|
-
"../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-
|
|
4507
|
+
"../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-cal_da517a110fdd8af320b5bd05eef9033a/node_modules/@better-auth/core/dist/utils/url.mjs"() {
|
|
4508
4508
|
}
|
|
4509
4509
|
});
|
|
4510
4510
|
|
|
4511
|
-
// ../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-
|
|
4511
|
+
// ../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-cal_da517a110fdd8af320b5bd05eef9033a/node_modules/@better-auth/core/dist/utils/index.mjs
|
|
4512
4512
|
var init_utils = __esm({
|
|
4513
|
-
"../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-
|
|
4513
|
+
"../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-cal_da517a110fdd8af320b5bd05eef9033a/node_modules/@better-auth/core/dist/utils/index.mjs"() {
|
|
4514
4514
|
init_db();
|
|
4515
4515
|
init_deprecate();
|
|
4516
4516
|
init_error_codes();
|
|
@@ -4522,10 +4522,10 @@ var init_utils = __esm({
|
|
|
4522
4522
|
}
|
|
4523
4523
|
});
|
|
4524
4524
|
|
|
4525
|
-
// ../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-
|
|
4525
|
+
// ../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-cal_da517a110fdd8af320b5bd05eef9033a/node_modules/@better-auth/core/dist/error/codes.mjs
|
|
4526
4526
|
var BASE_ERROR_CODES;
|
|
4527
4527
|
var init_codes = __esm({
|
|
4528
|
-
"../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-
|
|
4528
|
+
"../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-cal_da517a110fdd8af320b5bd05eef9033a/node_modules/@better-auth/core/dist/error/codes.mjs"() {
|
|
4529
4529
|
init_error_codes();
|
|
4530
4530
|
init_utils();
|
|
4531
4531
|
BASE_ERROR_CODES = defineErrorCodes({
|
|
@@ -4576,10 +4576,10 @@ var init_codes = __esm({
|
|
|
4576
4576
|
}
|
|
4577
4577
|
});
|
|
4578
4578
|
|
|
4579
|
-
// ../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-
|
|
4579
|
+
// ../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-cal_da517a110fdd8af320b5bd05eef9033a/node_modules/@better-auth/core/dist/error/index.mjs
|
|
4580
4580
|
var BetterAuthError;
|
|
4581
4581
|
var init_error = __esm({
|
|
4582
|
-
"../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-
|
|
4582
|
+
"../../node_modules/.pnpm/@better-auth+core@1.4.18_@better-auth+utils@0.3.0_@better-fetch+fetch@1.1.21_better-cal_da517a110fdd8af320b5bd05eef9033a/node_modules/@better-auth/core/dist/error/index.mjs"() {
|
|
4583
4583
|
init_codes();
|
|
4584
4584
|
BetterAuthError = class extends Error {
|
|
4585
4585
|
static {
|
|
@@ -44568,7 +44568,7 @@ var init_document_dto = __esm({
|
|
|
44568
44568
|
});
|
|
44569
44569
|
|
|
44570
44570
|
// ../../packages/api-contracts/dist/esm/dtos/chat.dto.js
|
|
44571
|
-
var ChatMessageListDTOSchema, ChatDeletionDTOSchema, ChatDeletionDTO, ChatMessageListResponseSchema, ChatDeletionResponseSchema;
|
|
44571
|
+
var ChatMessageListDTOSchema, ChatMessagesPageDTOSchema, ChatDeletionDTOSchema, ChatDeletionDTO, ChatMessageListResponseSchema, ChatMessagesPageResponseSchema, ChatDeletionResponseSchema;
|
|
44572
44572
|
var init_chat_dto = __esm({
|
|
44573
44573
|
"../../packages/api-contracts/dist/esm/dtos/chat.dto.js"() {
|
|
44574
44574
|
"use strict";
|
|
@@ -44577,12 +44577,18 @@ var init_chat_dto = __esm({
|
|
|
44577
44577
|
init_response();
|
|
44578
44578
|
init_project_dto();
|
|
44579
44579
|
ChatMessageListDTOSchema = external_exports.array(ProjectMessageDTOSchema);
|
|
44580
|
+
ChatMessagesPageDTOSchema = external_exports.object({
|
|
44581
|
+
items: external_exports.array(ProjectMessagePublicDTOSchema),
|
|
44582
|
+
/** Cursor for the next (older) page — opaque base64 of `(createdAt, id)`. */
|
|
44583
|
+
nextCursor: external_exports.string().nullable()
|
|
44584
|
+
});
|
|
44580
44585
|
ChatDeletionDTOSchema = external_exports.object({
|
|
44581
44586
|
success: external_exports.boolean(),
|
|
44582
44587
|
deletedCount: external_exports.number()
|
|
44583
44588
|
});
|
|
44584
44589
|
ChatDeletionDTO = createDTO(ChatDeletionDTOSchema);
|
|
44585
44590
|
ChatMessageListResponseSchema = createResponseSchema(ChatMessageListDTOSchema);
|
|
44591
|
+
ChatMessagesPageResponseSchema = createResponseSchema(ChatMessagesPageDTOSchema);
|
|
44586
44592
|
ChatDeletionResponseSchema = createResponseSchema(ChatDeletionDTOSchema);
|
|
44587
44593
|
}
|
|
44588
44594
|
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface CollectionResponse {
|
|
2
|
+
readonly data: Record<string, unknown>[];
|
|
3
|
+
readonly meta: {
|
|
4
|
+
readonly limit: number;
|
|
5
|
+
readonly offset: number;
|
|
6
|
+
readonly total: number;
|
|
7
|
+
readonly hasMore: boolean;
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
export declare function parseCollectionResponse(value: unknown): CollectionResponse;
|
|
11
|
+
//# sourceMappingURL=parseCollectionResponse.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parseCollectionResponse.d.ts","sourceRoot":"","sources":["../../../src/runtime/content/parseCollectionResponse.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IACzC,QAAQ,CAAC,IAAI,EAAE;QACb,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;KAC3B,CAAC;CACH;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,kBAAkB,CAE1E"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
const collectionResponseSchema = z.object({
|
|
3
|
+
data: z.array(z.record(z.string(), z.unknown())),
|
|
4
|
+
meta: z.object({
|
|
5
|
+
limit: z.number().int().positive(),
|
|
6
|
+
offset: z.number().int().nonnegative(),
|
|
7
|
+
total: z.number().int().nonnegative(),
|
|
8
|
+
hasMore: z.boolean(),
|
|
9
|
+
}),
|
|
10
|
+
});
|
|
11
|
+
export function parseCollectionResponse(value) {
|
|
12
|
+
return collectionResponseSchema.parse(value);
|
|
13
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parseCollectionResponse.test.d.ts","sourceRoot":"","sources":["../../../src/runtime/content/parseCollectionResponse.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { parseCollectionResponse } from './parseCollectionResponse.js';
|
|
3
|
+
describe('parseCollectionResponse', () => {
|
|
4
|
+
it('accepts the collection envelope used by generated clients', () => {
|
|
5
|
+
const response = parseCollectionResponse({
|
|
6
|
+
data: [{ id: 'post-1', title: 'Hello' }],
|
|
7
|
+
meta: { limit: 12, offset: 24, total: 40, hasMore: true },
|
|
8
|
+
});
|
|
9
|
+
expect(response).toEqual({
|
|
10
|
+
data: [{ id: 'post-1', title: 'Hello' }],
|
|
11
|
+
meta: { limit: 12, offset: 24, total: 40, hasMore: true },
|
|
12
|
+
});
|
|
13
|
+
});
|
|
14
|
+
it('rejects invalid pagination metadata', () => {
|
|
15
|
+
expect(() => parseCollectionResponse({
|
|
16
|
+
data: [],
|
|
17
|
+
meta: { limit: 0, offset: -1, total: '40', hasMore: 'yes' },
|
|
18
|
+
})).toThrow();
|
|
19
|
+
});
|
|
20
|
+
});
|
package/dist/runtime/index.d.ts
CHANGED
|
@@ -6,6 +6,8 @@ export type { FimoLocaleContextValue } from './i18n/FimoLocaleContext.js';
|
|
|
6
6
|
export type { FimoLocaleResolution } from './i18n/locale.js';
|
|
7
7
|
export { DataSourcesProvider } from './content/DataSourcesProvider.js';
|
|
8
8
|
export { RefreshContentProvider } from './content/RefreshContentProvider.js';
|
|
9
|
+
export { parseCollectionResponse } from './content/parseCollectionResponse.js';
|
|
10
|
+
export type { CollectionResponse } from './content/parseCollectionResponse.js';
|
|
9
11
|
export { AppErrorBoundary } from './core/AppErrorBoundary.js';
|
|
10
12
|
export { ViteLifecycles } from './core/ViteLifecycles.js';
|
|
11
13
|
export { Pageview } from './t/Pageview.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/runtime/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACnE,YAAY,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AACvF,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACvE,YAAY,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAC1E,YAAY,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAG7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AACvE,OAAO,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/runtime/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACnE,YAAY,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AACvF,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACvE,YAAY,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAC1E,YAAY,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAG7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AACvE,OAAO,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAC;AAC7E,OAAO,EAAE,uBAAuB,EAAE,MAAM,sCAAsC,CAAC;AAC/E,YAAY,EAAE,kBAAkB,EAAE,MAAM,sCAAsC,CAAC;AAG/E,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAG1D,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAG3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAEpE,cAAc,uBAAuB,CAAC"}
|
package/dist/runtime/index.js
CHANGED
|
@@ -5,6 +5,7 @@ export { localizeFimoPath, resolveFimoLocale } from './i18n/locale.js';
|
|
|
5
5
|
// Content
|
|
6
6
|
export { DataSourcesProvider } from './content/DataSourcesProvider.js';
|
|
7
7
|
export { RefreshContentProvider } from './content/RefreshContentProvider.js';
|
|
8
|
+
export { parseCollectionResponse } from './content/parseCollectionResponse.js';
|
|
8
9
|
// Core
|
|
9
10
|
export { AppErrorBoundary } from './core/AppErrorBoundary.js';
|
|
10
11
|
export { ViteLifecycles } from './core/ViteLifecycles.js';
|
|
@@ -75,6 +75,7 @@ const SCHEMAS = {
|
|
|
75
75
|
};
|
|
76
76
|
const USAGE = `// Agent-style usage of the generated types — compile-time contract.
|
|
77
77
|
import type { PageResult, PageWhere } from "./Page";
|
|
78
|
+
import Post from "./Post";
|
|
78
79
|
import type { PostResult } from "./Post";
|
|
79
80
|
|
|
80
81
|
export function renderFeatured(page: PageResult<undefined, readonly ["featured", "hero"]>): string[] {
|
|
@@ -112,6 +113,45 @@ export function whereContract(): PageWhere {
|
|
|
112
113
|
featured: "some-document-id",
|
|
113
114
|
};
|
|
114
115
|
}
|
|
116
|
+
|
|
117
|
+
export function paginatedPostContract(): void {
|
|
118
|
+
const legacy = Post.useGet({ limit: 3 });
|
|
119
|
+
const page = Post.useList({
|
|
120
|
+
fields: ["title", "author"] as const,
|
|
121
|
+
populate: ["author"] as const,
|
|
122
|
+
limit: 12,
|
|
123
|
+
offset: 24,
|
|
124
|
+
});
|
|
125
|
+
const infinite = Post.useInfiniteList({
|
|
126
|
+
fields: ["title", "author"] as const,
|
|
127
|
+
populate: ["author"] as const,
|
|
128
|
+
limit: 12,
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
const legacyPosts: PostResult[] = legacy.data ?? [];
|
|
132
|
+
const pagePosts: PostResult<readonly ["title", "author"], readonly ["author"]>[] = page.data?.items ?? [];
|
|
133
|
+
const total: number = page.data?.pageInfo.total ?? 0;
|
|
134
|
+
const nextOffset: number | null = page.data?.pageInfo.nextOffset ?? null;
|
|
135
|
+
const infinitePosts: PostResult<readonly ["title", "author"], readonly ["author"]>[] = infinite.items;
|
|
136
|
+
const firstAuthorName: string = infinitePosts[0]?.author ? String(infinitePosts[0].author.name) : "";
|
|
137
|
+
const hasMore: boolean = infinite.hasMore;
|
|
138
|
+
const isLoadingMore: boolean = infinite.isLoadingMore;
|
|
139
|
+
|
|
140
|
+
void infinite.loadMore();
|
|
141
|
+
// @ts-expect-error infinite lists own offset progression
|
|
142
|
+
Post.useInfiniteList({ offset: 12 });
|
|
143
|
+
|
|
144
|
+
void [legacyPosts, pagePosts, total, nextOffset, infinitePosts, firstAuthorName, hasMore, isLoadingMore];
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export async function paginatedPostFetchContract(): Promise<void> {
|
|
148
|
+
const page = await Post.list({ limit: 12, offset: 24 });
|
|
149
|
+
const legacyPosts: PostResult[] = await Post.get({ limit: 3 });
|
|
150
|
+
const pagePosts: PostResult[] = page.items;
|
|
151
|
+
const hasMore: boolean = page.pageInfo.hasMore;
|
|
152
|
+
|
|
153
|
+
void [legacyPosts, pagePosts, hasMore];
|
|
154
|
+
}
|
|
115
155
|
`;
|
|
116
156
|
const SHIMS = `declare module "virtual:fimo-config" {
|
|
117
157
|
const config: Record<string, unknown>;
|
|
@@ -95,7 +95,7 @@ describe('syncSchemas', () => {
|
|
|
95
95
|
expect(settings).toContain('const LOCALIZED_REFERENCE_FIELDS = new Set<string>(["homepage"]);');
|
|
96
96
|
expect(settings).not.toContain(' locale: entry.locale,');
|
|
97
97
|
expect(settings).toContain('readLocale(params, LOCALIZED_CONTENT, useQueryLocale(params.locale))');
|
|
98
|
-
expect(settings.match(/readLocale\(params, LOCALIZED_CONTENT, useQueryLocale\(params\.locale\)\)/g)?.length).toBe(
|
|
98
|
+
expect(settings.match(/readLocale\(params, LOCALIZED_CONTENT, useQueryLocale\(params\.locale\)\)/g)?.length).toBe(4);
|
|
99
99
|
expect(settings.match(/readLocale\(options, false, useQueryLocale\(options\.locale\)\)/g)?.length).toBe(2);
|
|
100
100
|
});
|
|
101
101
|
it('generates singleton document APIs without collection mutations', () => {
|
|
@@ -115,6 +115,9 @@ describe('syncSchemas', () => {
|
|
|
115
115
|
expect(settings).not.toContain('export async function create(');
|
|
116
116
|
expect(settings).not.toContain('export async function remove(');
|
|
117
117
|
expect(settings).not.toContain('export function useCreate(');
|
|
118
|
+
expect(settings).not.toContain('export function useList(');
|
|
119
|
+
expect(settings).not.toContain('export function useInfiniteList(');
|
|
120
|
+
expect(settings).not.toContain('useInfiniteQuery');
|
|
118
121
|
expect(settingsTypes).toContain('siteName: string;');
|
|
119
122
|
expect(settingsTypes).not.toContain('documentId?: string;');
|
|
120
123
|
});
|
package/package.json
CHANGED
package/release.json
CHANGED