@contentstack/cli-audit 1.0.0 → 1.2.1
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/README.md +108 -25
- package/lib/audit-base-command.d.ts +83 -0
- package/lib/audit-base-command.js +263 -0
- package/lib/commands/cm/stacks/audit/fix.d.ts +9 -4
- package/lib/commands/cm/stacks/audit/fix.js +51 -7
- package/lib/commands/cm/stacks/audit/index.d.ts +2 -51
- package/lib/commands/cm/stacks/audit/index.js +5 -201
- package/lib/messages/index.d.ts +12 -6
- package/lib/messages/index.js +17 -10
- package/lib/modules/content-types.d.ts +59 -4
- package/lib/modules/content-types.js +241 -33
- package/lib/modules/entries.d.ts +128 -7
- package/lib/modules/entries.js +376 -60
- package/lib/types/content-types.d.ts +11 -4
- package/lib/types/entries.d.ts +6 -3
- package/oclif.manifest.json +102 -10
- package/package.json +9 -10
package/lib/modules/entries.js
CHANGED
|
@@ -2,25 +2,27 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const tslib_1 = require("tslib");
|
|
4
4
|
const find_1 = tslib_1.__importDefault(require("lodash/find"));
|
|
5
|
+
const core_1 = require("@oclif/core");
|
|
5
6
|
const values_1 = tslib_1.__importDefault(require("lodash/values"));
|
|
6
7
|
const isEmpty_1 = tslib_1.__importDefault(require("lodash/isEmpty"));
|
|
7
8
|
const path_1 = require("path");
|
|
8
|
-
const fs_1 = require("fs");
|
|
9
9
|
const cli_utilities_1 = require("@contentstack/cli-utilities");
|
|
10
|
+
const fs_1 = require("fs");
|
|
11
|
+
const content_types_1 = tslib_1.__importDefault(require("./content-types"));
|
|
10
12
|
const messages_1 = require("../messages");
|
|
11
13
|
class Entries {
|
|
12
|
-
constructor({ log, config, moduleName, ctSchema, gfSchema }) {
|
|
14
|
+
constructor({ log, fix, config, moduleName, ctSchema, gfSchema }) {
|
|
13
15
|
this.missingRefs = {};
|
|
14
16
|
this.entryMetaData = [];
|
|
15
|
-
this.moduleName = '
|
|
17
|
+
this.moduleName = 'entries';
|
|
16
18
|
this.log = log;
|
|
17
19
|
this.config = config;
|
|
20
|
+
this.fix = fix !== null && fix !== void 0 ? fix : false;
|
|
18
21
|
this.ctSchema = ctSchema;
|
|
19
22
|
this.gfSchema = gfSchema;
|
|
23
|
+
this.moduleName = moduleName !== null && moduleName !== void 0 ? moduleName : 'entries';
|
|
20
24
|
this.fileName = config.moduleConfig[this.moduleName].fileName;
|
|
21
25
|
this.folderPath = (0, path_1.resolve)(config.basePath, config.moduleConfig.entries.dirName);
|
|
22
|
-
if (moduleName)
|
|
23
|
-
this.moduleName = moduleName;
|
|
24
26
|
}
|
|
25
27
|
/**
|
|
26
28
|
* The `run` function checks if a folder path exists, sets the schema based on the module name,
|
|
@@ -32,36 +34,82 @@ class Entries {
|
|
|
32
34
|
throw new Error((0, messages_1.$t)(messages_1.auditMsg.NOT_VALID_PATH, { path: this.folderPath }));
|
|
33
35
|
}
|
|
34
36
|
await this.prepareEntryMetaData();
|
|
37
|
+
await this.fixPrerequisiteData();
|
|
35
38
|
for (const { code } of this.locales) {
|
|
36
39
|
for (const ctSchema of this.ctSchema) {
|
|
37
40
|
const basePath = (0, path_1.join)(this.folderPath, ctSchema.uid, code);
|
|
38
41
|
const fsUtility = new cli_utilities_1.FsUtility({ basePath, indexFileName: 'index.json' });
|
|
39
42
|
const indexer = fsUtility.indexFileContent;
|
|
40
|
-
for (const
|
|
43
|
+
for (const fileIndex in indexer) {
|
|
41
44
|
const entries = (await fsUtility.readChunkFiles.next());
|
|
42
|
-
|
|
43
|
-
|
|
45
|
+
this.entries = entries;
|
|
46
|
+
for (const entryUid in this.entries) {
|
|
47
|
+
const entry = this.entries[entryUid];
|
|
44
48
|
const { uid, title } = entry;
|
|
45
49
|
this.currentUid = uid;
|
|
46
50
|
this.currentTitle = title;
|
|
47
51
|
this.missingRefs[this.currentUid] = [];
|
|
48
|
-
|
|
52
|
+
this.lookForReference([{ uid, name: title }], ctSchema, this.entries[entryUid]);
|
|
49
53
|
this.log((0, messages_1.$t)(messages_1.auditMsg.SCAN_ENTRY_SUCCESS_MSG, {
|
|
50
54
|
title,
|
|
51
55
|
local: code,
|
|
52
56
|
module: this.config.moduleConfig.entries.name,
|
|
53
57
|
}), 'info');
|
|
54
58
|
}
|
|
59
|
+
if (this.fix) {
|
|
60
|
+
await this.writeFixContent(`${basePath}/${indexer[fileIndex]}`, this.entries);
|
|
61
|
+
}
|
|
55
62
|
}
|
|
56
63
|
}
|
|
57
64
|
}
|
|
58
65
|
this.log('', 'info'); // Adding empty line
|
|
66
|
+
this.removeEmptyVal();
|
|
67
|
+
return this.missingRefs;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* The function removes any properties from the `missingRefs` object that have an empty array value.
|
|
71
|
+
*/
|
|
72
|
+
removeEmptyVal() {
|
|
59
73
|
for (let propName in this.missingRefs) {
|
|
60
74
|
if (!this.missingRefs[propName].length) {
|
|
61
75
|
delete this.missingRefs[propName];
|
|
62
76
|
}
|
|
63
77
|
}
|
|
64
|
-
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* The function `fixPrerequisiteData` fixes the prerequisite data by updating the `ctSchema` and
|
|
81
|
+
* `gfSchema` properties using the `ContentType` class.
|
|
82
|
+
*/
|
|
83
|
+
async fixPrerequisiteData() {
|
|
84
|
+
this.ctSchema = (await new content_types_1.default({
|
|
85
|
+
fix: true,
|
|
86
|
+
log: () => { },
|
|
87
|
+
config: this.config,
|
|
88
|
+
moduleName: 'content-types',
|
|
89
|
+
ctSchema: this.ctSchema,
|
|
90
|
+
gfSchema: this.gfSchema,
|
|
91
|
+
}).run(true));
|
|
92
|
+
this.gfSchema = (await new content_types_1.default({
|
|
93
|
+
fix: true,
|
|
94
|
+
log: () => { },
|
|
95
|
+
config: this.config,
|
|
96
|
+
moduleName: 'entries',
|
|
97
|
+
ctSchema: this.ctSchema,
|
|
98
|
+
gfSchema: this.gfSchema,
|
|
99
|
+
}).run(true));
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* The function checks if it can write the fix content to a file and if so, it writes the content as
|
|
103
|
+
* JSON to the specified file path.
|
|
104
|
+
*/
|
|
105
|
+
async writeFixContent(filePath, schema) {
|
|
106
|
+
let canWrite = true;
|
|
107
|
+
if (this.fix && !this.config.flags['copy-dir']) {
|
|
108
|
+
canWrite = this.config.flags.yes || (await core_1.ux.confirm(messages_1.commonMsg.FIX_CONFIRMATION));
|
|
109
|
+
}
|
|
110
|
+
if (canWrite) {
|
|
111
|
+
(0, fs_1.writeFileSync)(filePath, JSON.stringify(schema));
|
|
112
|
+
}
|
|
65
113
|
}
|
|
66
114
|
/**
|
|
67
115
|
* The function `lookForReference` iterates over a given schema and validates different field types
|
|
@@ -75,30 +123,36 @@ class Entries {
|
|
|
75
123
|
* EntryGroupFieldDataType} entry - The `entry` parameter is an object that represents the data of an
|
|
76
124
|
* entry. It can have different types depending on the `schema` parameter.
|
|
77
125
|
*/
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
126
|
+
lookForReference(tree, field, entry) {
|
|
127
|
+
var _a;
|
|
128
|
+
if (this.fix) {
|
|
129
|
+
entry = this.runFixOnSchema(tree, field.schema, entry);
|
|
130
|
+
}
|
|
131
|
+
for (const child of (_a = field.schema) !== null && _a !== void 0 ? _a : []) {
|
|
132
|
+
const { uid } = child;
|
|
133
|
+
if (!(entry === null || entry === void 0 ? void 0 : entry[uid]))
|
|
134
|
+
return;
|
|
135
|
+
switch (child.data_type) {
|
|
82
136
|
case 'reference':
|
|
83
|
-
this.missingRefs[this.currentUid].push(...this.validateReferenceField([...tree, { uid:
|
|
137
|
+
this.missingRefs[this.currentUid].push(...this.validateReferenceField([...tree, { uid: child.uid, name: child.display_name, field: uid }], child, entry[uid]));
|
|
84
138
|
break;
|
|
85
139
|
case 'global_field':
|
|
86
|
-
|
|
140
|
+
this.validateGlobalField([...tree, { uid: child.uid, name: child.display_name, field: uid }], child, entry[uid]);
|
|
87
141
|
break;
|
|
88
142
|
case 'json':
|
|
89
|
-
if (
|
|
143
|
+
if (child.field_metadata.extension) {
|
|
90
144
|
// NOTE Custom field type
|
|
91
145
|
}
|
|
92
|
-
else if (
|
|
146
|
+
else if (child.field_metadata.allow_json_rte) {
|
|
93
147
|
// NOTE JSON RTE field type
|
|
94
|
-
|
|
148
|
+
this.validateJsonRTEFields([...tree, { uid: child.uid, name: child.display_name, field: uid }], child, entry[uid]);
|
|
95
149
|
}
|
|
96
150
|
break;
|
|
97
151
|
case 'blocks':
|
|
98
|
-
|
|
152
|
+
this.validateModularBlocksField([...tree, { uid: child.uid, name: child.display_name, field: uid }], child, entry[uid]);
|
|
99
153
|
break;
|
|
100
154
|
case 'group':
|
|
101
|
-
|
|
155
|
+
this.validateGroupField([...tree, { uid: field.uid, name: child.display_name, field: uid }], child, entry[uid]);
|
|
102
156
|
break;
|
|
103
157
|
}
|
|
104
158
|
}
|
|
@@ -131,9 +185,9 @@ class Entries {
|
|
|
131
185
|
* @param {EntryGlobalFieldDataType} field - The `field` parameter is of type
|
|
132
186
|
* `EntryGlobalFieldDataType`. It represents a single global field entry.
|
|
133
187
|
*/
|
|
134
|
-
|
|
188
|
+
validateGlobalField(tree, fieldStructure, field) {
|
|
135
189
|
// NOTE Any GlobalField related logic can be added here
|
|
136
|
-
|
|
190
|
+
this.lookForReference(tree, fieldStructure, field);
|
|
137
191
|
}
|
|
138
192
|
/**
|
|
139
193
|
* The function `validateJsonRTEFields` is used to validate the JSON RTE fields by checking if the
|
|
@@ -147,32 +201,18 @@ class Entries {
|
|
|
147
201
|
* `EntryJsonRTEFieldDataType`, which represents a JSON RTE field in an entry. It contains properties
|
|
148
202
|
* such as `uid`, `attrs`, and `children`.
|
|
149
203
|
*/
|
|
150
|
-
|
|
204
|
+
validateJsonRTEFields(tree, fieldStructure, field) {
|
|
151
205
|
var _a;
|
|
206
|
+
// const missingRefIndex = []
|
|
152
207
|
// NOTE Other possible reference logic will be added related to JSON RTE (Ex missing assets, extensions etc.,)
|
|
153
|
-
for (const
|
|
154
|
-
const
|
|
155
|
-
const {
|
|
156
|
-
if (
|
|
157
|
-
|
|
158
|
-
if (!refExist) {
|
|
159
|
-
tree.push({ field: 'children' }, { field: childrenUid, uid: fieldStructure.uid });
|
|
160
|
-
this.missingRefs[this.currentUid].push({
|
|
161
|
-
tree,
|
|
162
|
-
uid: this.currentUid,
|
|
163
|
-
name: this.currentTitle,
|
|
164
|
-
data_type: fieldStructure.data_type,
|
|
165
|
-
display_name: fieldStructure.display_name,
|
|
166
|
-
treeStr: tree
|
|
167
|
-
.map(({ name }) => name)
|
|
168
|
-
.filter((val) => val)
|
|
169
|
-
.join(' ➜ '),
|
|
170
|
-
missingRefs: [{ uid: entryUid, 'content-type-uid': contentTypeUid }],
|
|
171
|
-
});
|
|
172
|
-
}
|
|
208
|
+
for (const index in (_a = field === null || field === void 0 ? void 0 : field.children) !== null && _a !== void 0 ? _a : []) {
|
|
209
|
+
const child = field.children[index];
|
|
210
|
+
const { children } = child;
|
|
211
|
+
if (!this.fix) {
|
|
212
|
+
this.jsonRefCheck(tree, fieldStructure, child);
|
|
173
213
|
}
|
|
174
214
|
if (!(0, isEmpty_1.default)(children)) {
|
|
175
|
-
|
|
215
|
+
this.validateJsonRTEFields(tree, fieldStructure, field.children[index]);
|
|
176
216
|
}
|
|
177
217
|
}
|
|
178
218
|
}
|
|
@@ -189,15 +229,18 @@ class Entries {
|
|
|
189
229
|
* @param {EntryModularBlocksDataType[]} field - The `field` parameter is an array of objects of type
|
|
190
230
|
* `EntryModularBlocksDataType`.
|
|
191
231
|
*/
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
232
|
+
validateModularBlocksField(tree, fieldStructure, field) {
|
|
233
|
+
if (!this.fix) {
|
|
234
|
+
for (const index in field) {
|
|
235
|
+
this.modularBlockRefCheck(tree, fieldStructure.blocks, field[index], +index);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
for (const block of fieldStructure.blocks) {
|
|
239
|
+
const { uid, title } = block;
|
|
240
|
+
for (const eBlock of field) {
|
|
241
|
+
if (eBlock[uid]) {
|
|
242
|
+
this.lookForReference([...tree, { uid, name: title }], block, eBlock[uid]);
|
|
243
|
+
}
|
|
201
244
|
}
|
|
202
245
|
}
|
|
203
246
|
}
|
|
@@ -210,9 +253,16 @@ class Entries {
|
|
|
210
253
|
* @param {EntryGroupFieldDataType} field - The `field` parameter is of type
|
|
211
254
|
* `EntryGroupFieldDataType` and represents a single group field entry.
|
|
212
255
|
*/
|
|
213
|
-
|
|
256
|
+
validateGroupField(tree, fieldStructure, field) {
|
|
214
257
|
// NOTE Any Group Field related logic can be added here (Ex data serialization or picking any metadata for report etc.,)
|
|
215
|
-
|
|
258
|
+
if (Array.isArray(field)) {
|
|
259
|
+
field.forEach((eGroup) => {
|
|
260
|
+
this.lookForReference([...tree, { uid: fieldStructure.uid, display_name: fieldStructure.display_name }], fieldStructure, eGroup);
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
else {
|
|
264
|
+
this.lookForReference(tree, fieldStructure, field);
|
|
265
|
+
}
|
|
216
266
|
}
|
|
217
267
|
/**
|
|
218
268
|
* The function `validateReferenceValues` checks if the references in a given field exist in the
|
|
@@ -230,9 +280,12 @@ class Entries {
|
|
|
230
280
|
* objects.
|
|
231
281
|
*/
|
|
232
282
|
validateReferenceValues(tree, fieldStructure, field) {
|
|
283
|
+
if (this.fix)
|
|
284
|
+
return [];
|
|
233
285
|
const missingRefs = [];
|
|
234
|
-
const { data_type, display_name } = fieldStructure;
|
|
235
|
-
for (const
|
|
286
|
+
const { uid: data_type, display_name } = fieldStructure;
|
|
287
|
+
for (const index in field !== null && field !== void 0 ? field : []) {
|
|
288
|
+
const reference = field[index];
|
|
236
289
|
const { uid } = reference;
|
|
237
290
|
// NOTE Can skip specific references keys (Ex, system defined keys can be skipped)
|
|
238
291
|
// if (this.config.skipRefs.includes(reference)) continue;
|
|
@@ -258,6 +311,269 @@ class Entries {
|
|
|
258
311
|
]
|
|
259
312
|
: [];
|
|
260
313
|
}
|
|
314
|
+
/**
|
|
315
|
+
* The function `runFixOnSchema` takes in a tree, schema, and entry, and applies fixes to the entry
|
|
316
|
+
* based on the schema.
|
|
317
|
+
* @param {Record<string, unknown>[]} tree - An array of objects representing the tree structure of
|
|
318
|
+
* the schema. Each object has the following properties:
|
|
319
|
+
* @param {ContentTypeSchemaType[]} schema - The `schema` parameter is an array of objects
|
|
320
|
+
* representing the content type schema. Each object in the array contains information about a
|
|
321
|
+
* specific field in the schema, such as its unique identifier (`uid`) and data type (`data_type`).
|
|
322
|
+
* @param {EntryFieldType} entry - The `entry` parameter is of type `EntryFieldType`, which
|
|
323
|
+
* represents the data of an entry. It is an object that contains fields as key-value pairs, where
|
|
324
|
+
* the key is the field UID (unique identifier) and the value is the field data.
|
|
325
|
+
* @returns the updated `entry` object after applying fixes to the fields based on the provided
|
|
326
|
+
* `schema`.
|
|
327
|
+
*/
|
|
328
|
+
runFixOnSchema(tree, schema, entry) {
|
|
329
|
+
// NOTE Global field Fix
|
|
330
|
+
schema.forEach((field) => {
|
|
331
|
+
const { uid, data_type } = field;
|
|
332
|
+
switch (data_type) {
|
|
333
|
+
case 'global_field':
|
|
334
|
+
entry[uid] = this.fixGlobalFieldReferences([...tree, { uid: field.uid, name: field.display_name, data_type: field.data_type }], field, entry[uid]);
|
|
335
|
+
break;
|
|
336
|
+
case 'json':
|
|
337
|
+
case 'reference':
|
|
338
|
+
if (data_type === 'json') {
|
|
339
|
+
if (field.field_metadata.extension) {
|
|
340
|
+
// NOTE Custom field type
|
|
341
|
+
break;
|
|
342
|
+
}
|
|
343
|
+
else if (field.field_metadata.allow_json_rte) {
|
|
344
|
+
this.fixJsonRteMissingReferences([...tree, { uid: field.uid, name: field.display_name, data_type: field.data_type }], field, entry[uid]);
|
|
345
|
+
break;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
// NOTE Reference field
|
|
349
|
+
entry[uid] = this.fixMissingReferences([...tree, { uid: field.uid, name: field.display_name, data_type: field.data_type }], field, entry[uid]);
|
|
350
|
+
break;
|
|
351
|
+
case 'blocks':
|
|
352
|
+
entry[uid] = this.fixModularBlocksReferences([...tree, { uid: field.uid, name: field.display_name, data_type: field.data_type }], field.blocks, entry[uid]);
|
|
353
|
+
break;
|
|
354
|
+
case 'group':
|
|
355
|
+
entry[uid] = this.fixGroupField([...tree, { uid: field.uid, name: field.display_name, data_type: field.data_type }], field, entry[uid]);
|
|
356
|
+
break;
|
|
357
|
+
}
|
|
358
|
+
});
|
|
359
|
+
return entry;
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* The function `fixGlobalFieldReferences` adds a new entry to a tree data structure and runs a fix
|
|
363
|
+
* on the schema.
|
|
364
|
+
* @param {Record<string, unknown>[]} tree - An array of objects representing the tree structure.
|
|
365
|
+
* @param {GlobalFieldDataType} field - The `field` parameter is of type `GlobalFieldDataType` and
|
|
366
|
+
* represents a global field object. It contains properties such as `uid` and `display_name`.
|
|
367
|
+
* @param {EntryGlobalFieldDataType} entry - The `entry` parameter is of type
|
|
368
|
+
* `EntryGlobalFieldDataType` and represents the global field entry that needs to be fixed.
|
|
369
|
+
* @returns the result of calling the `runFixOnSchema` method with the updated `tree` array,
|
|
370
|
+
* `field.schema`, and `entry` as arguments.
|
|
371
|
+
*/
|
|
372
|
+
fixGlobalFieldReferences(tree, field, entry) {
|
|
373
|
+
return this.runFixOnSchema([...tree, { uid: field.uid, display_name: field.display_name }], field.schema, entry);
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* The function `fixModularBlocksReferences` takes in a tree, a list of blocks, and an entry, and
|
|
377
|
+
* performs various operations to fix references within the entry.
|
|
378
|
+
* @param {Record<string, unknown>[]} tree - An array of objects representing the tree structure of
|
|
379
|
+
* the modular blocks.
|
|
380
|
+
* @param {ModularBlockType[]} blocks - An array of objects representing modular blocks. Each object
|
|
381
|
+
* has properties like `uid` (unique identifier) and `title` (display name).
|
|
382
|
+
* @param {EntryModularBlocksDataType[]} entry - An array of objects representing the modular blocks
|
|
383
|
+
* data in an entry. Each object in the array represents a modular block and contains its unique
|
|
384
|
+
* identifier (uid) and other properties.
|
|
385
|
+
* @returns the updated `entry` array after performing some modifications.
|
|
386
|
+
*/
|
|
387
|
+
fixModularBlocksReferences(tree, blocks, entry) {
|
|
388
|
+
entry = entry
|
|
389
|
+
.map((block, index) => this.modularBlockRefCheck(tree, blocks, block, index))
|
|
390
|
+
.filter((val) => !(0, isEmpty_1.default)(val));
|
|
391
|
+
blocks.forEach((block) => {
|
|
392
|
+
entry = entry
|
|
393
|
+
.map((eBlock) => {
|
|
394
|
+
if (!(0, isEmpty_1.default)(block.schema)) {
|
|
395
|
+
if (eBlock[block.uid]) {
|
|
396
|
+
eBlock[block.uid] = this.runFixOnSchema([...tree, { uid: block.uid, display_name: block.title }], block.schema, eBlock[block.uid]);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
return eBlock;
|
|
400
|
+
})
|
|
401
|
+
.filter((val) => !(0, isEmpty_1.default)(val));
|
|
402
|
+
});
|
|
403
|
+
return entry;
|
|
404
|
+
}
|
|
405
|
+
/**
|
|
406
|
+
* The function `fixGroupField` takes in a tree, a field, and an entry, and if the field has a
|
|
407
|
+
* schema, it runs a fix on the schema and returns the updated entry, otherwise it returns the
|
|
408
|
+
* original entry.
|
|
409
|
+
* @param {Record<string, unknown>[]} tree - An array of objects representing the tree structure.
|
|
410
|
+
* @param {GroupFieldDataType} field - The `field` parameter is of type `GroupFieldDataType` and
|
|
411
|
+
* represents a group field object. It contains properties such as `uid` (unique identifier) and
|
|
412
|
+
* `display_name` (name of the field).
|
|
413
|
+
* @param {EntryGroupFieldDataType} entry - The `entry` parameter is of type
|
|
414
|
+
* `EntryGroupFieldDataType`.
|
|
415
|
+
* @returns If the `field.schema` is not empty, the function will return the result of calling
|
|
416
|
+
* `this.runFixOnSchema` with the updated `tree`, `field.schema`, and `entry` as arguments.
|
|
417
|
+
* Otherwise, it will return the `entry` as is.
|
|
418
|
+
*/
|
|
419
|
+
fixGroupField(tree, field, entry) {
|
|
420
|
+
if (!(0, isEmpty_1.default)(field.schema)) {
|
|
421
|
+
if (Array.isArray(entry)) {
|
|
422
|
+
entry = entry.map((eGroup) => {
|
|
423
|
+
return this.runFixOnSchema([...tree, { uid: field.uid, display_name: field.display_name }], field.schema, eGroup);
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
else {
|
|
427
|
+
entry = this.runFixOnSchema([...tree, { uid: field.uid, display_name: field.display_name }], field.schema, entry);
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
return entry;
|
|
431
|
+
}
|
|
432
|
+
/**
|
|
433
|
+
* The function fixes missing references in a JSON tree structure.
|
|
434
|
+
* @param {Record<string, unknown>[]} tree - An array of objects representing a tree structure. Each
|
|
435
|
+
* object in the array has a string key and an unknown value.
|
|
436
|
+
* @param {ReferenceFieldDataType | JsonRTEFieldDataType} field - The `field` parameter can be of
|
|
437
|
+
* type `ReferenceFieldDataType` or `JsonRTEFieldDataType`.
|
|
438
|
+
* @param {EntryJsonRTEFieldDataType} entry - The `entry` parameter is of type
|
|
439
|
+
* `EntryJsonRTEFieldDataType`, which represents an entry in a JSON Rich Text Editor (JsonRTE) field.
|
|
440
|
+
* @returns the updated `entry` object with fixed missing references in the `children` property.
|
|
441
|
+
*/
|
|
442
|
+
fixJsonRteMissingReferences(tree, field, entry) {
|
|
443
|
+
if (Array.isArray(entry)) {
|
|
444
|
+
entry = entry.map((child, index) => {
|
|
445
|
+
return this.fixJsonRteMissingReferences([...tree, { index, type: child === null || child === void 0 ? void 0 : child.type, uid: child === null || child === void 0 ? void 0 : child.uid }], field, child);
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
else {
|
|
449
|
+
entry.children = entry.children
|
|
450
|
+
.map((child) => {
|
|
451
|
+
const refExist = this.jsonRefCheck(tree, field, child);
|
|
452
|
+
if (!refExist)
|
|
453
|
+
return null;
|
|
454
|
+
if ((0, isEmpty_1.default)(child.children)) {
|
|
455
|
+
child = this.fixJsonRteMissingReferences(tree, field, child);
|
|
456
|
+
}
|
|
457
|
+
return child;
|
|
458
|
+
})
|
|
459
|
+
.filter((val) => val);
|
|
460
|
+
}
|
|
461
|
+
return entry;
|
|
462
|
+
}
|
|
463
|
+
/**
|
|
464
|
+
* The `fixMissingReferences` function checks for missing references in an entry and adds them to a
|
|
465
|
+
* list if they are not found.
|
|
466
|
+
* @param {Record<string, unknown>[]} tree - An array of objects representing a tree structure. Each
|
|
467
|
+
* object in the array should have a "name" property and an optional "index" property.
|
|
468
|
+
* @param {ReferenceFieldDataType | JsonRTEFieldDataType} field - The `field` parameter is of type
|
|
469
|
+
* `ReferenceFieldDataType` or `JsonRTEFieldDataType`.
|
|
470
|
+
* @param {EntryReferenceFieldDataType[]} entry - The `entry` parameter is an array of objects that
|
|
471
|
+
* represent references to other entries. Each object in the array has the following properties:
|
|
472
|
+
* @returns the `entry` variable.
|
|
473
|
+
*/
|
|
474
|
+
fixMissingReferences(tree, field, entry) {
|
|
475
|
+
const missingRefs = [];
|
|
476
|
+
entry = entry
|
|
477
|
+
.map((reference) => {
|
|
478
|
+
const { uid } = reference;
|
|
479
|
+
const refExist = (0, find_1.default)(this.entryMetaData, { uid });
|
|
480
|
+
if (!refExist) {
|
|
481
|
+
missingRefs.push(reference);
|
|
482
|
+
return null;
|
|
483
|
+
}
|
|
484
|
+
return reference;
|
|
485
|
+
})
|
|
486
|
+
.filter((val) => val);
|
|
487
|
+
if (!(0, isEmpty_1.default)(missingRefs)) {
|
|
488
|
+
this.missingRefs[this.currentUid].push({
|
|
489
|
+
tree,
|
|
490
|
+
fixStatus: 'Fixed',
|
|
491
|
+
uid: this.currentUid,
|
|
492
|
+
name: this.currentTitle,
|
|
493
|
+
data_type: field.data_type,
|
|
494
|
+
display_name: field.display_name,
|
|
495
|
+
treeStr: tree
|
|
496
|
+
.map(({ name, index }) => (index || index === 0 ? `[${+index}].${name}` : name))
|
|
497
|
+
.filter((val) => val)
|
|
498
|
+
.join(' ➜ '),
|
|
499
|
+
missingRefs,
|
|
500
|
+
});
|
|
501
|
+
}
|
|
502
|
+
return entry;
|
|
503
|
+
}
|
|
504
|
+
/**
|
|
505
|
+
* The function `modularBlockRefCheck` checks for invalid keys in an entry block and returns the
|
|
506
|
+
* updated entry block.
|
|
507
|
+
* @param {Record<string, unknown>[]} tree - An array of objects representing the tree structure of
|
|
508
|
+
* the blocks.
|
|
509
|
+
* @param {ModularBlockType[]} blocks - The `blocks` parameter is an array of `ModularBlockType`
|
|
510
|
+
* objects.
|
|
511
|
+
* @param {EntryModularBlocksDataType} entryBlock - The `entryBlock` parameter is an object that
|
|
512
|
+
* represents a modular block entry. It contains key-value pairs where the keys are the UIDs of the
|
|
513
|
+
* modular blocks and the values are the data associated with each modular block.
|
|
514
|
+
* @param {Number} index - The `index` parameter is a number that represents the index of the current
|
|
515
|
+
* block in the `tree` array.
|
|
516
|
+
* @returns the `entryBlock` object.
|
|
517
|
+
*/
|
|
518
|
+
modularBlockRefCheck(tree, blocks, entryBlock, index) {
|
|
519
|
+
const validBlockUid = blocks.map((block) => block.uid);
|
|
520
|
+
const invalidKeys = Object.keys(entryBlock).filter((key) => !validBlockUid.includes(key));
|
|
521
|
+
invalidKeys.forEach((key) => {
|
|
522
|
+
if (this.fix) {
|
|
523
|
+
delete entryBlock[key];
|
|
524
|
+
}
|
|
525
|
+
this.missingRefs[this.currentUid].push({
|
|
526
|
+
uid: this.currentUid,
|
|
527
|
+
name: this.currentTitle,
|
|
528
|
+
data_type: key,
|
|
529
|
+
display_name: key,
|
|
530
|
+
fixStatus: this.fix ? 'Fixed' : undefined,
|
|
531
|
+
tree: [...tree, { index, uid: key, name: key }],
|
|
532
|
+
treeStr: [...tree, { index, uid: key, name: key }]
|
|
533
|
+
.map(({ name, index }) => (index || index === 0 ? `[${+index}].${name}` : name))
|
|
534
|
+
.filter((val) => val)
|
|
535
|
+
.join(' ➜ '),
|
|
536
|
+
missingRefs: [key],
|
|
537
|
+
});
|
|
538
|
+
});
|
|
539
|
+
return entryBlock;
|
|
540
|
+
}
|
|
541
|
+
/**
|
|
542
|
+
* The `jsonRefCheck` function checks if a reference exists in a JSON tree and adds missing
|
|
543
|
+
* references to a list if they are not found.
|
|
544
|
+
* @param {Record<string, unknown>[]} tree - An array of objects representing the tree structure.
|
|
545
|
+
* @param {JsonRTEFieldDataType} schema - The `schema` parameter is of type `JsonRTEFieldDataType`
|
|
546
|
+
* and represents the schema of a JSON field. It contains properties such as `uid`, `data_type`, and
|
|
547
|
+
* `display_name`.
|
|
548
|
+
* @param {EntryJsonRTEFieldDataType} child - The `child` parameter is an object that represents a
|
|
549
|
+
* child entry in a JSON tree. It has the following properties:
|
|
550
|
+
* @returns The function `jsonRefCheck` returns either `null` or `true`.
|
|
551
|
+
*/
|
|
552
|
+
jsonRefCheck(tree, schema, child) {
|
|
553
|
+
const { uid: childrenUid } = child;
|
|
554
|
+
const { 'entry-uid': entryUid, 'content-type-uid': contentTypeUid } = child.attrs || {};
|
|
555
|
+
if (entryUid) {
|
|
556
|
+
const refExist = (0, find_1.default)(this.entryMetaData, { uid: entryUid });
|
|
557
|
+
if (!refExist) {
|
|
558
|
+
tree.push({ field: 'children' }, { field: childrenUid, uid: schema.uid });
|
|
559
|
+
this.missingRefs[this.currentUid].push({
|
|
560
|
+
tree,
|
|
561
|
+
uid: this.currentUid,
|
|
562
|
+
name: this.currentTitle,
|
|
563
|
+
data_type: schema.data_type,
|
|
564
|
+
display_name: schema.display_name,
|
|
565
|
+
fixStatus: this.fix ? 'Fixed' : undefined,
|
|
566
|
+
treeStr: tree
|
|
567
|
+
.map(({ name }) => name)
|
|
568
|
+
.filter((val) => val)
|
|
569
|
+
.join(' ➜ '),
|
|
570
|
+
missingRefs: [{ uid: entryUid, 'content-type-uid': contentTypeUid }],
|
|
571
|
+
});
|
|
572
|
+
return null;
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
return true;
|
|
576
|
+
}
|
|
261
577
|
/**
|
|
262
578
|
* The function prepares entry metadata by reading and processing files from different locales and
|
|
263
579
|
* schemas.
|
|
@@ -267,8 +583,8 @@ class Entries {
|
|
|
267
583
|
const localesFolderPath = (0, path_1.resolve)(this.config.basePath, this.config.moduleConfig.locales.dirName);
|
|
268
584
|
const localesPath = (0, path_1.join)(localesFolderPath, this.config.moduleConfig.locales.fileName);
|
|
269
585
|
const masterLocalesPath = (0, path_1.join)(localesFolderPath, 'master-locale.json');
|
|
270
|
-
this.locales = (0, values_1.default)(JSON.parse((0, fs_1.readFileSync)(masterLocalesPath, '
|
|
271
|
-
this.locales.push(...(0, values_1.default)(JSON.parse((0, fs_1.readFileSync)(localesPath, '
|
|
586
|
+
this.locales = (0, values_1.default)(JSON.parse((0, fs_1.readFileSync)(masterLocalesPath, 'utf8')));
|
|
587
|
+
this.locales.push(...(0, values_1.default)(JSON.parse((0, fs_1.readFileSync)(localesPath, 'utf8'))));
|
|
272
588
|
for (const { code } of this.locales) {
|
|
273
589
|
for (const { uid } of this.ctSchema) {
|
|
274
590
|
let basePath = (0, path_1.join)(this.folderPath, uid, code);
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import config from '../config';
|
|
2
2
|
import { ConfigType, LogFn } from './utils';
|
|
3
|
+
type ContentTypeSchemaType = ReferenceFieldDataType | GlobalFieldDataType | CustomFieldDataType | JsonRTEFieldDataType | GroupFieldDataType | ModularBlocksDataType;
|
|
3
4
|
type ContentTypeStruct = {
|
|
4
5
|
uid: string;
|
|
5
6
|
title: string;
|
|
6
7
|
description: string;
|
|
7
|
-
schema?:
|
|
8
|
+
schema?: ContentTypeSchemaType[];
|
|
8
9
|
};
|
|
9
10
|
type ModuleConstructorParam = {
|
|
10
11
|
log: LogFn;
|
|
12
|
+
fix?: boolean;
|
|
11
13
|
config: ConfigType;
|
|
12
14
|
moduleName?: keyof typeof config.moduleConfig;
|
|
13
15
|
};
|
|
@@ -30,6 +32,7 @@ type RefErrorReturnType = {
|
|
|
30
32
|
ct_uid: string;
|
|
31
33
|
treeStr: string;
|
|
32
34
|
data_type: string;
|
|
35
|
+
fixStatus?: string;
|
|
33
36
|
missingRefs: string[];
|
|
34
37
|
display_name: string;
|
|
35
38
|
tree: Record<string, unknown>[];
|
|
@@ -38,10 +41,13 @@ type ReferenceFieldDataType = CommonDataTypeStruct & {
|
|
|
38
41
|
reference_to: string[];
|
|
39
42
|
};
|
|
40
43
|
type GlobalFieldDataType = CommonDataTypeStruct & {
|
|
41
|
-
reference_to
|
|
44
|
+
reference_to?: string;
|
|
42
45
|
schema: GlobalFieldSchemaTypes[];
|
|
43
46
|
};
|
|
44
|
-
type CustomFieldDataType = CommonDataTypeStruct & {
|
|
47
|
+
type CustomFieldDataType = CommonDataTypeStruct & {
|
|
48
|
+
reference_to: string[];
|
|
49
|
+
extension_uid: string;
|
|
50
|
+
};
|
|
45
51
|
type JsonRTEFieldDataType = CommonDataTypeStruct & {
|
|
46
52
|
reference_to: string[];
|
|
47
53
|
};
|
|
@@ -51,6 +57,7 @@ type GroupFieldDataType = CommonDataTypeStruct & {
|
|
|
51
57
|
type ModularBlockType = {
|
|
52
58
|
uid: string;
|
|
53
59
|
title: string;
|
|
60
|
+
reference_to?: string;
|
|
54
61
|
schema: (JsonRTEFieldDataType | ModularBlocksDataType | ReferenceFieldDataType | CustomFieldDataType | GroupFieldDataType)[];
|
|
55
62
|
};
|
|
56
63
|
type ModularBlocksDataType = CommonDataTypeStruct & {
|
|
@@ -66,4 +73,4 @@ declare enum OutputColumn {
|
|
|
66
73
|
'Missing references' = "missingRefs",
|
|
67
74
|
Path = "treeStr"
|
|
68
75
|
}
|
|
69
|
-
export { CtConstructorParam, ContentTypeStruct, ModuleConstructorParam, ReferenceFieldDataType, GlobalFieldDataType, CustomFieldDataType, JsonRTEFieldDataType, GroupFieldDataType, ModularBlocksDataType, RefErrorReturnType, ModularBlocksSchemaTypes, ModularBlockType, OutputColumn, };
|
|
76
|
+
export { CtConstructorParam, ContentTypeStruct, ModuleConstructorParam, ReferenceFieldDataType, GlobalFieldDataType, CustomFieldDataType, JsonRTEFieldDataType, GroupFieldDataType, ModularBlocksDataType, RefErrorReturnType, ModularBlocksSchemaTypes, ModularBlockType, OutputColumn, ContentTypeSchemaType, };
|
package/lib/types/entries.d.ts
CHANGED
|
@@ -25,8 +25,9 @@ type EntryJsonRTEFieldDataType = {
|
|
|
25
25
|
attrs: Record<string, any>;
|
|
26
26
|
children: EntryJsonRTEFieldDataType[];
|
|
27
27
|
};
|
|
28
|
+
type GroupFieldType = EntryReferenceFieldDataType[] | EntryGlobalFieldDataType | EntryJsonRTEFieldDataType;
|
|
28
29
|
type EntryGroupFieldDataType = {
|
|
29
|
-
[key: string]:
|
|
30
|
+
[key: string]: GroupFieldType;
|
|
30
31
|
};
|
|
31
32
|
type EntryModularBlockType = {
|
|
32
33
|
[key: string]: EntryJsonRTEFieldDataType | EntryModularBlocksDataType | EntryReferenceFieldDataType[] | EntryGroupFieldDataType;
|
|
@@ -39,8 +40,10 @@ type EntryRefErrorReturnType = {
|
|
|
39
40
|
uid: string;
|
|
40
41
|
treeStr: string;
|
|
41
42
|
data_type: string;
|
|
42
|
-
|
|
43
|
+
fixStatus?: string;
|
|
43
44
|
display_name: string;
|
|
44
45
|
tree: Record<string, unknown>[];
|
|
46
|
+
missingRefs: string[] | Record<string, unknown>[];
|
|
45
47
|
};
|
|
46
|
-
|
|
48
|
+
type EntryFieldType = EntryStruct | EntryGlobalFieldDataType | EntryModularBlocksDataType | EntryGroupFieldDataType;
|
|
49
|
+
export { Locale, EntryStruct, EntryFieldType, EntryGlobalFieldDataType, EntryCustomFieldDataType, EntryJsonRTEFieldDataType, EntryGroupFieldDataType, EntryModularBlocksDataType, EntryReferenceFieldDataType, EntryRefErrorReturnType, GroupFieldType, EntryModularBlockType, };
|