nextjs-cms 0.5.9 → 0.5.10

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 +2 -3
@@ -1,277 +1,277 @@
1
- import { baseFieldConfigSchema } from "./field.js";
2
- import { entityKind } from "../helpers.js";
3
- import * as z from 'zod';
4
- import fs from 'fs';
5
- import { customAlphabet } from 'nanoid';
6
- import path from 'path';
7
- import { FileField } from "./fileField.js";
8
- import { getCMSConfig } from "../config.js";
9
- const maxFileSizeSchema = z.strictObject({
10
- size: z.number().describe('Maximum file size'),
11
- unit: z.enum(['kb', 'mb']).describe('Size unit'),
12
- });
13
- const configSchema = z.strictObject({
14
- /**
15
- * Maximum file size
16
- * @example
17
- * maxFileSize: {
18
- * size: 512,
19
- * unit: 'kb',
20
- * }
21
- */
22
- maxFileSize: maxFileSizeSchema.optional(),
23
- /**
24
- * Allowed document types
25
- * @example
26
- * type: ['pdf', 'doc', 'docx']
27
- * @default ['pdf']
28
- */
29
- type: z.array(z.enum(['pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'csv'])).optional(),
30
- });
31
- export class DocumentField extends FileField {
32
- static [entityKind] = 'DocumentField';
33
- maxFileSize;
34
- mimeType;
35
- extensions;
36
- possibleExtensions = ['pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'csv'];
37
- /**
38
- * _file is the file object if it's present
39
- * Whereas the value is the path to the file
40
- */
41
- _file;
42
- _buffer;
43
- _folder;
44
- _allowedExtensions;
45
- uploadsFolder = getCMSConfig().files.upload.uploadPath;
46
- constructor(config, file) {
47
- super(config, 'document');
48
- if (file) {
49
- this._file = file;
50
- }
51
- this.maxFileSize = config.maxFileSize ?? { size: 2, unit: 'mb' };
52
- /**
53
- * Check if the config type is valid
54
- */
55
- if (config.type && config.type.some((type) => !this.possibleExtensions.includes(type))) {
56
- throw new Error(`Invalid document type provided: ${config.type.join(', ')}, allowed types are: ${this.possibleExtensions.join(', ')}`);
57
- }
58
- this.extensions = config.type ?? ['pdf'];
59
- /**
60
- * Extract the mime types from the extensions
61
- * @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types
62
- */
63
- this.mimeType = this.extensions.map((e) => {
64
- switch (e) {
65
- case 'pdf':
66
- return 'application/pdf';
67
- case 'doc':
68
- return 'application/msword';
69
- case 'docx':
70
- return 'application/vnd.openxmlformats-officedocument.wordprocessingml.document';
71
- case 'xls':
72
- return 'application/vnd.ms-excel';
73
- case 'xlsx':
74
- return 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
75
- case 'ppt':
76
- return 'application/vnd.ms-powerpoint';
77
- case 'pptx':
78
- return 'application/vnd.openxmlformats-officedocument.presentationml.presentation';
79
- case 'txt':
80
- return 'text/plain';
81
- case 'csv':
82
- return 'text/csv';
83
- default:
84
- throw new Error(`Invalid image extension provided: ${e}`);
85
- }
86
- });
87
- /**
88
- * Set the allowed extensions, add jpg if jpeg is present
89
- */
90
- this._allowedExtensions = this.extensions;
91
- }
92
- exportForClient() {
93
- return {
94
- ...super.exportForClient(),
95
- maxFileSize: this.maxFileSize,
96
- extensions: this._allowedExtensions,
97
- mimeType: this.mimeType,
98
- };
99
- }
100
- async readChunkFromFile({ arrayBuffer, length, startPosition = 0, }) {
101
- return new Promise(async (resolve, reject) => {
102
- try {
103
- if (arrayBuffer) {
104
- const buffer = new Uint8Array(arrayBuffer, startPosition, length);
105
- resolve(buffer);
106
- }
107
- else {
108
- reject(new Error('Error reading file'));
109
- }
110
- }
111
- catch (error) {
112
- reject(new Error('Error reading file'));
113
- }
114
- });
115
- }
116
- /**
117
- * Write the file to the disk
118
- */
119
- async writeToFile() {
120
- if (!this._folder) {
121
- throw new Error(`${this.label}: Folder is not set. Make sure to set the folder by call postSubmit() before writing the file to disk`);
122
- }
123
- if (!this._buffer) {
124
- throw new Error(`${this.label}: Buffer is not set. Make sure to call prepareForSubmission() before writing the file to disk`);
125
- }
126
- try {
127
- /**
128
- * If .documents, and 'sectionName' folders don't exist, create them
129
- */
130
- const documentsFolder = path.join(this.uploadsFolder, '.documents', this._folder);
131
- if (!fs.existsSync(documentsFolder)) {
132
- fs.mkdirSync(documentsFolder, { recursive: true });
133
- }
134
- /**
135
- * Write the file to disk
136
- */
137
- await fs.promises.writeFile(path.join(this.uploadsFolder, '.documents', this._folder, this.value), this._buffer);
138
- }
139
- catch (error) {
140
- throw new Error(`${this.label}: Error writing file to disk ${error.message}`);
141
- }
142
- }
143
- async postSubmit(folder) {
144
- if (!this._file)
145
- return;
146
- this._folder = folder;
147
- await this.writeToFile();
148
- }
149
- async postSubmitRollback() {
150
- if (!this._file)
151
- return;
152
- if (!this._folder) {
153
- throw new Error(`${this.label}: Folder is not set. Make sure to set the folder before writing the file to disk`);
154
- }
155
- try {
156
- const pathToFile = path.join(this.uploadsFolder, '.documents', this._folder, this.value);
157
- await fs.promises.unlink(pathToFile);
158
- }
159
- catch (error) {
160
- throw new Error(`${this.label}: Error deleting file from disk`);
161
- }
162
- }
163
- /**
164
- * Get the value of the field
165
- */
166
- getValue() {
167
- return this.value;
168
- }
169
- setFileName(value) {
170
- this.value = value;
171
- }
172
- setValue(value) {
173
- if (typeof value === 'string') {
174
- this.setFileName(value);
175
- return;
176
- }
177
- this.setFile(value);
178
- }
179
- setFile(file) {
180
- if (!file || file.size === 0 || file.name?.trim() === '')
181
- return;
182
- this._file = file;
183
- }
184
- checkRequired() {
185
- /**
186
- * Check if the field is required
187
- * If it is, check if the file is present
188
- * If it's not, throw an error
189
- * Note: Those values are coming from the browser (not safe)
190
- */
191
- if (!this.required)
192
- return;
193
- if (!this._file || !this._file?.type || !this._file?.name || !this._file?.size) {
194
- throw new Error(`Field ${this.label} is required`);
195
- }
196
- }
197
- /**
198
- * Prepare the field for submission
199
- */
200
- async prepareForSubmission() {
201
- if (!this._file)
202
- return;
203
- /**
204
- * Check the actual file size
205
- */
206
- const arrayBuffer = await this._file.arrayBuffer();
207
- this._buffer = Buffer.from(arrayBuffer);
208
- if (!this._buffer.length) {
209
- throw new Error(`Field ${this.label} is required`);
210
- }
211
- /**
212
- * Check extension
213
- */
214
- const ext = this._file.name.split('.').pop();
215
- if (!ext || !this.extensions.includes(ext)) {
216
- throw new Error(`${this.label}: Invalid file type or extension. Allowed extensions: ${this.extensions.join(', ')}`);
217
- }
218
- /**
219
- * Read the first 4100 bytes of the file
220
- */
221
- const chunkBuffer = await this.readChunkFromFile({ arrayBuffer, length: 4100 });
222
- /**
223
- * Get the file type from the buffer
224
- */
225
- const { fileTypeFromBuffer } = await import('file-type');
226
- const fileType = await fileTypeFromBuffer(chunkBuffer);
227
- /**
228
- * If the file type is invalid, return an error
229
- */
230
- if (!fileType) {
231
- throw new Error(`${this.label}: Invalid file type`);
232
- }
233
- /**
234
- * Don't just trust the file extension
235
- * Check the `fileType.ext` against the allowed extensions
236
- */
237
- if (!fileType.ext || !this.extensions.includes(fileType.ext)) {
238
- throw new Error(`${this.label}: Invalid file type or extension. Allowed extensions: ${this.extensions.join(', ')}`);
239
- }
240
- /**
241
- * Generate a random name for the file
242
- */
243
- this.value = customAlphabet('1234567890abcdef', 21)();
244
- }
245
- }
246
- const optionsSchema = z.strictObject({
247
- ...baseFieldConfigSchema.shape,
248
- ...configSchema.shape,
249
- });
250
- const documentFieldConfigSchema = z.strictObject({
251
- ...optionsSchema.shape,
252
- type: z.literal('document').describe('The type of the field'),
253
- build: z.function().output(z.instanceof(DocumentField)).describe('Build a DocumentField instance from this config'),
254
- });
255
- /**
256
- * Helper function to create a document field configuration
257
- * Returns a config object with a build() method that can be serialized and used anywhere
258
- * @param field
259
- */
260
- export function documentField(field) {
261
- /**
262
- * Validate the field config
263
- */
264
- const result = optionsSchema.safeParse(field);
265
- if (!result.success) {
266
- throw new Error(`[Field: ${field.name}]: ${z.prettifyError(result.error)}`);
267
- }
268
- const config = {
269
- ...field,
270
- type: 'document',
271
- build() {
272
- // Use the original field config directly (it doesn't have build() method)
273
- return new DocumentField(field);
274
- },
275
- };
276
- return config;
277
- }
1
+ import { baseFieldConfigSchema } from './field.js';
2
+ import { entityKind } from '../helpers/index.js';
3
+ import * as z from 'zod';
4
+ import fs from 'fs';
5
+ import { customAlphabet } from 'nanoid';
6
+ import path from 'path';
7
+ import { FileField } from './fileField.js';
8
+ import { getCMSConfig } from '../config/index.js';
9
+ const maxFileSizeSchema = z.strictObject({
10
+ size: z.number().describe('Maximum file size'),
11
+ unit: z.enum(['kb', 'mb']).describe('Size unit'),
12
+ });
13
+ const configSchema = z.strictObject({
14
+ /**
15
+ * Maximum file size
16
+ * @example
17
+ * maxFileSize: {
18
+ * size: 512,
19
+ * unit: 'kb',
20
+ * }
21
+ */
22
+ maxFileSize: maxFileSizeSchema.optional(),
23
+ /**
24
+ * Allowed document types
25
+ * @example
26
+ * type: ['pdf', 'doc', 'docx']
27
+ * @default ['pdf']
28
+ */
29
+ type: z.array(z.enum(['pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'csv'])).optional(),
30
+ });
31
+ export class DocumentField extends FileField {
32
+ static [entityKind] = 'DocumentField';
33
+ maxFileSize;
34
+ mimeType;
35
+ extensions;
36
+ possibleExtensions = ['pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'csv'];
37
+ /**
38
+ * _file is the file object if it's present
39
+ * Whereas the value is the path to the file
40
+ */
41
+ _file;
42
+ _buffer;
43
+ _folder;
44
+ _allowedExtensions;
45
+ uploadsFolder = getCMSConfig().files.upload.uploadPath;
46
+ constructor(config, file) {
47
+ super(config, 'document');
48
+ if (file) {
49
+ this._file = file;
50
+ }
51
+ this.maxFileSize = config.maxFileSize ?? { size: 2, unit: 'mb' };
52
+ /**
53
+ * Check if the config type is valid
54
+ */
55
+ if (config.type && config.type.some((type) => !this.possibleExtensions.includes(type))) {
56
+ throw new Error(`Invalid document type provided: ${config.type.join(', ')}, allowed types are: ${this.possibleExtensions.join(', ')}`);
57
+ }
58
+ this.extensions = config.type ?? ['pdf'];
59
+ /**
60
+ * Extract the mime types from the extensions
61
+ * @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types
62
+ */
63
+ this.mimeType = this.extensions.map((e) => {
64
+ switch (e) {
65
+ case 'pdf':
66
+ return 'application/pdf';
67
+ case 'doc':
68
+ return 'application/msword';
69
+ case 'docx':
70
+ return 'application/vnd.openxmlformats-officedocument.wordprocessingml.document';
71
+ case 'xls':
72
+ return 'application/vnd.ms-excel';
73
+ case 'xlsx':
74
+ return 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
75
+ case 'ppt':
76
+ return 'application/vnd.ms-powerpoint';
77
+ case 'pptx':
78
+ return 'application/vnd.openxmlformats-officedocument.presentationml.presentation';
79
+ case 'txt':
80
+ return 'text/plain';
81
+ case 'csv':
82
+ return 'text/csv';
83
+ default:
84
+ throw new Error(`Invalid image extension provided: ${e}`);
85
+ }
86
+ });
87
+ /**
88
+ * Set the allowed extensions, add jpg if jpeg is present
89
+ */
90
+ this._allowedExtensions = this.extensions;
91
+ }
92
+ exportForClient() {
93
+ return {
94
+ ...super.exportForClient(),
95
+ maxFileSize: this.maxFileSize,
96
+ extensions: this._allowedExtensions,
97
+ mimeType: this.mimeType,
98
+ };
99
+ }
100
+ async readChunkFromFile({ arrayBuffer, length, startPosition = 0, }) {
101
+ return new Promise(async (resolve, reject) => {
102
+ try {
103
+ if (arrayBuffer) {
104
+ const buffer = new Uint8Array(arrayBuffer, startPosition, length);
105
+ resolve(buffer);
106
+ }
107
+ else {
108
+ reject(new Error('Error reading file'));
109
+ }
110
+ }
111
+ catch (error) {
112
+ reject(new Error('Error reading file'));
113
+ }
114
+ });
115
+ }
116
+ /**
117
+ * Write the file to the disk
118
+ */
119
+ async writeToFile() {
120
+ if (!this._folder) {
121
+ throw new Error(`${this.label}: Folder is not set. Make sure to set the folder by call postSubmit() before writing the file to disk`);
122
+ }
123
+ if (!this._buffer) {
124
+ throw new Error(`${this.label}: Buffer is not set. Make sure to call prepareForSubmission() before writing the file to disk`);
125
+ }
126
+ try {
127
+ /**
128
+ * If .documents, and 'sectionName' folders don't exist, create them
129
+ */
130
+ const documentsFolder = path.join(this.uploadsFolder, '.documents', this._folder);
131
+ if (!fs.existsSync(documentsFolder)) {
132
+ fs.mkdirSync(documentsFolder, { recursive: true });
133
+ }
134
+ /**
135
+ * Write the file to disk
136
+ */
137
+ await fs.promises.writeFile(path.join(this.uploadsFolder, '.documents', this._folder, this.value), this._buffer);
138
+ }
139
+ catch (error) {
140
+ throw new Error(`${this.label}: Error writing file to disk ${error.message}`);
141
+ }
142
+ }
143
+ async postSubmit(folder) {
144
+ if (!this._file)
145
+ return;
146
+ this._folder = folder;
147
+ await this.writeToFile();
148
+ }
149
+ async postSubmitRollback() {
150
+ if (!this._file)
151
+ return;
152
+ if (!this._folder) {
153
+ throw new Error(`${this.label}: Folder is not set. Make sure to set the folder before writing the file to disk`);
154
+ }
155
+ try {
156
+ const pathToFile = path.join(this.uploadsFolder, '.documents', this._folder, this.value);
157
+ await fs.promises.unlink(pathToFile);
158
+ }
159
+ catch (error) {
160
+ throw new Error(`${this.label}: Error deleting file from disk`);
161
+ }
162
+ }
163
+ /**
164
+ * Get the value of the field
165
+ */
166
+ getValue() {
167
+ return this.value;
168
+ }
169
+ setFileName(value) {
170
+ this.value = value;
171
+ }
172
+ setValue(value) {
173
+ if (typeof value === 'string') {
174
+ this.setFileName(value);
175
+ return;
176
+ }
177
+ this.setFile(value);
178
+ }
179
+ setFile(file) {
180
+ if (!file || file.size === 0 || file.name?.trim() === '')
181
+ return;
182
+ this._file = file;
183
+ }
184
+ checkRequired() {
185
+ /**
186
+ * Check if the field is required
187
+ * If it is, check if the file is present
188
+ * If it's not, throw an error
189
+ * Note: Those values are coming from the browser (not safe)
190
+ */
191
+ if (!this.required)
192
+ return;
193
+ if (!this._file || !this._file?.type || !this._file?.name || !this._file?.size) {
194
+ throw new Error(`Field ${this.label} is required`);
195
+ }
196
+ }
197
+ /**
198
+ * Prepare the field for submission
199
+ */
200
+ async prepareForSubmission() {
201
+ if (!this._file)
202
+ return;
203
+ /**
204
+ * Check the actual file size
205
+ */
206
+ const arrayBuffer = await this._file.arrayBuffer();
207
+ this._buffer = Buffer.from(arrayBuffer);
208
+ if (!this._buffer.length) {
209
+ throw new Error(`Field ${this.label} is required`);
210
+ }
211
+ /**
212
+ * Check extension
213
+ */
214
+ const ext = this._file.name.split('.').pop();
215
+ if (!ext || !this.extensions.includes(ext)) {
216
+ throw new Error(`${this.label}: Invalid file type or extension. Allowed extensions: ${this.extensions.join(', ')}`);
217
+ }
218
+ /**
219
+ * Read the first 4100 bytes of the file
220
+ */
221
+ const chunkBuffer = await this.readChunkFromFile({ arrayBuffer, length: 4100 });
222
+ /**
223
+ * Get the file type from the buffer
224
+ */
225
+ const { fileTypeFromBuffer } = await import('file-type');
226
+ const fileType = await fileTypeFromBuffer(chunkBuffer);
227
+ /**
228
+ * If the file type is invalid, return an error
229
+ */
230
+ if (!fileType) {
231
+ throw new Error(`${this.label}: Invalid file type`);
232
+ }
233
+ /**
234
+ * Don't just trust the file extension
235
+ * Check the `fileType.ext` against the allowed extensions
236
+ */
237
+ if (!fileType.ext || !this.extensions.includes(fileType.ext)) {
238
+ throw new Error(`${this.label}: Invalid file type or extension. Allowed extensions: ${this.extensions.join(', ')}`);
239
+ }
240
+ /**
241
+ * Generate a random name for the file
242
+ */
243
+ this.value = customAlphabet('1234567890abcdef', 21)();
244
+ }
245
+ }
246
+ const optionsSchema = z.strictObject({
247
+ ...baseFieldConfigSchema.shape,
248
+ ...configSchema.shape,
249
+ });
250
+ const documentFieldConfigSchema = z.strictObject({
251
+ ...optionsSchema.shape,
252
+ type: z.literal('document').describe('The type of the field'),
253
+ build: z.function().output(z.instanceof(DocumentField)).describe('Build a DocumentField instance from this config'),
254
+ });
255
+ /**
256
+ * Helper function to create a document field configuration
257
+ * Returns a config object with a build() method that can be serialized and used anywhere
258
+ * @param field
259
+ */
260
+ export function documentField(field) {
261
+ /**
262
+ * Validate the field config
263
+ */
264
+ const result = optionsSchema.safeParse(field);
265
+ if (!result.success) {
266
+ throw new Error(`[Field: ${field.name}]: ${z.prettifyError(result.error)}`);
267
+ }
268
+ const config = {
269
+ ...field,
270
+ type: 'document',
271
+ build() {
272
+ // Use the original field config directly (it doesn't have build() method)
273
+ return new DocumentField(field);
274
+ },
275
+ };
276
+ return config;
277
+ }
@@ -1,18 +1,18 @@
1
- import type { Field, FieldConfig } from "..js";
2
- import type { Prettify } from "../types.js";
3
- export type FieldGroupOptions = {
4
- title?: string;
5
- order?: number;
6
- fields: FieldConfig[];
7
- };
8
- export type FieldGroupConfig = Prettify<FieldGroupOptions> & {
9
- type: 'field_group';
10
- };
11
- export type FieldGroup = {
12
- id: number;
13
- title?: string;
14
- order?: number;
15
- fields: Field[];
16
- };
17
- export declare function fieldGroup(group: FieldGroupOptions): FieldGroupConfig;
1
+ import type { Field, FieldConfig } from './index.js';
2
+ import type { Prettify } from '../types/index.js';
3
+ export type FieldGroupOptions = {
4
+ title?: string;
5
+ order?: number;
6
+ fields: FieldConfig[];
7
+ };
8
+ export type FieldGroupConfig = Prettify<FieldGroupOptions> & {
9
+ type: 'field_group';
10
+ };
11
+ export type FieldGroup = {
12
+ id: number;
13
+ title?: string;
14
+ order?: number;
15
+ fields: Field[];
16
+ };
17
+ export declare function fieldGroup(group: FieldGroupOptions): FieldGroupConfig;
18
18
  //# sourceMappingURL=field-group.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"field-group.d.ts","sourceRoot":"","sources":["../../../src/core/fields/field-group.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,GAAG,CAAA;AAC3C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAExC,MAAM,MAAM,iBAAiB,GAAG;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,WAAW,EAAE,CAAA;CACxB,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG,QAAQ,CAAC,iBAAiB,CAAC,GAAG;IACzD,IAAI,EAAE,aAAa,CAAA;CACtB,CAAA;AAED,MAAM,MAAM,UAAU,GAAG;IACrB,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,KAAK,EAAE,CAAA;CAClB,CAAA;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,iBAAiB,GAAG,gBAAgB,CAKrE"}
1
+ {"version":3,"file":"field-group.d.ts","sourceRoot":"","sources":["../../../src/core/fields/field-group.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AACpD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAEjD,MAAM,MAAM,iBAAiB,GAAG;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,WAAW,EAAE,CAAA;CACxB,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG,QAAQ,CAAC,iBAAiB,CAAC,GAAG;IACzD,IAAI,EAAE,aAAa,CAAA;CACtB,CAAA;AAED,MAAM,MAAM,UAAU,GAAG;IACrB,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,KAAK,EAAE,CAAA;CAClB,CAAA;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,iBAAiB,GAAG,gBAAgB,CAKrE"}
@@ -1,6 +1,6 @@
1
- export function fieldGroup(group) {
2
- return {
3
- ...group,
4
- type: 'field_group',
5
- };
6
- }
1
+ export function fieldGroup(group) {
2
+ return {
3
+ ...group,
4
+ type: 'field_group',
5
+ };
6
+ }