@btst/stack 1.8.0 → 1.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/packages/better-stack/src/plugins/cms/api/plugin.cjs +445 -16
- package/dist/packages/better-stack/src/plugins/cms/api/plugin.mjs +445 -16
- package/dist/packages/better-stack/src/plugins/cms/client/components/forms/content-form.cjs +28 -11
- package/dist/packages/better-stack/src/plugins/cms/client/components/forms/content-form.mjs +26 -9
- package/dist/packages/better-stack/src/plugins/cms/client/components/forms/relation-field.cjs +224 -0
- package/dist/packages/better-stack/src/plugins/cms/client/components/forms/relation-field.mjs +222 -0
- package/dist/packages/better-stack/src/plugins/cms/client/components/inverse-relations-panel.cjs +243 -0
- package/dist/packages/better-stack/src/plugins/cms/client/components/inverse-relations-panel.mjs +241 -0
- package/dist/packages/better-stack/src/plugins/cms/client/components/pages/content-editor-page.internal.cjs +56 -2
- package/dist/packages/better-stack/src/plugins/cms/client/components/pages/content-editor-page.internal.mjs +56 -2
- package/dist/packages/better-stack/src/plugins/cms/client/hooks/cms-hooks.cjs +190 -0
- package/dist/packages/better-stack/src/plugins/cms/client/hooks/cms-hooks.mjs +187 -1
- package/dist/packages/better-stack/src/plugins/cms/db.cjs +38 -0
- package/dist/packages/better-stack/src/plugins/cms/db.mjs +38 -0
- package/dist/packages/better-stack/src/plugins/form-builder/client/components/forms/form-renderer.cjs +2 -2
- package/dist/packages/better-stack/src/plugins/form-builder/client/components/forms/form-renderer.mjs +1 -1
- package/dist/packages/ui/src/components/auto-form/fields/array.cjs +2 -2
- package/dist/packages/ui/src/components/auto-form/fields/array.mjs +1 -1
- package/dist/packages/ui/src/components/auto-form/fields/date.cjs +2 -2
- package/dist/packages/ui/src/components/auto-form/fields/date.mjs +1 -1
- package/dist/packages/ui/src/components/auto-form/fields/enum.cjs +2 -2
- package/dist/packages/ui/src/components/auto-form/fields/enum.mjs +1 -1
- package/dist/packages/ui/src/components/auto-form/fields/object.cjs +88 -8
- package/dist/packages/ui/src/components/auto-form/fields/object.mjs +82 -2
- package/dist/packages/ui/src/components/auto-form/fields/radio-group.cjs +2 -2
- package/dist/packages/ui/src/components/auto-form/fields/radio-group.mjs +1 -1
- package/dist/packages/ui/src/components/auto-form/index.cjs +5 -5
- package/dist/packages/ui/src/components/auto-form/index.mjs +1 -1
- package/dist/packages/ui/src/components/button.cjs +4 -2
- package/dist/packages/ui/src/components/button.mjs +4 -2
- package/dist/packages/ui/src/components/dialog.cjs +7 -1
- package/dist/packages/ui/src/components/dialog.mjs +7 -2
- package/dist/packages/ui/src/components/form-builder/edit-field-dialog.cjs +2 -2
- package/dist/packages/ui/src/components/form-builder/edit-field-dialog.mjs +1 -1
- package/dist/packages/ui/src/components/form-builder/form-preview.cjs +5 -5
- package/dist/packages/ui/src/components/form-builder/form-preview.mjs +1 -1
- package/dist/packages/ui/src/components/select.cjs +9 -2
- package/dist/packages/ui/src/components/select.mjs +9 -2
- package/dist/plugins/blog/api/index.d.cts +1 -1
- package/dist/plugins/blog/api/index.d.mts +1 -1
- package/dist/plugins/blog/api/index.d.ts +1 -1
- 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 +1 -1
- package/dist/plugins/blog/client/index.d.mts +1 -1
- package/dist/plugins/blog/client/index.d.ts +1 -1
- 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/cms/api/index.d.cts +66 -2
- package/dist/plugins/cms/api/index.d.mts +66 -2
- package/dist/plugins/cms/api/index.d.ts +66 -2
- package/dist/plugins/cms/client/hooks/index.cjs +4 -0
- package/dist/plugins/cms/client/hooks/index.d.cts +82 -3
- package/dist/plugins/cms/client/hooks/index.d.mts +82 -3
- package/dist/plugins/cms/client/hooks/index.d.ts +82 -3
- package/dist/plugins/cms/client/hooks/index.mjs +1 -1
- package/dist/plugins/cms/client/index.d.cts +2 -2
- package/dist/plugins/cms/client/index.d.mts +2 -2
- package/dist/plugins/cms/client/index.d.ts +2 -2
- package/dist/plugins/cms/query-keys.d.cts +1 -1
- package/dist/plugins/cms/query-keys.d.mts +1 -1
- package/dist/plugins/cms/query-keys.d.ts +1 -1
- package/dist/plugins/form-builder/client/components/index.d.cts +1 -1
- package/dist/plugins/form-builder/client/components/index.d.mts +1 -1
- package/dist/plugins/form-builder/client/components/index.d.ts +1 -1
- package/dist/plugins/form-builder/client/index.d.cts +2 -2
- package/dist/plugins/form-builder/client/index.d.mts +2 -2
- package/dist/plugins/form-builder/client/index.d.ts +2 -2
- package/dist/shared/{stack.AX5nZ6A3.d.ts → stack.Co034Fpm.d.cts} +0 -21
- package/dist/shared/{stack.AX5nZ6A3.d.cts → stack.Co034Fpm.d.mts} +0 -21
- package/dist/shared/{stack.AX5nZ6A3.d.mts → stack.Co034Fpm.d.ts} +0 -21
- package/dist/shared/{stack.BIh2AXaW.d.cts → stack.DGjhPqmF.d.cts} +0 -9
- package/dist/shared/{stack.BIh2AXaW.d.mts → stack.DGjhPqmF.d.mts} +0 -9
- package/dist/shared/{stack.BIh2AXaW.d.ts → stack.DGjhPqmF.d.ts} +0 -9
- package/dist/shared/{stack.L-UFwz2G.d.mts → stack.oGOteE6g.d.cts} +27 -5
- package/dist/shared/{stack.L-UFwz2G.d.cts → stack.oGOteE6g.d.mts} +27 -5
- package/dist/shared/{stack.L-UFwz2G.d.ts → stack.oGOteE6g.d.ts} +27 -5
- package/package.json +1 -1
- package/src/plugins/cms/api/plugin.ts +667 -21
- package/src/plugins/cms/client/components/forms/content-form.tsx +62 -20
- package/src/plugins/cms/client/components/forms/relation-field.tsx +299 -0
- package/src/plugins/cms/client/components/inverse-relations-panel.tsx +329 -0
- package/src/plugins/cms/client/components/pages/content-editor-page.internal.tsx +127 -1
- package/src/plugins/cms/client/hooks/cms-hooks.tsx +344 -0
- package/src/plugins/cms/db.ts +38 -0
- package/src/plugins/cms/types.ts +99 -10
- package/src/plugins/form-builder/client/components/forms/form-renderer.tsx +1 -1
- package/dist/packages/ui/src/components/auto-form/{utils.cjs → helpers.cjs} +0 -0
- package/dist/packages/ui/src/components/auto-form/{utils.mjs → helpers.mjs} +0 -0
- package/dist/shared/{stack.DLhzx1-D.d.mts → stack.CcI4sYJP.d.cts} +1 -1
- package/dist/shared/{stack.DLhzx1-D.d.cts → stack.CcI4sYJP.d.mts} +1 -1
- package/dist/shared/{stack.DLhzx1-D.d.ts → stack.CcI4sYJP.d.ts} +1 -1
|
@@ -388,15 +388,205 @@ function useDeleteContent(typeSlug) {
|
|
|
388
388
|
}
|
|
389
389
|
});
|
|
390
390
|
}
|
|
391
|
+
function useContentItemPopulated(typeSlug, id) {
|
|
392
|
+
const { apiBaseURL, apiBasePath, headers } = context.usePluginOverrides("cms");
|
|
393
|
+
const client$1 = client.createApiClient({
|
|
394
|
+
baseURL: apiBaseURL,
|
|
395
|
+
basePath: apiBasePath
|
|
396
|
+
});
|
|
397
|
+
const { data, isLoading, error, refetch } = reactQuery.useQuery({
|
|
398
|
+
queryKey: ["cmsContent", typeSlug, id, "populated"],
|
|
399
|
+
queryFn: async () => {
|
|
400
|
+
const response = await client$1(
|
|
401
|
+
"/content/:typeSlug/:id/populated",
|
|
402
|
+
{
|
|
403
|
+
method: "GET",
|
|
404
|
+
params: { typeSlug, id },
|
|
405
|
+
headers
|
|
406
|
+
}
|
|
407
|
+
);
|
|
408
|
+
if (isErrorResponse(response)) {
|
|
409
|
+
throw toError(response.error);
|
|
410
|
+
}
|
|
411
|
+
return response.data;
|
|
412
|
+
},
|
|
413
|
+
...SHARED_QUERY_CONFIG,
|
|
414
|
+
enabled: !!typeSlug && !!id
|
|
415
|
+
});
|
|
416
|
+
return {
|
|
417
|
+
item: data ?? null,
|
|
418
|
+
isLoading,
|
|
419
|
+
error,
|
|
420
|
+
refetch
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
function useSuspenseContentItemPopulated(typeSlug, id) {
|
|
424
|
+
const { apiBaseURL, apiBasePath, headers } = context.usePluginOverrides("cms");
|
|
425
|
+
const client$1 = client.createApiClient({
|
|
426
|
+
baseURL: apiBaseURL,
|
|
427
|
+
basePath: apiBasePath
|
|
428
|
+
});
|
|
429
|
+
const { data, refetch, error, isFetching } = reactQuery.useSuspenseQuery({
|
|
430
|
+
queryKey: ["cmsContent", typeSlug, id, "populated"],
|
|
431
|
+
queryFn: async () => {
|
|
432
|
+
const response = await client$1(
|
|
433
|
+
"/content/:typeSlug/:id/populated",
|
|
434
|
+
{
|
|
435
|
+
method: "GET",
|
|
436
|
+
params: { typeSlug, id },
|
|
437
|
+
headers
|
|
438
|
+
}
|
|
439
|
+
);
|
|
440
|
+
if (isErrorResponse(response)) {
|
|
441
|
+
throw toError(response.error);
|
|
442
|
+
}
|
|
443
|
+
return response.data;
|
|
444
|
+
},
|
|
445
|
+
...SHARED_QUERY_CONFIG
|
|
446
|
+
});
|
|
447
|
+
if (error && !isFetching) {
|
|
448
|
+
throw error;
|
|
449
|
+
}
|
|
450
|
+
return {
|
|
451
|
+
item: data ?? null,
|
|
452
|
+
refetch
|
|
453
|
+
};
|
|
454
|
+
}
|
|
455
|
+
function useContentByRelation(typeSlug, fieldName, targetId, options = {}) {
|
|
456
|
+
const { apiBaseURL, apiBasePath, headers } = context.usePluginOverrides("cms");
|
|
457
|
+
const client$1 = client.createApiClient({
|
|
458
|
+
baseURL: apiBaseURL,
|
|
459
|
+
basePath: apiBasePath
|
|
460
|
+
});
|
|
461
|
+
const { limit = 20, enabled = true } = options;
|
|
462
|
+
const {
|
|
463
|
+
data,
|
|
464
|
+
isLoading,
|
|
465
|
+
error,
|
|
466
|
+
fetchNextPage,
|
|
467
|
+
hasNextPage,
|
|
468
|
+
isFetchingNextPage,
|
|
469
|
+
refetch
|
|
470
|
+
} = reactQuery.useInfiniteQuery({
|
|
471
|
+
queryKey: ["cmsContent", typeSlug, "by-relation", fieldName, targetId],
|
|
472
|
+
queryFn: async ({ pageParam = 0 }) => {
|
|
473
|
+
const response = await client$1("/content/:typeSlug/by-relation", {
|
|
474
|
+
method: "GET",
|
|
475
|
+
params: { typeSlug },
|
|
476
|
+
query: { field: fieldName, targetId, limit, offset: pageParam },
|
|
477
|
+
headers
|
|
478
|
+
});
|
|
479
|
+
if (isErrorResponse(response)) {
|
|
480
|
+
throw toError(response.error);
|
|
481
|
+
}
|
|
482
|
+
return response.data;
|
|
483
|
+
},
|
|
484
|
+
...SHARED_QUERY_CONFIG,
|
|
485
|
+
initialPageParam: 0,
|
|
486
|
+
getNextPageParam: (lastPage, allPages) => {
|
|
487
|
+
if (!lastPage || typeof lastPage !== "object") return void 0;
|
|
488
|
+
const items2 = lastPage?.items;
|
|
489
|
+
if (!Array.isArray(items2) || items2.length < limit) return void 0;
|
|
490
|
+
const loadedCount = (allPages || []).reduce(
|
|
491
|
+
(sum, page) => sum + (Array.isArray(page?.items) ? page.items.length : 0),
|
|
492
|
+
0
|
|
493
|
+
);
|
|
494
|
+
const total2 = lastPage?.total ?? 0;
|
|
495
|
+
if (loadedCount >= total2) return void 0;
|
|
496
|
+
return loadedCount;
|
|
497
|
+
},
|
|
498
|
+
enabled: enabled && !!typeSlug && !!fieldName && !!targetId
|
|
499
|
+
});
|
|
500
|
+
const pages = data?.pages;
|
|
501
|
+
const items = pages?.flatMap(
|
|
502
|
+
(page) => Array.isArray(page?.items) ? page.items : []
|
|
503
|
+
) ?? [];
|
|
504
|
+
const total = pages?.[0]?.total ?? 0;
|
|
505
|
+
return {
|
|
506
|
+
items,
|
|
507
|
+
total,
|
|
508
|
+
isLoading,
|
|
509
|
+
error,
|
|
510
|
+
loadMore: fetchNextPage,
|
|
511
|
+
hasMore: !!hasNextPage,
|
|
512
|
+
isLoadingMore: isFetchingNextPage,
|
|
513
|
+
refetch
|
|
514
|
+
};
|
|
515
|
+
}
|
|
516
|
+
function useSuspenseContentByRelation(typeSlug, fieldName, targetId, options = {}) {
|
|
517
|
+
const { apiBaseURL, apiBasePath, headers } = context.usePluginOverrides("cms");
|
|
518
|
+
const client$1 = client.createApiClient({
|
|
519
|
+
baseURL: apiBaseURL,
|
|
520
|
+
basePath: apiBasePath
|
|
521
|
+
});
|
|
522
|
+
const { limit = 20 } = options;
|
|
523
|
+
const {
|
|
524
|
+
data,
|
|
525
|
+
fetchNextPage,
|
|
526
|
+
hasNextPage,
|
|
527
|
+
isFetchingNextPage,
|
|
528
|
+
refetch,
|
|
529
|
+
error,
|
|
530
|
+
isFetching
|
|
531
|
+
} = reactQuery.useSuspenseInfiniteQuery({
|
|
532
|
+
queryKey: ["cmsContent", typeSlug, "by-relation", fieldName, targetId],
|
|
533
|
+
queryFn: async ({ pageParam = 0 }) => {
|
|
534
|
+
const response = await client$1("/content/:typeSlug/by-relation", {
|
|
535
|
+
method: "GET",
|
|
536
|
+
params: { typeSlug },
|
|
537
|
+
query: { field: fieldName, targetId, limit, offset: pageParam },
|
|
538
|
+
headers
|
|
539
|
+
});
|
|
540
|
+
if (isErrorResponse(response)) {
|
|
541
|
+
throw toError(response.error);
|
|
542
|
+
}
|
|
543
|
+
return response.data;
|
|
544
|
+
},
|
|
545
|
+
...SHARED_QUERY_CONFIG,
|
|
546
|
+
initialPageParam: 0,
|
|
547
|
+
getNextPageParam: (lastPage, allPages) => {
|
|
548
|
+
if (!lastPage || typeof lastPage !== "object") return void 0;
|
|
549
|
+
const items2 = lastPage?.items;
|
|
550
|
+
if (!Array.isArray(items2) || items2.length < limit) return void 0;
|
|
551
|
+
const loadedCount = (allPages || []).reduce(
|
|
552
|
+
(sum, page) => sum + (Array.isArray(page?.items) ? page.items.length : 0),
|
|
553
|
+
0
|
|
554
|
+
);
|
|
555
|
+
const total2 = lastPage?.total ?? 0;
|
|
556
|
+
if (loadedCount >= total2) return void 0;
|
|
557
|
+
return loadedCount;
|
|
558
|
+
}
|
|
559
|
+
});
|
|
560
|
+
if (error && !isFetching) {
|
|
561
|
+
throw error;
|
|
562
|
+
}
|
|
563
|
+
const pages = data.pages;
|
|
564
|
+
const items = pages?.flatMap(
|
|
565
|
+
(page) => Array.isArray(page?.items) ? page.items : []
|
|
566
|
+
) ?? [];
|
|
567
|
+
const total = pages?.[0]?.total ?? 0;
|
|
568
|
+
return {
|
|
569
|
+
items,
|
|
570
|
+
total,
|
|
571
|
+
loadMore: fetchNextPage,
|
|
572
|
+
hasMore: !!hasNextPage,
|
|
573
|
+
isLoadingMore: isFetchingNextPage,
|
|
574
|
+
refetch
|
|
575
|
+
};
|
|
576
|
+
}
|
|
391
577
|
|
|
392
578
|
exports.useContent = useContent;
|
|
579
|
+
exports.useContentByRelation = useContentByRelation;
|
|
393
580
|
exports.useContentItem = useContentItem;
|
|
394
581
|
exports.useContentItemBySlug = useContentItemBySlug;
|
|
582
|
+
exports.useContentItemPopulated = useContentItemPopulated;
|
|
395
583
|
exports.useContentType = useContentType;
|
|
396
584
|
exports.useContentTypes = useContentTypes;
|
|
397
585
|
exports.useCreateContent = useCreateContent;
|
|
398
586
|
exports.useDeleteContent = useDeleteContent;
|
|
399
587
|
exports.useSuspenseContent = useSuspenseContent;
|
|
588
|
+
exports.useSuspenseContentByRelation = useSuspenseContentByRelation;
|
|
400
589
|
exports.useSuspenseContentItem = useSuspenseContentItem;
|
|
590
|
+
exports.useSuspenseContentItemPopulated = useSuspenseContentItemPopulated;
|
|
401
591
|
exports.useSuspenseContentTypes = useSuspenseContentTypes;
|
|
402
592
|
exports.useUpdateContent = useUpdateContent;
|
|
@@ -386,5 +386,191 @@ function useDeleteContent(typeSlug) {
|
|
|
386
386
|
}
|
|
387
387
|
});
|
|
388
388
|
}
|
|
389
|
+
function useContentItemPopulated(typeSlug, id) {
|
|
390
|
+
const { apiBaseURL, apiBasePath, headers } = usePluginOverrides("cms");
|
|
391
|
+
const client = createApiClient({
|
|
392
|
+
baseURL: apiBaseURL,
|
|
393
|
+
basePath: apiBasePath
|
|
394
|
+
});
|
|
395
|
+
const { data, isLoading, error, refetch } = useQuery({
|
|
396
|
+
queryKey: ["cmsContent", typeSlug, id, "populated"],
|
|
397
|
+
queryFn: async () => {
|
|
398
|
+
const response = await client(
|
|
399
|
+
"/content/:typeSlug/:id/populated",
|
|
400
|
+
{
|
|
401
|
+
method: "GET",
|
|
402
|
+
params: { typeSlug, id },
|
|
403
|
+
headers
|
|
404
|
+
}
|
|
405
|
+
);
|
|
406
|
+
if (isErrorResponse(response)) {
|
|
407
|
+
throw toError(response.error);
|
|
408
|
+
}
|
|
409
|
+
return response.data;
|
|
410
|
+
},
|
|
411
|
+
...SHARED_QUERY_CONFIG,
|
|
412
|
+
enabled: !!typeSlug && !!id
|
|
413
|
+
});
|
|
414
|
+
return {
|
|
415
|
+
item: data ?? null,
|
|
416
|
+
isLoading,
|
|
417
|
+
error,
|
|
418
|
+
refetch
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
function useSuspenseContentItemPopulated(typeSlug, id) {
|
|
422
|
+
const { apiBaseURL, apiBasePath, headers } = usePluginOverrides("cms");
|
|
423
|
+
const client = createApiClient({
|
|
424
|
+
baseURL: apiBaseURL,
|
|
425
|
+
basePath: apiBasePath
|
|
426
|
+
});
|
|
427
|
+
const { data, refetch, error, isFetching } = useSuspenseQuery({
|
|
428
|
+
queryKey: ["cmsContent", typeSlug, id, "populated"],
|
|
429
|
+
queryFn: async () => {
|
|
430
|
+
const response = await client(
|
|
431
|
+
"/content/:typeSlug/:id/populated",
|
|
432
|
+
{
|
|
433
|
+
method: "GET",
|
|
434
|
+
params: { typeSlug, id },
|
|
435
|
+
headers
|
|
436
|
+
}
|
|
437
|
+
);
|
|
438
|
+
if (isErrorResponse(response)) {
|
|
439
|
+
throw toError(response.error);
|
|
440
|
+
}
|
|
441
|
+
return response.data;
|
|
442
|
+
},
|
|
443
|
+
...SHARED_QUERY_CONFIG
|
|
444
|
+
});
|
|
445
|
+
if (error && !isFetching) {
|
|
446
|
+
throw error;
|
|
447
|
+
}
|
|
448
|
+
return {
|
|
449
|
+
item: data ?? null,
|
|
450
|
+
refetch
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
function useContentByRelation(typeSlug, fieldName, targetId, options = {}) {
|
|
454
|
+
const { apiBaseURL, apiBasePath, headers } = usePluginOverrides("cms");
|
|
455
|
+
const client = createApiClient({
|
|
456
|
+
baseURL: apiBaseURL,
|
|
457
|
+
basePath: apiBasePath
|
|
458
|
+
});
|
|
459
|
+
const { limit = 20, enabled = true } = options;
|
|
460
|
+
const {
|
|
461
|
+
data,
|
|
462
|
+
isLoading,
|
|
463
|
+
error,
|
|
464
|
+
fetchNextPage,
|
|
465
|
+
hasNextPage,
|
|
466
|
+
isFetchingNextPage,
|
|
467
|
+
refetch
|
|
468
|
+
} = useInfiniteQuery({
|
|
469
|
+
queryKey: ["cmsContent", typeSlug, "by-relation", fieldName, targetId],
|
|
470
|
+
queryFn: async ({ pageParam = 0 }) => {
|
|
471
|
+
const response = await client("/content/:typeSlug/by-relation", {
|
|
472
|
+
method: "GET",
|
|
473
|
+
params: { typeSlug },
|
|
474
|
+
query: { field: fieldName, targetId, limit, offset: pageParam },
|
|
475
|
+
headers
|
|
476
|
+
});
|
|
477
|
+
if (isErrorResponse(response)) {
|
|
478
|
+
throw toError(response.error);
|
|
479
|
+
}
|
|
480
|
+
return response.data;
|
|
481
|
+
},
|
|
482
|
+
...SHARED_QUERY_CONFIG,
|
|
483
|
+
initialPageParam: 0,
|
|
484
|
+
getNextPageParam: (lastPage, allPages) => {
|
|
485
|
+
if (!lastPage || typeof lastPage !== "object") return void 0;
|
|
486
|
+
const items2 = lastPage?.items;
|
|
487
|
+
if (!Array.isArray(items2) || items2.length < limit) return void 0;
|
|
488
|
+
const loadedCount = (allPages || []).reduce(
|
|
489
|
+
(sum, page) => sum + (Array.isArray(page?.items) ? page.items.length : 0),
|
|
490
|
+
0
|
|
491
|
+
);
|
|
492
|
+
const total2 = lastPage?.total ?? 0;
|
|
493
|
+
if (loadedCount >= total2) return void 0;
|
|
494
|
+
return loadedCount;
|
|
495
|
+
},
|
|
496
|
+
enabled: enabled && !!typeSlug && !!fieldName && !!targetId
|
|
497
|
+
});
|
|
498
|
+
const pages = data?.pages;
|
|
499
|
+
const items = pages?.flatMap(
|
|
500
|
+
(page) => Array.isArray(page?.items) ? page.items : []
|
|
501
|
+
) ?? [];
|
|
502
|
+
const total = pages?.[0]?.total ?? 0;
|
|
503
|
+
return {
|
|
504
|
+
items,
|
|
505
|
+
total,
|
|
506
|
+
isLoading,
|
|
507
|
+
error,
|
|
508
|
+
loadMore: fetchNextPage,
|
|
509
|
+
hasMore: !!hasNextPage,
|
|
510
|
+
isLoadingMore: isFetchingNextPage,
|
|
511
|
+
refetch
|
|
512
|
+
};
|
|
513
|
+
}
|
|
514
|
+
function useSuspenseContentByRelation(typeSlug, fieldName, targetId, options = {}) {
|
|
515
|
+
const { apiBaseURL, apiBasePath, headers } = usePluginOverrides("cms");
|
|
516
|
+
const client = createApiClient({
|
|
517
|
+
baseURL: apiBaseURL,
|
|
518
|
+
basePath: apiBasePath
|
|
519
|
+
});
|
|
520
|
+
const { limit = 20 } = options;
|
|
521
|
+
const {
|
|
522
|
+
data,
|
|
523
|
+
fetchNextPage,
|
|
524
|
+
hasNextPage,
|
|
525
|
+
isFetchingNextPage,
|
|
526
|
+
refetch,
|
|
527
|
+
error,
|
|
528
|
+
isFetching
|
|
529
|
+
} = useSuspenseInfiniteQuery({
|
|
530
|
+
queryKey: ["cmsContent", typeSlug, "by-relation", fieldName, targetId],
|
|
531
|
+
queryFn: async ({ pageParam = 0 }) => {
|
|
532
|
+
const response = await client("/content/:typeSlug/by-relation", {
|
|
533
|
+
method: "GET",
|
|
534
|
+
params: { typeSlug },
|
|
535
|
+
query: { field: fieldName, targetId, limit, offset: pageParam },
|
|
536
|
+
headers
|
|
537
|
+
});
|
|
538
|
+
if (isErrorResponse(response)) {
|
|
539
|
+
throw toError(response.error);
|
|
540
|
+
}
|
|
541
|
+
return response.data;
|
|
542
|
+
},
|
|
543
|
+
...SHARED_QUERY_CONFIG,
|
|
544
|
+
initialPageParam: 0,
|
|
545
|
+
getNextPageParam: (lastPage, allPages) => {
|
|
546
|
+
if (!lastPage || typeof lastPage !== "object") return void 0;
|
|
547
|
+
const items2 = lastPage?.items;
|
|
548
|
+
if (!Array.isArray(items2) || items2.length < limit) return void 0;
|
|
549
|
+
const loadedCount = (allPages || []).reduce(
|
|
550
|
+
(sum, page) => sum + (Array.isArray(page?.items) ? page.items.length : 0),
|
|
551
|
+
0
|
|
552
|
+
);
|
|
553
|
+
const total2 = lastPage?.total ?? 0;
|
|
554
|
+
if (loadedCount >= total2) return void 0;
|
|
555
|
+
return loadedCount;
|
|
556
|
+
}
|
|
557
|
+
});
|
|
558
|
+
if (error && !isFetching) {
|
|
559
|
+
throw error;
|
|
560
|
+
}
|
|
561
|
+
const pages = data.pages;
|
|
562
|
+
const items = pages?.flatMap(
|
|
563
|
+
(page) => Array.isArray(page?.items) ? page.items : []
|
|
564
|
+
) ?? [];
|
|
565
|
+
const total = pages?.[0]?.total ?? 0;
|
|
566
|
+
return {
|
|
567
|
+
items,
|
|
568
|
+
total,
|
|
569
|
+
loadMore: fetchNextPage,
|
|
570
|
+
hasMore: !!hasNextPage,
|
|
571
|
+
isLoadingMore: isFetchingNextPage,
|
|
572
|
+
refetch
|
|
573
|
+
};
|
|
574
|
+
}
|
|
389
575
|
|
|
390
|
-
export { useContent, useContentItem, useContentItemBySlug, useContentType, useContentTypes, useCreateContent, useDeleteContent, useSuspenseContent, useSuspenseContentItem, useSuspenseContentTypes, useUpdateContent };
|
|
576
|
+
export { useContent, useContentByRelation, useContentItem, useContentItemBySlug, useContentItemPopulated, useContentType, useContentTypes, useCreateContent, useDeleteContent, useSuspenseContent, useSuspenseContentByRelation, useSuspenseContentItem, useSuspenseContentItemPopulated, useSuspenseContentTypes, useUpdateContent };
|
|
@@ -74,6 +74,44 @@ const cmsSchema = db.createDbPlugin("cms", {
|
|
|
74
74
|
defaultValue: () => /* @__PURE__ */ new Date()
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
|
+
},
|
|
78
|
+
/**
|
|
79
|
+
* Junction table for content item relationships
|
|
80
|
+
* Stores many-to-many and one-to-many relations between content items
|
|
81
|
+
*/
|
|
82
|
+
contentRelation: {
|
|
83
|
+
modelName: "contentRelation",
|
|
84
|
+
fields: {
|
|
85
|
+
/** The content item that has the relation field */
|
|
86
|
+
sourceId: {
|
|
87
|
+
type: "string",
|
|
88
|
+
required: true,
|
|
89
|
+
references: {
|
|
90
|
+
model: "contentItem",
|
|
91
|
+
field: "id",
|
|
92
|
+
onDelete: "cascade"
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
/** The content item being referenced */
|
|
96
|
+
targetId: {
|
|
97
|
+
type: "string",
|
|
98
|
+
required: true,
|
|
99
|
+
references: {
|
|
100
|
+
model: "contentItem",
|
|
101
|
+
field: "id",
|
|
102
|
+
onDelete: "cascade"
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
/** The field name in the source content type schema (e.g., "categoryIds") */
|
|
106
|
+
fieldName: {
|
|
107
|
+
type: "string",
|
|
108
|
+
required: true
|
|
109
|
+
},
|
|
110
|
+
createdAt: {
|
|
111
|
+
type: "date",
|
|
112
|
+
defaultValue: () => /* @__PURE__ */ new Date()
|
|
113
|
+
}
|
|
114
|
+
}
|
|
77
115
|
}
|
|
78
116
|
});
|
|
79
117
|
|
|
@@ -72,6 +72,44 @@ const cmsSchema = createDbPlugin("cms", {
|
|
|
72
72
|
defaultValue: () => /* @__PURE__ */ new Date()
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
|
+
},
|
|
76
|
+
/**
|
|
77
|
+
* Junction table for content item relationships
|
|
78
|
+
* Stores many-to-many and one-to-many relations between content items
|
|
79
|
+
*/
|
|
80
|
+
contentRelation: {
|
|
81
|
+
modelName: "contentRelation",
|
|
82
|
+
fields: {
|
|
83
|
+
/** The content item that has the relation field */
|
|
84
|
+
sourceId: {
|
|
85
|
+
type: "string",
|
|
86
|
+
required: true,
|
|
87
|
+
references: {
|
|
88
|
+
model: "contentItem",
|
|
89
|
+
field: "id",
|
|
90
|
+
onDelete: "cascade"
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
/** The content item being referenced */
|
|
94
|
+
targetId: {
|
|
95
|
+
type: "string",
|
|
96
|
+
required: true,
|
|
97
|
+
references: {
|
|
98
|
+
model: "contentItem",
|
|
99
|
+
field: "id",
|
|
100
|
+
onDelete: "cascade"
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
/** The field name in the source content type schema (e.g., "categoryIds") */
|
|
104
|
+
fieldName: {
|
|
105
|
+
type: "string",
|
|
106
|
+
required: true
|
|
107
|
+
},
|
|
108
|
+
createdAt: {
|
|
109
|
+
type: "date",
|
|
110
|
+
defaultValue: () => /* @__PURE__ */ new Date()
|
|
111
|
+
}
|
|
112
|
+
}
|
|
75
113
|
}
|
|
76
114
|
});
|
|
77
115
|
|
|
@@ -5,7 +5,7 @@ const jsxRuntime = require('react/jsx-runtime');
|
|
|
5
5
|
const React = require('react');
|
|
6
6
|
const context = require('@btst/stack/context');
|
|
7
7
|
const steppedAutoForm = require('../../../../../../../ui/src/components/auto-form/stepped-auto-form.cjs');
|
|
8
|
-
const
|
|
8
|
+
const helpers = require('../../../../../../../ui/src/components/auto-form/helpers.cjs');
|
|
9
9
|
const schemaConverter = require('../../../../../../../ui/src/lib/schema-converter.cjs');
|
|
10
10
|
const skeleton = require('../../../../../../../ui/src/components/skeleton.cjs');
|
|
11
11
|
const lucideReact = require('lucide-react');
|
|
@@ -69,7 +69,7 @@ function FormRenderer({
|
|
|
69
69
|
try {
|
|
70
70
|
const parsedSchema = JSON.parse(form.schema);
|
|
71
71
|
const zod = schemaConverter.formSchemaToZod(parsedSchema);
|
|
72
|
-
const config =
|
|
72
|
+
const config = helpers.buildFieldConfigFromJsonSchema(
|
|
73
73
|
parsedSchema,
|
|
74
74
|
mergedFieldComponents
|
|
75
75
|
);
|
|
@@ -3,7 +3,7 @@ import { jsx, jsxs } from 'react/jsx-runtime';
|
|
|
3
3
|
import { useState, useMemo } from 'react';
|
|
4
4
|
import { usePluginOverrides } from '@btst/stack/context';
|
|
5
5
|
import SteppedAutoForm from '../../../../../../../ui/src/components/auto-form/stepped-auto-form.mjs';
|
|
6
|
-
import { buildFieldConfigFromJsonSchema } from '../../../../../../../ui/src/components/auto-form/
|
|
6
|
+
import { buildFieldConfigFromJsonSchema } from '../../../../../../../ui/src/components/auto-form/helpers.mjs';
|
|
7
7
|
import { formSchemaToZod } from '../../../../../../../ui/src/lib/schema-converter.mjs';
|
|
8
8
|
import { Skeleton } from '../../../../../../../ui/src/components/skeleton.mjs';
|
|
9
9
|
import { AlertCircle, CheckCircle } from 'lucide-react';
|
|
@@ -6,7 +6,7 @@ const button = require('../../button.cjs');
|
|
|
6
6
|
const separator = require('../../separator.cjs');
|
|
7
7
|
const lucideReact = require('lucide-react');
|
|
8
8
|
const reactHookForm = require('react-hook-form');
|
|
9
|
-
const
|
|
9
|
+
const helpers = require('../helpers.cjs');
|
|
10
10
|
const object = require('./object.cjs');
|
|
11
11
|
|
|
12
12
|
function getDefType(schema) {
|
|
@@ -38,7 +38,7 @@ function AutoFormArray({
|
|
|
38
38
|
control: form.control,
|
|
39
39
|
name: fieldPath
|
|
40
40
|
});
|
|
41
|
-
const title = fieldConfig?.label ??
|
|
41
|
+
const title = fieldConfig?.label ?? helpers.beautifyObjectName(name);
|
|
42
42
|
const itemDefType = getArrayElementType(item);
|
|
43
43
|
return /* @__PURE__ */ jsxRuntime.jsxs(accordion.AccordionItem, { value: name, className: "border-none", children: [
|
|
44
44
|
/* @__PURE__ */ jsxRuntime.jsx(accordion.AccordionTrigger, { children: title }),
|
|
@@ -4,7 +4,7 @@ import { Button } from '../../button.mjs';
|
|
|
4
4
|
import { Separator } from '../../separator.mjs';
|
|
5
5
|
import { Trash, Plus } from 'lucide-react';
|
|
6
6
|
import { useFieldArray } from 'react-hook-form';
|
|
7
|
-
import { beautifyObjectName } from '../
|
|
7
|
+
import { beautifyObjectName } from '../helpers.mjs';
|
|
8
8
|
import AutoFormObject from './object.mjs';
|
|
9
9
|
|
|
10
10
|
function getDefType(schema) {
|
|
@@ -5,7 +5,7 @@ const datePicker = require('../../date-picker.cjs');
|
|
|
5
5
|
const form = require('../../form.cjs');
|
|
6
6
|
const label = require('../common/label.cjs');
|
|
7
7
|
const tooltip = require('../common/tooltip.cjs');
|
|
8
|
-
const
|
|
8
|
+
const helpers = require('../helpers.cjs');
|
|
9
9
|
|
|
10
10
|
function toDate(value) {
|
|
11
11
|
if (!value) return void 0;
|
|
@@ -24,7 +24,7 @@ function AutoFormDate({
|
|
|
24
24
|
fieldProps,
|
|
25
25
|
zodItem
|
|
26
26
|
}) {
|
|
27
|
-
const baseType =
|
|
27
|
+
const baseType = helpers.getBaseType(zodItem);
|
|
28
28
|
const expectsDateObject = baseType === "ZodDate";
|
|
29
29
|
const handleChange = (date) => {
|
|
30
30
|
if (!date) {
|
|
@@ -3,7 +3,7 @@ import { DatePicker } from '../../date-picker.mjs';
|
|
|
3
3
|
import { FormItem, FormControl, FormMessage } from '../../form.mjs';
|
|
4
4
|
import AutoFormLabel from '../common/label.mjs';
|
|
5
5
|
import AutoFormTooltip from '../common/tooltip.mjs';
|
|
6
|
-
import { getBaseType } from '../
|
|
6
|
+
import { getBaseType } from '../helpers.mjs';
|
|
7
7
|
|
|
8
8
|
function toDate(value) {
|
|
9
9
|
if (!value) return void 0;
|
|
@@ -5,7 +5,7 @@ const form = require('../../form.cjs');
|
|
|
5
5
|
const select = require('../../select.cjs');
|
|
6
6
|
const label = require('../common/label.cjs');
|
|
7
7
|
const tooltip = require('../common/tooltip.cjs');
|
|
8
|
-
const
|
|
8
|
+
const helpers = require('../helpers.cjs');
|
|
9
9
|
|
|
10
10
|
function getEnumValues(schema) {
|
|
11
11
|
if (Array.isArray(schema.options)) {
|
|
@@ -28,7 +28,7 @@ function AutoFormEnum({
|
|
|
28
28
|
zodItem,
|
|
29
29
|
fieldProps
|
|
30
30
|
}) {
|
|
31
|
-
const baseSchema =
|
|
31
|
+
const baseSchema = helpers.getBaseSchema(zodItem);
|
|
32
32
|
const baseValues = getEnumValues(baseSchema);
|
|
33
33
|
let values = [];
|
|
34
34
|
if (!baseValues || baseValues.length === 0) {
|
|
@@ -3,7 +3,7 @@ import { FormItem, FormControl, FormMessage } from '../../form.mjs';
|
|
|
3
3
|
import { Select, SelectTrigger, SelectValue, SelectContent, SelectItem } from '../../select.mjs';
|
|
4
4
|
import AutoFormLabel from '../common/label.mjs';
|
|
5
5
|
import AutoFormTooltip from '../common/tooltip.mjs';
|
|
6
|
-
import { getBaseSchema } from '../
|
|
6
|
+
import { getBaseSchema } from '../helpers.mjs';
|
|
7
7
|
|
|
8
8
|
function getEnumValues(schema) {
|
|
9
9
|
if (Array.isArray(schema.options)) {
|