@contentstack/cli-audit 1.0.0 → 1.2.0
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 +119 -7
- package/lib/modules/entries.js +359 -57
- 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,26 +34,46 @@ 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
|
+
this.ctSchema = (await new content_types_1.default({
|
|
38
|
+
fix: true,
|
|
39
|
+
log: () => { },
|
|
40
|
+
config: this.config,
|
|
41
|
+
moduleName: 'content-types',
|
|
42
|
+
ctSchema: this.ctSchema,
|
|
43
|
+
gfSchema: this.gfSchema,
|
|
44
|
+
}).run(true));
|
|
45
|
+
this.gfSchema = (await new content_types_1.default({
|
|
46
|
+
fix: true,
|
|
47
|
+
log: () => { },
|
|
48
|
+
config: this.config,
|
|
49
|
+
moduleName: 'entries',
|
|
50
|
+
ctSchema: this.ctSchema,
|
|
51
|
+
gfSchema: this.gfSchema,
|
|
52
|
+
}).run(true));
|
|
35
53
|
for (const { code } of this.locales) {
|
|
36
54
|
for (const ctSchema of this.ctSchema) {
|
|
37
55
|
const basePath = (0, path_1.join)(this.folderPath, ctSchema.uid, code);
|
|
38
56
|
const fsUtility = new cli_utilities_1.FsUtility({ basePath, indexFileName: 'index.json' });
|
|
39
57
|
const indexer = fsUtility.indexFileContent;
|
|
40
|
-
for (const
|
|
58
|
+
for (const fileIndex in indexer) {
|
|
41
59
|
const entries = (await fsUtility.readChunkFiles.next());
|
|
42
|
-
|
|
43
|
-
|
|
60
|
+
this.entries = entries;
|
|
61
|
+
for (const entryUid in this.entries) {
|
|
62
|
+
const entry = this.entries[entryUid];
|
|
44
63
|
const { uid, title } = entry;
|
|
45
64
|
this.currentUid = uid;
|
|
46
65
|
this.currentTitle = title;
|
|
47
66
|
this.missingRefs[this.currentUid] = [];
|
|
48
|
-
|
|
67
|
+
this.lookForReference([{ uid, name: title }], ctSchema, this.entries[entryUid]);
|
|
49
68
|
this.log((0, messages_1.$t)(messages_1.auditMsg.SCAN_ENTRY_SUCCESS_MSG, {
|
|
50
69
|
title,
|
|
51
70
|
local: code,
|
|
52
71
|
module: this.config.moduleConfig.entries.name,
|
|
53
72
|
}), 'info');
|
|
54
73
|
}
|
|
74
|
+
if (this.fix) {
|
|
75
|
+
await this.writeFixContent(`${basePath}/${indexer[fileIndex]}`, this.entries);
|
|
76
|
+
}
|
|
55
77
|
}
|
|
56
78
|
}
|
|
57
79
|
}
|
|
@@ -63,6 +85,19 @@ class Entries {
|
|
|
63
85
|
}
|
|
64
86
|
return this.missingRefs;
|
|
65
87
|
}
|
|
88
|
+
/**
|
|
89
|
+
* The function checks if it can write the fix content to a file and if so, it writes the content as
|
|
90
|
+
* JSON to the specified file path.
|
|
91
|
+
*/
|
|
92
|
+
async writeFixContent(filePath, schema) {
|
|
93
|
+
let canWrite = true;
|
|
94
|
+
if (this.fix && !this.config.flags['copy-dir']) {
|
|
95
|
+
canWrite = this.config.flags.yes || (await core_1.ux.confirm(messages_1.commonMsg.FIX_CONFIRMATION));
|
|
96
|
+
}
|
|
97
|
+
if (canWrite) {
|
|
98
|
+
(0, fs_1.writeFileSync)(filePath, JSON.stringify(schema));
|
|
99
|
+
}
|
|
100
|
+
}
|
|
66
101
|
/**
|
|
67
102
|
* The function `lookForReference` iterates over a given schema and validates different field types
|
|
68
103
|
* such as reference, global field, JSON, modular blocks, and group fields.
|
|
@@ -75,30 +110,36 @@ class Entries {
|
|
|
75
110
|
* EntryGroupFieldDataType} entry - The `entry` parameter is an object that represents the data of an
|
|
76
111
|
* entry. It can have different types depending on the `schema` parameter.
|
|
77
112
|
*/
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
113
|
+
lookForReference(tree, field, entry) {
|
|
114
|
+
var _a;
|
|
115
|
+
if (this.fix) {
|
|
116
|
+
entry = this.runFixOnSchema(tree, field.schema, entry);
|
|
117
|
+
}
|
|
118
|
+
for (const child of (_a = field.schema) !== null && _a !== void 0 ? _a : []) {
|
|
119
|
+
const { uid } = child;
|
|
120
|
+
if (!(entry === null || entry === void 0 ? void 0 : entry[uid]))
|
|
121
|
+
return;
|
|
122
|
+
switch (child.data_type) {
|
|
82
123
|
case 'reference':
|
|
83
|
-
this.missingRefs[this.currentUid].push(...this.validateReferenceField([...tree, { uid:
|
|
124
|
+
this.missingRefs[this.currentUid].push(...this.validateReferenceField([...tree, { uid: child.uid, name: child.display_name, field: uid }], child, entry[uid]));
|
|
84
125
|
break;
|
|
85
126
|
case 'global_field':
|
|
86
|
-
|
|
127
|
+
this.validateGlobalField([...tree, { uid: child.uid, name: child.display_name, field: uid }], child, entry[uid]);
|
|
87
128
|
break;
|
|
88
129
|
case 'json':
|
|
89
|
-
if (
|
|
130
|
+
if (child.field_metadata.extension) {
|
|
90
131
|
// NOTE Custom field type
|
|
91
132
|
}
|
|
92
|
-
else if (
|
|
133
|
+
else if (child.field_metadata.allow_json_rte) {
|
|
93
134
|
// NOTE JSON RTE field type
|
|
94
|
-
|
|
135
|
+
this.validateJsonRTEFields([...tree, { uid: child.uid, name: child.display_name, field: uid }], child, entry[uid]);
|
|
95
136
|
}
|
|
96
137
|
break;
|
|
97
138
|
case 'blocks':
|
|
98
|
-
|
|
139
|
+
this.validateModularBlocksField([...tree, { uid: child.uid, name: child.display_name, field: uid }], child, entry[uid]);
|
|
99
140
|
break;
|
|
100
141
|
case 'group':
|
|
101
|
-
|
|
142
|
+
this.validateGroupField([...tree, { uid: field.uid, name: child.display_name, field: uid }], child, entry[uid]);
|
|
102
143
|
break;
|
|
103
144
|
}
|
|
104
145
|
}
|
|
@@ -131,9 +172,9 @@ class Entries {
|
|
|
131
172
|
* @param {EntryGlobalFieldDataType} field - The `field` parameter is of type
|
|
132
173
|
* `EntryGlobalFieldDataType`. It represents a single global field entry.
|
|
133
174
|
*/
|
|
134
|
-
|
|
175
|
+
validateGlobalField(tree, fieldStructure, field) {
|
|
135
176
|
// NOTE Any GlobalField related logic can be added here
|
|
136
|
-
|
|
177
|
+
this.lookForReference(tree, fieldStructure, field);
|
|
137
178
|
}
|
|
138
179
|
/**
|
|
139
180
|
* The function `validateJsonRTEFields` is used to validate the JSON RTE fields by checking if the
|
|
@@ -147,32 +188,18 @@ class Entries {
|
|
|
147
188
|
* `EntryJsonRTEFieldDataType`, which represents a JSON RTE field in an entry. It contains properties
|
|
148
189
|
* such as `uid`, `attrs`, and `children`.
|
|
149
190
|
*/
|
|
150
|
-
|
|
191
|
+
validateJsonRTEFields(tree, fieldStructure, field) {
|
|
151
192
|
var _a;
|
|
193
|
+
// const missingRefIndex = []
|
|
152
194
|
// 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
|
-
}
|
|
195
|
+
for (const index in (_a = field === null || field === void 0 ? void 0 : field.children) !== null && _a !== void 0 ? _a : []) {
|
|
196
|
+
const child = field.children[index];
|
|
197
|
+
const { children } = child;
|
|
198
|
+
if (!this.fix) {
|
|
199
|
+
this.jsonRefCheck(tree, fieldStructure, child);
|
|
173
200
|
}
|
|
174
201
|
if (!(0, isEmpty_1.default)(children)) {
|
|
175
|
-
|
|
202
|
+
this.validateJsonRTEFields(tree, fieldStructure, field.children[index]);
|
|
176
203
|
}
|
|
177
204
|
}
|
|
178
205
|
}
|
|
@@ -189,15 +216,18 @@ class Entries {
|
|
|
189
216
|
* @param {EntryModularBlocksDataType[]} field - The `field` parameter is an array of objects of type
|
|
190
217
|
* `EntryModularBlocksDataType`.
|
|
191
218
|
*/
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
219
|
+
validateModularBlocksField(tree, fieldStructure, field) {
|
|
220
|
+
if (!this.fix) {
|
|
221
|
+
for (const index in field) {
|
|
222
|
+
this.modularBlockRefCheck(tree, fieldStructure.blocks, field[index], +index);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
for (const block of fieldStructure.blocks) {
|
|
226
|
+
const { uid, title } = block;
|
|
227
|
+
for (const eBlock of field) {
|
|
228
|
+
if (eBlock[uid]) {
|
|
229
|
+
this.lookForReference([...tree, { uid, name: title }], block, eBlock[uid]);
|
|
230
|
+
}
|
|
201
231
|
}
|
|
202
232
|
}
|
|
203
233
|
}
|
|
@@ -210,9 +240,16 @@ class Entries {
|
|
|
210
240
|
* @param {EntryGroupFieldDataType} field - The `field` parameter is of type
|
|
211
241
|
* `EntryGroupFieldDataType` and represents a single group field entry.
|
|
212
242
|
*/
|
|
213
|
-
|
|
243
|
+
validateGroupField(tree, fieldStructure, field) {
|
|
214
244
|
// NOTE Any Group Field related logic can be added here (Ex data serialization or picking any metadata for report etc.,)
|
|
215
|
-
|
|
245
|
+
if (Array.isArray(field)) {
|
|
246
|
+
field.forEach((eGroup) => {
|
|
247
|
+
this.lookForReference([...tree, { uid: fieldStructure.uid, display_name: fieldStructure.display_name }], fieldStructure, eGroup);
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
else {
|
|
251
|
+
this.lookForReference(tree, fieldStructure, field);
|
|
252
|
+
}
|
|
216
253
|
}
|
|
217
254
|
/**
|
|
218
255
|
* The function `validateReferenceValues` checks if the references in a given field exist in the
|
|
@@ -230,9 +267,12 @@ class Entries {
|
|
|
230
267
|
* objects.
|
|
231
268
|
*/
|
|
232
269
|
validateReferenceValues(tree, fieldStructure, field) {
|
|
270
|
+
if (this.fix)
|
|
271
|
+
return [];
|
|
233
272
|
const missingRefs = [];
|
|
234
|
-
const { data_type, display_name } = fieldStructure;
|
|
235
|
-
for (const
|
|
273
|
+
const { uid: data_type, display_name } = fieldStructure;
|
|
274
|
+
for (const index in field !== null && field !== void 0 ? field : []) {
|
|
275
|
+
const reference = field[index];
|
|
236
276
|
const { uid } = reference;
|
|
237
277
|
// NOTE Can skip specific references keys (Ex, system defined keys can be skipped)
|
|
238
278
|
// if (this.config.skipRefs.includes(reference)) continue;
|
|
@@ -258,6 +298,268 @@ class Entries {
|
|
|
258
298
|
]
|
|
259
299
|
: [];
|
|
260
300
|
}
|
|
301
|
+
/**
|
|
302
|
+
* The function `runFixOnSchema` takes in a tree, schema, and entry, and applies fixes to the entry
|
|
303
|
+
* based on the schema.
|
|
304
|
+
* @param {Record<string, unknown>[]} tree - An array of objects representing the tree structure of
|
|
305
|
+
* the schema. Each object has the following properties:
|
|
306
|
+
* @param {ContentTypeSchemaType[]} schema - The `schema` parameter is an array of objects
|
|
307
|
+
* representing the content type schema. Each object in the array contains information about a
|
|
308
|
+
* specific field in the schema, such as its unique identifier (`uid`) and data type (`data_type`).
|
|
309
|
+
* @param {EntryFieldType} entry - The `entry` parameter is of type `EntryFieldType`, which
|
|
310
|
+
* represents the data of an entry. It is an object that contains fields as key-value pairs, where
|
|
311
|
+
* the key is the field UID (unique identifier) and the value is the field data.
|
|
312
|
+
* @returns the updated `entry` object after applying fixes to the fields based on the provided
|
|
313
|
+
* `schema`.
|
|
314
|
+
*/
|
|
315
|
+
runFixOnSchema(tree, schema, entry) {
|
|
316
|
+
// NOTE Global field Fix
|
|
317
|
+
schema.forEach((field) => {
|
|
318
|
+
const { uid, data_type } = field;
|
|
319
|
+
switch (data_type) {
|
|
320
|
+
case 'global_field':
|
|
321
|
+
entry[uid] = this.fixGlobalFieldReferences([...tree, { uid: field.uid, name: field.display_name, data_type: field.data_type }], field, entry[uid]);
|
|
322
|
+
break;
|
|
323
|
+
case 'json':
|
|
324
|
+
case 'reference':
|
|
325
|
+
if (data_type === 'json') {
|
|
326
|
+
if (field.field_metadata.extension) {
|
|
327
|
+
// NOTE Custom field type
|
|
328
|
+
return field;
|
|
329
|
+
}
|
|
330
|
+
else if (field.field_metadata.allow_json_rte) {
|
|
331
|
+
return this.fixJsonRteMissingReferences([...tree, { uid: field.uid, name: field.display_name, data_type: field.data_type }], field, entry[uid]);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
// NOTE Reference field
|
|
335
|
+
entry[uid] = this.fixMissingReferences([...tree, { uid: field.uid, name: field.display_name, data_type: field.data_type }], field, entry[uid]);
|
|
336
|
+
break;
|
|
337
|
+
case 'blocks':
|
|
338
|
+
entry[uid] = this.fixModularBlocksReferences([...tree, { uid: field.uid, name: field.display_name, data_type: field.data_type }], field.blocks, entry[uid]);
|
|
339
|
+
break;
|
|
340
|
+
case 'group':
|
|
341
|
+
entry[uid] = this.fixGroupField([...tree, { uid: field.uid, name: field.display_name, data_type: field.data_type }], field, entry[uid]);
|
|
342
|
+
break;
|
|
343
|
+
}
|
|
344
|
+
});
|
|
345
|
+
return entry;
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* The function `fixGlobalFieldReferences` adds a new entry to a tree data structure and runs a fix
|
|
349
|
+
* on the schema.
|
|
350
|
+
* @param {Record<string, unknown>[]} tree - An array of objects representing the tree structure.
|
|
351
|
+
* @param {GlobalFieldDataType} field - The `field` parameter is of type `GlobalFieldDataType` and
|
|
352
|
+
* represents a global field object. It contains properties such as `uid` and `display_name`.
|
|
353
|
+
* @param {EntryGlobalFieldDataType} entry - The `entry` parameter is of type
|
|
354
|
+
* `EntryGlobalFieldDataType` and represents the global field entry that needs to be fixed.
|
|
355
|
+
* @returns the result of calling the `runFixOnSchema` method with the updated `tree` array,
|
|
356
|
+
* `field.schema`, and `entry` as arguments.
|
|
357
|
+
*/
|
|
358
|
+
fixGlobalFieldReferences(tree, field, entry) {
|
|
359
|
+
return this.runFixOnSchema([...tree, { uid: field.uid, display_name: field.display_name }], field.schema, entry);
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* The function `fixModularBlocksReferences` takes in a tree, a list of blocks, and an entry, and
|
|
363
|
+
* performs various operations to fix references within the entry.
|
|
364
|
+
* @param {Record<string, unknown>[]} tree - An array of objects representing the tree structure of
|
|
365
|
+
* the modular blocks.
|
|
366
|
+
* @param {ModularBlockType[]} blocks - An array of objects representing modular blocks. Each object
|
|
367
|
+
* has properties like `uid` (unique identifier) and `title` (display name).
|
|
368
|
+
* @param {EntryModularBlocksDataType[]} entry - An array of objects representing the modular blocks
|
|
369
|
+
* data in an entry. Each object in the array represents a modular block and contains its unique
|
|
370
|
+
* identifier (uid) and other properties.
|
|
371
|
+
* @returns the updated `entry` array after performing some modifications.
|
|
372
|
+
*/
|
|
373
|
+
fixModularBlocksReferences(tree, blocks, entry) {
|
|
374
|
+
entry = entry
|
|
375
|
+
.map((block, index) => this.modularBlockRefCheck(tree, blocks, block, index))
|
|
376
|
+
.filter((val) => !(0, isEmpty_1.default)(val));
|
|
377
|
+
blocks.forEach((block) => {
|
|
378
|
+
entry = entry
|
|
379
|
+
.map((eBlock) => {
|
|
380
|
+
if (!(0, isEmpty_1.default)(block.schema)) {
|
|
381
|
+
if (eBlock[block.uid]) {
|
|
382
|
+
eBlock[block.uid] = this.runFixOnSchema([...tree, { uid: block.uid, display_name: block.title }], block.schema, eBlock[block.uid]);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
return eBlock;
|
|
386
|
+
})
|
|
387
|
+
.filter((val) => !(0, isEmpty_1.default)(val));
|
|
388
|
+
});
|
|
389
|
+
return entry;
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* The function `fixGroupField` takes in a tree, a field, and an entry, and if the field has a
|
|
393
|
+
* schema, it runs a fix on the schema and returns the updated entry, otherwise it returns the
|
|
394
|
+
* original entry.
|
|
395
|
+
* @param {Record<string, unknown>[]} tree - An array of objects representing the tree structure.
|
|
396
|
+
* @param {GroupFieldDataType} field - The `field` parameter is of type `GroupFieldDataType` and
|
|
397
|
+
* represents a group field object. It contains properties such as `uid` (unique identifier) and
|
|
398
|
+
* `display_name` (name of the field).
|
|
399
|
+
* @param {EntryGroupFieldDataType} entry - The `entry` parameter is of type
|
|
400
|
+
* `EntryGroupFieldDataType`.
|
|
401
|
+
* @returns If the `field.schema` is not empty, the function will return the result of calling
|
|
402
|
+
* `this.runFixOnSchema` with the updated `tree`, `field.schema`, and `entry` as arguments.
|
|
403
|
+
* Otherwise, it will return the `entry` as is.
|
|
404
|
+
*/
|
|
405
|
+
fixGroupField(tree, field, entry) {
|
|
406
|
+
if (!(0, isEmpty_1.default)(field.schema)) {
|
|
407
|
+
if (Array.isArray(entry)) {
|
|
408
|
+
entry = entry.map((eGroup) => {
|
|
409
|
+
return this.runFixOnSchema([...tree, { uid: field.uid, display_name: field.display_name }], field.schema, eGroup);
|
|
410
|
+
});
|
|
411
|
+
}
|
|
412
|
+
else {
|
|
413
|
+
entry = this.runFixOnSchema([...tree, { uid: field.uid, display_name: field.display_name }], field.schema, entry);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
return entry;
|
|
417
|
+
}
|
|
418
|
+
/**
|
|
419
|
+
* The function fixes missing references in a JSON tree structure.
|
|
420
|
+
* @param {Record<string, unknown>[]} tree - An array of objects representing a tree structure. Each
|
|
421
|
+
* object in the array has a string key and an unknown value.
|
|
422
|
+
* @param {ReferenceFieldDataType | JsonRTEFieldDataType} field - The `field` parameter can be of
|
|
423
|
+
* type `ReferenceFieldDataType` or `JsonRTEFieldDataType`.
|
|
424
|
+
* @param {EntryJsonRTEFieldDataType} entry - The `entry` parameter is of type
|
|
425
|
+
* `EntryJsonRTEFieldDataType`, which represents an entry in a JSON Rich Text Editor (JsonRTE) field.
|
|
426
|
+
* @returns the updated `entry` object with fixed missing references in the `children` property.
|
|
427
|
+
*/
|
|
428
|
+
fixJsonRteMissingReferences(tree, field, entry) {
|
|
429
|
+
if (Array.isArray(entry)) {
|
|
430
|
+
entry = entry.map((child, index) => {
|
|
431
|
+
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);
|
|
432
|
+
});
|
|
433
|
+
}
|
|
434
|
+
else {
|
|
435
|
+
entry.children = entry.children
|
|
436
|
+
.map((child) => {
|
|
437
|
+
const refExist = this.jsonRefCheck(tree, field, child);
|
|
438
|
+
if (!refExist)
|
|
439
|
+
return null;
|
|
440
|
+
if ((0, isEmpty_1.default)(child.children)) {
|
|
441
|
+
child = this.fixJsonRteMissingReferences(tree, field, child);
|
|
442
|
+
}
|
|
443
|
+
return child;
|
|
444
|
+
})
|
|
445
|
+
.filter((val) => val);
|
|
446
|
+
}
|
|
447
|
+
return entry;
|
|
448
|
+
}
|
|
449
|
+
/**
|
|
450
|
+
* The `fixMissingReferences` function checks for missing references in an entry and adds them to a
|
|
451
|
+
* list if they are not found.
|
|
452
|
+
* @param {Record<string, unknown>[]} tree - An array of objects representing a tree structure. Each
|
|
453
|
+
* object in the array should have a "name" property and an optional "index" property.
|
|
454
|
+
* @param {ReferenceFieldDataType | JsonRTEFieldDataType} field - The `field` parameter is of type
|
|
455
|
+
* `ReferenceFieldDataType` or `JsonRTEFieldDataType`.
|
|
456
|
+
* @param {EntryReferenceFieldDataType[]} entry - The `entry` parameter is an array of objects that
|
|
457
|
+
* represent references to other entries. Each object in the array has the following properties:
|
|
458
|
+
* @returns the `entry` variable.
|
|
459
|
+
*/
|
|
460
|
+
fixMissingReferences(tree, field, entry) {
|
|
461
|
+
const missingRefs = [];
|
|
462
|
+
entry = entry
|
|
463
|
+
.map((reference) => {
|
|
464
|
+
const { uid } = reference;
|
|
465
|
+
const refExist = (0, find_1.default)(this.entryMetaData, { uid });
|
|
466
|
+
if (!refExist) {
|
|
467
|
+
missingRefs.push(reference);
|
|
468
|
+
return null;
|
|
469
|
+
}
|
|
470
|
+
return reference;
|
|
471
|
+
})
|
|
472
|
+
.filter((val) => val);
|
|
473
|
+
if (!(0, isEmpty_1.default)(missingRefs)) {
|
|
474
|
+
this.missingRefs[this.currentUid].push({
|
|
475
|
+
tree,
|
|
476
|
+
fixStatus: 'Fixed',
|
|
477
|
+
uid: this.currentUid,
|
|
478
|
+
name: this.currentTitle,
|
|
479
|
+
data_type: field.data_type,
|
|
480
|
+
display_name: field.display_name,
|
|
481
|
+
treeStr: tree
|
|
482
|
+
.map(({ name, index }) => (index || index === 0 ? `[${index}].${name}` : name))
|
|
483
|
+
.filter((val) => val)
|
|
484
|
+
.join(' ➜ '),
|
|
485
|
+
missingRefs,
|
|
486
|
+
});
|
|
487
|
+
}
|
|
488
|
+
return entry;
|
|
489
|
+
}
|
|
490
|
+
/**
|
|
491
|
+
* The function `modularBlockRefCheck` checks for invalid keys in an entry block and returns the
|
|
492
|
+
* updated entry block.
|
|
493
|
+
* @param {Record<string, unknown>[]} tree - An array of objects representing the tree structure of
|
|
494
|
+
* the blocks.
|
|
495
|
+
* @param {ModularBlockType[]} blocks - The `blocks` parameter is an array of `ModularBlockType`
|
|
496
|
+
* objects.
|
|
497
|
+
* @param {EntryModularBlocksDataType} entryBlock - The `entryBlock` parameter is an object that
|
|
498
|
+
* represents a modular block entry. It contains key-value pairs where the keys are the UIDs of the
|
|
499
|
+
* modular blocks and the values are the data associated with each modular block.
|
|
500
|
+
* @param {Number} index - The `index` parameter is a number that represents the index of the current
|
|
501
|
+
* block in the `tree` array.
|
|
502
|
+
* @returns the `entryBlock` object.
|
|
503
|
+
*/
|
|
504
|
+
modularBlockRefCheck(tree, blocks, entryBlock, index) {
|
|
505
|
+
const validBlockUid = blocks.map((block) => block.uid);
|
|
506
|
+
const invalidKeys = Object.keys(entryBlock).filter((key) => !validBlockUid.includes(key));
|
|
507
|
+
invalidKeys.forEach((key) => {
|
|
508
|
+
if (this.fix) {
|
|
509
|
+
delete entryBlock[key];
|
|
510
|
+
}
|
|
511
|
+
this.missingRefs[this.currentUid].push({
|
|
512
|
+
uid: this.currentUid,
|
|
513
|
+
name: this.currentTitle,
|
|
514
|
+
data_type: key,
|
|
515
|
+
display_name: key,
|
|
516
|
+
fixStatus: this.fix ? 'Fixed' : undefined,
|
|
517
|
+
tree: [...tree, { index, uid: key, name: key }],
|
|
518
|
+
treeStr: [...tree, { index, uid: key, name: key }]
|
|
519
|
+
.map(({ name, index }) => (index || index === 0 ? `[${index}].${name}` : name))
|
|
520
|
+
.filter((val) => val)
|
|
521
|
+
.join(' ➜ '),
|
|
522
|
+
missingRefs: [key],
|
|
523
|
+
});
|
|
524
|
+
});
|
|
525
|
+
return entryBlock;
|
|
526
|
+
}
|
|
527
|
+
/**
|
|
528
|
+
* The `jsonRefCheck` function checks if a reference exists in a JSON tree and adds missing
|
|
529
|
+
* references to a list if they are not found.
|
|
530
|
+
* @param {Record<string, unknown>[]} tree - An array of objects representing the tree structure.
|
|
531
|
+
* @param {JsonRTEFieldDataType} schema - The `schema` parameter is of type `JsonRTEFieldDataType`
|
|
532
|
+
* and represents the schema of a JSON field. It contains properties such as `uid`, `data_type`, and
|
|
533
|
+
* `display_name`.
|
|
534
|
+
* @param {EntryJsonRTEFieldDataType} child - The `child` parameter is an object that represents a
|
|
535
|
+
* child entry in a JSON tree. It has the following properties:
|
|
536
|
+
* @returns The function `jsonRefCheck` returns either `null` or `true`.
|
|
537
|
+
*/
|
|
538
|
+
jsonRefCheck(tree, schema, child) {
|
|
539
|
+
const { uid: childrenUid } = child;
|
|
540
|
+
const { 'entry-uid': entryUid, 'content-type-uid': contentTypeUid } = child.attrs || {};
|
|
541
|
+
if (entryUid) {
|
|
542
|
+
const refExist = (0, find_1.default)(this.entryMetaData, { uid: entryUid });
|
|
543
|
+
if (!refExist) {
|
|
544
|
+
tree.push({ field: 'children' }, { field: childrenUid, uid: schema.uid });
|
|
545
|
+
this.missingRefs[this.currentUid].push({
|
|
546
|
+
tree,
|
|
547
|
+
uid: this.currentUid,
|
|
548
|
+
name: this.currentTitle,
|
|
549
|
+
data_type: schema.data_type,
|
|
550
|
+
display_name: schema.display_name,
|
|
551
|
+
fixStatus: this.fix ? 'Fixed' : undefined,
|
|
552
|
+
treeStr: tree
|
|
553
|
+
.map(({ name }) => name)
|
|
554
|
+
.filter((val) => val)
|
|
555
|
+
.join(' ➜ '),
|
|
556
|
+
missingRefs: [{ uid: entryUid, 'content-type-uid': contentTypeUid }],
|
|
557
|
+
});
|
|
558
|
+
return null;
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
return true;
|
|
562
|
+
}
|
|
261
563
|
/**
|
|
262
564
|
* The function prepares entry metadata by reading and processing files from different locales and
|
|
263
565
|
* schemas.
|
|
@@ -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, };
|