nextjs-cms 0.5.9 → 0.5.11

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 (258) hide show
  1. package/dist/api/axios/axiosInstance.d.ts +1 -1
  2. package/dist/api/axios/axiosInstance.js +8 -8
  3. package/dist/api/index.d.ts +855 -855
  4. package/dist/api/index.d.ts.map +1 -1
  5. package/dist/api/index.js +12 -12
  6. package/dist/api/lib/serverActions.d.ts +239 -239
  7. package/dist/api/lib/serverActions.d.ts.map +1 -1
  8. package/dist/api/lib/serverActions.js +834 -834
  9. package/dist/api/root.d.ts +828 -828
  10. package/dist/api/root.js +30 -30
  11. package/dist/api/routers/accountSettings.d.ts +60 -60
  12. package/dist/api/routers/accountSettings.js +108 -108
  13. package/dist/api/routers/admins.d.ts +105 -105
  14. package/dist/api/routers/admins.js +219 -219
  15. package/dist/api/routers/auth.d.ts +47 -47
  16. package/dist/api/routers/auth.js +25 -25
  17. package/dist/api/routers/categorySection.d.ts +103 -103
  18. package/dist/api/routers/categorySection.js +38 -38
  19. package/dist/api/routers/cmsSettings.d.ts +48 -48
  20. package/dist/api/routers/cmsSettings.js +51 -51
  21. package/dist/api/routers/cpanel.d.ts +83 -83
  22. package/dist/api/routers/cpanel.js +216 -216
  23. package/dist/api/routers/files.d.ts +47 -47
  24. package/dist/api/routers/files.js +23 -23
  25. package/dist/api/routers/gallery.d.ts +35 -35
  26. package/dist/api/routers/gallery.js +62 -62
  27. package/dist/api/routers/googleAnalytics.d.ts +30 -30
  28. package/dist/api/routers/googleAnalytics.js +7 -7
  29. package/dist/api/routers/hasItemsSection.d.ts +139 -139
  30. package/dist/api/routers/hasItemsSection.js +34 -34
  31. package/dist/api/routers/navigation.d.ts +51 -51
  32. package/dist/api/routers/navigation.js +11 -11
  33. package/dist/api/routers/simpleSection.d.ts +57 -57
  34. package/dist/api/routers/simpleSection.js +12 -12
  35. package/dist/api/trpc.d.ts +106 -106
  36. package/dist/api/trpc.js +72 -72
  37. package/dist/auth/axios/axiosInstance.d.ts +1 -1
  38. package/dist/auth/axios/axiosInstance.js +8 -8
  39. package/dist/auth/csrf.d.ts +29 -29
  40. package/dist/auth/csrf.js +76 -76
  41. package/dist/auth/hooks/index.d.ts +3 -3
  42. package/dist/auth/hooks/index.d.ts.map +1 -1
  43. package/dist/auth/hooks/index.js +3 -3
  44. package/dist/auth/hooks/useAxiosPrivate.d.ts +4 -4
  45. package/dist/auth/hooks/useAxiosPrivate.js +74 -74
  46. package/dist/auth/hooks/useRefreshToken.d.ts +6 -6
  47. package/dist/auth/hooks/useRefreshToken.js +79 -79
  48. package/dist/auth/index.d.ts +22 -22
  49. package/dist/auth/index.js +44 -44
  50. package/dist/auth/jwt.d.ts +5 -5
  51. package/dist/auth/jwt.js +25 -25
  52. package/dist/auth/lib/actions.d.ts +32 -32
  53. package/dist/auth/lib/actions.d.ts.map +1 -1
  54. package/dist/auth/lib/actions.js +209 -209
  55. package/dist/auth/lib/client.d.ts +3 -3
  56. package/dist/auth/lib/client.js +46 -46
  57. package/dist/auth/lib/index.d.ts +2 -2
  58. package/dist/auth/lib/index.d.ts.map +1 -1
  59. package/dist/auth/lib/index.js +2 -2
  60. package/dist/auth/react.d.ts +105 -105
  61. package/dist/auth/react.d.ts.map +1 -1
  62. package/dist/auth/react.js +347 -347
  63. package/dist/auth/trpc.d.ts +5 -5
  64. package/dist/auth/trpc.d.ts.map +1 -1
  65. package/dist/auth/trpc.js +81 -81
  66. package/dist/core/config/config-loader.d.ts +91 -91
  67. package/dist/core/config/config-loader.js +230 -230
  68. package/dist/core/config/index.d.ts +2 -2
  69. package/dist/core/config/index.d.ts.map +1 -1
  70. package/dist/core/config/index.js +1 -1
  71. package/dist/core/config/loader.d.ts +1 -1
  72. package/dist/core/config/loader.js +42 -42
  73. package/dist/core/db/index.d.ts +1 -1
  74. package/dist/core/db/index.d.ts.map +1 -1
  75. package/dist/core/db/index.js +1 -1
  76. package/dist/core/db/table-checker/DbTable.d.ts +5 -5
  77. package/dist/core/db/table-checker/DbTable.js +5 -5
  78. package/dist/core/db/table-checker/MysqlTable.d.ts +33 -33
  79. package/dist/core/db/table-checker/MysqlTable.d.ts.map +1 -1
  80. package/dist/core/db/table-checker/MysqlTable.js +94 -94
  81. package/dist/core/db/table-checker/index.d.ts +1 -1
  82. package/dist/core/db/table-checker/index.d.ts.map +1 -1
  83. package/dist/core/db/table-checker/index.js +1 -1
  84. package/dist/core/factories/FieldFactory.d.ts +123 -123
  85. package/dist/core/factories/FieldFactory.d.ts.map +1 -1
  86. package/dist/core/factories/FieldFactory.js +411 -411
  87. package/dist/core/factories/SectionFactory.d.ts +109 -109
  88. package/dist/core/factories/SectionFactory.d.ts.map +1 -1
  89. package/dist/core/factories/SectionFactory.js +415 -415
  90. package/dist/core/factories/index.d.ts +2 -2
  91. package/dist/core/factories/index.d.ts.map +1 -1
  92. package/dist/core/factories/index.js +2 -2
  93. package/dist/core/fields/checkbox.d.ts +62 -62
  94. package/dist/core/fields/checkbox.d.ts.map +1 -1
  95. package/dist/core/fields/checkbox.js +62 -62
  96. package/dist/core/fields/color.d.ts +83 -83
  97. package/dist/core/fields/color.d.ts.map +1 -1
  98. package/dist/core/fields/color.js +91 -91
  99. package/dist/core/fields/date.d.ts +99 -99
  100. package/dist/core/fields/date.d.ts.map +1 -1
  101. package/dist/core/fields/date.js +108 -108
  102. package/dist/core/fields/document.d.ts +179 -179
  103. package/dist/core/fields/document.d.ts.map +1 -1
  104. package/dist/core/fields/document.js +277 -277
  105. package/dist/core/fields/field-group.d.ts +17 -17
  106. package/dist/core/fields/field-group.d.ts.map +1 -1
  107. package/dist/core/fields/field-group.js +6 -6
  108. package/dist/core/fields/field.d.ts +125 -125
  109. package/dist/core/fields/field.d.ts.map +1 -1
  110. package/dist/core/fields/field.js +148 -148
  111. package/dist/core/fields/fileField.d.ts +14 -14
  112. package/dist/core/fields/fileField.d.ts.map +1 -1
  113. package/dist/core/fields/fileField.js +5 -5
  114. package/dist/core/fields/index.d.ts +64 -64
  115. package/dist/core/fields/index.d.ts.map +1 -1
  116. package/dist/core/fields/index.js +18 -18
  117. package/dist/core/fields/map.d.ts +166 -166
  118. package/dist/core/fields/map.d.ts.map +1 -1
  119. package/dist/core/fields/map.js +152 -152
  120. package/dist/core/fields/number.d.ts +185 -185
  121. package/dist/core/fields/number.d.ts.map +1 -1
  122. package/dist/core/fields/number.js +241 -241
  123. package/dist/core/fields/password.d.ts +108 -108
  124. package/dist/core/fields/password.d.ts.map +1 -1
  125. package/dist/core/fields/password.js +133 -133
  126. package/dist/core/fields/photo.d.ts +288 -288
  127. package/dist/core/fields/photo.d.ts.map +1 -1
  128. package/dist/core/fields/photo.js +410 -410
  129. package/dist/core/fields/richText.d.ts +294 -294
  130. package/dist/core/fields/richText.d.ts.map +1 -1
  131. package/dist/core/fields/richText.js +338 -338
  132. package/dist/core/fields/select.d.ts +365 -365
  133. package/dist/core/fields/select.d.ts.map +1 -1
  134. package/dist/core/fields/select.js +499 -499
  135. package/dist/core/fields/selectMultiple.d.ts +235 -235
  136. package/dist/core/fields/selectMultiple.d.ts.map +1 -1
  137. package/dist/core/fields/selectMultiple.js +417 -417
  138. package/dist/core/fields/tags.d.ts +130 -130
  139. package/dist/core/fields/tags.d.ts.map +1 -1
  140. package/dist/core/fields/tags.js +105 -105
  141. package/dist/core/fields/text.d.ts +135 -135
  142. package/dist/core/fields/text.d.ts.map +1 -1
  143. package/dist/core/fields/text.js +157 -157
  144. package/dist/core/fields/textArea.d.ts +106 -106
  145. package/dist/core/fields/textArea.d.ts.map +1 -1
  146. package/dist/core/fields/textArea.js +126 -126
  147. package/dist/core/fields/video.d.ts +147 -147
  148. package/dist/core/fields/video.d.ts.map +1 -1
  149. package/dist/core/fields/video.js +248 -248
  150. package/dist/core/helpers/entity.d.ts +7 -7
  151. package/dist/core/helpers/entity.js +27 -27
  152. package/dist/core/helpers/index.d.ts +4 -4
  153. package/dist/core/helpers/index.d.ts.map +1 -1
  154. package/dist/core/helpers/index.js +3 -3
  155. package/dist/core/index.d.ts +7 -7
  156. package/dist/core/index.d.ts.map +1 -1
  157. package/dist/core/index.js +7 -7
  158. package/dist/core/sections/category.d.ts +282 -282
  159. package/dist/core/sections/category.d.ts.map +1 -1
  160. package/dist/core/sections/category.js +147 -147
  161. package/dist/core/sections/hasItems.d.ts +631 -631
  162. package/dist/core/sections/hasItems.d.ts.map +1 -1
  163. package/dist/core/sections/hasItems.js +144 -144
  164. package/dist/core/sections/index.d.ts +4 -4
  165. package/dist/core/sections/index.d.ts.map +1 -1
  166. package/dist/core/sections/index.js +4 -4
  167. package/dist/core/sections/section.d.ts +225 -225
  168. package/dist/core/sections/section.d.ts.map +1 -1
  169. package/dist/core/sections/section.js +341 -341
  170. package/dist/core/sections/simple.d.ts +98 -98
  171. package/dist/core/sections/simple.d.ts.map +1 -1
  172. package/dist/core/sections/simple.js +95 -95
  173. package/dist/core/security/dom.d.ts +10 -10
  174. package/dist/core/security/dom.js +92 -92
  175. package/dist/core/submit/ItemEditSubmit.d.ts +75 -75
  176. package/dist/core/submit/ItemEditSubmit.js +186 -186
  177. package/dist/core/submit/NewItemSubmit.d.ts +13 -13
  178. package/dist/core/submit/NewItemSubmit.js +93 -93
  179. package/dist/core/submit/SimpleSectionSubmit.d.ts +12 -12
  180. package/dist/core/submit/SimpleSectionSubmit.js +93 -93
  181. package/dist/core/submit/index.d.ts +4 -4
  182. package/dist/core/submit/index.js +4 -4
  183. package/dist/core/submit/submit.d.ts +115 -115
  184. package/dist/core/submit/submit.js +479 -479
  185. package/dist/core/types/index.d.ts +279 -279
  186. package/dist/core/types/index.d.ts.map +1 -1
  187. package/dist/core/types/index.js +1 -1
  188. package/dist/db/client.d.ts +8 -8
  189. package/dist/db/client.d.ts.map +1 -1
  190. package/dist/db/client.js +19 -19
  191. package/dist/db/config.d.ts +5 -5
  192. package/dist/db/config.js +22 -22
  193. package/dist/db/drizzle.config.d.ts +5 -5
  194. package/dist/db/drizzle.config.js +18 -18
  195. package/dist/db/index.d.ts +2 -2
  196. package/dist/db/index.js +3 -3
  197. package/dist/db/schema.d.ts +638 -638
  198. package/dist/db/schema.js +73 -73
  199. package/dist/index.d.ts +7 -7
  200. package/dist/index.d.ts.map +1 -1
  201. package/dist/index.js +7 -7
  202. package/dist/translations/index.d.ts +2 -2
  203. package/dist/translations/index.js +15 -15
  204. package/dist/utils/CpanelApi.d.ts +24 -24
  205. package/dist/utils/CpanelApi.js +64 -64
  206. package/dist/utils/constants.d.ts +13 -13
  207. package/dist/utils/constants.js +61 -61
  208. package/dist/utils/index.d.ts +4 -4
  209. package/dist/utils/index.d.ts.map +1 -1
  210. package/dist/utils/index.js +4 -4
  211. package/dist/utils/utils.d.ts +59 -59
  212. package/dist/utils/utils.js +132 -132
  213. package/dist/validators/checkbox.d.ts +3 -3
  214. package/dist/validators/checkbox.d.ts.map +1 -1
  215. package/dist/validators/checkbox.js +12 -12
  216. package/dist/validators/color.d.ts +3 -3
  217. package/dist/validators/color.d.ts.map +1 -1
  218. package/dist/validators/color.js +7 -7
  219. package/dist/validators/date.d.ts +3 -3
  220. package/dist/validators/date.d.ts.map +1 -1
  221. package/dist/validators/date.js +5 -5
  222. package/dist/validators/document.d.ts +3 -3
  223. package/dist/validators/document.d.ts.map +1 -1
  224. package/dist/validators/document.js +57 -57
  225. package/dist/validators/index.d.ts +14 -14
  226. package/dist/validators/index.d.ts.map +1 -1
  227. package/dist/validators/index.js +14 -14
  228. package/dist/validators/map.d.ts +3 -3
  229. package/dist/validators/map.d.ts.map +1 -1
  230. package/dist/validators/map.js +5 -5
  231. package/dist/validators/number.d.ts +3 -3
  232. package/dist/validators/number.d.ts.map +1 -1
  233. package/dist/validators/number.js +20 -20
  234. package/dist/validators/password.d.ts +3 -3
  235. package/dist/validators/password.d.ts.map +1 -1
  236. package/dist/validators/password.js +11 -11
  237. package/dist/validators/photo.d.ts +3 -3
  238. package/dist/validators/photo.d.ts.map +1 -1
  239. package/dist/validators/photo.js +100 -100
  240. package/dist/validators/richText.d.ts +3 -3
  241. package/dist/validators/richText.d.ts.map +1 -1
  242. package/dist/validators/richText.js +8 -8
  243. package/dist/validators/select-multiple.d.ts +9 -9
  244. package/dist/validators/select-multiple.d.ts.map +1 -1
  245. package/dist/validators/select-multiple.js +20 -20
  246. package/dist/validators/select.d.ts +3 -3
  247. package/dist/validators/select.d.ts.map +1 -1
  248. package/dist/validators/select.js +5 -5
  249. package/dist/validators/text.d.ts +3 -3
  250. package/dist/validators/text.d.ts.map +1 -1
  251. package/dist/validators/text.js +7 -7
  252. package/dist/validators/textarea.d.ts +3 -3
  253. package/dist/validators/textarea.d.ts.map +1 -1
  254. package/dist/validators/textarea.js +7 -7
  255. package/dist/validators/video.d.ts +3 -3
  256. package/dist/validators/video.d.ts.map +1 -1
  257. package/dist/validators/video.js +57 -57
  258. package/package.json +4 -5
@@ -1,341 +1,341 @@
1
- import { entityKind } from "../helpers.js";
2
- import { numberField } from "../fields.js";
3
- import chalk from 'chalk';
4
- import * as z from 'zod';
5
- import { getCMSConfig } from "../config/config-loader.js";
6
- const cmsConfig = getCMSConfig();
7
- export const fieldConfigSchema = z.custom();
8
- export const FieldGroupConfigSchema = z.custom();
9
- const variantSchema = z.custom();
10
- const hooksSchema = z.custom();
11
- export const baseSectionOptionsSchema = z.strictObject({
12
- name: z.string().describe('The name of the section'),
13
- order: z.number(),
14
- icon: z.string().optional(),
15
- readonly: z.boolean().default(false).optional(),
16
- gallery: z
17
- .strictObject({
18
- db: z.strictObject({
19
- tableName: z.string(),
20
- identifierField: z.string().optional(),
21
- photoNameField: z.string().optional(),
22
- metaField: z.string().optional(),
23
- }),
24
- watermark: z.boolean().optional(),
25
- thumbnail: z
26
- .strictObject({
27
- width: z.number(),
28
- height: z.number(),
29
- crop: z.boolean(),
30
- quality: z.number(),
31
- })
32
- .optional(),
33
- })
34
- .optional(),
35
- db: z.strictObject({
36
- table: z.string(),
37
- identifier: fieldConfigSchema.optional(),
38
- orderByField: fieldConfigSchema.optional(),
39
- primaryKey: z.array(fieldConfigSchema).optional(),
40
- foreignKeys: z
41
- .array(z.strictObject({
42
- columns: z.array(fieldConfigSchema),
43
- foreignColumns: z.array(fieldConfigSchema),
44
- name: z.string(),
45
- }))
46
- .optional(),
47
- index: z
48
- .array(z.strictObject({
49
- columns: z.array(fieldConfigSchema),
50
- name: z.string().optional(),
51
- }))
52
- .optional(),
53
- unique: z
54
- .array(z.strictObject({
55
- columns: z.array(fieldConfigSchema),
56
- name: z.string().optional(),
57
- }))
58
- .optional(),
59
- fulltext: z
60
- .array(z.strictObject({
61
- columns: z.array(fieldConfigSchema),
62
- name: z.string().optional(),
63
- }))
64
- .optional(),
65
- }),
66
- fields: z.array(fieldConfigSchema),
67
- fieldGroups: z.array(FieldGroupConfigSchema).optional(),
68
- variants: z.array(variantSchema).optional(),
69
- hooks: hooksSchema.optional(),
70
- });
71
- /**
72
- * This is the options schema for the helper functions that create section configs
73
- * We omit the fields and fieldGroups properties from the baseSectionOptionsSchema
74
- * and change the fields to be an array of field configs or field group configs
75
- */
76
- export const baseHelperFunctionOptionsSchema = z.strictObject({
77
- ...baseSectionOptionsSchema.omit({ fields: true, fieldGroups: true }).shape,
78
- fields: z
79
- .array(fieldConfigSchema)
80
- .min(1)
81
- .describe('The fields of the section')
82
- .or(z
83
- .array(FieldGroupConfigSchema)
84
- .min(1)
85
- .describe('The field groups of the section')
86
- .describe('The fields or field groups of the section')),
87
- });
88
- export function validateSectionConfig(config) {
89
- const result = baseSectionOptionsSchema.safeParse(config);
90
- if (!result.success) {
91
- throw new Error(result.error.message);
92
- }
93
- }
94
- export class Section {
95
- static [entityKind] = 'Section';
96
- name;
97
- order;
98
- icon;
99
- readonly = false;
100
- gallery;
101
- _fields = undefined;
102
- _fieldGroupConfigs = undefined;
103
- _hasFieldGroups;
104
- _fieldGroups = undefined;
105
- _fieldConfigs;
106
- /**
107
- * A helper property to access the field configs.
108
- * Sometimes it's handy to access the field configs without building the actual fields array.
109
- */
110
- get fieldConfigs() {
111
- return this._fieldConfigs ?? [];
112
- }
113
- get fieldGroups() {
114
- return this._fieldGroups ?? [];
115
- }
116
- get fields() {
117
- if (this._fields === undefined) {
118
- const errorMessage = `Fields are not yer built for section "${this.name}". Please run buildFields() before accessing the fields property.`;
119
- const reportMessage = 'If this is a system bug, please open a bug report on GitHub.';
120
- console.error('\n');
121
- console.error(chalk.bold.red('[Section Error]', errorMessage));
122
- console.error(chalk.bold.bgRed(reportMessage));
123
- console.error('\n');
124
- throw new Error(errorMessage);
125
- }
126
- return this._fields;
127
- }
128
- set fields(value) {
129
- this._fields = value;
130
- }
131
- db;
132
- variants;
133
- hooks;
134
- constructor(config) {
135
- // this.id = config.id
136
- this.name = config.name;
137
- this.order = config.order;
138
- this.icon = config.icon;
139
- this.readonly = config.readonly ?? false;
140
- /**
141
- * Resolve gallery config
142
- */
143
- if (config.gallery) {
144
- this.gallery = {
145
- db: {
146
- tableName: config.gallery.db.tableName,
147
- referenceIdentifierField: config.gallery.db.identifierField ?? 'reference_id',
148
- photoNameField: config.gallery.db.photoNameField ?? 'photo',
149
- metaField: config.gallery.db.metaField ?? 'meta',
150
- },
151
- watermark: config.gallery.watermark ?? cmsConfig.files.images.watermark,
152
- thumbnail: config.gallery.thumbnail ?? cmsConfig.files.images.thumbnail,
153
- };
154
- }
155
- /**
156
- * Check for db identifier field config
157
- */
158
- if (!config.db.identifier) {
159
- // Create default id field config
160
- const idFieldConfig = numberField({
161
- name: 'id',
162
- label: 'ID',
163
- required: true,
164
- hasAutoIncrement: true,
165
- order: 0,
166
- });
167
- config.db.identifier = idFieldConfig;
168
- config.fields.unshift(idFieldConfig);
169
- }
170
- else {
171
- /**
172
- * Make sure the identifier field config is a number or text field config
173
- */
174
- if (config.db.identifier.type !== 'number' && config.db.identifier.type !== 'text') {
175
- const message = `[Section: ${this.name}]: DB identifier field config must be a number or text field. Got type: ${config.db.identifier.type}`;
176
- console.error(chalk.red.bold(message));
177
- console.error(chalk.yellow('Please make sure the identifier field config is a number or text field.'));
178
- throw new Error(message);
179
- }
180
- }
181
- /**
182
- * Resolve db configuration fields
183
- * If user doesn't specify primaryKey, default to identifier field
184
- */
185
- this.db = {
186
- table: config.db.table,
187
- identifier: config.db.identifier,
188
- orderByField: config.db.orderByField,
189
- primaryKey: config.db.primaryKey ?? [config.db.identifier],
190
- foreignKeys: config.db.foreignKeys,
191
- fulltext: config.db.fulltext,
192
- index: config.db.index,
193
- unique: config.db.unique ?? [],
194
- };
195
- /**
196
- * Add the identifier field to the unique array if it's not already there
197
- */
198
- if (!this.db.unique.some((unique) => unique.columns.includes(this.db.identifier))) {
199
- /**
200
- * Add the identifier field as the first item in the unique array
201
- */
202
- this.db.unique.unshift({ columns: [this.db.identifier] });
203
- }
204
- this._fieldConfigs = config.fields;
205
- this._fieldGroupConfigs = config.fieldGroups;
206
- // Cache the hasFieldGroups check once during construction (immutable after this point)
207
- this._hasFieldGroups = (this._fieldGroupConfigs?.length ?? 0) > 0;
208
- this.variants = config.variants;
209
- this.hooks = config.hooks;
210
- }
211
- /**
212
- * Returns whether this section has field groups.
213
- * Value is cached during construction for optimal performance.
214
- */
215
- get hasFieldGroups() {
216
- return this._hasFieldGroups;
217
- }
218
- buildFieldGroups() {
219
- const configs = this._fieldGroupConfigs;
220
- if (!configs?.length)
221
- return;
222
- const fieldGroups = [];
223
- const fields = [];
224
- configs.forEach((groupConfig, index) => {
225
- const fields = groupConfig.fields.map((fieldConfig) => this.resolveField(fieldConfig));
226
- fieldGroups.push({
227
- id: index + 1,
228
- title: groupConfig.title,
229
- order: groupConfig.order,
230
- fields,
231
- });
232
- fields.push(...fields);
233
- });
234
- this._fieldGroups = fieldGroups;
235
- this._fields = fields;
236
- }
237
- buildFields() {
238
- if (this.hasFieldGroups) {
239
- this.buildFieldGroups();
240
- return;
241
- }
242
- if (this._fieldConfigs === undefined) {
243
- throw new Error(`This section: (${this.name}) has no fields. Please set at least one field.`);
244
- }
245
- this._fields = this._fieldConfigs.map((input) => this.resolveField(input));
246
- /**
247
- * Create one group to hold all the fields
248
- */
249
- this._fieldGroups = [
250
- {
251
- id: 1,
252
- title: '',
253
- order: 1,
254
- fields: this._fields,
255
- },
256
- ];
257
- }
258
- /**
259
- * Helper function to resolve a field config to an instance
260
- * by calling the build() method on the config
261
- * @param config - The field config to resolve
262
- * @returns The field instance
263
- * @throws An error if the field config does not have a build() method
264
- */
265
- resolveField(config) {
266
- // Config must have a build() method
267
- if (typeof config.build === 'function') {
268
- return config.build();
269
- }
270
- throw new Error(`[Section: ${this.name}]: Field "${config.name}" config must have a build() method. Use helper functions like textField(), numberField(), etc. to create field configs.`);
271
- }
272
- }
273
- /**
274
- * Helper function to ensure a section config has a db identifier field
275
- * If db.identifier is missing, creates a default 'id' number field config
276
- * and prepends it to fields and sets it as db.identifier
277
- *
278
- * @param section - Section config that may or may not have db.identifier
279
- * @returns Section config with db.identifier guaranteed to exist
280
- */
281
- export function ensureSectionDbIdentifier(section) {
282
- // If identifier already exists, return as-is
283
- if (section.db.identifier) {
284
- return section;
285
- }
286
- // Create default id field config
287
- const idFieldConfig = numberField({
288
- name: 'id',
289
- label: 'ID',
290
- required: true,
291
- hasAutoIncrement: true,
292
- order: 0,
293
- });
294
- // Return modified config with identifier
295
- return {
296
- ...section,
297
- fields: [idFieldConfig, ...section.fields],
298
- db: {
299
- ...section.db,
300
- identifier: idFieldConfig,
301
- },
302
- };
303
- }
304
- /**
305
- * Helper function to normalize gallery config with default values
306
- * Sets defaults for identifierField, photoNameField, and metaField if not provided
307
- *
308
- * @param section - Section config that may or may not have gallery config
309
- * @returns Section config with normalized gallery config
310
- */
311
- export function ensureSectionGallery(section) {
312
- // If no gallery config, return as-is
313
- if (!section.gallery) {
314
- return section;
315
- }
316
- // Return config with normalized gallery
317
- return {
318
- ...section,
319
- gallery: {
320
- ...section.gallery,
321
- db: {
322
- tableName: section.gallery.db.tableName,
323
- identifierField: section.gallery.db.identifierField ?? 'reference_id',
324
- photoNameField: section.gallery.db.photoNameField ?? 'photo',
325
- metaField: section.gallery.db.metaField ?? 'meta',
326
- },
327
- },
328
- };
329
- }
330
- export function resolveFieldsAndFieldGroups(config) {
331
- if (config.fields.length) {
332
- return {
333
- fields: config.fields,
334
- fieldGroups: [],
335
- };
336
- }
337
- return {
338
- fields: config.fieldGroups.flatMap((group) => group.fields),
339
- fieldGroups: config.fieldGroups,
340
- };
341
- }
1
+ import { entityKind } from '../helpers/index.js';
2
+ import { numberField } from '../fields/index.js';
3
+ import chalk from 'chalk';
4
+ import * as z from 'zod';
5
+ import { getCMSConfig } from '../config/config-loader.js';
6
+ const cmsConfig = getCMSConfig();
7
+ export const fieldConfigSchema = z.custom();
8
+ export const FieldGroupConfigSchema = z.custom();
9
+ const variantSchema = z.custom();
10
+ const hooksSchema = z.custom();
11
+ export const baseSectionOptionsSchema = z.strictObject({
12
+ name: z.string().describe('The name of the section'),
13
+ order: z.number(),
14
+ icon: z.string().optional(),
15
+ readonly: z.boolean().default(false).optional(),
16
+ gallery: z
17
+ .strictObject({
18
+ db: z.strictObject({
19
+ tableName: z.string(),
20
+ identifierField: z.string().optional(),
21
+ photoNameField: z.string().optional(),
22
+ metaField: z.string().optional(),
23
+ }),
24
+ watermark: z.boolean().optional(),
25
+ thumbnail: z
26
+ .strictObject({
27
+ width: z.number(),
28
+ height: z.number(),
29
+ crop: z.boolean(),
30
+ quality: z.number(),
31
+ })
32
+ .optional(),
33
+ })
34
+ .optional(),
35
+ db: z.strictObject({
36
+ table: z.string(),
37
+ identifier: fieldConfigSchema.optional(),
38
+ orderByField: fieldConfigSchema.optional(),
39
+ primaryKey: z.array(fieldConfigSchema).optional(),
40
+ foreignKeys: z
41
+ .array(z.strictObject({
42
+ columns: z.array(fieldConfigSchema),
43
+ foreignColumns: z.array(fieldConfigSchema),
44
+ name: z.string(),
45
+ }))
46
+ .optional(),
47
+ index: z
48
+ .array(z.strictObject({
49
+ columns: z.array(fieldConfigSchema),
50
+ name: z.string().optional(),
51
+ }))
52
+ .optional(),
53
+ unique: z
54
+ .array(z.strictObject({
55
+ columns: z.array(fieldConfigSchema),
56
+ name: z.string().optional(),
57
+ }))
58
+ .optional(),
59
+ fulltext: z
60
+ .array(z.strictObject({
61
+ columns: z.array(fieldConfigSchema),
62
+ name: z.string().optional(),
63
+ }))
64
+ .optional(),
65
+ }),
66
+ fields: z.array(fieldConfigSchema),
67
+ fieldGroups: z.array(FieldGroupConfigSchema).optional(),
68
+ variants: z.array(variantSchema).optional(),
69
+ hooks: hooksSchema.optional(),
70
+ });
71
+ /**
72
+ * This is the options schema for the helper functions that create section configs
73
+ * We omit the fields and fieldGroups properties from the baseSectionOptionsSchema
74
+ * and change the fields to be an array of field configs or field group configs
75
+ */
76
+ export const baseHelperFunctionOptionsSchema = z.strictObject({
77
+ ...baseSectionOptionsSchema.omit({ fields: true, fieldGroups: true }).shape,
78
+ fields: z
79
+ .array(fieldConfigSchema)
80
+ .min(1)
81
+ .describe('The fields of the section')
82
+ .or(z
83
+ .array(FieldGroupConfigSchema)
84
+ .min(1)
85
+ .describe('The field groups of the section')
86
+ .describe('The fields or field groups of the section')),
87
+ });
88
+ export function validateSectionConfig(config) {
89
+ const result = baseSectionOptionsSchema.safeParse(config);
90
+ if (!result.success) {
91
+ throw new Error(result.error.message);
92
+ }
93
+ }
94
+ export class Section {
95
+ static [entityKind] = 'Section';
96
+ name;
97
+ order;
98
+ icon;
99
+ readonly = false;
100
+ gallery;
101
+ _fields = undefined;
102
+ _fieldGroupConfigs = undefined;
103
+ _hasFieldGroups;
104
+ _fieldGroups = undefined;
105
+ _fieldConfigs;
106
+ /**
107
+ * A helper property to access the field configs.
108
+ * Sometimes it's handy to access the field configs without building the actual fields array.
109
+ */
110
+ get fieldConfigs() {
111
+ return this._fieldConfigs ?? [];
112
+ }
113
+ get fieldGroups() {
114
+ return this._fieldGroups ?? [];
115
+ }
116
+ get fields() {
117
+ if (this._fields === undefined) {
118
+ const errorMessage = `Fields are not yer built for section "${this.name}". Please run buildFields() before accessing the fields property.`;
119
+ const reportMessage = 'If this is a system bug, please open a bug report on GitHub.';
120
+ console.error('\n');
121
+ console.error(chalk.bold.red('[Section Error]', errorMessage));
122
+ console.error(chalk.bold.bgRed(reportMessage));
123
+ console.error('\n');
124
+ throw new Error(errorMessage);
125
+ }
126
+ return this._fields;
127
+ }
128
+ set fields(value) {
129
+ this._fields = value;
130
+ }
131
+ db;
132
+ variants;
133
+ hooks;
134
+ constructor(config) {
135
+ // this.id = config.id
136
+ this.name = config.name;
137
+ this.order = config.order;
138
+ this.icon = config.icon;
139
+ this.readonly = config.readonly ?? false;
140
+ /**
141
+ * Resolve gallery config
142
+ */
143
+ if (config.gallery) {
144
+ this.gallery = {
145
+ db: {
146
+ tableName: config.gallery.db.tableName,
147
+ referenceIdentifierField: config.gallery.db.identifierField ?? 'reference_id',
148
+ photoNameField: config.gallery.db.photoNameField ?? 'photo',
149
+ metaField: config.gallery.db.metaField ?? 'meta',
150
+ },
151
+ watermark: config.gallery.watermark ?? cmsConfig.files.images.watermark,
152
+ thumbnail: config.gallery.thumbnail ?? cmsConfig.files.images.thumbnail,
153
+ };
154
+ }
155
+ /**
156
+ * Check for db identifier field config
157
+ */
158
+ if (!config.db.identifier) {
159
+ // Create default id field config
160
+ const idFieldConfig = numberField({
161
+ name: 'id',
162
+ label: 'ID',
163
+ required: true,
164
+ hasAutoIncrement: true,
165
+ order: 0,
166
+ });
167
+ config.db.identifier = idFieldConfig;
168
+ config.fields.unshift(idFieldConfig);
169
+ }
170
+ else {
171
+ /**
172
+ * Make sure the identifier field config is a number or text field config
173
+ */
174
+ if (config.db.identifier.type !== 'number' && config.db.identifier.type !== 'text') {
175
+ const message = `[Section: ${this.name}]: DB identifier field config must be a number or text field. Got type: ${config.db.identifier.type}`;
176
+ console.error(chalk.red.bold(message));
177
+ console.error(chalk.yellow('Please make sure the identifier field config is a number or text field.'));
178
+ throw new Error(message);
179
+ }
180
+ }
181
+ /**
182
+ * Resolve db configuration fields
183
+ * If user doesn't specify primaryKey, default to identifier field
184
+ */
185
+ this.db = {
186
+ table: config.db.table,
187
+ identifier: config.db.identifier,
188
+ orderByField: config.db.orderByField,
189
+ primaryKey: config.db.primaryKey ?? [config.db.identifier],
190
+ foreignKeys: config.db.foreignKeys,
191
+ fulltext: config.db.fulltext,
192
+ index: config.db.index,
193
+ unique: config.db.unique ?? [],
194
+ };
195
+ /**
196
+ * Add the identifier field to the unique array if it's not already there
197
+ */
198
+ if (!this.db.unique.some((unique) => unique.columns.includes(this.db.identifier))) {
199
+ /**
200
+ * Add the identifier field as the first item in the unique array
201
+ */
202
+ this.db.unique.unshift({ columns: [this.db.identifier] });
203
+ }
204
+ this._fieldConfigs = config.fields;
205
+ this._fieldGroupConfigs = config.fieldGroups;
206
+ // Cache the hasFieldGroups check once during construction (immutable after this point)
207
+ this._hasFieldGroups = (this._fieldGroupConfigs?.length ?? 0) > 0;
208
+ this.variants = config.variants;
209
+ this.hooks = config.hooks;
210
+ }
211
+ /**
212
+ * Returns whether this section has field groups.
213
+ * Value is cached during construction for optimal performance.
214
+ */
215
+ get hasFieldGroups() {
216
+ return this._hasFieldGroups;
217
+ }
218
+ buildFieldGroups() {
219
+ const configs = this._fieldGroupConfigs;
220
+ if (!configs?.length)
221
+ return;
222
+ const fieldGroups = [];
223
+ const fields = [];
224
+ configs.forEach((groupConfig, index) => {
225
+ const fields = groupConfig.fields.map((fieldConfig) => this.resolveField(fieldConfig));
226
+ fieldGroups.push({
227
+ id: index + 1,
228
+ title: groupConfig.title,
229
+ order: groupConfig.order,
230
+ fields,
231
+ });
232
+ fields.push(...fields);
233
+ });
234
+ this._fieldGroups = fieldGroups;
235
+ this._fields = fields;
236
+ }
237
+ buildFields() {
238
+ if (this.hasFieldGroups) {
239
+ this.buildFieldGroups();
240
+ return;
241
+ }
242
+ if (this._fieldConfigs === undefined) {
243
+ throw new Error(`This section: (${this.name}) has no fields. Please set at least one field.`);
244
+ }
245
+ this._fields = this._fieldConfigs.map((input) => this.resolveField(input));
246
+ /**
247
+ * Create one group to hold all the fields
248
+ */
249
+ this._fieldGroups = [
250
+ {
251
+ id: 1,
252
+ title: '',
253
+ order: 1,
254
+ fields: this._fields,
255
+ },
256
+ ];
257
+ }
258
+ /**
259
+ * Helper function to resolve a field config to an instance
260
+ * by calling the build() method on the config
261
+ * @param config - The field config to resolve
262
+ * @returns The field instance
263
+ * @throws An error if the field config does not have a build() method
264
+ */
265
+ resolveField(config) {
266
+ // Config must have a build() method
267
+ if (typeof config.build === 'function') {
268
+ return config.build();
269
+ }
270
+ throw new Error(`[Section: ${this.name}]: Field "${config.name}" config must have a build() method. Use helper functions like textField(), numberField(), etc. to create field configs.`);
271
+ }
272
+ }
273
+ /**
274
+ * Helper function to ensure a section config has a db identifier field
275
+ * If db.identifier is missing, creates a default 'id' number field config
276
+ * and prepends it to fields and sets it as db.identifier
277
+ *
278
+ * @param section - Section config that may or may not have db.identifier
279
+ * @returns Section config with db.identifier guaranteed to exist
280
+ */
281
+ export function ensureSectionDbIdentifier(section) {
282
+ // If identifier already exists, return as-is
283
+ if (section.db.identifier) {
284
+ return section;
285
+ }
286
+ // Create default id field config
287
+ const idFieldConfig = numberField({
288
+ name: 'id',
289
+ label: 'ID',
290
+ required: true,
291
+ hasAutoIncrement: true,
292
+ order: 0,
293
+ });
294
+ // Return modified config with identifier
295
+ return {
296
+ ...section,
297
+ fields: [idFieldConfig, ...section.fields],
298
+ db: {
299
+ ...section.db,
300
+ identifier: idFieldConfig,
301
+ },
302
+ };
303
+ }
304
+ /**
305
+ * Helper function to normalize gallery config with default values
306
+ * Sets defaults for identifierField, photoNameField, and metaField if not provided
307
+ *
308
+ * @param section - Section config that may or may not have gallery config
309
+ * @returns Section config with normalized gallery config
310
+ */
311
+ export function ensureSectionGallery(section) {
312
+ // If no gallery config, return as-is
313
+ if (!section.gallery) {
314
+ return section;
315
+ }
316
+ // Return config with normalized gallery
317
+ return {
318
+ ...section,
319
+ gallery: {
320
+ ...section.gallery,
321
+ db: {
322
+ tableName: section.gallery.db.tableName,
323
+ identifierField: section.gallery.db.identifierField ?? 'reference_id',
324
+ photoNameField: section.gallery.db.photoNameField ?? 'photo',
325
+ metaField: section.gallery.db.metaField ?? 'meta',
326
+ },
327
+ },
328
+ };
329
+ }
330
+ export function resolveFieldsAndFieldGroups(config) {
331
+ if (config.fields.length) {
332
+ return {
333
+ fields: config.fields,
334
+ fieldGroups: [],
335
+ };
336
+ }
337
+ return {
338
+ fields: config.fieldGroups.flatMap((group) => group.fields),
339
+ fieldGroups: config.fieldGroups,
340
+ };
341
+ }