@btst/stack 5.0.0 → 5.1.0
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/dist/api/index.d.cts +2 -2
- package/dist/api/index.d.mts +2 -2
- package/dist/api/index.d.ts +2 -2
- package/dist/client/index.d.cts +2 -2
- package/dist/client/index.d.mts +2 -2
- package/dist/client/index.d.ts +2 -2
- package/dist/context/index.d.cts +1 -1
- package/dist/context/index.d.mts +1 -1
- package/dist/context/index.d.ts +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/packages/stack/src/plugins/cms/api/getters.cjs +142 -6
- package/dist/packages/stack/src/plugins/cms/api/getters.mjs +139 -8
- package/dist/packages/stack/src/plugins/cms/api/operations.cjs +67 -61
- package/dist/packages/stack/src/plugins/cms/api/operations.mjs +69 -63
- package/dist/packages/stack/src/plugins/cms/api/plugin.cjs +26 -8
- package/dist/packages/stack/src/plugins/cms/api/plugin.mjs +27 -9
- package/dist/packages/stack/src/plugins/cms/api/query-key-defs.cjs +15 -1
- package/dist/packages/stack/src/plugins/cms/api/query-key-defs.mjs +14 -2
- package/dist/packages/stack/src/plugins/cms/client/hooks/cms-hooks.cjs +45 -24
- package/dist/packages/stack/src/plugins/cms/client/hooks/cms-hooks.mjs +45 -24
- package/dist/packages/stack/src/plugins/cms/schemas.cjs +22 -0
- package/dist/packages/stack/src/plugins/cms/schemas.mjs +20 -1
- package/dist/plugins/api/index.d.cts +2 -2
- package/dist/plugins/api/index.d.mts +2 -2
- package/dist/plugins/api/index.d.ts +2 -2
- package/dist/plugins/blog/api/index.d.cts +2 -2
- package/dist/plugins/blog/api/index.d.mts +2 -2
- package/dist/plugins/blog/api/index.d.ts +2 -2
- package/dist/plugins/blog/client/hooks/index.d.cts +2 -2
- package/dist/plugins/blog/client/hooks/index.d.mts +2 -2
- package/dist/plugins/blog/client/hooks/index.d.ts +2 -2
- package/dist/plugins/blog/client/index.d.cts +2 -2
- package/dist/plugins/blog/client/index.d.mts +2 -2
- package/dist/plugins/blog/client/index.d.ts +2 -2
- package/dist/plugins/blog/query-keys.d.cts +2 -2
- package/dist/plugins/blog/query-keys.d.mts +2 -2
- package/dist/plugins/blog/query-keys.d.ts +2 -2
- package/dist/plugins/client/index.d.cts +2 -2
- package/dist/plugins/client/index.d.mts +2 -2
- package/dist/plugins/client/index.d.ts +2 -2
- package/dist/plugins/cms/api/index.cjs +1 -0
- package/dist/plugins/cms/api/index.d.cts +43 -11
- package/dist/plugins/cms/api/index.d.mts +43 -11
- package/dist/plugins/cms/api/index.d.ts +43 -11
- package/dist/plugins/cms/api/index.mjs +1 -1
- package/dist/plugins/cms/client/hooks/index.d.cts +90 -45
- package/dist/plugins/cms/client/hooks/index.d.mts +90 -45
- package/dist/plugins/cms/client/hooks/index.d.ts +90 -45
- package/dist/plugins/cms/client/index.d.cts +2 -1
- package/dist/plugins/cms/client/index.d.mts +2 -1
- package/dist/plugins/cms/client/index.d.ts +2 -1
- package/dist/plugins/cms/query-keys.cjs +69 -13
- package/dist/plugins/cms/query-keys.d.cts +89 -212
- package/dist/plugins/cms/query-keys.d.mts +89 -212
- package/dist/plugins/cms/query-keys.d.ts +89 -212
- package/dist/plugins/cms/query-keys.mjs +70 -14
- package/dist/plugins/kanban/client/index.d.cts +1 -1
- package/dist/plugins/kanban/client/index.d.mts +1 -1
- package/dist/plugins/kanban/client/index.d.ts +1 -1
- package/dist/plugins/route-docs/client/index.d.cts +1 -1
- package/dist/plugins/route-docs/client/index.d.mts +1 -1
- package/dist/plugins/route-docs/client/index.d.ts +1 -1
- package/dist/plugins/ui-builder/client/hooks/index.d.cts +3 -3
- package/dist/plugins/ui-builder/client/hooks/index.d.mts +3 -3
- package/dist/plugins/ui-builder/client/hooks/index.d.ts +3 -3
- package/dist/plugins/ui-builder/client/index.d.cts +3 -3
- package/dist/plugins/ui-builder/client/index.d.mts +3 -3
- package/dist/plugins/ui-builder/client/index.d.ts +3 -3
- package/dist/plugins/ui-builder/query-keys.d.cts +4 -3
- package/dist/plugins/ui-builder/query-keys.d.mts +4 -3
- package/dist/plugins/ui-builder/query-keys.d.ts +4 -3
- package/dist/shared/{stack.DMj68qY0.d.mts → stack.B2jlVVhD.d.mts} +5 -5
- package/dist/shared/{stack.Cvnj99cs.d.ts → stack.BB9tubJJ.d.ts} +9 -3
- package/dist/shared/{stack.Bt3WG2yb.d.cts → stack.BWduIMKG.d.cts} +35 -35
- package/dist/shared/stack.Bw09Lg2z.d.ts +1420 -0
- package/dist/shared/{stack.CkEz7vSt.d.mts → stack.C2Pvl-RS.d.mts} +9 -3
- package/dist/shared/{stack.C2l2wd_X.d.ts → stack.Ch9-ppmQ.d.ts} +35 -35
- package/dist/shared/{stack.Ht8mhDj5.d.cts → stack.D17yFglU.d.cts} +5 -5
- package/dist/shared/{stack.CiD115Ov.d.mts → stack.D6fPBfYe.d.mts} +35 -35
- package/dist/shared/stack.DFGj0gb7.d.mts +1420 -0
- package/dist/shared/{stack.pi0FxoEa.d.ts → stack.Dcfg4GNN.d.ts} +5 -5
- package/dist/shared/{stack.3rxARhgS.d.cts → stack.DrB3L7Ih.d.cts} +52 -3
- package/dist/shared/{stack.3rxARhgS.d.mts → stack.DrB3L7Ih.d.mts} +52 -3
- package/dist/shared/{stack.3rxARhgS.d.ts → stack.DrB3L7Ih.d.ts} +52 -3
- package/dist/shared/stack.NNrBKBkM.d.cts +1420 -0
- package/dist/shared/{stack.mRRyZBUg.d.cts → stack.Rb87lHqK.d.cts} +9 -3
- package/package.json +1 -1
- package/src/__tests__/cms-query-keys.test.ts +57 -0
- package/src/plugins/api/index.ts +1 -0
- package/src/plugins/api/operation.ts +16 -3
- package/src/plugins/cms/__tests__/authorization.test.ts +652 -187
- package/src/plugins/cms/__tests__/client-runtime.browser.test.tsx +655 -0
- package/src/plugins/cms/__tests__/content-read.typecheck.ts +351 -0
- package/src/plugins/cms/__tests__/getters.test.ts +286 -0
- package/src/plugins/cms/api/getters.ts +270 -12
- package/src/plugins/cms/api/index.ts +10 -0
- package/src/plugins/cms/api/operations.ts +163 -75
- package/src/plugins/cms/api/plugin.ts +50 -12
- package/src/plugins/cms/api/query-key-defs.ts +29 -2
- package/src/plugins/cms/client/hooks/cms-hooks.tsx +400 -91
- package/src/plugins/cms/client/index.ts +9 -0
- package/src/plugins/cms/query-keys.ts +171 -16
- package/src/plugins/cms/schemas.ts +30 -0
- package/src/plugins/cms/types.ts +49 -2
- package/src/plugins/media/__tests__/identity-partition.test.tsx +26 -16
- package/dist/shared/stack.CAmVUwjV.d.cts +0 -764
- package/dist/shared/stack.CQK02ujt.d.ts +0 -764
- package/dist/shared/stack.D9x1fR5a.d.mts +0 -764
- package/dist/shared/{stack.CKc_Bais.d.cts → stack.Csi-4Mgz.d.cts} +7 -7
- package/dist/shared/{stack.CKc_Bais.d.mts → stack.Csi-4Mgz.d.mts} +7 -7
- package/dist/shared/{stack.CKc_Bais.d.ts → stack.Csi-4Mgz.d.ts} +7 -7
|
@@ -10,17 +10,28 @@ import type {
|
|
|
10
10
|
SerializedContentItemWithType,
|
|
11
11
|
PaginatedContentItems,
|
|
12
12
|
InverseRelation,
|
|
13
|
+
CMSReadOptions,
|
|
14
|
+
CMSContentFields,
|
|
15
|
+
CMSReadView,
|
|
16
|
+
CMSContentItemResult,
|
|
17
|
+
CMSContentTypeMap,
|
|
13
18
|
} from "../../types";
|
|
14
19
|
import { cms } from "./cms-resource";
|
|
15
20
|
|
|
16
21
|
/** Flattens infinite-query pages of `{ items, total }` envelopes. */
|
|
17
|
-
function flattenPages<
|
|
18
|
-
|
|
22
|
+
function flattenPages<
|
|
23
|
+
TData,
|
|
24
|
+
TView extends CMSReadView = undefined,
|
|
25
|
+
TFields extends CMSContentFields = undefined,
|
|
26
|
+
>(
|
|
27
|
+
pages: PaginatedContentItems[] | undefined,
|
|
28
|
+
): {
|
|
29
|
+
items: CMSContentItemResult<TData, TView, TFields>[];
|
|
19
30
|
total: number;
|
|
20
31
|
} {
|
|
21
32
|
const items = (pages?.flatMap((page) =>
|
|
22
33
|
Array.isArray(page?.items) ? page.items : [],
|
|
23
|
-
) ?? []) as
|
|
34
|
+
) ?? []) as CMSContentItemResult<TData, TView, TFields>[];
|
|
24
35
|
const total = pages?.[0]?.total ?? 0;
|
|
25
36
|
return { items, total };
|
|
26
37
|
}
|
|
@@ -86,7 +97,10 @@ export function useContentType(slug: string): {
|
|
|
86
97
|
|
|
87
98
|
// ========== Content Items Hooks ==========
|
|
88
99
|
|
|
89
|
-
export interface UseContentOptions
|
|
100
|
+
export interface UseContentOptions<
|
|
101
|
+
TView extends CMSReadView = CMSReadView,
|
|
102
|
+
TFields extends CMSContentFields = CMSContentFields,
|
|
103
|
+
> extends CMSReadOptions<TView, TFields> {
|
|
90
104
|
/** Number of items per page (default: 10) */
|
|
91
105
|
limit?: number;
|
|
92
106
|
/** Whether to enable the query (default: true) */
|
|
@@ -99,9 +113,13 @@ export interface UseContentOptions {
|
|
|
99
113
|
* Result type for useContent hook with load more functionality
|
|
100
114
|
* @template TData - The type of parsedData (defaults to Record<string, unknown>)
|
|
101
115
|
*/
|
|
102
|
-
export interface UseContentResult<
|
|
116
|
+
export interface UseContentResult<
|
|
117
|
+
TData = Record<string, unknown>,
|
|
118
|
+
TView extends CMSReadView = undefined,
|
|
119
|
+
TFields extends CMSContentFields = undefined,
|
|
120
|
+
> {
|
|
103
121
|
/** Array of all loaded content items */
|
|
104
|
-
items:
|
|
122
|
+
items: CMSContentItemResult<TData, TView, TFields>[];
|
|
105
123
|
/** Total number of items available */
|
|
106
124
|
total: number;
|
|
107
125
|
/** Whether the initial load is in progress */
|
|
@@ -140,17 +158,49 @@ export interface UseContentResult<TData = Record<string, unknown>> {
|
|
|
140
158
|
* // items[0].parsedData.price is number
|
|
141
159
|
* ```
|
|
142
160
|
*/
|
|
161
|
+
export function useContent<
|
|
162
|
+
TMap extends CMSContentTypeMap = CMSContentTypeMap,
|
|
163
|
+
TSlug extends keyof TMap = keyof TMap,
|
|
164
|
+
const TFields extends readonly string[] = readonly string[],
|
|
165
|
+
>(
|
|
166
|
+
typeSlug: TSlug & string,
|
|
167
|
+
options: UseContentOptions<"content", TFields> & {
|
|
168
|
+
view: "content";
|
|
169
|
+
fields: TFields;
|
|
170
|
+
},
|
|
171
|
+
): UseContentResult<TMap[TSlug], "content", TFields>;
|
|
172
|
+
export function useContent<
|
|
173
|
+
TMap extends CMSContentTypeMap = CMSContentTypeMap,
|
|
174
|
+
TSlug extends keyof TMap = keyof TMap,
|
|
175
|
+
>(
|
|
176
|
+
typeSlug: TSlug & string,
|
|
177
|
+
options: UseContentOptions<"content"> & {
|
|
178
|
+
view: "content";
|
|
179
|
+
fields?: undefined;
|
|
180
|
+
},
|
|
181
|
+
): UseContentResult<TMap[TSlug], "content">;
|
|
182
|
+
export function useContent<
|
|
183
|
+
TMap extends CMSContentTypeMap = CMSContentTypeMap,
|
|
184
|
+
TSlug extends keyof TMap = keyof TMap,
|
|
185
|
+
TView extends CMSReadView = undefined,
|
|
186
|
+
TFields extends CMSContentFields = undefined,
|
|
187
|
+
>(
|
|
188
|
+
typeSlug: TSlug & string,
|
|
189
|
+
options?: UseContentOptions<TView, TFields>,
|
|
190
|
+
): UseContentResult<TMap[TSlug], TView, TFields>;
|
|
143
191
|
export function useContent<
|
|
144
192
|
TMap extends Record<string, Record<string, unknown>> = Record<
|
|
145
193
|
string,
|
|
146
194
|
Record<string, unknown>
|
|
147
195
|
>,
|
|
148
196
|
TSlug extends keyof TMap = keyof TMap,
|
|
197
|
+
TView extends CMSReadView = undefined,
|
|
198
|
+
TFields extends CMSContentFields = undefined,
|
|
149
199
|
>(
|
|
150
200
|
typeSlug: TSlug & string,
|
|
151
|
-
options: UseContentOptions = {},
|
|
152
|
-
): UseContentResult<TMap[TSlug]> {
|
|
153
|
-
const { limit = 10, enabled = true, search } = options;
|
|
201
|
+
options: UseContentOptions<TView, TFields> = {},
|
|
202
|
+
): UseContentResult<TMap[TSlug], TView, TFields> {
|
|
203
|
+
const { limit = 10, enabled = true, search, view, fields } = options;
|
|
154
204
|
|
|
155
205
|
const {
|
|
156
206
|
data,
|
|
@@ -160,11 +210,16 @@ export function useContent<
|
|
|
160
210
|
hasNextPage,
|
|
161
211
|
isFetchingNextPage,
|
|
162
212
|
refetch,
|
|
163
|
-
} = cms.cmsContent.list.useInfinite(
|
|
164
|
-
|
|
165
|
-
|
|
213
|
+
} = cms.cmsContent.list.useInfinite(
|
|
214
|
+
[{ typeSlug, limit, search, view, fields }],
|
|
215
|
+
{
|
|
216
|
+
enabled: enabled && !!typeSlug,
|
|
217
|
+
},
|
|
218
|
+
);
|
|
166
219
|
|
|
167
|
-
const { items, total } = flattenPages<TMap[TSlug]>(
|
|
220
|
+
const { items, total } = flattenPages<TMap[TSlug], TView, TFields>(
|
|
221
|
+
data?.pages,
|
|
222
|
+
);
|
|
168
223
|
|
|
169
224
|
return {
|
|
170
225
|
items,
|
|
@@ -184,29 +239,71 @@ export function useContent<
|
|
|
184
239
|
* @template TMap - A type map of content type slugs to their data types
|
|
185
240
|
* @template TSlug - The content type slug (inferred from typeSlug parameter)
|
|
186
241
|
*/
|
|
242
|
+
type SuspenseContentResult<
|
|
243
|
+
TData,
|
|
244
|
+
TView extends CMSReadView,
|
|
245
|
+
TFields extends CMSContentFields = undefined,
|
|
246
|
+
> = {
|
|
247
|
+
items: CMSContentItemResult<TData, TView, TFields>[];
|
|
248
|
+
total: number;
|
|
249
|
+
loadMore: () => Promise<unknown>;
|
|
250
|
+
hasMore: boolean;
|
|
251
|
+
isLoadingMore: boolean;
|
|
252
|
+
refetch: () => Promise<unknown>;
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
export function useSuspenseContent<
|
|
256
|
+
TMap extends CMSContentTypeMap = CMSContentTypeMap,
|
|
257
|
+
TSlug extends keyof TMap = keyof TMap,
|
|
258
|
+
const TFields extends readonly string[] = readonly string[],
|
|
259
|
+
>(
|
|
260
|
+
typeSlug: TSlug & string,
|
|
261
|
+
options: UseContentOptions<"content", TFields> & {
|
|
262
|
+
view: "content";
|
|
263
|
+
fields: TFields;
|
|
264
|
+
},
|
|
265
|
+
): SuspenseContentResult<TMap[TSlug], "content", TFields>;
|
|
266
|
+
export function useSuspenseContent<
|
|
267
|
+
TMap extends CMSContentTypeMap = CMSContentTypeMap,
|
|
268
|
+
TSlug extends keyof TMap = keyof TMap,
|
|
269
|
+
>(
|
|
270
|
+
typeSlug: TSlug & string,
|
|
271
|
+
options: UseContentOptions<"content"> & {
|
|
272
|
+
view: "content";
|
|
273
|
+
fields?: undefined;
|
|
274
|
+
},
|
|
275
|
+
): SuspenseContentResult<TMap[TSlug], "content">;
|
|
276
|
+
export function useSuspenseContent<
|
|
277
|
+
TMap extends CMSContentTypeMap = CMSContentTypeMap,
|
|
278
|
+
TSlug extends keyof TMap = keyof TMap,
|
|
279
|
+
TView extends CMSReadView = undefined,
|
|
280
|
+
TFields extends CMSContentFields = undefined,
|
|
281
|
+
>(
|
|
282
|
+
typeSlug: TSlug & string,
|
|
283
|
+
options?: UseContentOptions<TView, TFields>,
|
|
284
|
+
): SuspenseContentResult<TMap[TSlug], TView, TFields>;
|
|
187
285
|
export function useSuspenseContent<
|
|
188
286
|
TMap extends Record<string, Record<string, unknown>> = Record<
|
|
189
287
|
string,
|
|
190
288
|
Record<string, unknown>
|
|
191
289
|
>,
|
|
192
290
|
TSlug extends keyof TMap = keyof TMap,
|
|
291
|
+
TView extends CMSReadView = undefined,
|
|
292
|
+
TFields extends CMSContentFields = undefined,
|
|
193
293
|
>(
|
|
194
294
|
typeSlug: TSlug & string,
|
|
195
|
-
options: UseContentOptions = {},
|
|
196
|
-
): {
|
|
197
|
-
|
|
198
|
-
total: number;
|
|
199
|
-
loadMore: () => Promise<unknown>;
|
|
200
|
-
hasMore: boolean;
|
|
201
|
-
isLoadingMore: boolean;
|
|
202
|
-
refetch: () => Promise<unknown>;
|
|
203
|
-
} {
|
|
204
|
-
const { limit = 10, search } = options;
|
|
295
|
+
options: UseContentOptions<TView, TFields> = {},
|
|
296
|
+
): SuspenseContentResult<TMap[TSlug], TView, TFields> {
|
|
297
|
+
const { limit = 10, search, view, fields } = options;
|
|
205
298
|
|
|
206
299
|
const { data, fetchNextPage, hasNextPage, isFetchingNextPage, refetch } =
|
|
207
|
-
cms.cmsContent.list.useSuspenseInfinite([
|
|
300
|
+
cms.cmsContent.list.useSuspenseInfinite([
|
|
301
|
+
{ typeSlug, limit, search, view, fields },
|
|
302
|
+
]);
|
|
208
303
|
|
|
209
|
-
const { items, total } = flattenPages<TMap[TSlug]>(
|
|
304
|
+
const { items, total } = flattenPages<TMap[TSlug], TView, TFields>(
|
|
305
|
+
data.pages,
|
|
306
|
+
);
|
|
210
307
|
|
|
211
308
|
return {
|
|
212
309
|
items,
|
|
@@ -231,28 +328,69 @@ export function useSuspenseContent<
|
|
|
231
328
|
* // item?.parsedData.name is string
|
|
232
329
|
* ```
|
|
233
330
|
*/
|
|
331
|
+
type ContentItemQueryResult<
|
|
332
|
+
TData,
|
|
333
|
+
TView extends CMSReadView,
|
|
334
|
+
TFields extends CMSContentFields = undefined,
|
|
335
|
+
> = {
|
|
336
|
+
item: CMSContentItemResult<TData, TView, TFields> | null;
|
|
337
|
+
isLoading: boolean;
|
|
338
|
+
error: Error | null;
|
|
339
|
+
refetch: () => void;
|
|
340
|
+
};
|
|
341
|
+
|
|
342
|
+
export function useContentItem<
|
|
343
|
+
TMap extends CMSContentTypeMap = CMSContentTypeMap,
|
|
344
|
+
TSlug extends keyof TMap = keyof TMap,
|
|
345
|
+
const TFields extends readonly string[] = readonly string[],
|
|
346
|
+
>(
|
|
347
|
+
typeSlug: TSlug & string,
|
|
348
|
+
id: string,
|
|
349
|
+
options: CMSReadOptions<"content", TFields> & {
|
|
350
|
+
view: "content";
|
|
351
|
+
fields: TFields;
|
|
352
|
+
},
|
|
353
|
+
): ContentItemQueryResult<TMap[TSlug], "content", TFields>;
|
|
354
|
+
export function useContentItem<
|
|
355
|
+
TMap extends CMSContentTypeMap = CMSContentTypeMap,
|
|
356
|
+
TSlug extends keyof TMap = keyof TMap,
|
|
357
|
+
>(
|
|
358
|
+
typeSlug: TSlug & string,
|
|
359
|
+
id: string,
|
|
360
|
+
options: CMSReadOptions<"content"> & { view: "content"; fields?: undefined },
|
|
361
|
+
): ContentItemQueryResult<TMap[TSlug], "content">;
|
|
362
|
+
export function useContentItem<
|
|
363
|
+
TMap extends CMSContentTypeMap = CMSContentTypeMap,
|
|
364
|
+
TSlug extends keyof TMap = keyof TMap,
|
|
365
|
+
TView extends CMSReadView = undefined,
|
|
366
|
+
TFields extends CMSContentFields = undefined,
|
|
367
|
+
>(
|
|
368
|
+
typeSlug: TSlug & string,
|
|
369
|
+
id: string,
|
|
370
|
+
options?: CMSReadOptions<TView, TFields>,
|
|
371
|
+
): ContentItemQueryResult<TMap[TSlug], TView, TFields>;
|
|
234
372
|
export function useContentItem<
|
|
235
373
|
TMap extends Record<string, Record<string, unknown>> = Record<
|
|
236
374
|
string,
|
|
237
375
|
Record<string, unknown>
|
|
238
376
|
>,
|
|
239
377
|
TSlug extends keyof TMap = keyof TMap,
|
|
378
|
+
TView extends CMSReadView = undefined,
|
|
379
|
+
TFields extends CMSContentFields = undefined,
|
|
240
380
|
>(
|
|
241
381
|
typeSlug: TSlug & string,
|
|
242
382
|
id: string,
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
isLoading: boolean;
|
|
246
|
-
error: Error | null;
|
|
247
|
-
refetch: () => void;
|
|
248
|
-
} {
|
|
383
|
+
options?: CMSReadOptions<TView, TFields>,
|
|
384
|
+
): ContentItemQueryResult<TMap[TSlug], TView, TFields> {
|
|
249
385
|
const { data, isLoading, error, refetch } = cms.cmsContent.detail.use(
|
|
250
|
-
[typeSlug, id],
|
|
386
|
+
[typeSlug, id, options],
|
|
251
387
|
{ enabled: !!typeSlug && !!id },
|
|
252
388
|
);
|
|
253
389
|
|
|
254
390
|
return {
|
|
255
|
-
item:
|
|
391
|
+
item:
|
|
392
|
+
(data as CMSContentItemResult<TMap[TSlug], TView, TFields> | null) ??
|
|
393
|
+
null,
|
|
256
394
|
isLoading,
|
|
257
395
|
error,
|
|
258
396
|
refetch,
|
|
@@ -265,23 +403,68 @@ export function useContentItem<
|
|
|
265
403
|
* @template TMap - A type map of content type slugs to their data types
|
|
266
404
|
* @template TSlug - The content type slug (inferred from typeSlug parameter)
|
|
267
405
|
*/
|
|
406
|
+
type SuspenseContentItemResult<
|
|
407
|
+
TData,
|
|
408
|
+
TView extends CMSReadView,
|
|
409
|
+
TFields extends CMSContentFields = undefined,
|
|
410
|
+
> = {
|
|
411
|
+
item: CMSContentItemResult<TData, TView, TFields> | null;
|
|
412
|
+
refetch: () => Promise<unknown>;
|
|
413
|
+
};
|
|
414
|
+
|
|
415
|
+
export function useSuspenseContentItem<
|
|
416
|
+
TMap extends CMSContentTypeMap = CMSContentTypeMap,
|
|
417
|
+
TSlug extends keyof TMap = keyof TMap,
|
|
418
|
+
const TFields extends readonly string[] = readonly string[],
|
|
419
|
+
>(
|
|
420
|
+
typeSlug: TSlug & string,
|
|
421
|
+
id: string,
|
|
422
|
+
options: CMSReadOptions<"content", TFields> & {
|
|
423
|
+
view: "content";
|
|
424
|
+
fields: TFields;
|
|
425
|
+
},
|
|
426
|
+
): SuspenseContentItemResult<TMap[TSlug], "content", TFields>;
|
|
427
|
+
export function useSuspenseContentItem<
|
|
428
|
+
TMap extends CMSContentTypeMap = CMSContentTypeMap,
|
|
429
|
+
TSlug extends keyof TMap = keyof TMap,
|
|
430
|
+
>(
|
|
431
|
+
typeSlug: TSlug & string,
|
|
432
|
+
id: string,
|
|
433
|
+
options: CMSReadOptions<"content"> & { view: "content"; fields?: undefined },
|
|
434
|
+
): SuspenseContentItemResult<TMap[TSlug], "content">;
|
|
435
|
+
export function useSuspenseContentItem<
|
|
436
|
+
TMap extends CMSContentTypeMap = CMSContentTypeMap,
|
|
437
|
+
TSlug extends keyof TMap = keyof TMap,
|
|
438
|
+
TView extends CMSReadView = undefined,
|
|
439
|
+
TFields extends CMSContentFields = undefined,
|
|
440
|
+
>(
|
|
441
|
+
typeSlug: TSlug & string,
|
|
442
|
+
id: string,
|
|
443
|
+
options?: CMSReadOptions<TView, TFields>,
|
|
444
|
+
): SuspenseContentItemResult<TMap[TSlug], TView, TFields>;
|
|
268
445
|
export function useSuspenseContentItem<
|
|
269
446
|
TMap extends Record<string, Record<string, unknown>> = Record<
|
|
270
447
|
string,
|
|
271
448
|
Record<string, unknown>
|
|
272
449
|
>,
|
|
273
450
|
TSlug extends keyof TMap = keyof TMap,
|
|
451
|
+
TView extends CMSReadView = undefined,
|
|
452
|
+
TFields extends CMSContentFields = undefined,
|
|
274
453
|
>(
|
|
275
454
|
typeSlug: TSlug & string,
|
|
276
455
|
id: string,
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
refetch
|
|
280
|
-
|
|
281
|
-
|
|
456
|
+
options?: CMSReadOptions<TView, TFields>,
|
|
457
|
+
): SuspenseContentItemResult<TMap[TSlug], TView, TFields> {
|
|
458
|
+
const { data, refetch } = cms.cmsContent.detail.useSuspense([
|
|
459
|
+
typeSlug,
|
|
460
|
+
id,
|
|
461
|
+
options,
|
|
462
|
+
]);
|
|
282
463
|
|
|
283
464
|
return {
|
|
284
|
-
item:
|
|
465
|
+
item:
|
|
466
|
+
(data as CMSContentItemResult<TMap[TSlug], TView, TFields> | null) ??
|
|
467
|
+
null,
|
|
285
468
|
refetch,
|
|
286
469
|
};
|
|
287
470
|
}
|
|
@@ -299,28 +482,58 @@ export function useSuspenseContentItem<
|
|
|
299
482
|
* // item?.parsedData.price is number
|
|
300
483
|
* ```
|
|
301
484
|
*/
|
|
485
|
+
export function useContentItemBySlug<
|
|
486
|
+
TMap extends CMSContentTypeMap = CMSContentTypeMap,
|
|
487
|
+
TSlug extends keyof TMap = keyof TMap,
|
|
488
|
+
const TFields extends readonly string[] = readonly string[],
|
|
489
|
+
>(
|
|
490
|
+
typeSlug: TSlug & string,
|
|
491
|
+
slug: string,
|
|
492
|
+
options: CMSReadOptions<"content", TFields> & {
|
|
493
|
+
view: "content";
|
|
494
|
+
fields: TFields;
|
|
495
|
+
},
|
|
496
|
+
): ContentItemQueryResult<TMap[TSlug], "content", TFields>;
|
|
497
|
+
export function useContentItemBySlug<
|
|
498
|
+
TMap extends CMSContentTypeMap = CMSContentTypeMap,
|
|
499
|
+
TSlug extends keyof TMap = keyof TMap,
|
|
500
|
+
>(
|
|
501
|
+
typeSlug: TSlug & string,
|
|
502
|
+
slug: string,
|
|
503
|
+
options: CMSReadOptions<"content"> & { view: "content"; fields?: undefined },
|
|
504
|
+
): ContentItemQueryResult<TMap[TSlug], "content">;
|
|
505
|
+
export function useContentItemBySlug<
|
|
506
|
+
TMap extends CMSContentTypeMap = CMSContentTypeMap,
|
|
507
|
+
TSlug extends keyof TMap = keyof TMap,
|
|
508
|
+
TView extends CMSReadView = undefined,
|
|
509
|
+
TFields extends CMSContentFields = undefined,
|
|
510
|
+
>(
|
|
511
|
+
typeSlug: TSlug & string,
|
|
512
|
+
slug: string,
|
|
513
|
+
options?: CMSReadOptions<TView, TFields>,
|
|
514
|
+
): ContentItemQueryResult<TMap[TSlug], TView, TFields>;
|
|
302
515
|
export function useContentItemBySlug<
|
|
303
516
|
TMap extends Record<string, Record<string, unknown>> = Record<
|
|
304
517
|
string,
|
|
305
518
|
Record<string, unknown>
|
|
306
519
|
>,
|
|
307
520
|
TSlug extends keyof TMap = keyof TMap,
|
|
521
|
+
TView extends CMSReadView = undefined,
|
|
522
|
+
TFields extends CMSContentFields = undefined,
|
|
308
523
|
>(
|
|
309
524
|
typeSlug: TSlug & string,
|
|
310
525
|
slug: string,
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
isLoading: boolean;
|
|
314
|
-
error: Error | null;
|
|
315
|
-
refetch: () => void;
|
|
316
|
-
} {
|
|
526
|
+
options?: CMSReadOptions<TView, TFields>,
|
|
527
|
+
): ContentItemQueryResult<TMap[TSlug], TView, TFields> {
|
|
317
528
|
const { data, isLoading, error, refetch } = cms.cmsContent.bySlug.use(
|
|
318
|
-
[typeSlug, slug],
|
|
529
|
+
[typeSlug, slug, options],
|
|
319
530
|
{ enabled: !!typeSlug && !!slug },
|
|
320
531
|
);
|
|
321
532
|
|
|
322
533
|
return {
|
|
323
|
-
item:
|
|
534
|
+
item:
|
|
535
|
+
(data as CMSContentItemResult<TMap[TSlug], TView, TFields> | null) ??
|
|
536
|
+
null,
|
|
324
537
|
isLoading,
|
|
325
538
|
error,
|
|
326
539
|
refetch,
|
|
@@ -455,24 +668,35 @@ export function useContentItemForm<TValues>(
|
|
|
455
668
|
* query, with selected ids missing from the current results preloaded via
|
|
456
669
|
* the `detail` query (typeSlug, id) so their labels resolve.
|
|
457
670
|
*
|
|
458
|
-
* Used by the relation picker (`RelationField`).
|
|
671
|
+
* Used by the relation picker (`RelationField`). Optional content view/fields
|
|
672
|
+
* apply to both search results and selected-ID preloads; full records remain the default.
|
|
459
673
|
*/
|
|
460
|
-
export function useContentOptions
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
674
|
+
export function useContentOptions<
|
|
675
|
+
TView extends CMSReadView = undefined,
|
|
676
|
+
const TFields extends CMSContentFields = undefined,
|
|
677
|
+
>(
|
|
678
|
+
config: {
|
|
679
|
+
/** Content type slug to search within. */
|
|
680
|
+
targetType: string;
|
|
681
|
+
/** Currently selected IDs, preloaded when absent from search results. */
|
|
682
|
+
value: string[];
|
|
683
|
+
getOptionLabel: (
|
|
684
|
+
item: CMSContentItemResult<Record<string, unknown>, TView, TFields>,
|
|
685
|
+
) => string;
|
|
686
|
+
} & CMSReadOptions<TView, TFields>,
|
|
687
|
+
): ResourceSelectResult<
|
|
688
|
+
CMSContentItemResult<Record<string, unknown>, TView, TFields>
|
|
689
|
+
> {
|
|
690
|
+
const { targetType, value, getOptionLabel, view, fields } = config;
|
|
691
|
+
return cms.cmsContent.useSelect<
|
|
692
|
+
CMSContentItemResult<Record<string, unknown>, TView, TFields>
|
|
693
|
+
>({
|
|
470
694
|
query: "options",
|
|
471
|
-
searchArgs: (search) => [{ typeSlug: targetType, search }],
|
|
695
|
+
searchArgs: (search) => [{ typeSlug: targetType, search, view, fields }],
|
|
472
696
|
getOptionValue: (item) => item.id,
|
|
473
697
|
getOptionLabel,
|
|
474
698
|
value,
|
|
475
|
-
preload: { args: (id) => [targetType, id] },
|
|
699
|
+
preload: { args: (id) => [targetType, id, { view, fields }] },
|
|
476
700
|
enabled: !!targetType,
|
|
477
701
|
});
|
|
478
702
|
}
|
|
@@ -560,7 +784,10 @@ export function useSuspenseContentItemPopulated<
|
|
|
560
784
|
/**
|
|
561
785
|
* Options for useContentByRelation hook
|
|
562
786
|
*/
|
|
563
|
-
export interface UseContentByRelationOptions
|
|
787
|
+
export interface UseContentByRelationOptions<
|
|
788
|
+
TView extends CMSReadView = CMSReadView,
|
|
789
|
+
TFields extends CMSContentFields = CMSContentFields,
|
|
790
|
+
> extends CMSReadOptions<TView, TFields> {
|
|
564
791
|
/** Number of items per page (default: 20) */
|
|
565
792
|
limit?: number;
|
|
566
793
|
/** Whether to enable the query (default: true) */
|
|
@@ -580,28 +807,57 @@ export interface UseContentByRelationOptions {
|
|
|
580
807
|
* const { items } = useContentByRelation("resource", "categoryIds", categoryId)
|
|
581
808
|
* ```
|
|
582
809
|
*/
|
|
810
|
+
export function useContentByRelation<
|
|
811
|
+
TMap extends CMSContentTypeMap = CMSContentTypeMap,
|
|
812
|
+
TSlug extends keyof TMap = keyof TMap,
|
|
813
|
+
const TFields extends readonly string[] = readonly string[],
|
|
814
|
+
>(
|
|
815
|
+
typeSlug: TSlug & string,
|
|
816
|
+
fieldName: string,
|
|
817
|
+
targetId: string,
|
|
818
|
+
options: UseContentByRelationOptions<"content", TFields> & {
|
|
819
|
+
view: "content";
|
|
820
|
+
fields: TFields;
|
|
821
|
+
},
|
|
822
|
+
): UseContentResult<TMap[TSlug], "content", TFields>;
|
|
823
|
+
export function useContentByRelation<
|
|
824
|
+
TMap extends CMSContentTypeMap = CMSContentTypeMap,
|
|
825
|
+
TSlug extends keyof TMap = keyof TMap,
|
|
826
|
+
>(
|
|
827
|
+
typeSlug: TSlug & string,
|
|
828
|
+
fieldName: string,
|
|
829
|
+
targetId: string,
|
|
830
|
+
options: UseContentByRelationOptions<"content"> & {
|
|
831
|
+
view: "content";
|
|
832
|
+
fields?: undefined;
|
|
833
|
+
},
|
|
834
|
+
): UseContentResult<TMap[TSlug], "content">;
|
|
835
|
+
export function useContentByRelation<
|
|
836
|
+
TMap extends CMSContentTypeMap = CMSContentTypeMap,
|
|
837
|
+
TSlug extends keyof TMap = keyof TMap,
|
|
838
|
+
TView extends CMSReadView = undefined,
|
|
839
|
+
TFields extends CMSContentFields = undefined,
|
|
840
|
+
>(
|
|
841
|
+
typeSlug: TSlug & string,
|
|
842
|
+
fieldName: string,
|
|
843
|
+
targetId: string,
|
|
844
|
+
options?: UseContentByRelationOptions<TView, TFields>,
|
|
845
|
+
): UseContentResult<TMap[TSlug], TView, TFields>;
|
|
583
846
|
export function useContentByRelation<
|
|
584
847
|
TMap extends Record<string, Record<string, unknown>> = Record<
|
|
585
848
|
string,
|
|
586
849
|
Record<string, unknown>
|
|
587
850
|
>,
|
|
588
851
|
TSlug extends keyof TMap = keyof TMap,
|
|
852
|
+
TView extends CMSReadView = undefined,
|
|
853
|
+
TFields extends CMSContentFields = undefined,
|
|
589
854
|
>(
|
|
590
855
|
typeSlug: TSlug & string,
|
|
591
856
|
fieldName: string,
|
|
592
857
|
targetId: string,
|
|
593
|
-
options: UseContentByRelationOptions = {},
|
|
594
|
-
): {
|
|
595
|
-
|
|
596
|
-
total: number;
|
|
597
|
-
isLoading: boolean;
|
|
598
|
-
error: Error | null;
|
|
599
|
-
loadMore: () => void;
|
|
600
|
-
hasMore: boolean;
|
|
601
|
-
isLoadingMore: boolean;
|
|
602
|
-
refetch: () => void;
|
|
603
|
-
} {
|
|
604
|
-
const { limit = 20, enabled = true } = options;
|
|
858
|
+
options: UseContentByRelationOptions<TView, TFields> = {},
|
|
859
|
+
): UseContentResult<TMap[TSlug], TView, TFields> {
|
|
860
|
+
const { limit = 20, enabled = true, view, fields } = options;
|
|
605
861
|
|
|
606
862
|
const {
|
|
607
863
|
data,
|
|
@@ -612,11 +868,13 @@ export function useContentByRelation<
|
|
|
612
868
|
isFetchingNextPage,
|
|
613
869
|
refetch,
|
|
614
870
|
} = cms.cmsContent.byRelation.useInfinite(
|
|
615
|
-
[{ typeSlug, field: fieldName, targetId, limit }],
|
|
871
|
+
[{ typeSlug, field: fieldName, targetId, limit, view, fields }],
|
|
616
872
|
{ enabled: enabled && !!typeSlug && !!fieldName && !!targetId },
|
|
617
873
|
);
|
|
618
874
|
|
|
619
|
-
const { items, total } = flattenPages<TMap[TSlug]>(
|
|
875
|
+
const { items, total } = flattenPages<TMap[TSlug], TView, TFields>(
|
|
876
|
+
data?.pages,
|
|
877
|
+
);
|
|
620
878
|
|
|
621
879
|
return {
|
|
622
880
|
items,
|
|
@@ -633,33 +891,66 @@ export function useContentByRelation<
|
|
|
633
891
|
/**
|
|
634
892
|
* Suspense variant of useContentByRelation
|
|
635
893
|
*/
|
|
894
|
+
export function useSuspenseContentByRelation<
|
|
895
|
+
TMap extends CMSContentTypeMap = CMSContentTypeMap,
|
|
896
|
+
TSlug extends keyof TMap = keyof TMap,
|
|
897
|
+
const TFields extends readonly string[] = readonly string[],
|
|
898
|
+
>(
|
|
899
|
+
typeSlug: TSlug & string,
|
|
900
|
+
fieldName: string,
|
|
901
|
+
targetId: string,
|
|
902
|
+
options: UseContentByRelationOptions<"content", TFields> & {
|
|
903
|
+
view: "content";
|
|
904
|
+
fields: TFields;
|
|
905
|
+
},
|
|
906
|
+
): SuspenseContentResult<TMap[TSlug], "content", TFields>;
|
|
907
|
+
export function useSuspenseContentByRelation<
|
|
908
|
+
TMap extends CMSContentTypeMap = CMSContentTypeMap,
|
|
909
|
+
TSlug extends keyof TMap = keyof TMap,
|
|
910
|
+
>(
|
|
911
|
+
typeSlug: TSlug & string,
|
|
912
|
+
fieldName: string,
|
|
913
|
+
targetId: string,
|
|
914
|
+
options: UseContentByRelationOptions<"content"> & {
|
|
915
|
+
view: "content";
|
|
916
|
+
fields?: undefined;
|
|
917
|
+
},
|
|
918
|
+
): SuspenseContentResult<TMap[TSlug], "content">;
|
|
919
|
+
export function useSuspenseContentByRelation<
|
|
920
|
+
TMap extends CMSContentTypeMap = CMSContentTypeMap,
|
|
921
|
+
TSlug extends keyof TMap = keyof TMap,
|
|
922
|
+
TView extends CMSReadView = undefined,
|
|
923
|
+
TFields extends CMSContentFields = undefined,
|
|
924
|
+
>(
|
|
925
|
+
typeSlug: TSlug & string,
|
|
926
|
+
fieldName: string,
|
|
927
|
+
targetId: string,
|
|
928
|
+
options?: UseContentByRelationOptions<TView, TFields>,
|
|
929
|
+
): SuspenseContentResult<TMap[TSlug], TView, TFields>;
|
|
636
930
|
export function useSuspenseContentByRelation<
|
|
637
931
|
TMap extends Record<string, Record<string, unknown>> = Record<
|
|
638
932
|
string,
|
|
639
933
|
Record<string, unknown>
|
|
640
934
|
>,
|
|
641
935
|
TSlug extends keyof TMap = keyof TMap,
|
|
936
|
+
TView extends CMSReadView = undefined,
|
|
937
|
+
TFields extends CMSContentFields = undefined,
|
|
642
938
|
>(
|
|
643
939
|
typeSlug: TSlug & string,
|
|
644
940
|
fieldName: string,
|
|
645
941
|
targetId: string,
|
|
646
|
-
options: UseContentByRelationOptions = {},
|
|
647
|
-
): {
|
|
648
|
-
|
|
649
|
-
total: number;
|
|
650
|
-
loadMore: () => Promise<unknown>;
|
|
651
|
-
hasMore: boolean;
|
|
652
|
-
isLoadingMore: boolean;
|
|
653
|
-
refetch: () => Promise<unknown>;
|
|
654
|
-
} {
|
|
655
|
-
const { limit = 20 } = options;
|
|
942
|
+
options: UseContentByRelationOptions<TView, TFields> = {},
|
|
943
|
+
): SuspenseContentResult<TMap[TSlug], TView, TFields> {
|
|
944
|
+
const { limit = 20, view, fields } = options;
|
|
656
945
|
|
|
657
946
|
const { data, fetchNextPage, hasNextPage, isFetchingNextPage, refetch } =
|
|
658
947
|
cms.cmsContent.byRelation.useSuspenseInfinite([
|
|
659
|
-
{ typeSlug, field: fieldName, targetId, limit },
|
|
948
|
+
{ typeSlug, field: fieldName, targetId, limit, view, fields },
|
|
660
949
|
]);
|
|
661
950
|
|
|
662
|
-
const { items, total } = flattenPages<TMap[TSlug]>(
|
|
951
|
+
const { items, total } = flattenPages<TMap[TSlug], TView, TFields>(
|
|
952
|
+
data.pages,
|
|
953
|
+
);
|
|
663
954
|
|
|
664
955
|
return {
|
|
665
956
|
items,
|
|
@@ -703,16 +994,26 @@ export function useInverseRelations(
|
|
|
703
994
|
* Hook for listing the items behind one inverse relation (e.g. all comments
|
|
704
995
|
* whose `resourceId` points at this resource).
|
|
705
996
|
*/
|
|
706
|
-
export function useInverseRelationItems
|
|
997
|
+
export function useInverseRelationItems<
|
|
998
|
+
TView extends CMSReadView = undefined,
|
|
999
|
+
const TFields extends CMSContentFields = undefined,
|
|
1000
|
+
>(
|
|
707
1001
|
params: {
|
|
708
1002
|
contentTypeSlug: string;
|
|
709
1003
|
sourceType: string;
|
|
710
1004
|
itemId: string;
|
|
711
1005
|
fieldName: string;
|
|
712
1006
|
},
|
|
713
|
-
options:
|
|
1007
|
+
options: CMSReadOptions<TView, TFields> & {
|
|
1008
|
+
/** Whether to enable the query (default: true). */
|
|
1009
|
+
enabled?: boolean;
|
|
1010
|
+
/** Number of items per page (default: 20). */
|
|
1011
|
+
limit?: number;
|
|
1012
|
+
/** Number of matching items to skip (default: 0). */
|
|
1013
|
+
offset?: number;
|
|
1014
|
+
} = {},
|
|
714
1015
|
): {
|
|
715
|
-
items:
|
|
1016
|
+
items: CMSContentItemResult<Record<string, unknown>, TView, TFields>[];
|
|
716
1017
|
total: number;
|
|
717
1018
|
isLoading: boolean;
|
|
718
1019
|
error: Error | null;
|
|
@@ -726,13 +1027,21 @@ export function useInverseRelationItems(
|
|
|
726
1027
|
sourceType: params.sourceType,
|
|
727
1028
|
itemId: params.itemId,
|
|
728
1029
|
fieldName: params.fieldName,
|
|
1030
|
+
view: options.view,
|
|
1031
|
+
fields: options.fields,
|
|
1032
|
+
limit: options.limit,
|
|
1033
|
+
offset: options.offset,
|
|
729
1034
|
},
|
|
730
1035
|
],
|
|
731
1036
|
{ enabled: options.enabled ?? true },
|
|
732
1037
|
);
|
|
733
1038
|
|
|
734
1039
|
return {
|
|
735
|
-
items: data?.items ?? []
|
|
1040
|
+
items: (data?.items ?? []) as CMSContentItemResult<
|
|
1041
|
+
Record<string, unknown>,
|
|
1042
|
+
TView,
|
|
1043
|
+
TFields
|
|
1044
|
+
>[],
|
|
736
1045
|
total: data?.total ?? 0,
|
|
737
1046
|
isLoading,
|
|
738
1047
|
error,
|