@btst/plugin-cms 1.0.0-beta.0 → 1.2.0-beta.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.
Files changed (76) hide show
  1. package/dist/api/getters.cjs +37 -25
  2. package/dist/api/getters.mjs +37 -25
  3. package/dist/api/index.cjs +1 -0
  4. package/dist/api/index.d.cts +17 -8
  5. package/dist/api/index.d.mts +17 -8
  6. package/dist/api/index.d.ts +17 -8
  7. package/dist/api/index.mjs +1 -1
  8. package/dist/api/mutations.cjs +46 -19
  9. package/dist/api/mutations.mjs +46 -20
  10. package/dist/api/operations.cjs +586 -177
  11. package/dist/api/operations.mjs +585 -178
  12. package/dist/api/plugin.cjs +56 -7
  13. package/dist/api/plugin.mjs +57 -8
  14. package/dist/api/publication.cjs +8 -0
  15. package/dist/api/publication.mjs +6 -0
  16. package/dist/client/components/forms/content-form.cjs +107 -1
  17. package/dist/client/components/forms/content-form.mjs +108 -2
  18. package/dist/client/components/pages/content-editor-page.internal.cjs +23 -5
  19. package/dist/client/components/pages/content-editor-page.internal.mjs +23 -5
  20. package/dist/client/components/pages/content-list-page.internal.cjs +3 -0
  21. package/dist/client/components/pages/content-list-page.internal.mjs +3 -0
  22. package/dist/client/components/pages/dashboard-page.internal.cjs +10 -30
  23. package/dist/client/components/pages/dashboard-page.internal.mjs +10 -30
  24. package/dist/client/components/revision-history.cjs +161 -0
  25. package/dist/client/components/revision-history.mjs +159 -0
  26. package/dist/client/components/shared/content-type-card.cjs +56 -0
  27. package/dist/client/components/shared/content-type-card.mjs +54 -0
  28. package/dist/client/components/shared/empty-state.cjs +18 -1
  29. package/dist/client/components/shared/empty-state.mjs +19 -2
  30. package/dist/client/hooks/cms-hooks.cjs +18 -2
  31. package/dist/client/hooks/cms-hooks.mjs +17 -3
  32. package/dist/client/hooks/index.cjs +2 -0
  33. package/dist/client/hooks/index.d.cts +306 -2
  34. package/dist/client/hooks/index.d.mts +306 -2
  35. package/dist/client/hooks/index.d.ts +306 -2
  36. package/dist/client/hooks/index.mjs +1 -1
  37. package/dist/client/index.d.cts +55 -2
  38. package/dist/client/index.d.mts +55 -2
  39. package/dist/client/index.d.ts +55 -2
  40. package/dist/db.cjs +25 -0
  41. package/dist/db.mjs +25 -0
  42. package/dist/permissions.cjs +2 -0
  43. package/dist/permissions.d.cts +1 -0
  44. package/dist/permissions.d.mts +1 -0
  45. package/dist/permissions.d.ts +1 -0
  46. package/dist/permissions.mjs +2 -0
  47. package/dist/query-keys.cjs +31 -1
  48. package/dist/query-keys.d.cts +1 -1
  49. package/dist/query-keys.d.mts +1 -1
  50. package/dist/query-keys.d.ts +1 -1
  51. package/dist/query-keys.mjs +31 -1
  52. package/dist/shared/{plugin-cms.Csx7tNDO.d.mts → plugin-cms.DAAUZ41w.d.mts} +314 -81
  53. package/dist/shared/{plugin-cms.eNW9_FO5.d.ts → plugin-cms.DJ_293QU.d.cts} +314 -81
  54. package/dist/shared/{plugin-cms.Bptwe33B.d.cts → plugin-cms.DlUSv7wz.d.ts} +314 -81
  55. package/dist/types.d.cts +38 -2
  56. package/dist/types.d.mts +38 -2
  57. package/dist/types.d.ts +38 -2
  58. package/dist/ui/src/components/auto-form/config.cjs +2 -0
  59. package/dist/ui/src/components/auto-form/config.mjs +2 -0
  60. package/dist/ui/src/components/auto-form/fields/file.cjs +68 -0
  61. package/dist/ui/src/components/auto-form/fields/file.mjs +63 -0
  62. package/dist/ui/src/components/auto-form/fields/object.cjs +9 -2
  63. package/dist/ui/src/components/auto-form/fields/object.mjs +9 -2
  64. package/dist/ui/src/components/auto-form/helpers.cjs +9 -0
  65. package/dist/ui/src/components/auto-form/helpers.mjs +9 -0
  66. package/dist/ui/src/components/auto-form/index.cjs +29 -4
  67. package/dist/ui/src/components/auto-form/index.mjs +31 -6
  68. package/dist/ui/src/components/auto-form/stepped-auto-form.cjs +34 -29
  69. package/dist/ui/src/components/auto-form/stepped-auto-form.mjs +35 -30
  70. package/dist/ui/src/components/sheet.cjs +126 -0
  71. package/dist/ui/src/components/sheet.mjs +105 -0
  72. package/dist/ui/src/lib/form-visibility.cjs +20 -0
  73. package/dist/ui/src/lib/form-visibility.mjs +18 -0
  74. package/dist/ui/src/lib/schema-converter.cjs +101 -0
  75. package/dist/ui/src/lib/schema-converter.mjs +100 -1
  76. package/package.json +5 -4
@@ -4,12 +4,30 @@ import * as _btst_yar from '@btst/yar';
4
4
  import * as react from 'react';
5
5
  import { ComponentType } from 'react';
6
6
  import { D as DashboardPageComponent } from '../shared/plugin-cms.BBshPRkb.js';
7
- import { ContentTypeConfig } from '../types.js';
7
+ import { SerializedContentType, ContentTypeConfig } from '../types.js';
8
8
  export { CMSContentFields, CMSContentItemResult, CMSReadOptions, CMSReadView, CMSSelectedData, PaginatedContentItems, SerializedContentItemContent } from '../types.js';
9
9
  import { ControllerRenderProps, FieldValues } from 'react-hook-form';
10
10
  import * as z from 'zod';
11
11
  import { z as z$1 } from 'zod';
12
12
 
13
+ /** Content supplied to a CMS empty-state presentation. */
14
+ interface EmptyStateProps {
15
+ title: string;
16
+ description?: string;
17
+ action?: React.ReactNode;
18
+ }
19
+
20
+ /** Display data and navigation supplied by the CMS dashboard. */
21
+ interface ContentTypeCardProps {
22
+ contentType: SerializedContentType & {
23
+ itemCount: number;
24
+ };
25
+ itemCountLabel: string;
26
+ onOpen: () => void;
27
+ className?: string;
28
+ titleClassName?: string;
29
+ }
30
+
13
31
  declare const CMS_LOCALIZATION: {
14
32
  CMS_RELATION_LOADING: string;
15
33
  CMS_RELATION_SELECT_PLACEHOLDER: string;
@@ -93,6 +111,15 @@ declare const CMS_LOCALIZATION: {
93
111
  };
94
112
  type CMSLocalization = typeof CMS_LOCALIZATION;
95
113
 
114
+ /** A single visibility condition against a sibling field's value. */
115
+ type ShowIfCondition = {
116
+ field: string;
117
+ operator: "equals" | "notEquals" | "in" | "isTruthy";
118
+ value?: unknown;
119
+ };
120
+
121
+ declare function AutoFormFile({ field, fieldProps, fieldConfigItem, label, isRequired }: AutoFormInputComponentProps): react.JSX.Element;
122
+
96
123
  declare function AutoFormCheckbox({ label, isRequired, field, fieldConfigItem, fieldProps, }: AutoFormInputComponentProps): react.JSX.Element;
97
124
 
98
125
  declare function AutoFormDate({ label, isRequired, field, fieldConfigItem, fieldProps, zodItem, }: AutoFormInputComponentProps): react.JSX.Element;
@@ -110,6 +137,7 @@ declare function AutoFormSwitch({ label, isRequired, field, fieldConfigItem, fie
110
137
  declare function AutoFormTextarea({ label, isRequired, fieldConfigItem, fieldProps, }: AutoFormInputComponentProps): react.JSX.Element;
111
138
 
112
139
  declare const INPUT_COMPONENTS: {
140
+ file: typeof AutoFormFile;
113
141
  checkbox: typeof AutoFormCheckbox;
114
142
  date: typeof AutoFormDate;
115
143
  select: typeof AutoFormEnum;
@@ -173,6 +201,10 @@ type FieldInputProps = SerializableInputProps & Omit<React.InputHTMLAttributes<H
173
201
  * so that JSON Schema properties can be easily converted to field configs.
174
202
  */
175
203
  type FieldConfigItem = {
204
+ /** Show this field only when the condition matches. */
205
+ showIf?: ShowIfCondition;
206
+ /** Standalone file upload handler; resolves to a stored URL. */
207
+ onUpload?: (file: File) => Promise<string>;
176
208
  /** Description text or React node */
177
209
  description?: React.ReactNode;
178
210
  /** Input props passed to the field component */
@@ -238,6 +270,22 @@ interface RouteContext {
238
270
  * plugin-specific components and behavior.
239
271
  */
240
272
  interface CMSPluginOverrides {
273
+ /** Presentation scoped to built-in route keys. */
274
+ pageOverrides?: {
275
+ dashboard?: {
276
+ ContentTypeCard?: ComponentType<ContentTypeCardProps>;
277
+ EmptyState?: ComponentType<EmptyStateProps>;
278
+ };
279
+ contentList?: {
280
+ EmptyState?: ComponentType<EmptyStateProps>;
281
+ };
282
+ newContent?: {
283
+ EmptyState?: ComponentType<EmptyStateProps>;
284
+ };
285
+ editContent?: {
286
+ EmptyState?: ComponentType<EmptyStateProps>;
287
+ };
288
+ };
241
289
  /**
242
290
  * Function used to upload a new image file and return its URL.
243
291
  * Used by the default "file" field component when not selecting an existing
@@ -542,6 +590,8 @@ declare const cmsClientPlugin: (config?: CMSClientConfig) => _btst_stack_client.
542
590
  interface FormStep {
543
591
  id: string;
544
592
  title: string;
593
+ /** Display this step only when its condition matches. */
594
+ showIf?: ShowIfCondition;
545
595
  }
546
596
  interface FormSchemaMetadata {
547
597
  /** Multi-step form step definitions */
@@ -555,6 +605,9 @@ interface JsonSchemaProperty {
555
605
  formatMinimum?: string;
556
606
  formatMaximum?: string;
557
607
  stepGroup?: number;
608
+ showIf?: ShowIfCondition;
609
+ items?: JsonSchemaProperty;
610
+ required?: string[];
558
611
  properties?: Record<string, JsonSchemaProperty>;
559
612
  [key: string]: unknown;
560
613
  }
@@ -651,4 +704,4 @@ interface CMSFileUploadProps extends AutoFormInputComponentProps {
651
704
  declare function CMSFileUpload({ label, isRequired, fieldConfigItem, fieldProps, field, uploadImage, imageInputField: ImageInputField, imagePicker: ImagePickerTrigger, }: CMSFileUploadProps): react.JSX.Element;
652
705
 
653
706
  export { CMSFileUpload, ContentTypeConfig, cmsClientPlugin, formSchemaToZod, getStepGroupMap, getSteps, hasSteps, zodToFormSchema };
654
- export type { AutoFormInputComponentProps, CMSClientConfig, CMSClientHooks, CMSFileUploadProps, CMSLocalization, CMSPluginOverrides, CMSProviderConfig, FormSchemaMetadata, FormStep, LoaderContext, RouteContext };
707
+ export type { AutoFormInputComponentProps, CMSClientConfig, CMSClientHooks, CMSFileUploadProps, CMSLocalization, CMSPluginOverrides, CMSProviderConfig, ContentTypeCardProps, EmptyStateProps, FormSchemaMetadata, FormStep, LoaderContext, RouteContext };
package/dist/db.cjs CHANGED
@@ -65,6 +65,10 @@ const cmsSchema = db.createDbPlugin("cms", {
65
65
  type: "string",
66
66
  required: false
67
67
  },
68
+ publishAt: {
69
+ type: "date",
70
+ required: false
71
+ },
68
72
  createdAt: {
69
73
  type: "date",
70
74
  defaultValue: () => /* @__PURE__ */ new Date()
@@ -75,6 +79,27 @@ const cmsSchema = db.createDbPlugin("cms", {
75
79
  }
76
80
  }
77
81
  },
82
+ contentRevision: {
83
+ modelName: "contentRevision",
84
+ fields: {
85
+ contentItemId: {
86
+ type: "string",
87
+ required: true,
88
+ references: {
89
+ model: "contentItem",
90
+ field: "id",
91
+ onDelete: "cascade"
92
+ }
93
+ },
94
+ revisionKey: { type: "string", required: true, unique: true },
95
+ version: { type: "number", required: true },
96
+ slug: { type: "string", required: true },
97
+ data: { type: "string", required: true },
98
+ publishAt: { type: "date", required: false },
99
+ authorId: { type: "string", required: false },
100
+ createdAt: { type: "date", defaultValue: () => /* @__PURE__ */ new Date() }
101
+ }
102
+ },
78
103
  /**
79
104
  * Junction table for content item relationships
80
105
  * Stores many-to-many and one-to-many relations between content items
package/dist/db.mjs CHANGED
@@ -63,6 +63,10 @@ const cmsSchema = createDbPlugin("cms", {
63
63
  type: "string",
64
64
  required: false
65
65
  },
66
+ publishAt: {
67
+ type: "date",
68
+ required: false
69
+ },
66
70
  createdAt: {
67
71
  type: "date",
68
72
  defaultValue: () => /* @__PURE__ */ new Date()
@@ -73,6 +77,27 @@ const cmsSchema = createDbPlugin("cms", {
73
77
  }
74
78
  }
75
79
  },
80
+ contentRevision: {
81
+ modelName: "contentRevision",
82
+ fields: {
83
+ contentItemId: {
84
+ type: "string",
85
+ required: true,
86
+ references: {
87
+ model: "contentItem",
88
+ field: "id",
89
+ onDelete: "cascade"
90
+ }
91
+ },
92
+ revisionKey: { type: "string", required: true, unique: true },
93
+ version: { type: "number", required: true },
94
+ slug: { type: "string", required: true },
95
+ data: { type: "string", required: true },
96
+ publishAt: { type: "date", required: false },
97
+ authorId: { type: "string", required: false },
98
+ createdAt: { type: "date", defaultValue: () => /* @__PURE__ */ new Date() }
99
+ }
100
+ },
76
101
  /**
77
102
  * Junction table for content item relationships
78
103
  * Stores many-to-many and one-to-many relations between content items
@@ -18,6 +18,8 @@ const cmsPermissions = authorization.definePermissions("cms", {
18
18
  z.z.object({
19
19
  contentType: z.z.string(),
20
20
  scope: z.z.enum(["collection", "record"]),
21
+ /** Set only for publication-filtered content projections; absent for editor/legacy reads. */
22
+ view: z.z.literal("content").optional(),
21
23
  recordId: z.z.string().optional(),
22
24
  authorId: z.z.string().optional()
23
25
  })
@@ -17,6 +17,7 @@ declare const cmsPermissions: _btst_stack_authorization.PermissionCatalog<"cms",
17
17
  record: "record";
18
18
  collection: "collection";
19
19
  }>;
20
+ view: z.ZodOptional<z.ZodLiteral<"content">>;
20
21
  recordId: z.ZodOptional<z.ZodString>;
21
22
  authorId: z.ZodOptional<z.ZodString>;
22
23
  }, z.core.$strip>>;
@@ -17,6 +17,7 @@ declare const cmsPermissions: _btst_stack_authorization.PermissionCatalog<"cms",
17
17
  record: "record";
18
18
  collection: "collection";
19
19
  }>;
20
+ view: z.ZodOptional<z.ZodLiteral<"content">>;
20
21
  recordId: z.ZodOptional<z.ZodString>;
21
22
  authorId: z.ZodOptional<z.ZodString>;
22
23
  }, z.core.$strip>>;
@@ -17,6 +17,7 @@ declare const cmsPermissions: _btst_stack_authorization.PermissionCatalog<"cms",
17
17
  record: "record";
18
18
  collection: "collection";
19
19
  }>;
20
+ view: z.ZodOptional<z.ZodLiteral<"content">>;
20
21
  recordId: z.ZodOptional<z.ZodString>;
21
22
  authorId: z.ZodOptional<z.ZodString>;
22
23
  }, z.core.$strip>>;
@@ -16,6 +16,8 @@ const cmsPermissions = definePermissions("cms", {
16
16
  z.object({
17
17
  contentType: z.string(),
18
18
  scope: z.enum(["collection", "record"]),
19
+ /** Set only for publication-filtered content projections; absent for editor/legacy reads. */
20
+ view: z.literal("content").optional(),
19
21
  recordId: z.string().optional(),
20
22
  authorId: z.string().optional()
21
23
  })
@@ -75,6 +75,33 @@ const cmsResources = {
75
75
  }
76
76
  }
77
77
  },
78
+ cmsRevisions: {
79
+ queries: {
80
+ list: {
81
+ path: "/content/:typeSlug/:id/revisions",
82
+ params: (typeSlug, id) => ({ typeSlug, id }),
83
+ key: (typeSlug, id) => [typeSlug, id],
84
+ select: (data) => data ?? { items: [], total: 0 },
85
+ infinite: true,
86
+ pageSize: () => 20,
87
+ nextPageParam: (lastPage, allPages) => paginatedNextPageParam(lastPage, allPages, 20)
88
+ }
89
+ },
90
+ mutations: {
91
+ restore: {
92
+ path: "@post/content/:typeSlug/:id/revisions/:revisionId/restore",
93
+ method: "POST",
94
+ input: (vars) => ({ params: vars }),
95
+ select: (data) => data,
96
+ invalidates: [
97
+ "cmsContent",
98
+ "cmsRevisions",
99
+ "cmsTypes.inverseRelationItems",
100
+ "cmsTypes.inverseRelations"
101
+ ]
102
+ }
103
+ }
104
+ },
78
105
  cmsContent: {
79
106
  queries: {
80
107
  list: {
@@ -175,11 +202,12 @@ const cmsResources = {
175
202
  method: "POST",
176
203
  input: (vars) => ({
177
204
  params: { typeSlug: vars.typeSlug },
178
- body: { slug: vars.slug, data: vars.data }
205
+ body: { slug: vars.slug, data: vars.data, publishAt: vars.publishAt }
179
206
  }),
180
207
  select: (data) => data,
181
208
  invalidates: [
182
209
  "cmsContent",
210
+ "cmsRevisions",
183
211
  "cmsTypes.list",
184
212
  "cmsTypes.inverseRelationItems",
185
213
  "cmsTypes.inverseRelations"
@@ -195,6 +223,7 @@ const cmsResources = {
195
223
  select: (data) => data,
196
224
  invalidates: [
197
225
  "cmsContent",
226
+ "cmsRevisions",
198
227
  "cmsTypes.inverseRelationItems",
199
228
  "cmsTypes.inverseRelations"
200
229
  ],
@@ -212,6 +241,7 @@ const cmsResources = {
212
241
  select: (data) => data,
213
242
  invalidates: [
214
243
  "cmsContent",
244
+ "cmsRevisions",
215
245
  "cmsTypes.list",
216
246
  "cmsTypes.inverseRelationItems",
217
247
  "cmsTypes.inverseRelations"
@@ -1,4 +1,4 @@
1
- export { e as ContentListDiscriminator, f as ContentListParams, g as cmsResources, h as contentListDiscriminator, d as createCMSQueryKeys } from './shared/plugin-cms.Bptwe33B.cjs';
1
+ export { e as ContentListDiscriminator, f as ContentListParams, g as cmsResources, h as contentListDiscriminator, d as createCMSQueryKeys } from './shared/plugin-cms.DJ_293QU.cjs';
2
2
  import '@btst/stack/plugins/client';
3
3
  import './types.cjs';
4
4
  import '@btst/stack/authorization';
@@ -1,4 +1,4 @@
1
- export { e as ContentListDiscriminator, f as ContentListParams, g as cmsResources, h as contentListDiscriminator, d as createCMSQueryKeys } from './shared/plugin-cms.Csx7tNDO.mjs';
1
+ export { e as ContentListDiscriminator, f as ContentListParams, g as cmsResources, h as contentListDiscriminator, d as createCMSQueryKeys } from './shared/plugin-cms.DAAUZ41w.mjs';
2
2
  import '@btst/stack/plugins/client';
3
3
  import './types.mjs';
4
4
  import '@btst/stack/authorization';
@@ -1,4 +1,4 @@
1
- export { e as ContentListDiscriminator, f as ContentListParams, g as cmsResources, h as contentListDiscriminator, d as createCMSQueryKeys } from './shared/plugin-cms.eNW9_FO5.js';
1
+ export { e as ContentListDiscriminator, f as ContentListParams, g as cmsResources, h as contentListDiscriminator, d as createCMSQueryKeys } from './shared/plugin-cms.DlUSv7wz.js';
2
2
  import '@btst/stack/plugins/client';
3
3
  import './types.js';
4
4
  import '@btst/stack/authorization';
@@ -73,6 +73,33 @@ const cmsResources = {
73
73
  }
74
74
  }
75
75
  },
76
+ cmsRevisions: {
77
+ queries: {
78
+ list: {
79
+ path: "/content/:typeSlug/:id/revisions",
80
+ params: (typeSlug, id) => ({ typeSlug, id }),
81
+ key: (typeSlug, id) => [typeSlug, id],
82
+ select: (data) => data ?? { items: [], total: 0 },
83
+ infinite: true,
84
+ pageSize: () => 20,
85
+ nextPageParam: (lastPage, allPages) => paginatedNextPageParam(lastPage, allPages, 20)
86
+ }
87
+ },
88
+ mutations: {
89
+ restore: {
90
+ path: "@post/content/:typeSlug/:id/revisions/:revisionId/restore",
91
+ method: "POST",
92
+ input: (vars) => ({ params: vars }),
93
+ select: (data) => data,
94
+ invalidates: [
95
+ "cmsContent",
96
+ "cmsRevisions",
97
+ "cmsTypes.inverseRelationItems",
98
+ "cmsTypes.inverseRelations"
99
+ ]
100
+ }
101
+ }
102
+ },
76
103
  cmsContent: {
77
104
  queries: {
78
105
  list: {
@@ -173,11 +200,12 @@ const cmsResources = {
173
200
  method: "POST",
174
201
  input: (vars) => ({
175
202
  params: { typeSlug: vars.typeSlug },
176
- body: { slug: vars.slug, data: vars.data }
203
+ body: { slug: vars.slug, data: vars.data, publishAt: vars.publishAt }
177
204
  }),
178
205
  select: (data) => data,
179
206
  invalidates: [
180
207
  "cmsContent",
208
+ "cmsRevisions",
181
209
  "cmsTypes.list",
182
210
  "cmsTypes.inverseRelationItems",
183
211
  "cmsTypes.inverseRelations"
@@ -193,6 +221,7 @@ const cmsResources = {
193
221
  select: (data) => data,
194
222
  invalidates: [
195
223
  "cmsContent",
224
+ "cmsRevisions",
196
225
  "cmsTypes.inverseRelationItems",
197
226
  "cmsTypes.inverseRelations"
198
227
  ],
@@ -210,6 +239,7 @@ const cmsResources = {
210
239
  select: (data) => data,
211
240
  invalidates: [
212
241
  "cmsContent",
242
+ "cmsRevisions",
213
243
  "cmsTypes.list",
214
244
  "cmsTypes.inverseRelationItems",
215
245
  "cmsTypes.inverseRelations"