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,341 +1,341 @@
|
|
|
1
|
-
import { entityKind } from
|
|
2
|
-
import { numberField } from
|
|
3
|
-
import chalk from 'chalk';
|
|
4
|
-
import * as z from 'zod';
|
|
5
|
-
import { getCMSConfig } from
|
|
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
|
+
}
|