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.
- package/dist/api/axios/axiosInstance.d.ts +1 -1
- package/dist/api/axios/axiosInstance.js +8 -8
- package/dist/api/index.d.ts +855 -855
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +12 -12
- package/dist/api/lib/serverActions.d.ts +239 -239
- package/dist/api/lib/serverActions.d.ts.map +1 -1
- package/dist/api/lib/serverActions.js +834 -834
- package/dist/api/root.d.ts +828 -828
- package/dist/api/root.js +30 -30
- package/dist/api/routers/accountSettings.d.ts +60 -60
- package/dist/api/routers/accountSettings.js +108 -108
- package/dist/api/routers/admins.d.ts +105 -105
- package/dist/api/routers/admins.js +219 -219
- package/dist/api/routers/auth.d.ts +47 -47
- package/dist/api/routers/auth.js +25 -25
- package/dist/api/routers/categorySection.d.ts +103 -103
- package/dist/api/routers/categorySection.js +38 -38
- package/dist/api/routers/cmsSettings.d.ts +48 -48
- package/dist/api/routers/cmsSettings.js +51 -51
- package/dist/api/routers/cpanel.d.ts +83 -83
- package/dist/api/routers/cpanel.js +216 -216
- package/dist/api/routers/files.d.ts +47 -47
- package/dist/api/routers/files.js +23 -23
- package/dist/api/routers/gallery.d.ts +35 -35
- package/dist/api/routers/gallery.js +62 -62
- package/dist/api/routers/googleAnalytics.d.ts +30 -30
- package/dist/api/routers/googleAnalytics.js +7 -7
- package/dist/api/routers/hasItemsSection.d.ts +139 -139
- package/dist/api/routers/hasItemsSection.js +34 -34
- package/dist/api/routers/navigation.d.ts +51 -51
- package/dist/api/routers/navigation.js +11 -11
- package/dist/api/routers/simpleSection.d.ts +57 -57
- package/dist/api/routers/simpleSection.js +12 -12
- package/dist/api/trpc.d.ts +106 -106
- package/dist/api/trpc.js +72 -72
- package/dist/auth/axios/axiosInstance.d.ts +1 -1
- package/dist/auth/axios/axiosInstance.js +8 -8
- package/dist/auth/csrf.d.ts +29 -29
- package/dist/auth/csrf.js +76 -76
- package/dist/auth/hooks/index.d.ts +3 -3
- package/dist/auth/hooks/index.d.ts.map +1 -1
- package/dist/auth/hooks/index.js +3 -3
- package/dist/auth/hooks/useAxiosPrivate.d.ts +4 -4
- package/dist/auth/hooks/useAxiosPrivate.js +74 -74
- package/dist/auth/hooks/useRefreshToken.d.ts +6 -6
- package/dist/auth/hooks/useRefreshToken.js +79 -79
- package/dist/auth/index.d.ts +22 -22
- package/dist/auth/index.js +44 -44
- package/dist/auth/jwt.d.ts +5 -5
- package/dist/auth/jwt.js +25 -25
- package/dist/auth/lib/actions.d.ts +32 -32
- package/dist/auth/lib/actions.d.ts.map +1 -1
- package/dist/auth/lib/actions.js +209 -209
- package/dist/auth/lib/client.d.ts +3 -3
- package/dist/auth/lib/client.js +46 -46
- package/dist/auth/lib/index.d.ts +2 -2
- package/dist/auth/lib/index.d.ts.map +1 -1
- package/dist/auth/lib/index.js +2 -2
- package/dist/auth/react.d.ts +105 -105
- package/dist/auth/react.d.ts.map +1 -1
- package/dist/auth/react.js +347 -347
- package/dist/auth/trpc.d.ts +5 -5
- package/dist/auth/trpc.d.ts.map +1 -1
- package/dist/auth/trpc.js +81 -81
- package/dist/core/config/config-loader.d.ts +91 -91
- package/dist/core/config/config-loader.js +230 -230
- package/dist/core/config/index.d.ts +2 -2
- package/dist/core/config/index.d.ts.map +1 -1
- package/dist/core/config/index.js +1 -1
- package/dist/core/config/loader.d.ts +1 -1
- package/dist/core/config/loader.js +42 -42
- package/dist/core/db/index.d.ts +1 -1
- package/dist/core/db/index.d.ts.map +1 -1
- package/dist/core/db/index.js +1 -1
- package/dist/core/db/table-checker/DbTable.d.ts +5 -5
- package/dist/core/db/table-checker/DbTable.js +5 -5
- package/dist/core/db/table-checker/MysqlTable.d.ts +33 -33
- package/dist/core/db/table-checker/MysqlTable.d.ts.map +1 -1
- package/dist/core/db/table-checker/MysqlTable.js +94 -94
- package/dist/core/db/table-checker/index.d.ts +1 -1
- package/dist/core/db/table-checker/index.d.ts.map +1 -1
- package/dist/core/db/table-checker/index.js +1 -1
- package/dist/core/factories/FieldFactory.d.ts +123 -123
- package/dist/core/factories/FieldFactory.d.ts.map +1 -1
- package/dist/core/factories/FieldFactory.js +411 -411
- package/dist/core/factories/SectionFactory.d.ts +109 -109
- package/dist/core/factories/SectionFactory.d.ts.map +1 -1
- package/dist/core/factories/SectionFactory.js +415 -415
- package/dist/core/factories/index.d.ts +2 -2
- package/dist/core/factories/index.d.ts.map +1 -1
- package/dist/core/factories/index.js +2 -2
- package/dist/core/fields/checkbox.d.ts +62 -62
- package/dist/core/fields/checkbox.d.ts.map +1 -1
- package/dist/core/fields/checkbox.js +62 -62
- package/dist/core/fields/color.d.ts +83 -83
- package/dist/core/fields/color.d.ts.map +1 -1
- package/dist/core/fields/color.js +91 -91
- package/dist/core/fields/date.d.ts +99 -99
- package/dist/core/fields/date.d.ts.map +1 -1
- package/dist/core/fields/date.js +108 -108
- package/dist/core/fields/document.d.ts +179 -179
- package/dist/core/fields/document.d.ts.map +1 -1
- package/dist/core/fields/document.js +277 -277
- package/dist/core/fields/field-group.d.ts +17 -17
- package/dist/core/fields/field-group.d.ts.map +1 -1
- package/dist/core/fields/field-group.js +6 -6
- package/dist/core/fields/field.d.ts +125 -125
- package/dist/core/fields/field.d.ts.map +1 -1
- package/dist/core/fields/field.js +148 -148
- package/dist/core/fields/fileField.d.ts +14 -14
- package/dist/core/fields/fileField.d.ts.map +1 -1
- package/dist/core/fields/fileField.js +5 -5
- package/dist/core/fields/index.d.ts +64 -64
- package/dist/core/fields/index.d.ts.map +1 -1
- package/dist/core/fields/index.js +18 -18
- package/dist/core/fields/map.d.ts +166 -166
- package/dist/core/fields/map.d.ts.map +1 -1
- package/dist/core/fields/map.js +152 -152
- package/dist/core/fields/number.d.ts +185 -185
- package/dist/core/fields/number.d.ts.map +1 -1
- package/dist/core/fields/number.js +241 -241
- package/dist/core/fields/password.d.ts +108 -108
- package/dist/core/fields/password.d.ts.map +1 -1
- package/dist/core/fields/password.js +133 -133
- package/dist/core/fields/photo.d.ts +288 -288
- package/dist/core/fields/photo.d.ts.map +1 -1
- package/dist/core/fields/photo.js +410 -410
- package/dist/core/fields/richText.d.ts +294 -294
- package/dist/core/fields/richText.d.ts.map +1 -1
- package/dist/core/fields/richText.js +338 -338
- package/dist/core/fields/select.d.ts +365 -365
- package/dist/core/fields/select.d.ts.map +1 -1
- package/dist/core/fields/select.js +499 -499
- package/dist/core/fields/selectMultiple.d.ts +235 -235
- package/dist/core/fields/selectMultiple.d.ts.map +1 -1
- package/dist/core/fields/selectMultiple.js +417 -417
- package/dist/core/fields/tags.d.ts +130 -130
- package/dist/core/fields/tags.d.ts.map +1 -1
- package/dist/core/fields/tags.js +105 -105
- package/dist/core/fields/text.d.ts +135 -135
- package/dist/core/fields/text.d.ts.map +1 -1
- package/dist/core/fields/text.js +157 -157
- package/dist/core/fields/textArea.d.ts +106 -106
- package/dist/core/fields/textArea.d.ts.map +1 -1
- package/dist/core/fields/textArea.js +126 -126
- package/dist/core/fields/video.d.ts +147 -147
- package/dist/core/fields/video.d.ts.map +1 -1
- package/dist/core/fields/video.js +248 -248
- package/dist/core/helpers/entity.d.ts +7 -7
- package/dist/core/helpers/entity.js +27 -27
- package/dist/core/helpers/index.d.ts +4 -4
- package/dist/core/helpers/index.d.ts.map +1 -1
- package/dist/core/helpers/index.js +3 -3
- package/dist/core/index.d.ts +7 -7
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +7 -7
- package/dist/core/sections/category.d.ts +282 -282
- package/dist/core/sections/category.d.ts.map +1 -1
- package/dist/core/sections/category.js +147 -147
- package/dist/core/sections/hasItems.d.ts +631 -631
- package/dist/core/sections/hasItems.d.ts.map +1 -1
- package/dist/core/sections/hasItems.js +144 -144
- package/dist/core/sections/index.d.ts +4 -4
- package/dist/core/sections/index.d.ts.map +1 -1
- package/dist/core/sections/index.js +4 -4
- package/dist/core/sections/section.d.ts +225 -225
- package/dist/core/sections/section.d.ts.map +1 -1
- package/dist/core/sections/section.js +341 -341
- package/dist/core/sections/simple.d.ts +98 -98
- package/dist/core/sections/simple.d.ts.map +1 -1
- package/dist/core/sections/simple.js +95 -95
- package/dist/core/security/dom.d.ts +10 -10
- package/dist/core/security/dom.js +92 -92
- package/dist/core/submit/ItemEditSubmit.d.ts +75 -75
- package/dist/core/submit/ItemEditSubmit.js +186 -186
- package/dist/core/submit/NewItemSubmit.d.ts +13 -13
- package/dist/core/submit/NewItemSubmit.js +93 -93
- package/dist/core/submit/SimpleSectionSubmit.d.ts +12 -12
- package/dist/core/submit/SimpleSectionSubmit.js +93 -93
- package/dist/core/submit/index.d.ts +4 -4
- package/dist/core/submit/index.js +4 -4
- package/dist/core/submit/submit.d.ts +115 -115
- package/dist/core/submit/submit.js +479 -479
- package/dist/core/types/index.d.ts +279 -279
- package/dist/core/types/index.d.ts.map +1 -1
- package/dist/core/types/index.js +1 -1
- package/dist/db/client.d.ts +8 -8
- package/dist/db/client.d.ts.map +1 -1
- package/dist/db/client.js +19 -19
- package/dist/db/config.d.ts +5 -5
- package/dist/db/config.js +22 -22
- package/dist/db/drizzle.config.d.ts +5 -5
- package/dist/db/drizzle.config.js +18 -18
- package/dist/db/index.d.ts +2 -2
- package/dist/db/index.js +3 -3
- package/dist/db/schema.d.ts +638 -638
- package/dist/db/schema.js +73 -73
- package/dist/index.d.ts +7 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -7
- package/dist/translations/index.d.ts +2 -2
- package/dist/translations/index.js +15 -15
- package/dist/utils/CpanelApi.d.ts +24 -24
- package/dist/utils/CpanelApi.js +64 -64
- package/dist/utils/constants.d.ts +13 -13
- package/dist/utils/constants.js +61 -61
- package/dist/utils/index.d.ts +4 -4
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +4 -4
- package/dist/utils/utils.d.ts +59 -59
- package/dist/utils/utils.js +132 -132
- package/dist/validators/checkbox.d.ts +3 -3
- package/dist/validators/checkbox.d.ts.map +1 -1
- package/dist/validators/checkbox.js +12 -12
- package/dist/validators/color.d.ts +3 -3
- package/dist/validators/color.d.ts.map +1 -1
- package/dist/validators/color.js +7 -7
- package/dist/validators/date.d.ts +3 -3
- package/dist/validators/date.d.ts.map +1 -1
- package/dist/validators/date.js +5 -5
- package/dist/validators/document.d.ts +3 -3
- package/dist/validators/document.d.ts.map +1 -1
- package/dist/validators/document.js +57 -57
- package/dist/validators/index.d.ts +14 -14
- package/dist/validators/index.d.ts.map +1 -1
- package/dist/validators/index.js +14 -14
- package/dist/validators/map.d.ts +3 -3
- package/dist/validators/map.d.ts.map +1 -1
- package/dist/validators/map.js +5 -5
- package/dist/validators/number.d.ts +3 -3
- package/dist/validators/number.d.ts.map +1 -1
- package/dist/validators/number.js +20 -20
- package/dist/validators/password.d.ts +3 -3
- package/dist/validators/password.d.ts.map +1 -1
- package/dist/validators/password.js +11 -11
- package/dist/validators/photo.d.ts +3 -3
- package/dist/validators/photo.d.ts.map +1 -1
- package/dist/validators/photo.js +100 -100
- package/dist/validators/richText.d.ts +3 -3
- package/dist/validators/richText.d.ts.map +1 -1
- package/dist/validators/richText.js +8 -8
- package/dist/validators/select-multiple.d.ts +9 -9
- package/dist/validators/select-multiple.d.ts.map +1 -1
- package/dist/validators/select-multiple.js +20 -20
- package/dist/validators/select.d.ts +3 -3
- package/dist/validators/select.d.ts.map +1 -1
- package/dist/validators/select.js +5 -5
- package/dist/validators/text.d.ts +3 -3
- package/dist/validators/text.d.ts.map +1 -1
- package/dist/validators/text.js +7 -7
- package/dist/validators/textarea.d.ts +3 -3
- package/dist/validators/textarea.d.ts.map +1 -1
- package/dist/validators/textarea.js +7 -7
- package/dist/validators/video.d.ts +3 -3
- package/dist/validators/video.d.ts.map +1 -1
- package/dist/validators/video.js +57 -57
- package/package.json +4 -5
|
@@ -1,248 +1,248 @@
|
|
|
1
|
-
import { baseFieldConfigSchema } from
|
|
2
|
-
import { entityKind } from
|
|
3
|
-
import fs from 'fs';
|
|
4
|
-
import { customAlphabet } from 'nanoid';
|
|
5
|
-
import path from 'path';
|
|
6
|
-
import { FileField } from
|
|
7
|
-
import { getCMSConfig } from
|
|
8
|
-
import * as z from 'zod';
|
|
9
|
-
const configSchema = z.strictObject({
|
|
10
|
-
/**
|
|
11
|
-
* Maximum file size
|
|
12
|
-
*/
|
|
13
|
-
maxFileSize: z
|
|
14
|
-
.strictObject({
|
|
15
|
-
size: z.number().describe('The size value'),
|
|
16
|
-
unit: z.enum(['kb', 'mb']).describe('The unit of the size'),
|
|
17
|
-
})
|
|
18
|
-
.optional()
|
|
19
|
-
.describe('Maximum file size'),
|
|
20
|
-
/**
|
|
21
|
-
* Allowed file types
|
|
22
|
-
* @default ['mp4']
|
|
23
|
-
*/
|
|
24
|
-
type: z
|
|
25
|
-
.array(z.enum(['mp4', 'webm', 'ogg']))
|
|
26
|
-
.optional()
|
|
27
|
-
.describe('Allowed file types'),
|
|
28
|
-
});
|
|
29
|
-
export class VideoField extends FileField {
|
|
30
|
-
static [entityKind] = 'VideoField';
|
|
31
|
-
maxFileSize;
|
|
32
|
-
mimeType;
|
|
33
|
-
extensions;
|
|
34
|
-
/**
|
|
35
|
-
* _file is the file object if it's present
|
|
36
|
-
* Whereas the value is the path to the file
|
|
37
|
-
*/
|
|
38
|
-
_file;
|
|
39
|
-
_buffer;
|
|
40
|
-
_folder;
|
|
41
|
-
_allowedExtensions;
|
|
42
|
-
uploadsFolder = getCMSConfig().files.upload.uploadPath;
|
|
43
|
-
constructor(config, file) {
|
|
44
|
-
super(config, 'video');
|
|
45
|
-
this._file = file;
|
|
46
|
-
this.extensions = config.type ?? ['mp4'];
|
|
47
|
-
this.maxFileSize = config.maxFileSize ?? { size: 2, unit: 'mb' };
|
|
48
|
-
/**
|
|
49
|
-
* Extract the mime types from the extensions
|
|
50
|
-
* @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types
|
|
51
|
-
*/
|
|
52
|
-
this.mimeType = this.extensions.map((e) => {
|
|
53
|
-
switch (e) {
|
|
54
|
-
case 'mp4':
|
|
55
|
-
return 'video/mp4';
|
|
56
|
-
case 'webm':
|
|
57
|
-
return 'video/webm';
|
|
58
|
-
case 'ogg':
|
|
59
|
-
return 'video/ogg';
|
|
60
|
-
default:
|
|
61
|
-
return '';
|
|
62
|
-
}
|
|
63
|
-
});
|
|
64
|
-
/**
|
|
65
|
-
* Set the allowed extensions, add jpg if jpeg is present
|
|
66
|
-
*/
|
|
67
|
-
this._allowedExtensions = this.extensions;
|
|
68
|
-
}
|
|
69
|
-
exportForClient() {
|
|
70
|
-
return {
|
|
71
|
-
...super.exportForClient(),
|
|
72
|
-
maxFileSize: this.maxFileSize,
|
|
73
|
-
extensions: this._allowedExtensions,
|
|
74
|
-
mimeType: this.mimeType,
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
async readChunkFromFile({ arrayBuffer, length, startPosition = 0, }) {
|
|
78
|
-
return new Promise(async (resolve, reject) => {
|
|
79
|
-
try {
|
|
80
|
-
if (arrayBuffer) {
|
|
81
|
-
const buffer = new Uint8Array(arrayBuffer, startPosition, length);
|
|
82
|
-
resolve(buffer);
|
|
83
|
-
}
|
|
84
|
-
else {
|
|
85
|
-
reject(new Error('Error reading file'));
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
catch (error) {
|
|
89
|
-
reject(new Error('Error reading file'));
|
|
90
|
-
}
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
/**
|
|
94
|
-
* Write the file to the disk
|
|
95
|
-
*/
|
|
96
|
-
async writeToFile() {
|
|
97
|
-
if (!this._folder) {
|
|
98
|
-
throw new Error(`${this.label}: Folder is not set. Make sure to set the folder by call postSubmit() before writing the file to disk`);
|
|
99
|
-
}
|
|
100
|
-
if (!this._buffer) {
|
|
101
|
-
throw new Error(`${this.label}: Buffer is not set. Make sure to call prepareForSubmission() before writing the file to disk`);
|
|
102
|
-
}
|
|
103
|
-
try {
|
|
104
|
-
/**
|
|
105
|
-
* If .videos, and 'sectionName' folders don't exist, create them
|
|
106
|
-
*/
|
|
107
|
-
const vdieosFolder = path.join(this.uploadsFolder, '.videos', this._folder);
|
|
108
|
-
if (!fs.existsSync(vdieosFolder)) {
|
|
109
|
-
fs.mkdirSync(vdieosFolder, { recursive: true });
|
|
110
|
-
}
|
|
111
|
-
/**
|
|
112
|
-
* Write the file to disk
|
|
113
|
-
*/
|
|
114
|
-
await fs.promises.writeFile(path.join(this.uploadsFolder, '.videos', this._folder, this.value), this._buffer);
|
|
115
|
-
}
|
|
116
|
-
catch (error) {
|
|
117
|
-
throw new Error(`${this.label}: Error writing file to disk ${error.message}`);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
async postSubmit(folder) {
|
|
121
|
-
this._folder = folder;
|
|
122
|
-
await this.writeToFile();
|
|
123
|
-
}
|
|
124
|
-
async postSubmitRollback() {
|
|
125
|
-
if (!this._folder) {
|
|
126
|
-
throw new Error(`${this.label}: Folder is not set. Make sure to set the folder before writing the file to disk`);
|
|
127
|
-
}
|
|
128
|
-
try {
|
|
129
|
-
const pathToFile = path.join(this.uploadsFolder, '.videos', this._folder, this.value);
|
|
130
|
-
await fs.promises.unlink(pathToFile);
|
|
131
|
-
}
|
|
132
|
-
catch (error) {
|
|
133
|
-
throw new Error(`${this.label}: Error deleting file from disk`);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
/**
|
|
137
|
-
* Get the value of the field
|
|
138
|
-
*/
|
|
139
|
-
getValue() {
|
|
140
|
-
return this.value;
|
|
141
|
-
}
|
|
142
|
-
setFileName(value) {
|
|
143
|
-
this.value = value;
|
|
144
|
-
}
|
|
145
|
-
setValue(value) {
|
|
146
|
-
if (typeof value === 'string') {
|
|
147
|
-
this.setFileName(value);
|
|
148
|
-
return;
|
|
149
|
-
}
|
|
150
|
-
this.setFile(value);
|
|
151
|
-
}
|
|
152
|
-
setFile(file) {
|
|
153
|
-
if (!file || file.size === 0 || file.name?.trim() === '')
|
|
154
|
-
return;
|
|
155
|
-
this._file = file;
|
|
156
|
-
}
|
|
157
|
-
checkRequired() {
|
|
158
|
-
/**
|
|
159
|
-
* Check if the field is required
|
|
160
|
-
* If it is, check if the file is present
|
|
161
|
-
* If it's not, throw an error
|
|
162
|
-
* Note: Those values are coming from the browser (not safe)
|
|
163
|
-
*/
|
|
164
|
-
if ((this.required && !this._file) || !this._file?.type || !this._file?.name || !this._file?.size) {
|
|
165
|
-
throw new Error(`Field ${this.label} is required`);
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
/**
|
|
169
|
-
* Prepare the field for submission
|
|
170
|
-
*/
|
|
171
|
-
async prepareForSubmission() {
|
|
172
|
-
if (!this._file)
|
|
173
|
-
return;
|
|
174
|
-
/**
|
|
175
|
-
* Check the actual file size
|
|
176
|
-
*/
|
|
177
|
-
const arrayBuffer = await this._file.arrayBuffer();
|
|
178
|
-
this._buffer = Buffer.from(arrayBuffer);
|
|
179
|
-
if (!this._buffer.length) {
|
|
180
|
-
throw new Error(`Field ${this.label} is required`);
|
|
181
|
-
}
|
|
182
|
-
/**
|
|
183
|
-
* Check extension
|
|
184
|
-
*/
|
|
185
|
-
const ext = this._file.name.split('.').pop();
|
|
186
|
-
if (!ext || !this.extensions.includes(ext)) {
|
|
187
|
-
throw new Error(`${this.label}: Invalid file type or extension. Allowed extensions: ${this.extensions.join(', ')}`);
|
|
188
|
-
}
|
|
189
|
-
/**
|
|
190
|
-
* Read the first 4100 bytes of the file
|
|
191
|
-
*/
|
|
192
|
-
const chunkBuffer = await this.readChunkFromFile({ arrayBuffer, length: 4100 });
|
|
193
|
-
/**
|
|
194
|
-
* Get the file type from the buffer
|
|
195
|
-
*/
|
|
196
|
-
const { fileTypeFromBuffer } = await import('file-type');
|
|
197
|
-
const fileType = await fileTypeFromBuffer(chunkBuffer);
|
|
198
|
-
/**
|
|
199
|
-
* If the file type is invalid, return an error
|
|
200
|
-
*/
|
|
201
|
-
if (!fileType) {
|
|
202
|
-
throw new Error(`${this.label}: Invalid file type`);
|
|
203
|
-
}
|
|
204
|
-
/**
|
|
205
|
-
* Don't just trust the file extension
|
|
206
|
-
* Check the `fileType.ext` against the allowed extensions
|
|
207
|
-
*/
|
|
208
|
-
if (!fileType.ext || !this.extensions.includes(fileType.ext)) {
|
|
209
|
-
throw new Error(`${this.label}: Invalid file type or extension. Allowed extensions: ${this.extensions.join(', ')}`);
|
|
210
|
-
}
|
|
211
|
-
/**
|
|
212
|
-
* Generate a random name for the file
|
|
213
|
-
*/
|
|
214
|
-
this.value = customAlphabet('1234567890abcdef', 21)();
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
const optionsSchema = z.strictObject({
|
|
218
|
-
...baseFieldConfigSchema.shape,
|
|
219
|
-
...configSchema.shape,
|
|
220
|
-
});
|
|
221
|
-
const videoFieldConfigSchema = z.strictObject({
|
|
222
|
-
...optionsSchema.shape,
|
|
223
|
-
type: z.literal('video').describe('The type of the field'),
|
|
224
|
-
build: z.function().output(z.instanceof(VideoField)).describe('Build a VideoField instance from this config'),
|
|
225
|
-
});
|
|
226
|
-
/**
|
|
227
|
-
* Helper function to create a video field configuration
|
|
228
|
-
* Returns a config object with a build() method that can be serialized and used anywhere
|
|
229
|
-
* @param field
|
|
230
|
-
*/
|
|
231
|
-
export function videoField(field) {
|
|
232
|
-
/**
|
|
233
|
-
* Validate the field config
|
|
234
|
-
*/
|
|
235
|
-
const result = optionsSchema.safeParse(field);
|
|
236
|
-
if (!result.success) {
|
|
237
|
-
throw new Error(`[Field: ${field.name}]: ${z.prettifyError(result.error)}`);
|
|
238
|
-
}
|
|
239
|
-
const config = {
|
|
240
|
-
...field,
|
|
241
|
-
type: 'video',
|
|
242
|
-
build() {
|
|
243
|
-
// Use the original field config directly (it doesn't have build() method)
|
|
244
|
-
return new VideoField(field);
|
|
245
|
-
},
|
|
246
|
-
};
|
|
247
|
-
return config;
|
|
248
|
-
}
|
|
1
|
+
import { baseFieldConfigSchema } from './field.js';
|
|
2
|
+
import { entityKind } from '../helpers/index.js';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import { customAlphabet } from 'nanoid';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
import { FileField } from './fileField.js';
|
|
7
|
+
import { getCMSConfig } from '../config/index.js';
|
|
8
|
+
import * as z from 'zod';
|
|
9
|
+
const configSchema = z.strictObject({
|
|
10
|
+
/**
|
|
11
|
+
* Maximum file size
|
|
12
|
+
*/
|
|
13
|
+
maxFileSize: z
|
|
14
|
+
.strictObject({
|
|
15
|
+
size: z.number().describe('The size value'),
|
|
16
|
+
unit: z.enum(['kb', 'mb']).describe('The unit of the size'),
|
|
17
|
+
})
|
|
18
|
+
.optional()
|
|
19
|
+
.describe('Maximum file size'),
|
|
20
|
+
/**
|
|
21
|
+
* Allowed file types
|
|
22
|
+
* @default ['mp4']
|
|
23
|
+
*/
|
|
24
|
+
type: z
|
|
25
|
+
.array(z.enum(['mp4', 'webm', 'ogg']))
|
|
26
|
+
.optional()
|
|
27
|
+
.describe('Allowed file types'),
|
|
28
|
+
});
|
|
29
|
+
export class VideoField extends FileField {
|
|
30
|
+
static [entityKind] = 'VideoField';
|
|
31
|
+
maxFileSize;
|
|
32
|
+
mimeType;
|
|
33
|
+
extensions;
|
|
34
|
+
/**
|
|
35
|
+
* _file is the file object if it's present
|
|
36
|
+
* Whereas the value is the path to the file
|
|
37
|
+
*/
|
|
38
|
+
_file;
|
|
39
|
+
_buffer;
|
|
40
|
+
_folder;
|
|
41
|
+
_allowedExtensions;
|
|
42
|
+
uploadsFolder = getCMSConfig().files.upload.uploadPath;
|
|
43
|
+
constructor(config, file) {
|
|
44
|
+
super(config, 'video');
|
|
45
|
+
this._file = file;
|
|
46
|
+
this.extensions = config.type ?? ['mp4'];
|
|
47
|
+
this.maxFileSize = config.maxFileSize ?? { size: 2, unit: 'mb' };
|
|
48
|
+
/**
|
|
49
|
+
* Extract the mime types from the extensions
|
|
50
|
+
* @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types
|
|
51
|
+
*/
|
|
52
|
+
this.mimeType = this.extensions.map((e) => {
|
|
53
|
+
switch (e) {
|
|
54
|
+
case 'mp4':
|
|
55
|
+
return 'video/mp4';
|
|
56
|
+
case 'webm':
|
|
57
|
+
return 'video/webm';
|
|
58
|
+
case 'ogg':
|
|
59
|
+
return 'video/ogg';
|
|
60
|
+
default:
|
|
61
|
+
return '';
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
/**
|
|
65
|
+
* Set the allowed extensions, add jpg if jpeg is present
|
|
66
|
+
*/
|
|
67
|
+
this._allowedExtensions = this.extensions;
|
|
68
|
+
}
|
|
69
|
+
exportForClient() {
|
|
70
|
+
return {
|
|
71
|
+
...super.exportForClient(),
|
|
72
|
+
maxFileSize: this.maxFileSize,
|
|
73
|
+
extensions: this._allowedExtensions,
|
|
74
|
+
mimeType: this.mimeType,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
async readChunkFromFile({ arrayBuffer, length, startPosition = 0, }) {
|
|
78
|
+
return new Promise(async (resolve, reject) => {
|
|
79
|
+
try {
|
|
80
|
+
if (arrayBuffer) {
|
|
81
|
+
const buffer = new Uint8Array(arrayBuffer, startPosition, length);
|
|
82
|
+
resolve(buffer);
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
reject(new Error('Error reading file'));
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
reject(new Error('Error reading file'));
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Write the file to the disk
|
|
95
|
+
*/
|
|
96
|
+
async writeToFile() {
|
|
97
|
+
if (!this._folder) {
|
|
98
|
+
throw new Error(`${this.label}: Folder is not set. Make sure to set the folder by call postSubmit() before writing the file to disk`);
|
|
99
|
+
}
|
|
100
|
+
if (!this._buffer) {
|
|
101
|
+
throw new Error(`${this.label}: Buffer is not set. Make sure to call prepareForSubmission() before writing the file to disk`);
|
|
102
|
+
}
|
|
103
|
+
try {
|
|
104
|
+
/**
|
|
105
|
+
* If .videos, and 'sectionName' folders don't exist, create them
|
|
106
|
+
*/
|
|
107
|
+
const vdieosFolder = path.join(this.uploadsFolder, '.videos', this._folder);
|
|
108
|
+
if (!fs.existsSync(vdieosFolder)) {
|
|
109
|
+
fs.mkdirSync(vdieosFolder, { recursive: true });
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Write the file to disk
|
|
113
|
+
*/
|
|
114
|
+
await fs.promises.writeFile(path.join(this.uploadsFolder, '.videos', this._folder, this.value), this._buffer);
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
throw new Error(`${this.label}: Error writing file to disk ${error.message}`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
async postSubmit(folder) {
|
|
121
|
+
this._folder = folder;
|
|
122
|
+
await this.writeToFile();
|
|
123
|
+
}
|
|
124
|
+
async postSubmitRollback() {
|
|
125
|
+
if (!this._folder) {
|
|
126
|
+
throw new Error(`${this.label}: Folder is not set. Make sure to set the folder before writing the file to disk`);
|
|
127
|
+
}
|
|
128
|
+
try {
|
|
129
|
+
const pathToFile = path.join(this.uploadsFolder, '.videos', this._folder, this.value);
|
|
130
|
+
await fs.promises.unlink(pathToFile);
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
throw new Error(`${this.label}: Error deleting file from disk`);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Get the value of the field
|
|
138
|
+
*/
|
|
139
|
+
getValue() {
|
|
140
|
+
return this.value;
|
|
141
|
+
}
|
|
142
|
+
setFileName(value) {
|
|
143
|
+
this.value = value;
|
|
144
|
+
}
|
|
145
|
+
setValue(value) {
|
|
146
|
+
if (typeof value === 'string') {
|
|
147
|
+
this.setFileName(value);
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
this.setFile(value);
|
|
151
|
+
}
|
|
152
|
+
setFile(file) {
|
|
153
|
+
if (!file || file.size === 0 || file.name?.trim() === '')
|
|
154
|
+
return;
|
|
155
|
+
this._file = file;
|
|
156
|
+
}
|
|
157
|
+
checkRequired() {
|
|
158
|
+
/**
|
|
159
|
+
* Check if the field is required
|
|
160
|
+
* If it is, check if the file is present
|
|
161
|
+
* If it's not, throw an error
|
|
162
|
+
* Note: Those values are coming from the browser (not safe)
|
|
163
|
+
*/
|
|
164
|
+
if ((this.required && !this._file) || !this._file?.type || !this._file?.name || !this._file?.size) {
|
|
165
|
+
throw new Error(`Field ${this.label} is required`);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Prepare the field for submission
|
|
170
|
+
*/
|
|
171
|
+
async prepareForSubmission() {
|
|
172
|
+
if (!this._file)
|
|
173
|
+
return;
|
|
174
|
+
/**
|
|
175
|
+
* Check the actual file size
|
|
176
|
+
*/
|
|
177
|
+
const arrayBuffer = await this._file.arrayBuffer();
|
|
178
|
+
this._buffer = Buffer.from(arrayBuffer);
|
|
179
|
+
if (!this._buffer.length) {
|
|
180
|
+
throw new Error(`Field ${this.label} is required`);
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Check extension
|
|
184
|
+
*/
|
|
185
|
+
const ext = this._file.name.split('.').pop();
|
|
186
|
+
if (!ext || !this.extensions.includes(ext)) {
|
|
187
|
+
throw new Error(`${this.label}: Invalid file type or extension. Allowed extensions: ${this.extensions.join(', ')}`);
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Read the first 4100 bytes of the file
|
|
191
|
+
*/
|
|
192
|
+
const chunkBuffer = await this.readChunkFromFile({ arrayBuffer, length: 4100 });
|
|
193
|
+
/**
|
|
194
|
+
* Get the file type from the buffer
|
|
195
|
+
*/
|
|
196
|
+
const { fileTypeFromBuffer } = await import('file-type');
|
|
197
|
+
const fileType = await fileTypeFromBuffer(chunkBuffer);
|
|
198
|
+
/**
|
|
199
|
+
* If the file type is invalid, return an error
|
|
200
|
+
*/
|
|
201
|
+
if (!fileType) {
|
|
202
|
+
throw new Error(`${this.label}: Invalid file type`);
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Don't just trust the file extension
|
|
206
|
+
* Check the `fileType.ext` against the allowed extensions
|
|
207
|
+
*/
|
|
208
|
+
if (!fileType.ext || !this.extensions.includes(fileType.ext)) {
|
|
209
|
+
throw new Error(`${this.label}: Invalid file type or extension. Allowed extensions: ${this.extensions.join(', ')}`);
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Generate a random name for the file
|
|
213
|
+
*/
|
|
214
|
+
this.value = customAlphabet('1234567890abcdef', 21)();
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
const optionsSchema = z.strictObject({
|
|
218
|
+
...baseFieldConfigSchema.shape,
|
|
219
|
+
...configSchema.shape,
|
|
220
|
+
});
|
|
221
|
+
const videoFieldConfigSchema = z.strictObject({
|
|
222
|
+
...optionsSchema.shape,
|
|
223
|
+
type: z.literal('video').describe('The type of the field'),
|
|
224
|
+
build: z.function().output(z.instanceof(VideoField)).describe('Build a VideoField instance from this config'),
|
|
225
|
+
});
|
|
226
|
+
/**
|
|
227
|
+
* Helper function to create a video field configuration
|
|
228
|
+
* Returns a config object with a build() method that can be serialized and used anywhere
|
|
229
|
+
* @param field
|
|
230
|
+
*/
|
|
231
|
+
export function videoField(field) {
|
|
232
|
+
/**
|
|
233
|
+
* Validate the field config
|
|
234
|
+
*/
|
|
235
|
+
const result = optionsSchema.safeParse(field);
|
|
236
|
+
if (!result.success) {
|
|
237
|
+
throw new Error(`[Field: ${field.name}]: ${z.prettifyError(result.error)}`);
|
|
238
|
+
}
|
|
239
|
+
const config = {
|
|
240
|
+
...field,
|
|
241
|
+
type: 'video',
|
|
242
|
+
build() {
|
|
243
|
+
// Use the original field config directly (it doesn't have build() method)
|
|
244
|
+
return new VideoField(field);
|
|
245
|
+
},
|
|
246
|
+
};
|
|
247
|
+
return config;
|
|
248
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
export declare const entityKind: unique symbol;
|
|
2
|
-
export declare const hasOwnEntityKind: unique symbol;
|
|
3
|
-
export interface LZEntity {
|
|
4
|
-
[entityKind]: string;
|
|
5
|
-
}
|
|
6
|
-
export type LZEntityClass<T> = ((abstract new (...args: any[]) => T) | (new (...args: any[]) => T)) & LZEntity;
|
|
7
|
-
export declare function is<T extends LZEntityClass<any>>(value: any, type: T): value is InstanceType<T>;
|
|
1
|
+
export declare const entityKind: unique symbol;
|
|
2
|
+
export declare const hasOwnEntityKind: unique symbol;
|
|
3
|
+
export interface LZEntity {
|
|
4
|
+
[entityKind]: string;
|
|
5
|
+
}
|
|
6
|
+
export type LZEntityClass<T> = ((abstract new (...args: any[]) => T) | (new (...args: any[]) => T)) & LZEntity;
|
|
7
|
+
export declare function is<T extends LZEntityClass<any>>(value: any, type: T): value is InstanceType<T>;
|
|
8
8
|
//# sourceMappingURL=entity.d.ts.map
|
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
export const entityKind = Symbol.for('lz:entityKind');
|
|
2
|
-
export const hasOwnEntityKind = Symbol.for('lz:hasOwnEntityKind');
|
|
3
|
-
export function is(value, type) {
|
|
4
|
-
if (!value || typeof value !== 'object') {
|
|
5
|
-
return false;
|
|
6
|
-
}
|
|
7
|
-
if (value instanceof type) {
|
|
8
|
-
return true;
|
|
9
|
-
}
|
|
10
|
-
if (!Object.prototype.hasOwnProperty.call(type, entityKind)) {
|
|
11
|
-
throw new Error(`Class "${type.name ?? '<unknown>'}" doesn't look like a LZ entity. If this is incorrect and the class is provided by LZ, please report this as a bug.`);
|
|
12
|
-
}
|
|
13
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access
|
|
14
|
-
let cls = value.constructor;
|
|
15
|
-
if (cls) {
|
|
16
|
-
// Traverse the prototype chain to find the entityKind
|
|
17
|
-
while (cls) {
|
|
18
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
19
|
-
if (entityKind in cls && cls[entityKind] === type[entityKind]) {
|
|
20
|
-
return true;
|
|
21
|
-
}
|
|
22
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
23
|
-
cls = Object.getPrototypeOf(cls);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
return false;
|
|
27
|
-
}
|
|
1
|
+
export const entityKind = Symbol.for('lz:entityKind');
|
|
2
|
+
export const hasOwnEntityKind = Symbol.for('lz:hasOwnEntityKind');
|
|
3
|
+
export function is(value, type) {
|
|
4
|
+
if (!value || typeof value !== 'object') {
|
|
5
|
+
return false;
|
|
6
|
+
}
|
|
7
|
+
if (value instanceof type) {
|
|
8
|
+
return true;
|
|
9
|
+
}
|
|
10
|
+
if (!Object.prototype.hasOwnProperty.call(type, entityKind)) {
|
|
11
|
+
throw new Error(`Class "${type.name ?? '<unknown>'}" doesn't look like a LZ entity. If this is incorrect and the class is provided by LZ, please report this as a bug.`);
|
|
12
|
+
}
|
|
13
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access
|
|
14
|
+
let cls = value.constructor;
|
|
15
|
+
if (cls) {
|
|
16
|
+
// Traverse the prototype chain to find the entityKind
|
|
17
|
+
while (cls) {
|
|
18
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
19
|
+
if (entityKind in cls && cls[entityKind] === type[entityKind]) {
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
23
|
+
cls = Object.getPrototypeOf(cls);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { is } from
|
|
2
|
-
export { entityKind } from
|
|
3
|
-
export type { LZEntity } from
|
|
4
|
-
export { hasOwnEntityKind } from
|
|
1
|
+
export { is } from './entity.js';
|
|
2
|
+
export { entityKind } from './entity.js';
|
|
3
|
+
export type { LZEntity } from './entity.js';
|
|
4
|
+
export { hasOwnEntityKind } from './entity.js';
|
|
5
5
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/helpers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/helpers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAA;AAChC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,YAAY,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { is } from
|
|
2
|
-
export { entityKind } from
|
|
3
|
-
export { hasOwnEntityKind } from
|
|
1
|
+
export { is } from './entity.js';
|
|
2
|
+
export { entityKind } from './entity.js';
|
|
3
|
+
export { hasOwnEntityKind } from './entity.js';
|
package/dist/core/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
export * from
|
|
2
|
-
export * from
|
|
3
|
-
export * from
|
|
4
|
-
export * from
|
|
5
|
-
export * from
|
|
6
|
-
export * from
|
|
7
|
-
export * from
|
|
1
|
+
export * from './config/index.js';
|
|
2
|
+
export * from './factories/index.js';
|
|
3
|
+
export * from './fields/index.js';
|
|
4
|
+
export * from './sections/index.js';
|
|
5
|
+
export * from './submit/index.js';
|
|
6
|
+
export * from './db/index.js';
|
|
7
|
+
export * from './helpers/index.js';
|
|
8
8
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/core/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAA;AACjC,cAAc,sBAAsB,CAAA;AACpC,cAAc,mBAAmB,CAAA;AACjC,cAAc,qBAAqB,CAAA;AACnC,cAAc,mBAAmB,CAAA;AACjC,cAAc,eAAe,CAAA;AAC7B,cAAc,oBAAoB,CAAA"}
|
package/dist/core/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export * from
|
|
2
|
-
export * from
|
|
3
|
-
export * from
|
|
4
|
-
export * from
|
|
5
|
-
export * from
|
|
6
|
-
export * from
|
|
7
|
-
export * from
|
|
1
|
+
export * from './config/index.js';
|
|
2
|
+
export * from './factories/index.js';
|
|
3
|
+
export * from './fields/index.js';
|
|
4
|
+
export * from './sections/index.js';
|
|
5
|
+
export * from './submit/index.js';
|
|
6
|
+
export * from './db/index.js';
|
|
7
|
+
export * from './helpers/index.js';
|