@btst/stack 1.8.0 → 1.9.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 (44) hide show
  1. package/dist/packages/better-stack/src/plugins/cms/api/plugin.cjs +445 -16
  2. package/dist/packages/better-stack/src/plugins/cms/api/plugin.mjs +445 -16
  3. package/dist/packages/better-stack/src/plugins/cms/client/components/forms/content-form.cjs +24 -7
  4. package/dist/packages/better-stack/src/plugins/cms/client/components/forms/content-form.mjs +25 -8
  5. package/dist/packages/better-stack/src/plugins/cms/client/components/forms/relation-field.cjs +224 -0
  6. package/dist/packages/better-stack/src/plugins/cms/client/components/forms/relation-field.mjs +222 -0
  7. package/dist/packages/better-stack/src/plugins/cms/client/components/inverse-relations-panel.cjs +243 -0
  8. package/dist/packages/better-stack/src/plugins/cms/client/components/inverse-relations-panel.mjs +241 -0
  9. package/dist/packages/better-stack/src/plugins/cms/client/components/pages/content-editor-page.internal.cjs +56 -2
  10. package/dist/packages/better-stack/src/plugins/cms/client/components/pages/content-editor-page.internal.mjs +56 -2
  11. package/dist/packages/better-stack/src/plugins/cms/client/hooks/cms-hooks.cjs +190 -0
  12. package/dist/packages/better-stack/src/plugins/cms/client/hooks/cms-hooks.mjs +187 -1
  13. package/dist/packages/better-stack/src/plugins/cms/db.cjs +38 -0
  14. package/dist/packages/better-stack/src/plugins/cms/db.mjs +38 -0
  15. package/dist/packages/ui/src/components/auto-form/fields/object.cjs +81 -1
  16. package/dist/packages/ui/src/components/auto-form/fields/object.mjs +81 -1
  17. package/dist/packages/ui/src/components/dialog.cjs +6 -0
  18. package/dist/packages/ui/src/components/dialog.mjs +6 -1
  19. package/dist/plugins/cms/api/index.d.cts +67 -3
  20. package/dist/plugins/cms/api/index.d.mts +67 -3
  21. package/dist/plugins/cms/api/index.d.ts +67 -3
  22. package/dist/plugins/cms/client/hooks/index.cjs +4 -0
  23. package/dist/plugins/cms/client/hooks/index.d.cts +82 -3
  24. package/dist/plugins/cms/client/hooks/index.d.mts +82 -3
  25. package/dist/plugins/cms/client/hooks/index.d.ts +82 -3
  26. package/dist/plugins/cms/client/hooks/index.mjs +1 -1
  27. package/dist/plugins/cms/query-keys.d.cts +1 -1
  28. package/dist/plugins/cms/query-keys.d.mts +1 -1
  29. package/dist/plugins/cms/query-keys.d.ts +1 -1
  30. package/dist/plugins/form-builder/api/index.d.cts +1 -1
  31. package/dist/plugins/form-builder/api/index.d.mts +1 -1
  32. package/dist/plugins/form-builder/api/index.d.ts +1 -1
  33. package/dist/shared/{stack.L-UFwz2G.d.cts → stack.oGOteE6g.d.cts} +27 -5
  34. package/dist/shared/{stack.L-UFwz2G.d.mts → stack.oGOteE6g.d.mts} +27 -5
  35. package/dist/shared/{stack.L-UFwz2G.d.ts → stack.oGOteE6g.d.ts} +27 -5
  36. package/package.json +1 -1
  37. package/src/plugins/cms/api/plugin.ts +667 -21
  38. package/src/plugins/cms/client/components/forms/content-form.tsx +60 -18
  39. package/src/plugins/cms/client/components/forms/relation-field.tsx +299 -0
  40. package/src/plugins/cms/client/components/inverse-relations-panel.tsx +329 -0
  41. package/src/plugins/cms/client/components/pages/content-editor-page.internal.tsx +127 -1
  42. package/src/plugins/cms/client/hooks/cms-hooks.tsx +344 -0
  43. package/src/plugins/cms/db.ts +38 -0
  44. package/src/plugins/cms/types.ts +99 -10
@@ -97,8 +97,8 @@ declare const formBuilderBackendPlugin: (config?: FormBuilderBackendConfig) => _
97
97
  };
98
98
  submittedAt: string;
99
99
  id: string;
100
- data: string;
101
100
  formId: string;
101
+ data: string;
102
102
  submittedBy?: string | undefined;
103
103
  ipAddress?: string | undefined;
104
104
  userAgent?: string | undefined;
@@ -97,8 +97,8 @@ declare const formBuilderBackendPlugin: (config?: FormBuilderBackendConfig) => _
97
97
  };
98
98
  submittedAt: string;
99
99
  id: string;
100
- data: string;
101
100
  formId: string;
101
+ data: string;
102
102
  submittedBy?: string | undefined;
103
103
  ipAddress?: string | undefined;
104
104
  userAgent?: string | undefined;
@@ -97,8 +97,8 @@ declare const formBuilderBackendPlugin: (config?: FormBuilderBackendConfig) => _
97
97
  };
98
98
  submittedAt: string;
99
99
  id: string;
100
- data: string;
101
100
  formId: string;
101
+ data: string;
102
102
  submittedBy?: string | undefined;
103
103
  ipAddress?: string | undefined;
104
104
  userAgent?: string | undefined;
@@ -58,6 +58,19 @@ type ContentItem = {
58
58
  createdAt: Date;
59
59
  updatedAt: Date;
60
60
  };
61
+ /**
62
+ * Represents an inverse relation (content types that reference this type via belongsTo)
63
+ */
64
+ interface InverseRelation {
65
+ /** The content type slug that has the belongsTo relation */
66
+ sourceType: string;
67
+ /** Display name of the source content type */
68
+ sourceTypeName: string;
69
+ /** The field name that contains the belongsTo relation */
70
+ fieldName: string;
71
+ /** Count of items with this relation (when itemId is provided) */
72
+ count: number;
73
+ }
61
74
  /**
62
75
  * Serialized content type for API responses (dates as strings)
63
76
  */
@@ -81,6 +94,11 @@ interface SerializedContentItemWithType<TData = Record<string, unknown>> extends
81
94
  parsedData: TData;
82
95
  /** Joined content type */
83
96
  contentType?: SerializedContentType;
97
+ /**
98
+ * Populated relation data (only present when using populated endpoints/hooks).
99
+ * Keys are field names, values are arrays of related content items.
100
+ */
101
+ _relations?: Record<string, SerializedContentItemWithType[]>;
84
102
  }
85
103
  /**
86
104
  * Paginated list response for content items
@@ -105,14 +123,18 @@ interface CMSHookContext {
105
123
  }
106
124
  /**
107
125
  * Hooks for customizing CMS backend behavior
126
+ *
127
+ * Note: Before hooks can only deny operations by returning `false`.
128
+ * They cannot modify the data being saved. This ensures consistency
129
+ * between the stored content item data and relation junction tables.
108
130
  */
109
131
  interface CMSBackendHooks {
110
- /** Called before creating a content item */
111
- onBeforeCreate?: (data: Record<string, unknown>, context: CMSHookContext) => Promise<Record<string, unknown> | false> | Record<string, unknown> | false;
132
+ /** Called before creating a content item. Return false to deny the operation. */
133
+ onBeforeCreate?: (data: Record<string, unknown>, context: CMSHookContext) => Promise<false | void> | false | void;
112
134
  /** Called after creating a content item */
113
135
  onAfterCreate?: (item: SerializedContentItem, context: CMSHookContext) => Promise<void> | void;
114
- /** Called before updating a content item */
115
- onBeforeUpdate?: (id: string, data: Record<string, unknown>, context: CMSHookContext) => Promise<Record<string, unknown> | false> | Record<string, unknown> | false;
136
+ /** Called before updating a content item. Return false to deny the operation. */
137
+ onBeforeUpdate?: (id: string, data: Record<string, unknown>, context: CMSHookContext) => Promise<false | void> | false | void;
116
138
  /** Called after updating a content item */
117
139
  onAfterUpdate?: (item: SerializedContentItem, context: CMSHookContext) => Promise<void> | void;
118
140
  /** Called before deleting a content item */
@@ -132,4 +154,4 @@ interface CMSBackendConfig {
132
154
  hooks?: CMSBackendHooks;
133
155
  }
134
156
 
135
- export type { CMSBackendConfig as C, PaginatedContentItems as P, SerializedContentType as S, SerializedContentItemWithType as a };
157
+ export type { CMSBackendConfig as C, InverseRelation as I, PaginatedContentItems as P, SerializedContentType as S, SerializedContentItemWithType as a };
@@ -58,6 +58,19 @@ type ContentItem = {
58
58
  createdAt: Date;
59
59
  updatedAt: Date;
60
60
  };
61
+ /**
62
+ * Represents an inverse relation (content types that reference this type via belongsTo)
63
+ */
64
+ interface InverseRelation {
65
+ /** The content type slug that has the belongsTo relation */
66
+ sourceType: string;
67
+ /** Display name of the source content type */
68
+ sourceTypeName: string;
69
+ /** The field name that contains the belongsTo relation */
70
+ fieldName: string;
71
+ /** Count of items with this relation (when itemId is provided) */
72
+ count: number;
73
+ }
61
74
  /**
62
75
  * Serialized content type for API responses (dates as strings)
63
76
  */
@@ -81,6 +94,11 @@ interface SerializedContentItemWithType<TData = Record<string, unknown>> extends
81
94
  parsedData: TData;
82
95
  /** Joined content type */
83
96
  contentType?: SerializedContentType;
97
+ /**
98
+ * Populated relation data (only present when using populated endpoints/hooks).
99
+ * Keys are field names, values are arrays of related content items.
100
+ */
101
+ _relations?: Record<string, SerializedContentItemWithType[]>;
84
102
  }
85
103
  /**
86
104
  * Paginated list response for content items
@@ -105,14 +123,18 @@ interface CMSHookContext {
105
123
  }
106
124
  /**
107
125
  * Hooks for customizing CMS backend behavior
126
+ *
127
+ * Note: Before hooks can only deny operations by returning `false`.
128
+ * They cannot modify the data being saved. This ensures consistency
129
+ * between the stored content item data and relation junction tables.
108
130
  */
109
131
  interface CMSBackendHooks {
110
- /** Called before creating a content item */
111
- onBeforeCreate?: (data: Record<string, unknown>, context: CMSHookContext) => Promise<Record<string, unknown> | false> | Record<string, unknown> | false;
132
+ /** Called before creating a content item. Return false to deny the operation. */
133
+ onBeforeCreate?: (data: Record<string, unknown>, context: CMSHookContext) => Promise<false | void> | false | void;
112
134
  /** Called after creating a content item */
113
135
  onAfterCreate?: (item: SerializedContentItem, context: CMSHookContext) => Promise<void> | void;
114
- /** Called before updating a content item */
115
- onBeforeUpdate?: (id: string, data: Record<string, unknown>, context: CMSHookContext) => Promise<Record<string, unknown> | false> | Record<string, unknown> | false;
136
+ /** Called before updating a content item. Return false to deny the operation. */
137
+ onBeforeUpdate?: (id: string, data: Record<string, unknown>, context: CMSHookContext) => Promise<false | void> | false | void;
116
138
  /** Called after updating a content item */
117
139
  onAfterUpdate?: (item: SerializedContentItem, context: CMSHookContext) => Promise<void> | void;
118
140
  /** Called before deleting a content item */
@@ -132,4 +154,4 @@ interface CMSBackendConfig {
132
154
  hooks?: CMSBackendHooks;
133
155
  }
134
156
 
135
- export type { CMSBackendConfig as C, PaginatedContentItems as P, SerializedContentType as S, SerializedContentItemWithType as a };
157
+ export type { CMSBackendConfig as C, InverseRelation as I, PaginatedContentItems as P, SerializedContentType as S, SerializedContentItemWithType as a };
@@ -58,6 +58,19 @@ type ContentItem = {
58
58
  createdAt: Date;
59
59
  updatedAt: Date;
60
60
  };
61
+ /**
62
+ * Represents an inverse relation (content types that reference this type via belongsTo)
63
+ */
64
+ interface InverseRelation {
65
+ /** The content type slug that has the belongsTo relation */
66
+ sourceType: string;
67
+ /** Display name of the source content type */
68
+ sourceTypeName: string;
69
+ /** The field name that contains the belongsTo relation */
70
+ fieldName: string;
71
+ /** Count of items with this relation (when itemId is provided) */
72
+ count: number;
73
+ }
61
74
  /**
62
75
  * Serialized content type for API responses (dates as strings)
63
76
  */
@@ -81,6 +94,11 @@ interface SerializedContentItemWithType<TData = Record<string, unknown>> extends
81
94
  parsedData: TData;
82
95
  /** Joined content type */
83
96
  contentType?: SerializedContentType;
97
+ /**
98
+ * Populated relation data (only present when using populated endpoints/hooks).
99
+ * Keys are field names, values are arrays of related content items.
100
+ */
101
+ _relations?: Record<string, SerializedContentItemWithType[]>;
84
102
  }
85
103
  /**
86
104
  * Paginated list response for content items
@@ -105,14 +123,18 @@ interface CMSHookContext {
105
123
  }
106
124
  /**
107
125
  * Hooks for customizing CMS backend behavior
126
+ *
127
+ * Note: Before hooks can only deny operations by returning `false`.
128
+ * They cannot modify the data being saved. This ensures consistency
129
+ * between the stored content item data and relation junction tables.
108
130
  */
109
131
  interface CMSBackendHooks {
110
- /** Called before creating a content item */
111
- onBeforeCreate?: (data: Record<string, unknown>, context: CMSHookContext) => Promise<Record<string, unknown> | false> | Record<string, unknown> | false;
132
+ /** Called before creating a content item. Return false to deny the operation. */
133
+ onBeforeCreate?: (data: Record<string, unknown>, context: CMSHookContext) => Promise<false | void> | false | void;
112
134
  /** Called after creating a content item */
113
135
  onAfterCreate?: (item: SerializedContentItem, context: CMSHookContext) => Promise<void> | void;
114
- /** Called before updating a content item */
115
- onBeforeUpdate?: (id: string, data: Record<string, unknown>, context: CMSHookContext) => Promise<Record<string, unknown> | false> | Record<string, unknown> | false;
136
+ /** Called before updating a content item. Return false to deny the operation. */
137
+ onBeforeUpdate?: (id: string, data: Record<string, unknown>, context: CMSHookContext) => Promise<false | void> | false | void;
116
138
  /** Called after updating a content item */
117
139
  onAfterUpdate?: (item: SerializedContentItem, context: CMSHookContext) => Promise<void> | void;
118
140
  /** Called before deleting a content item */
@@ -132,4 +154,4 @@ interface CMSBackendConfig {
132
154
  hooks?: CMSBackendHooks;
133
155
  }
134
156
 
135
- export type { CMSBackendConfig as C, PaginatedContentItems as P, SerializedContentType as S, SerializedContentItemWithType as a };
157
+ export type { CMSBackendConfig as C, InverseRelation as I, PaginatedContentItems as P, SerializedContentType as S, SerializedContentItemWithType as a };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@btst/stack",
3
- "version": "1.8.0",
3
+ "version": "1.9.0",
4
4
  "description": "A composable, plugin-based library for building full-stack applications.",
5
5
  "repository": {
6
6
  "type": "git",